STM32 串口使用频繁的朋友可能知道一个问题,库自带的 USART_SendData 函数一次只能发送 1 Byte 字符 如果我们要输出一个带格式、带参数的串口数据就只能通过 sprintf 打印到一个临时数组,然后再使用一个for循环调用USART_SendData一个字符一个字符的输出,过程非常麻烦!
姜斌是一个非常怕麻烦的人所以这种方法无疑让我发疯!后来在原子(OpenEDV)那里购买了开发板拿到了例程。里面重定向了printf函数作为串口输出函数,有了这个函数之后就能够很轻松的参数输出,但问题就在这里我们串口1 串口2 都要带参数输出怎么办?
本次实验:自定义printf函数
实验数据来源:
-
配置usart2的串口配置
-
勾选usb micro lib,跟上面类似
-
添加头文件#include <stdarg.h>,,#include
编写USART2的printf函数:
-
void USART2_printf (char *fmt, ...)
-
{
-
char buffer[CMD_BUFFER_LEN+1]; // CMD_BUFFER_LEN长度自己定义吧
-
u8 i = 0;
-
-
va_list arg_ptr;
-
va_start(arg_ptr, fmt);
-
vsnprintf(buffer, CMD_BUFFER_LEN+1, fmt, arg_ptr);
-
while ((i < CMD_BUFFER_LEN) && buffer[i])
-
{
-
USART_SendData(USART2, (u8) buffer[i++]);
-
while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
-
}
-
va_end(arg_ptr);
-
}
注明:以上代码中的红色字体部分替换为USART1就成了串口1的printf函数,以此类推。
我们使用以上代码后发现可以带参数输出了OK! 就这样结束了!是吗?
姜斌在一次实际的项目中使用到了以上网友提供的函数发现在传输数据的时候经常丢数据导致CRC验证不通过,起初以为是硬件设计问题后来一一排除后发现问题就出在以上这个函数中。
-
while ((i < CMD_BUFFER_LEN) && buffer[i])
这个条件中说明 如果我们传输的数据是以下数据,那么我们0x00就传输不出去,那么网友的代码为什么要加入这个判断呢?其实他是想判断一个字符串的结尾。
u8 Text[8] = {0x05,0x03,0x00,0x04,0x06,0x06,0x06,0x06};
如果这个printf函数用来输出字符串数据那绝对是没问题的!因为
字符串结束符号 '\0' 对应的就是0x00,所以我们需要改进一下这个printf函数使其更加的具有通用性。
代码中的 vsnprintf 函数 用于向字符串中打印数据、数据格式用户自定义 ,其实网友忽略了它有返回值
返回值: 执行成功,返回写入到字符数组str中的字符个数(不包含终止符),最大不超过size;执行失败,返回负值,并置
erron
我们这里只要利用这个返回值就能知道我们需要输出多少个字符,所以改进版本的printf函数如下:
-
void usart1Printf(char *fmt, ...)
-
{
-
char buffer[CMD_BUFFER_LEN - 1];
-
u8 i = 0;
-
u8 len;
-
-
va_list arg_ptr; //Define convert parameters variable
-
va_start(arg_ptr, fmt); //Init variable
-
len = vsnprintf(buffer, CMD_BUFFER_LEN+1, fmt, arg_ptr); //parameters list format to buffer
-
-
while ((i < CMD_BUFFER_LEN) && (i < len) && (len > 0))
-
{
-
USART_SendData(USART1, (u8) buffer[i++]);
-
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
-
}
-
va_end(arg_ptr);
-
}
转载请注明出处:http://blog.chinaunix.net/blog/post/id/4326789.html 否则将承担法律风险
阅读(8084) | 评论(0) | 转发(0) |