【经验分享】单片机中如何实现printf输出log?

【经验分享】c51单片机中如何实现printf输出log?
你在真实的项目工程开发中,有考虑过在类似c51单片机中实现printf输出log吗?本文给出一种参考实现。
1 需求说明2 源码实现2.1 函数申明2.2 功能实现3 源码测试4 小小总结5 更多分享
1 需求说明这个需求比较简单,就是要在c51单片机中实现printf函数,并使用它来打印输出常用的几种类型的数据,比如整型数据,字符串数据等等。
2 源码实现2.1 函数申明通过查看man帮助,我们可以知道printf函数的功能及其简要申明。
​2.2 功能实现以下是我的一个简单实现源码,仅供参考:
​ #include #include log.h #include stdarg.h #include types.h ​ static xdata char simple_prn_buf[6]; uchar align_bit = 0; ​ void dark_fill_string(void) { unsigned char i, j; ​ j = 4; for(i=0;i<5;i++) { if (simple_prn_buf[i] != '0') { j = i; break; } } ​ if (j != 0) { for (i=j;ij) { for (i=0;i (3-i)*4)) & 0x000f; ​ if (simple_prn_buf[i] > 9) simple_prn_buf[i] += (x - 10); else simple_prn_buf[i] += '0'; } ​ simple_prn_buf[4] = ''; dark_fill_string(); } ​ int xprintf(char *fmt, ...) { char *str; int int_data; uchar fill_flag = 0; ​ va_list ap; va_start(ap, fmt); ​ while(*fmt) { if ((*fmt != '%') && (fill_flag == 0)) { push_to_tx_buffer(*fmt++); continue; } ​ if (*fmt == '%') { fmt++; align_bit = 0; fill_flag = 1; } switch(*fmt) { case 's': str = va_arg(ap, char *); for (; *str; str++) push_to_tx_buffer(*str); fill_flag = 0; align_bit = 0; break; ​ case 'd': int_data = va_arg(ap, int); inttostr(int_data); for (str=simple_prn_buf; *str; str++) { push_to_tx_buffer(*str); } fill_flag = 0; align_bit = 0; break; ​ case 'x': int_data = va_arg(ap, int); hextostr(int_data, 0); //小写 for (str=simple_prn_buf; *str; str++) { push_to_tx_buffer(*str); } fill_flag = 0; align_bit = 0; break; ​ case 'x': int_data = va_arg(ap, int); hextostr(int_data, 1); //大写 for (str=simple_prn_buf; *str; str++) { push_to_tx_buffer(*str); } fill_flag = 0; align_bit = 0; break; ​ default: //push_to_tx_buffer(*fmt); align_bit = *fmt - '0'; if (align_bit > 9) align_bit = 9; break; } fmt++; } va_end(ap); ​ return 0; } ​3 源码测试简单的测试代码如下:
#include #include #include ​ extern int xprintf(const char* format, ...); ​ #define log(fmt, arg...)xprintf(fmt, ##arg) ​ int main(int argc, const char *argv[]) { //uart_init(); #if 1 puts(hello world);/* unsigned int size1 = sizeof(char *); unsigned int size2 = sizeof(int *); unsigned int size3 = sizeof(int); unsigned int size4 = sizeof(short int); size = sizeof(int); printf(sizeof int = %d, size); size = sizeof(short int); printf(sizeof short int = %d, size);*/ uart2_send_string(hello world); uart1_send_string(); uart1_send_string(); log(1test log); log(2test log %c, '='); log(3test log %s %s, 123, 098); log(4--test log %d, -456); log(4test log %d, 456); log(5test log %u, 789); log(6test log %x, 0x12); log(6test log %x, 0x1a); log(6test log %x, 0x1a); log(6test log %x, 0x1b); log(6test log %x, 0xab); log(6test log %x, 0xab); log(6test log %x, 0x01); log(6test log %2x, 0x01); log(6test log %x, 0x00); log(6test log %2x, 0x00); #endif ​ return 0; }感兴趣的朋友可以把这段测试代码,在c51平台上编译运行下,相信它会给你惊喜的!
4 小小总结printf函数看似很常用,但是真正到了要自己去实现它的时候,你又会发现其实还是蛮多东西需要考虑的。
同时,即便是本文中的实现,还是有些类型的数据是不支持输出的,比如 long int 类型这种,就比较难输出;还有 float类型这种数据,也是没法输出的。
看到这里,你是否还有更好的实现方案呢?
5 更多分享[架构师李肯]
架构师李肯 ( 全网同名 ),一个专注于嵌入式iot领域的架构师。有着近10年的嵌入式一线开发经验,深耕iot领域多年,熟知iot领域的业务发展,深度掌握iot领域的相关技术栈,包括但不限于主流rtos内核的实现及其移植、硬件驱动移植开发、网络通讯协议开发、编译构建原理及其实现、底层汇编及编译原理、编译优化及代码重构、主流iot云平台的对接、嵌入式iot系统的架构设计等等。拥有多项iot领域的发明专利,热衷于技术分享,有多年撰写技术博客的经验积累,连续多月获得rt-thread官方技术社区原创技术博文优秀奖,荣获[csdn博客专家]、[csdn物联网领域优质创作者]、[2021年度csdn&rt-thread技术社区之星]、[2022年rt-thread全球技术大会讲师]、[rt-thread官方嵌入式开源社区认证专家]、[rt-thread 2021年度论坛之星top4]、[华为云云享专家(嵌入式物联网架构设计师)]等荣誉。坚信【知识改变命运,技术改变世界】!


声音渲染对创建可信VR体验而言十分关键
5G时代的到来,将会给汽车带来什么样的变化呢?
小型自动气象站的应用以及产品特点的介绍
如履薄冰 浅谈景驰的无人驾驶之路
优机库与紫光国微共建超级SIM卡生态,携手开拓智慧应用新格局
【经验分享】单片机中如何实现printf输出log?
Matlab常用操作指令详解
单片锂离子电池恒流/恒压线性电源管理芯片XT4054简介
【新闻中心】创新﹒融合﹒高质量发展-第二十五届中国高速公路信息化大会
高通宣布收购小型基地台数据机制造商DesignArt Networks
窄带物联网,开启万物互联新篇章
郭明錤再曝光iPhone8:电池容量双版本一致
蓝牙音箱FCC认证
TBS1102B数字存储示波器的主要性能指标
扎根底层技术,推动机器人换代式升级
吉时利KEITHLEY2612A 数字源表
思谋科技宣布已完成2亿美元B轮融资
直流开关电源保护电路
microBUCK系列集成同步降压稳压器SiC414(Vis
C语言的面向接口编程