完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
在前面学习了STM32的串口编程,通过USART1向计算机的串口调试助手打印数据,或者接收计算机串口调试助手的数据,接下来我们可以实现STM32工程上的printf()函数了,方便用于程序开发中调试信息的打印。
1. 法1:使用MicroLIB库 1.1 KEIL-MDK中的Use MicroLIB选项 在MDK开发环境中, MicroLib是缺省c库的备选库,它可装入少量内存中,与嵌入式应用程序配合使用,且这些应用程序不在操作系统中运行。 MicroLib进行了高度优化以使代码变得很小,功能比缺省c库少,不具备某些ISO c特性,部分库函数的运行速度也比较慢,如内存拷贝函数memcpy()。 MicroLib与缺省c库之间的主要差异在网上有许多文章都有写到,这里摘抄记录: (1)MicroLib 不符合 ISO C 库标准。 不支持某些 ISO 特性,并且其他特性具有的功能也较少。 (2)MicroLib 不符合 IEEE 754 二进制浮点算法标准。 (3)MicroLib 进行了高度优化以使代码变得很小。 (4)无法对区域设置进行配置。 缺省 C 区域设置是唯一可用的区域设置。 (5)不能将 main() 声明为使用参数,并且不能返回内容。 (6)不支持 stdio,但未缓冲的 stdin、stdout 和 stderr 除外。 (7)MicroLib对 C99 函数提供有限的支持。 (8)MicroLib不支持操作系统函数。 (9)MicroLib不支持与位置无关的代码。 (10)MicroLib不提供互斥锁来防止非线程安全的代码。 (11)MicroLib不支持宽字符或多字节字符串。 (12)与stdlib不同,MicroLib不支持可选择的单或双区内存模型。MicroLib只提供双区内存模型,即单独的堆栈和堆区。 MicroLib提供了一个有限的stdio子系统,它仅支持未缓冲的stdin、stdout和stderr,那么也就是说勾选了Use MicroLib选项后,在代码工程中就可以使用printf()函数咯? 然而事实并非如此,这样直接使用printf()函数,其打印的字符串最终不知道打印到何处。我们要做的是将调试信息打印到USART1中,所以需要对printf()函数所依赖的打印输出函数fputc()重定向(MicroLib中的printf()函数打印操作依赖fputc())。 1.2 重定向fputc函数 在MicroLib的stdio.h中,fputc()函数的原型为: int fputc(int ch, FILE* stream) 此函数原本是将字符ch打印到文件指针stream所指向的文件流去的,现在我们不需要打印到文件流,而是打印到串口1。基于前面的代码: #include int fputc(int ch, FILE* stream) { //USART_SendData(USART1, (unsigned char) ch); //while (!(USART1->SR & USART_FLAG_TXE)); USART_SendChar(USART1, (uint8_t)ch); return ch; } 注意,需要包含头文件stdio.h,否则FILE类型未定义。 勾选了Use MicroLib选项,重定向fputc()函数后,我们就可以在工程代码中使用printf()函数了: int main(void) { USART_Configuration(); //USART_SendString(USART1, "HelloWorldn"); //USART_SendChar(USART1, 'h'); printf("rnstm32f103rct6rn"); printf("rnCortex-M3rn"); while (1); return 0; } printf()函数的使用方法跟之前一样,运行结果: 2. 法2:不使用MicroLIB库 2.1 半主机模式 半主机模式是ARM的一种机制,实现将来ARM应用程序代码的输入/输出请求传送至运行着调试器的主机。例如设置使用半主机模式下的ARM应用程序,可以使用printf()和scanf()来使用主机的显示器和键盘,而不需要在ARM系统上搭配显示器和键盘。 半主机通过一组定义好的软件指令(如SVC)来实现的,这些指令在程序控制下产生异常,ARM应用程序调用半主机对应的异常处理函数,然后调试代理处理该异常。 第二段话感觉理解起来有点模糊,但是第一段还是懂它在讲什么的。一般的ARM应用程序中并不需要半主机操作,在这里为确保ARM应用程序中没有链接MicroLib的半主机相关函数,我们要取消ARM的半主机工作模式。 2.2 实现代码 在工程中加上如下代码: //取消ARM的半主机工作模式 #pragma import(__use_no_semihosting) struct __FILE { int handle; }; FILE __stdout; void _sys_exit(int x) { x = x; } int fputc(int ch, FILE *f){ while((USART1->SR&0X40)==0); USART1->DR = (u8) ch; return ch; } 上面的代码摘自正点原子的范例程序,具体每一行的意义目前也不大清楚。这样操作后,在不使用MicroLib的前提下,仍能使用printf()函数将调试信息打印到USART1上了。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1618 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1545 浏览 1 评论
979 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1597 浏览 2 评论
1865浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
647浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
517浏览 3评论
534浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
506浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-23 05:02 , Processed in 0.825141 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号