使用变参函数实现STM32串口的简易printf功能

如果要在串口上打印字符串和数字的混合信息,使用printf比普通的send函数要方便的多。

STM32printf设计,可以不调用标准C库函数,而使用变参函数实现。原理非常简单,只要获取了变参函数的第一个实参地址,变参地址在其基础上增加(参数的大小)即可。

实现如下:

int usart_printf(USART_TypeDef* USARTx, char *fmt, ...)

{

         char *p = (char *)&fmt + sizeof(fmt);

         uint8_t temp = 0, numLen = 0;

         while (1) {

                 temp = *fmt;

                 if (temp == '\0')

                         break;

                 else if (temp == '\\')

                         usart_send_byte(USARTx, *++fmt);

                 else if (temp == '%') {

                         numLen = PRINTF_LEN;

                         temp = *++fmt;

                         if (get_num_from_ASCII(temp, &temp, sFALSE) != sPARAM)

                                 goto dx_FIND;

                         numLen = temp;

                         temp = *++fmt;

                         if (get_num_from_ASCII(temp, &temp, sFALSE) != sPARAM)

                                 goto dx_FIND;

                         numLen = numLen * 10 + temp;

                         temp = *++fmt;

dx_FIND:

                         if (*fmt == 'd' || *fmt == 'D')

                                 usart_send_num(USARTx, *((int *)p), numLen, sFALSE);

                         else if (*fmt == 'x' || *fmt == 'X')

                                 usart_send_num(USARTx, *((int *)p), numLen, sTRUE);

                         p += sizeof(int);

                 } else

                         usart_send_byte(USARTx, temp);

                ++fmt;

         }

        return sFALSE;

}

 

USARTx用来选择串口,fmt是字符串的首地址,“...”是变参。在这个函数中,变参需要是int类型p始终指向当前调用的变参地址

变参也可以设计成其他类型,调用的时候注意存储特性即可。

numLen为打印字符宽度,因为之前设计的usart_send_num这个函数的功能是,以指定的宽度发送十进制或十六进制数的ascii码,所以这里需要将打印宽度传递进去,使用%4d发送123,则打印0123

下面是被调用的三个函数

void usart_send_byte(USART_TypeDef* USARTx, uint8_t byte);

使用串口x发送一个字节。

int get_num_from_ASCII(char ascii, uint8_t *num, int hexFlag);

将一个ASCII码转换成十或十六进制数,存放在*num中,如‘A’或者‘a’,转换成10

int usart_send_num(USART_TypeDef* USARTx, uint32_t num, uint8_t strlen, int hexFlag);

以指定的宽度发送十进制或十六进制数的ascii码,如num=0x5566strlen=5hexFlag=sTRUE,则发送05566

永不止步步 发表于10-12 15:37 浏览65535次
分享到:

已有0条评论

暂时还没有回复哟,快来抢沙发吧

添加一条新评论

只有登录用户才能评论,请先登录注册哦!

话题作者

永不止步步
金币:67410个|学分:307967个
立即注册
畅学电子网,带你进入电子开发学习世界
专业电子工程技术学习交流社区,加入畅学一起充电加油吧!

x

畅学电子网订阅号