笔记:重写printf,方便嵌入式使用。在别人的基础上做了一些自己的修改。
#include <stdarg.h>
char printf_uart(const char* string, ...)
{
va_list p_args; // 创建”指针“
va_start(p_args, string); // 指向定参首地址
// 循环打印所有格式字符串
while (*string != '\0')
{
if (*string != '%') // 普通字符正常打印
{
comSendChar(DEBUG_PORT, *string);
}
else // 格式字符特殊处理
{
switch (*(++string)) // 先++是为了取'%'后面的格式字符
{
case 'D':
case 'd': printDeci(va_arg(p_args, int));
break;
case 'O':
case 'o': printOct(va_arg(p_args, unsigned int));
break;
case 'X':
case 'x': printHex(va_arg(p_args, unsigned int));
break;
case 'C':
case 'c': comSendChar(DEBUG_PORT, va_arg(p_args, int));
break;
case 'P':
case 'p': printAddr(va_arg(p_args, unsigned long));
break;
case 'F':
case 'f': printFloat(va_arg(p_args, double));
break;
case 'S':
case 's': printStr(va_arg(p_args, char *));
break;
default : break;
}
}
string++; // 指向下一个字符
}
va_end(p_args); // 释放指针
}
/**
* @brief 通用数字打印函数可以把整型值打印成10进制数,8进制数,2进制数,16进制数
*
* @param num 需要打印的整数,无符号长整型是为了兼容地址格式打印
* @param base 打印的进制
*/
void printNum(unsigned long num, int base)
{
if (num < base) // 递归结束条件【比0少一层】
{
comSendChar(DEBUG_PORT, "0123456789abcdef"[num]);
return;
}
printNum(num/base, base); // 递归
comSendChar(DEBUG_PORT, "0123456789abcdef"[num%base]); // 逆序打印结果
}
void printDeci(int dec)
{
int num;
// 处理有符号整数为负数时的情况
if (dec < 0)
{
comSendChar(DEBUG_PORT, '-');
dec = (~(dec-1)); // abs()
printNum(dec, 10); // 打印十进制数
}
// 处理整数为时0的情况
else if (dec == 0)
{
comSendChar(DEBUG_PORT, '0');
}
else
{
printNum(dec, 10); // 打印十进制数
}
}
void printOct(int oct)
{
if (oct == 0) // 处理整数为0的情况
{
// 打印前缀
comSendChar(DEBUG_PORT, '0');
comSendChar(DEBUG_PORT, 'o');
comSendChar(DEBUG_PORT, '0');
}
else if (oct < 0)
{
oct = (~(oct-1));
comSendChar(DEBUG_PORT, '-');
// 打印前缀
comSendChar(DEBUG_PORT, '0');
comSendChar(DEBUG_PORT, 'o');
printNum(oct,8); // 打印8进制数
}
else
{
// 打印前缀
comSendChar(DEBUG_PORT, '0');
comSendChar(DEBUG_PORT, 'o');
printNum(oct,8); // 打印8进制数
}
}
void printHex(int hex)
{
if (hex == 0) // 处理整数为0的情况
{
// 打印前缀
comSendChar(DEBUG_PORT, '0');
comSendChar(DEBUG_PORT, 'x');
comSendChar(DEBUG_PORT, '0');
}
else if (hex < 0)
{
hex = (~(hex-1));
comSendChar(DEBUG_PORT, '-');
// 打印前缀
comSendChar(DEBUG_PORT, '0');
comSendChar(DEBUG_PORT, 'x');
printNum(hex,16); // 打印十六进制数
}
else
{
// 打印前缀
comSendChar(DEBUG_PORT, '0');
comSendChar(DEBUG_PORT, 'x');
printNum(hex,16); // 打印十六进制数
}
}
void printAddr(unsigned long addr)
{
// 打印地址:格式和十六进制一样
printHex(addr);
}
void printStr(char *str)
{
int i = 0;
while (str[i] != '\0')
{
comSendChar(DEBUG_PORT, str[i++]);
}
}
void printFloat(float f)
{
int temp;
temp = (int)f;
f -= temp; // 取小数
// 1先打印整数部分
if (temp < 0)
{
temp = (~(temp-1)); // abs()
comSendChar(DEBUG_PORT, '-');
}
printNum(temp,10);
// 2分隔点
comSendChar(DEBUG_PORT, '.');
// 3打印小数部分
if (f == 0)
{
// 浮点型数据至少六位精度
for (temp = 0; temp < 6; temp++)
{
comSendChar(DEBUG_PORT, '0');
}
return;
}
else
{
temp = (int)(f*1000000);
if (temp < 0)
{
temp = (~(temp-1)); // abs()
}
printNum(temp,10);
}
}
参考【如有侵权请联系本人】 https://blog.csdn.net/weixin_37663721/article/details/120343762