【目的】
在单片机的调试中,我们日常的日志输出,通常是通过串口来实现,而通过串口重定向来实现又是常规的操作之一。这次我在前面的基础之上增加了printf的面向对象的增加这项功能。
【实现步骤】
1、在工程中添加printf.c函数,并把他加入到libs的分组之中。
2、在工程的设置中,打开Use MincroLIB库。
3、在printf.c中,添加对输入输出的系统头文件<stdio.h>的引用,当然由于我需要调用驱动库要添加<devices.h>以及<hal_data.h>的引用。
4、重写fputc输出,在此函数中,我先查找Log这个串口的驱动,如果查找到,则使用他的write进行串口输出,代码如下:
int fputc(int ch, FILE *f) { (void)f; struct UartDev *pLogDevice = UartDeviceFind("Log"); pLogDevice->Write(pLogDevice, (unsigned char*)&ch, 1); return ch; }
5、重写scanf函数,在这个函数中,我也一样先查找以"Log"命名的串口,如果查找到,则使用这个驱动的write进行输出。其代码如下:
int fgetc(FILE *f) { uint8_t ch; (void)f; struct UartDev *pLogDevice = UartDeviceFind("Log"); /* 启动接收字符 */ while(pLogDevice->Read(pLogDevice, (unsigned char*)&ch, 1) != 1) {} /* 回显 */ { fputc(ch, &__stdout); /* 回车之后加换行 */ if (ch == '\r') { fputc('\n', &__stdout); } } return (int)ch; }
6、驱动设置好后,就可以在工程中使用printf进行串口输出了。
添加测试代码如下:
void led_blink(void) { uint32_t cnt; UartDevicesRegister(); LedDevice *pLED = LedGetDevice(); if(NULL == pLED) { printf("Error. There is no LED device!\r\n"); return; } pLED->Init(pLED); while(1) { cnt++; pLED->On(1); R_BSP_SoftwareDelay(1,BSP_DELAY_UNITS_SECONDS); pLED->Off(1); R_BSP_SoftwareDelay(1,BSP_DELAY_UNITS_SECONDS); pLED->On(2); R_BSP_SoftwareDelay(1,BSP_DELAY_UNITS_SECONDS); pLED->Off(2); R_BSP_SoftwareDelay(1,BSP_DELAY_UNITS_SECONDS); printf("run cnt %d\r\n",cnt); } }
测试结果如下:
【总结】
使用面向对象之编程,可以实现代码的快递移植,当然重写printf也是非常之简单。