## 概述
项目中往往需要调试信息,调试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 /* 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工程 需要配置的地方是: 第二章配置图: 在这里可以修改串口工作的一下参数,软件就可以生成配置好的工程,不需要亲自去配置这些了。 第二步。打开工程,编写代码,验证 代码清单 /* 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; } 最后,编译,下载验证代码!
上一篇:STM32F1xx HAL库中文版——USART篇
下一篇:【STM32】keil MDK下重定向printf到串口(基于STM32CubeMX)
推荐阅读最新更新时间:2024-11-16 19:57
设计资源 培训 开发板 精华推荐
- 使用 LTC4162IUFD-L42M 1-8 节、3.2A 降压型开关电池充电器和 PowerPath 的典型应用
- 用于开/关控制应用的 AM2G-4805DZ ±5V 2 瓦 DC-DC 转换器的典型应用
- openmv+滚球控制板
- DI-146 - 35 W 液晶显示器电源
- EVAL-ADM1064TQEB,评估 ADM1064ASU 电压监控器排序器的评估板
- DC1753B-A,基于 LTC3880EUJ 双相单输出 PMBus 降压的演示板 (RSENSE),6.5V = VIN= 24V,VOUT = 0.5V 至 3.3V @ 40A
- 金榜题名书签
- 使用 NXP Semiconductors 的 MC9S12G128ML 的参考设计
- TC7732FTG 子电源管理 IC 的典型应用
- 基于ESP12F模组制作宿舍物联网电路【长江大学】