如果要在串口上打印字符串和数字的混合信息,使用printf比普通的send函数要方便的多。
STM32的printf设计,可以不调用标准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=0x5566,strlen=5,hexFlag=sTRUE,则发送05566。