如何用单片机写出类似printf的函数

实现功能:stm32用类似printf的函数,通过串口发送数据。
首先,让我们在qt中用C语言模拟串口输出(用printf("%c",ch)代替void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)实现单个字符传输)。
先看代码:

#include 
#include 
#include 

void my_printf(const char *string_in,...)
{
    char string_out[10];
    const char *i=string_out;
    va_list ap;
    va_start(ap,string_in);
    vsnprintf(string_out,9,string_in,ap);
    va_end(ap);
    while(*i)
        printf("%c",*i++);

}

int main()
{
    my_printf("output%d%c",4,'a');
    return 0;
}

输出结果:
如何用单片机写出类似printf的函数_第1张图片
我们可以从代码可以看出,我们主要使用stdarg.h中的vsnprintf函数实现,函数功能的是将可变参数格式化输出到一个字符数组,具体参见:https://baike.baidu.com/item/_vsnprintf/5395011?fr=aladdin
我也是初学值,具体是现实原理我不是没清楚,我就说说使用流程:
1.定义va_list变量,VA_LIST 是在C语言中解决变参问题的一组宏(https://baike.baidu.com/item/va_list/8573665?fr=aladdin)。
2.调用函数va_start(v,l),得到第一个可变参数地址(https://baike.baidu.com/item/va_start),v是定义的va_list变量,l第一个可变参数的前一个参数,也就是…前的第一个参数(string_in)。
3.直接调用vsnprintf函数(https://baike.baidu.com/item/vsprintf/6390873?fr=aladdin),将string_in处理完成后,给string_out数组,中间的9是限定最大的字符数,这个自己定义,可以直接设一个宏去限定,如果在单片机上的话尽量小一点,毕竟资源少。
4.调用va_end函数将指针置为无效,释放指针。(好像不用也不会错,但为了避免出现莫名妙的BUG还是释放为好)
5.最后就是一个将赋值好的string_out字符串一个一个字符输出(string_out的个数最好也定了,不然字符多的时候可能会占到其它已有数据的内存空间,出现乱码等情况,我之前就遇到过)。
好了,值就是模拟的过程,好像说了和没说一样(笑哭)。
那让我们来看看用STM32怎么实现吧。
代码:

//串口发送字符串
//usartx:具体串口号
void uasrt_send_data(USART_TypeDef *usartx,const char *string_in,...)
{
    char string_out[max_size];
	  const char *i=string_out;
    va_list ap;
	
    va_start(ap, string_in);
    vsnprintf(string_out,max_size,string_in,ap);
    va_end(ap);
	
    while(*i)
    {
        USART_SendData(usartx,*i++);
    }
}
//调用形式:uasrt_send_data(USART1,"中文%d\r\n",666);uasrt_send_data(USART1,"English%d\r\n",0);

现象:
如何用单片机写出类似printf的函数_第2张图片这个看上去的话和上面qt的差不了多少,所以我就不多说了。
总结一下,这个实际上就是通过vsnprintf函数将占位符嵌入字符串中,后面我们就可以将它当成一个普通的字符串处理,要注意的是,用在其它地方时,它只能识别%的占位符,其它还是8位的字符,比如:/n,/r之类的就只是对应的ASCII码值,需要额外处理。
最后来一段总结代码:

void placeholder_deal(char *stringout, const char *string_in, ...)
{
    va_list ap;
    va_start(ap, string_in);
    vsnprintf(stringout,max_size,string_in,ap);
    va_end(ap);
}
//我们直接处理stringout字符串就行

(有错误或不懂得话可以评论出来,一起学习呀)

你可能感兴趣的:(单片机,嵌入式硬件)