电子说
C语言中有个很好用的函数:printf()。printf()是格式化输出函数,可以按照规定格式输出消息。相信每个工程师开始学习的C语言第一课都会遇到printf(“Hello World! n”);这条语句。
在嵌入式开发中,我们调试时时常需要输出一些调试信息,那这时候printf语句就非常有用了。但是遗憾的是,C标准库函数中默认的输出设备是显示器,所以当我们进行嵌入式开发的时候,是不能够直接使用printf的。如果我们想要方便的在嵌入式开发中进行printf操作,那么就必须重定向printf语句。
我们可以查一下C标准库函数,printf语句其实是使用了一个函数int fputc(int ch, FILE *f); 此函数原本是将字符ch打印到文件指针所指向的文件流中去的,现在我们不需要打印到文件流,而是打印到串口1。我们只需要重新编写这个函数。当系统检测到用户编写的fputc函数时,就会调用用户所编写的函数,而不是使用原本的fputc了。
函数如下:
注意这里需要使用到头文件stdio.h,否则FILE类型未定义。以上是基于MDK环境下,使用MicroLib的情况下重定向printf。还有一种方法是使用半主机模式。半主机模式是ARM的一种机制,不使用microLib库,实现ARM应用程序代码的输入/输出请求传至运行着调试器的主机,这样就可以使用主机的显示器和键盘,而不需要再ARM系统上搭配显示器和键盘。当然,这种做法并不常见,有兴趣的同学可以自己研究一下。
如果这篇文章到这里就结束了,那么就太常规了。下面我还要讲一个非常规的操作以实现串口输出字符串。
Printf重定向的方法是非常常规的,但是我就是不想用,而且我还想调用一个函数就能输出一串任意的字符串,怎么办?我就想出了另一种写法,先贴代码:
乍一看,这段代码非常简单啊,就是使用了一个指针,然后串口输出的时候指针指向的地址不停+1啊!但是我们再看一下调用:
我们这里直接将一个字符串作为参数进行了传递,编译器报了一个警告:warning: ‘char[25]’ to parameter of type ‘uint8_t *’ (aka ‘unsigned char *’) converts between pointers to integer types with different sign。
很明显,数据类型冲突了。但是在程序中我们将两种方式都进行了输出,最后发现调试结果是正确的。如下图所示。
这是为什么呢?其实也很简单,我们这里进行了一个非法操作。当我们调用该函数时,将字符串数组作为实参,在函数定义中强制转换成了一个指针。而这个指针,指向的是字符串数组的第一个地址,所以该函数运行时就能够正确输出我们所编写的字符串了。
全部0条评论
快来发表一下你的评论吧 !