STM32 KEIL 串口打印printf使用详解

您所在的位置:网站首页 printf函数在哪个头文件 STM32 KEIL 串口打印printf使用详解

STM32 KEIL 串口打印printf使用详解

2024-07-05 20:53| 来源: 网络整理| 查看: 265

常规打印方法

在STM32的应用中,我们常常对printf进行重定向的方式来把打印信息printf到我们的串口助手。

在MDK环境中,我们常常使用MicroLIB+fputc的方式实现串口打印功能,即:

要实现fputc函数的原因是:printf函数依赖于fputc函数,重新实现fputc内部从串口发送数据即可间接地实现printf打印输出数据到串口。

不知道大家有没有看过正点原子裸机串口相关的例程,他们的串口例程里不使用MicroLIB,而是使用标准库+fputc的方式。相关代码如:

#if 1 #pragma import(__use_no_semihosting) //标准库需要的支持函数 struct __FILE {     int handle; }; FILE __stdout; /**  * @brief 定义_sys_exit()以避免使用半主机模式  * @param void  * @return  void  */ void _sys_exit(int x) {     x = x; } int fputc(int ch, FILE *f) {     while((USART1->ISR & 0X40) == 0); //循环发送,直到发送完毕     USART1->TDR = (u8) ch;     return ch; } #endif

关于这两种方法的一些说明可以查看Mculover666兄的《重定向printf函数到串口输出的多种方法》这篇文章。这篇文章中不仅包含上面的两种方法,而且也包含着在GCC中使用标准库重定向printf的方法。

自己实现一个打印函数

以上的几种方法基本上是改造C库的printf函数来实现串口打印的功能。其实我们也可以自己实现一个串口打印的功能。

printf本身就是一个变参函数,其原型为:

int printf (const char *__format, ...);

所以,我们要重新封装的一个串口打印函数自然也应该是一个变参函数。具体实现如下:

1、基于STM32的HAL库

左右滑动查看全部代码>>>

#define TX_BUF_LEN  256     /* 发送缓冲区容量,根据需要进行调整 */ uint8_t TxBuf[TX_BUF_LEN];  /* 发送缓冲区                       */ void MyPrintf(const char *__format, ...) {   va_list ap;   va_start(ap, __format);      /* 清空发送缓冲区 */   memset(TxBuf, 0x0, TX_BUF_LEN);      /* 填充发送缓冲区 */   vsnprintf((char*)TxBuf, TX_BUF_LEN, (const char *)__format, ap);   va_end(ap);   int len = strlen((const char*)TxBuf);      /* 往串口发送数据 */   HAL_UART_Transmit(&huart1, (uint8_t*)&TxBuf, len, 0xFFFF); }

因为我们使用printf函数基本不使用其返回值,所以这里直接用void类型了。

自定义变参函数需要用到va_start、va_end等宏,需要包含头文件stdarg.h。关于变参函数的一些学习可以查看网上的一些博文,如:

https://www.cnblogs.com/wulei0630/p/9444062.html

这里我们使用的是STM32的HAL库,其给我们提供HAL_UART_Transmit接口可以直接把整个发送缓冲区的内容给一次性发出去。

2、基于STM32标准库

若是基于STM32的标准库,就需要一字节一字节的循环发送出去,具体代码如:

左右滑动查看全部代码>>>

#define TX_BUF_LEN  256     /* 发送缓冲区容量,根据需要进行调整 */ uint8_t TxBuf[TX_BUF_LEN];  /* 发送缓冲区                       */ void MyPrintf(const char *__format, ...) {   va_list ap;   va_start(ap, __format);        /* 清空发送缓冲区 */   memset(TxBuf, 0x0, TX_BUF_LEN);        /* 填充发送缓冲区 */   vsnprintf((char*)TxBuf, TX_BUF_LEN, (const char *)__format, ap);   va_end(ap);   int len = strlen((const char*)TxBuf);      /* 往串口发送数据 */   for (int i = 0; i 


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3