STM32CubeMx启动串口调试功能Printf调试

版权声明:本文为博主原创文章,未经博主允许不得转载。
https://blog.csdn.net/u012163234/article/details/52712477
https://blog.csdn.net/u014256685/article/details/45893097
关键词:stm32调试,printf,cubeMX调试模式,Stm32CubMx调试,MDK 调试,Stm32 printf,基于Stm32CubeMx的调试串口代码。stm32 printf 重定向,stm32 printf 调试口

## 概述
项目中往往需要调试信息,调试stm32的时候,需要标准库里面的printf函数。在keil MDK环境下重定向printf与keil C51不同,由于本人使用了STM32CubeMX生成工程模板,HAL_USART_Transmit函数即是模板里串口输出的函数。由于printf最终是调用fputc输出数据,fputc是一个弱引用(weak)函数,覆写即可重定向printf。

  • 代码清单
/* USER CODE BEGIN Includes */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include <stdio.h>
/* USER CODE END Includes */


/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
#ifdef __GNUC__
	#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
	#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
		HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
		return ch;
}
/* USER CODE END PV */




#### 华丽的分界线


例子:

硬件平台:stm32F407Zet6

软件平台:stm32cubeMX 4.7+MDK5.14

电路连接:PA9,PA10

第一步、通过Stm32CubeMX图形界面创建Keil工程

  • 需要配置的地方是:
    stm32串口调试2

  • 第二章配置图:
    stm32PrintfDebugPic2

  • 在这里可以修改串口工作的一下参数,软件就可以生成配置好的工程,不需要亲自去配置这些了。

第二步。打开工程,编写代码,验证

  • 代码清单
/* USER CODE BEGIN PV */
#include "stdio.h"
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE
{
	HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
	return ch;
}
/* USER CODE END PV */

这段程序为了可以使用printf()函数,对字符输出函数进行了重定向,这样我们就可以在程序中使用printf函数进行输出了,这里使用的是查询发送方式,有超时控制的。接下来来看中断方式的。

  • 代码清单
/**
  * @brief  This function handles UART interrupt request.
  * @param  huart: pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @retval None
  */
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
  uint32_t tmp1 = 0, tmp2 = 0;
 
  tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_PE);
  tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_PE);  
  /* UART parity error interrupt occurred ------------------------------------*/
  if((tmp1 != RESET) && (tmp2 != RESET))
  { 
    __HAL_UART_CLEAR_PEFLAG(huart);
    
    huart->ErrorCode |= HAL_UART_ERROR_PE;
  }
  
  tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_FE);
  tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR);
  /* UART frame error interrupt occurred -------------------------------------*/
  if((tmp1 != RESET) && (tmp2 != RESET))
  { 
    __HAL_UART_CLEAR_FEFLAG(huart);
    
    huart->ErrorCode |= HAL_UART_ERROR_FE;
  }
  
  tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_NE);
  tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR);
  /* UART noise error interrupt occurred -------------------------------------*/
  if((tmp1 != RESET) && (tmp2 != RESET))
  { 
    __HAL_UART_CLEAR_NEFLAG(huart);
    
    huart->ErrorCode |= HAL_UART_ERROR_NE;
  }
  
  tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_ORE);
  tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR);
  /* UART Over-Run interrupt occurred ----------------------------------------*/
  if((tmp1 != RESET) && (tmp2 != RESET))
  { 
    __HAL_UART_CLEAR_OREFLAG(huart);
    
    huart->ErrorCode |= HAL_UART_ERROR_ORE;
  }
  
  tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE);
  tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE);
  /* UART in mode Receiver ---------------------------------------------------*/
  if((tmp1 != RESET) && (tmp2 != RESET))
  { 
    UART_Receive_IT(huart);
  }
  
  tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_TXE);
  tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_TXE);
  /* UART in mode Transmitter ------------------------------------------------*/
  if((tmp1 != RESET) && (tmp2 != RESET))
  {
    UART_Transmit_IT(huart);
  }
  
  tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_TC);
  tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_TC);
  /* UART in mode Transmitter end --------------------------------------------*/
  if((tmp1 != RESET) && (tmp2 != RESET))
  {
    UART_EndTransmit_IT(huart);
  }
 
  if(huart->ErrorCode != HAL_UART_ERROR_NONE)
  {
    /* Set the UART state ready to be able to start again the process */
    huart->State = HAL_UART_STATE_READY;
    
    HAL_UART_ErrorCallback(huart);
  }  
}

这个函数中查询了所有可能发生的中断。用到的中断是发送完成中断,就找到了UART_EndTransmit_IT(huart);再跳进去看看:

  • 代码清单
/**
  * @brief  Wraps up transmission in non blocking mode.
  * @param  huart: pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @retval HAL status
  */
static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart)
{
  /* Disable the UART Transmit Complete Interrupt */    
  __HAL_UART_DISABLE_IT(huart, UART_IT_TC);
  
  /* Check if a receive process is ongoing or not */
  if(huart->State == HAL_UART_STATE_BUSY_TX_RX) 
  {
    huart->State = HAL_UART_STATE_BUSY_RX;
  }
  else
  {
    /* Disable the UART Parity Error Interrupt */
    __HAL_UART_DISABLE_IT(huart, UART_IT_PE);
 
    /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
    __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);
 
    huart->State = HAL_UART_STATE_READY;
  }
  
  HAL_UART_TxCpltCallback(huart);
  
  return HAL_OK;
}

这个函数在确定中断发生了之后调用了,HAL_UART_TxCpltCallback(huart);从函数名上可以看出,这是个回调函数,就是留给上层来实现的函数,由这个函数的实现不同,来实现不同的功能。这里来实现这个函数,让它在中断发生的时候吧USART1Ready置为SET;代码修改如下:

  • 代码清单
/* USER CODE BEGIN PV */
#include "stdio.h"
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
__IO ITStatus USART1Ready = RESET;
 
PUTCHAR_PROTOTYPE
{
	HAL_UART_Transmit_IT(&huart1 , (uint8_t *)&ch, 1);
	while (USART1Ready != SET)
  {
  }
	USART1Ready = RESET;
	return ch;
}
 
 
/* USER CODE END PV */

这是重定向函数的修改,启动发送之后,等待发送完成。重新实现的回调函数如下图所示:

/**
  * @brief  Tx Transfer completed callbacks.
  * @param  huart: pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @retval None
  */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_UART_TxCpltCallback could be implemented in the user file
   */ 
	USART1Ready = SET;
}

  • 最后,编译,下载验证代码!

猜你喜欢

转载自blog.csdn.net/mynameislinduan/article/details/81980282