如果上面看不懂我再解释一下原理:
核心内容:变参宏 “__VA_ARGS__” 与 “...”
1.首先三个点 "..." 在C语言中代表“参数个数可变的参数”,我们可以看一下printf()函数的原型:
int printf(const char* format,...);//printf()函数声明原型
//使用printf函数的方法
int num1;
printf("num1 = %d \r\n",num1);//一个参数时,参数是整型
float num2;
printf("num2 = %f \r\n",num2);//参数是浮点型
printf("num1 = %d,num2 = %f \r\n",num1,num2);//两个不同类型的参数时
printf("Hello World \r\n");//无参数时
由上述代码可以知道,"fomat"表示只读类型的字符串,而三个点 “...” 表示个数未确定的参数,可以没有参数,也可以有多个。
2.__VA_ARGS__是三个点"..."的宏定义形式。也就是说宏定义中的__VA_ARGS__会被替换成"..."
#define ps(format,...) printf(format,__VA_ARGS__)//第1种方法,有些C标准不支持要加##
#define ps(format,...) printf(format,##__VA_ARGS__)//第2种方法,##可以防止无参数时编译出错
#define ps(...) printf(format,__VA_ARGS__)//第3种方法
#define ps(...) printf(format,##__VA_ARGS__)//第4种方法
#define ps(...) printf(__VA_ARGS__)//第5种方法
#define ps(...) printf(##__VA_ARGS__)//第6种方法
以上六种都可以用 ps() 代替 printf() 函数,功能以及用法一模一样。C标准不一样的时候可能会有差别,总之编译出错时在以上6种之中更换即可。我只用第1、2、5这三种方法。
3.其实在单片机之中如果不重定向 printf() 函数。我们只要使用 sprintf() 函数即可:
int printf(const char* format,...);//printf()函数声明原型
int sprintf(char *buffer,const char* format,...);//sprintf()函数声明原型
sprintf() 只是比 printf() 多一个参数,即第一个字符数组,他们两功能也相似,只是有以下区别:
sprintf()----------》把内容转成字符串,并输出到一个字符数组中,返回字符串的字符个数;
printf()------------》把内容转成字符串,并输出到显示终端,返回字符串的字符个数;
我们可以利用sprintf()的特点把要显示的内容转换成字符串,存到一个预先定义好的字符数组中,然后再用HAL库串口发送函数,把该字符数组内的信息发出去,发送的个数就是sprintf()的返回值:
uint8_t USART_TX_BUF[200]; //发送缓冲数组,最大200字节
#define ps(...) HAL_UART_Transmit(&huart1,USART_TX_BUF,sprintf((char *)USART_TX_BUF,__VA_ARGS__),1000)//可修改到其他串口
|