串口怎么用printf函数发送数据?
串口和串口之间的通信是串口通信(Serial Communication), 它是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式。在51程序中我们常常使用printf函数对串口进行数据输出,很是方便。如此方便的函数,STM32(ARM处理器)在MDK中却是不能直接使用,它却需要我们进行一些修改和添加一些程序定义才可以像51使用。
MDK的编译环境:
- 01
Keil C 的标准库stdio.h: stdio.h:标准输入输出头文件 (C语言标准库),其默认输出设备是显示器,要实现在串口或LCD输出,必须重定义标准库函数里调用的与输出设备相关的函数.
- 02
库变量: FILE 这是一个对象的类型,适合用于存储信息的一个文件流。 库宏: stderr, stdin, and stdout 这些宏的文件类型对应的标准误差,标准输入,标准输出流的指针。
- 03
printf函数在keil的底层: 在keil中的标准C库中,printf、scanf等输入输出数据流函数是通过fputc、fgetc来实现最底层操作的,所以我们只需要在我们的工程中重定义这两个函数的功能就可以实现printf、scanf等数据流函数的重映射。
相关概念:
- 01
半主机模式: 半主机是用于 ARM 目标的一种机制,可将来自应用程序代码的输入/输出请求传送至运行调试器的主机。 例如,使用此机制可以启用 C 库中的函数,如 printf() 和 scanf(),来使用主机的屏幕和键盘,而不是在目标系统上配备屏幕和键盘。
- 02
重定义: 就是重新再一次的定义函数,使其拥有新的定义,然后完成新的功能的过程。 重定向: MDK原本目标是PC机的显示器,然后由于重定向,修改了printf的底层函数(重定义),使printf打印到单片机的外设中。
问题的分析与解决:
- 01
问题原 因: 因printf()之类的函数,使用了半主机模式。使用标准库会导致程序无法运行。所以要不使用半主机模式。
- 02
解决办法1: 使用微库【MicroLib】,虽然避免了半主机模式,但是开发板没有直接对目标(电脑的)显示器的使用权限,它必须使用外设(串口)发送数据到电脑的串口助手上面才能显示。并且需要重新定向到外设中,重定义printf底层的发送程序。程序如下: //重定义fputc函数 int fputc(int ch, FILE *f) { while((USART1->SR&0X40)==0); //循环发送,直到发送完毕 USART1->DR = (u8) ch; return ch; }
- 03
解决办法2: 1)确保程序中没有链接 C 库半主机函数#pragma import(__use_no_semihosting) 2)需要支持的标准库文件来消除被提及函数的问题 //支持使用半主机函数的标准库文件 struct __FILE { int handle; }; FILE __stdout; 3)因为使用了半主机函数,而被要求的函数 //重新定义_sys_exit(),消除编译出错的问题 _sys_exit(int x) { x = x; } 4)重定向,让printf输出到串口 int fputc(int ch, FILE *f) { USART_SendData(USART1,ch); while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); return ch; }