【HAL库】STM32上手体验 之 UART 串口应用
2019-07-02 本文已影响0人
dexfire
【HAL库】STM32上手体验 之 UART 串口应用
串口是非常方便的调试工具,如果没有串口很多程序只能根据可见现象盲调,非常不方便。灵活使用串口,甚至能达到超越 JTAG 等调试工具的便捷调试目的。
这里以USART1为例进行描述,PA10 -> RX, PA9 -> TX。
- 系统AHB、APB1、APB2的时钟初始化
STM32在初始化后是默认使用HSI频率作为SYSCLK使用,并默认关闭大部分外设,仅保留核心运行所必需的Flash、SRAM、JTAG时钟。这是几乎所有STM32应用所必须的过程,这里不多叙述。
- 启用并初始化UART1对应的GPIO
首先启用GPIOA时钟,并初始化对应端口 PA9、PA10为复用推挽输出模式
【PA10 -> RX, PA9 -> TX】
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_Init_Struct;
GPIO_Init_Struct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
GPIO_Init_Struct.Mode = GPIO_MODE_AF_PP;
GPIO_Init_Struct.Pull = GPIO_PULLUP;
GPIO_Init_Struct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA,&GPIO_Init_Struct);
然后初始化对应的UART外设
__HAL_RCC_USART1_CLK_ENABLE();
// __HAL_UART_ENABLE(&UART_Handler); // 调用后单片机会卡死
UART_Handler.Instance = USART1;
UART_Handler.Init.BaudRate = 9600;
UART_Handler.Init.WordLength = USART_WORDLENGTH_8B;
UART_Handler.Init.StopBits = USART_STOPBITS_1;
UART_Handler.Init.Mode = USART_MODE_TX_RX; // 同步收发模式
UART_Handler.Init.Parity = USART_PARITY_NONE; // 无奇偶校验
UART_Handler.Init.HwFlowCtl = UART_HWCONTROL_NONE;
// RTS:Ready to Send; CTS:Clear to Send; NONE:N/A
HAL_UART_Init(&UART_Handler);
char* str = "UART Initialzing ... OK!";
// printf(str);
HAL_UART_Transmit(&UART_Handler,(uint8_t*)str,strlen(str),0xffff);
使用 printf()
函数通过 UART1 输出字符
到这里其实就能够调用 HAL_UART_Transmit()
函数来输出串口数据了,但实际使用过程中还是随时随地360无死角好用的 printf()
函数更加可口,所以我们再研究一下如何配置为可用 printf()
输出。
根据网上资料和ST给的例程,发现复写 fputc(char ch,FILE *f)
函数就能实现 printf()
但是惨遭忽悠,实际使用并没有得到预期的串口输出。
#ifdef __GNUC__
/* With GCC, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART1 and Loop until the end of transmission */
HAL_UART_Transmit(&UART_Handler, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
虽然看起来很靠谱,但是实际应用并没有生效。用VS的追踪功能发现,使用的是预处理定义中的 __io_putchar(int ch)
分支,因为我使用的 ARM 编译器是基于 GCC 的。