STM32改写printf输出到串口需要注意的问题

发布于:2024-12-08 ⋅ 阅读:(116) ⋅ 点赞:(0)
int fputc(int ch, FILE *f)
{
    while ((USART1->SR & 0X40) == 0);                                       /* 等待上一个字符发送完成 */

    USART1->DR = (uint8_t)ch;                                               /* 将要发送的字符 ch 写入到DR寄存器 */
    return ch;
}

int fputc(int ch, FILE *f)
{      
    unsigned char temp[1]={ch};
    HAL_UART_Transmit(&huart1,temp,1,0xffff);  
    return ch;
}

可以看到上述两个fputc函数,其中第一个不可以使用在freertos系统中,因为多任务同时输出会导致输出错误。

这两个fputc函数的实现都是为了将字符通过STM32的串口(UART)发送出去,以支持通过printf等标准I/O函数将输出重定向到串口。然而,它们使用了不同的方法来达到这个目的,具体区别如下:

第一个fputc实现


c复制代码

int fputc(int ch, FILE *f)
{
while ((USART1->SR & 0X40) == 0); /* 等待上一个字符发送完成 */
USART1->DR = (uint8_t)ch; /* 将要发送的字符 ch 写入到DR寄存器 */
return ch;
}
  • 直接操作硬件寄存器:这个实现直接操作STM32的USART1的硬件寄存器。USART1->SR是状态寄存器,0X40(即USART_FLAG_TXE)表示发送数据寄存器空标志位,用于检查发送缓冲区是否为空。如果为空,表示可以发送新的数据。USART1->DR是数据寄存器,用于存放要发送的数据。
  • 阻塞等待:该实现使用了一个while循环来阻塞等待,直到发送缓冲区为空(即上一个字符发送完成)。这种方式简单直接,但可能会在某些情况下导致程序响应变慢,尤其是当串口通信速度较慢或通信频繁时。
  • 效率:直接操作寄存器通常具有较高的效率,因为没有函数调用和中断处理的开销。

第二个fputc实现


c复制代码

int fputc(int ch, FILE *f)
{
unsigned char temp[1]={ch};
HAL_UART_Transmit(&huart1,temp,1,0xffff);
return ch;
}
  • 使用HAL库:这个实现使用了STM32的硬件抽象层(HAL)库函数HAL_UART_Transmit来发送数据。HAL_UART_Transmit是一个非阻塞或可配置为超时阻塞的函数,用于通过指定的UART接口发送一定数量的数据字节。
  • 配置灵活:使用HAL库函数可以提供更多的配置选项,比如可以设置超时时间(在这个例子中为0xffff,即几乎无限等待),从而避免完全阻塞等待。
  • 代码可读性和可移植性:使用HAL库函数可以提高代码的可读性和可移植性,因为库函数封装了底层硬件操作的细节。
  • 开销:使用HAL库函数相比直接操作寄存器可能会有一定的性能开销,因为库函数内部可能包含额外的检查和错误处理逻辑。

总结

两个实现的主要区别在于它们如何与STM32的UART硬件接口交互:一个是直接操作硬件寄存器,另一个是通过STM32 HAL库提供的函数。选择哪种方法取决于具体的应用场景和需求,比如对性能的要求、代码的可读性和可维护性等。


网站公告

今日签到

点亮在社区的每一天
去签到