重定义/自定义printf到串口输出实现的三种方法(cubeide)
文章目录
- 重定义/自定义printf到串口输出实现的三种方法(cubeide)
- 1.重写_write函数
- 2.重定义PUTCHAR_PROTOTYPE宏
- 3.va_list自定义printf
- 总结:
1.重写_write函数
注释掉syscalls.c文件中的_write函数
重写_write函数
__attribute__((weak)) int _write(int file, char *ptr, int len)
{
if(HAL_UART_Transmit(&huart1,(uint8_t *)ptr,len,0xffff) != HAL_OK)
{
Error_Handler();
}
return len;
}
这段代码也是一个重定义的输出方法,用于重定向标准输出函数_write。通过使用__attribute__((weak))属性修饰,可以在用户自定义的函数中进行重定义。
具体分析如下:
函数的原型是int _write(int file, char *ptr, int len),表示重定义了标准输出函数_write。该函数接受三个参数,file表示文件描述符(在这里可以忽略),ptr表示要发送的数据指针,len表示要发送的数据长度。
在函数内部,使用HAL_UART_Transmit函数将数据指针ptr指向的内容通过UART进行传输。这里同样使用了名为huart1的UART句柄,您可能需要根据实际情况进行相应的修改。
如果UART传输过程中出现错误,通过调用Error_Handler函数进行错误处理。
最后,函数返回发送的数据长度len。
2.重定义PUTCHAR_PROTOTYPE宏
/* USER CODE BEGIN PFP */
#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 PFP */
这段代码是重定义了printf函数的输出方法,使用串口进行输出。它通过重定义PUTCHAR_PROTOTYPE宏来定义了一个名为__io_putchar(对于GCC编译器)或fputc(对于其他编译器)的函数。
首先,根据编译器类型,PUTCHAR_PROTOTYPE宏会被定义为__io_putchar或fputc。GCC编译器使用__io_putchar,而其他编译器使用fputc。
接下来,PUTCHAR_PROTOTYPE函数会被定义。它的返回类型是int,并接受一个字符参数ch。
在函数内部,使用HAL_UART_Transmit函数将字符ch通过UART进行传输。这里使用了名为huart1的UART句柄,你可能需要根据实际情况进行相应的修改。
最后,函数返回传输的字符ch。
3.va_list自定义printf
#define USART2_MAX_SEND_LEN 400
#pragma pack(8)
uint8_t USART1_TX_BUF[USART1_MAX_SEND_LEN]; //发送缓冲,最大USART2_MAX_SEND_LEN字节
#pragma pack()
void u1_printf(char* fmt,...)
{
uint16_t i,j;
va_list ap;
va_start(ap,fmt);
vsprintf((char*)USART1_TX_BUF,fmt,ap);
va_end(ap);
i=strlen((const char*)USART1_TX_BUF);//此次发送数据的长度
for(j=0;j<i;j++)//循环发送数据
{
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
USART1->DR=USART2_TX_BUF[j];
}
}
这段代码是一个用于在串口1上实现重定义的printf函数的例子。
具体分析如下:
首先,定义了一个名为u1_printf的函数,用于重定义printf函数在串口2上的输出。
函数接受一个格式化字符串fmt作为参数,后面跟着可变参数列表…。
在函数内部,首先使用va_start宏和va_list类型的变量ap来初始化可变参数列表。
然后,使用vsprintf函数将格式化后的字符串保存到全局数组USART1_TX_BUF中。这里假设数组已经定义,并且长度足够容纳格式化后的字符串。vsprintf函数的使用类似于sprintf,但是可以处理可变参数列表。
使用va_end宏结束可变参数的处理。
接下来,计算格式化后的字符串的长度,并将其存储在变量i中。
然后,通过循环逐个发送数据。在每次发送之前,使用while循环等待串口2发送寄存器为空,即等待上一次发送完成。
最后,将字符逐个发送到串口2的数据寄存器USART1->DR中,以便通过串口进行发送。
如果文章对您有所帮助,点赞支持,感谢!!!
总结:
重写_write函数:通过重定义_write函数,将数据通过UART发送。在函数内部使用HAL_UART_Transmit函数将数据发送到UART。如果发送过程中出现错误,会调用Error_Handler函数进行错误处理。
重定义PUTCHAR_PROTOTYPE宏:通过重定义PUTCHAR_PROTOTYPE宏,定义了一个名为__io_putchar(对于GCC编译器)或fputc(对于其他编译器)的函数。这个函数将字符通过UART发送。
自定义printf函数:定义了一个名为u1_printf的函数,用于在串口1上实现重定义的printf函数。函数接受一个格式化字符串作为参数,使用vsprintf函数将格式化后的字符串保存到全局数组USART1_TX_BUF中。然后通过循环逐个发送数据到串口1的数据寄存器。
这些重定义的函数和宏都用于实现在特定的串口上进行输出,并使用UART进行数据传输。请确保在使用这些重定义函数之前已经正确初始化了相关的硬件资源(例如UART)以及引入了正确的头文件。
如果文章对您有所帮助,点赞支持,感谢!!!