完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
在使用MDK进行嵌入式开发,特别是调试串口的时候经常要用到C语言的标准输入输出库函数,如printf();。这样写出来的程序,通常编译和链接过程都不会报错,但是程序却无法正常运行.
原因分析如下: 标准库函数的默认输出设备是显示器,要实现在串口或LCD输出,必须重定义标准库函数里调用的与输出设备相关的函数. 例如:printf输出到串口,需要将fputc里面的输出指向串口(重定向),方法如下: 只要自己添加一个int fputc(int ch, FILE *f)函数,能够输出字符就可以了 int fputc(int ch, FILE *f) { UART0_D = ch; while(!((UART0_S1)& 0x40)); return ch; } 因为printf()之类的函数,使用了半主机模式。使用标准库会导致程序无法运行,以下是解决方法: 方法1.使用微库,因为使用微库的话,不会使用半主机模式。 如果使用的是MDK,请在工程属性的“Target“-》”Code Generation“中勾选”Use MicroLIB“这样以后就可以使用printf,sprintf函数了 方法2.仍然使用标准库,但在主程序中需要添加以下代码: /*因为不使用半主机模式,所以标准C库stdio.h中有些使用半主机的函数需要重新写*/ #pragma import(__use_no_semihosting) //确保没有从 C 库链接使用半主机的函数 _sys_exit(int x) //定义_sys_exit()以避免使用半主机模式 { x = x; } struct __FILE //标准库需要的支持函数 { int handle; }; /* FILE is typedef’ d in stdio.h. */ FILE __stdout; int fputc(int ch, FILE *f) { UART0_D = ch; //发送数据缓存区 while(!((UART0_S1)& 0x40)); //串口发送中断标志位,等待发送完成 //如果中断标志位 = 0,则等待;while(!中断标志位) return ch; } 在独立应用程序中,不太可能支持半主机操作。 因此,必须确保您的应用程序中没有链接 C 库半主机函数。 为确保没有从 C 库链接使用半主机的函数,必须导入符号 __use_no_semihosting。可在工程的任何 C 或汇编语言源文件中执行此操作,如下所示: 在 C 模块中,使用 #pragma 指令: #pragma import(__use_no_semihosting) 在汇编语言模块中,使用 IMPORT 指令: IMPORT __use_no_semihosting 如果仍然链接了使用半主机的函数,则链接器就会报告错误 下面是网上关于半主机模式的解释: 【半主机是用于 ARM 目标的一种机制,可将来自应用程序代码的输入/输出请求传送至运行调试器的主机。 例如,使用此机制可以启用 C 库中的函数,如 printf() 和 scanf(),来使用主机的屏幕和键盘,而不是在目标系统上配备屏幕和键盘。 这种机制很有用,因为开发时使用的硬件通常没有最终系统的所有输入和输出设备。 半主机可让主机来提供这些设备。 半主机是通过一组定义好的软件指令(如 SVC)来实现的,这些指令通过程序控制生成异常。 应用程序调用相应的半主机调用,然后调试代理处理该异常。 调试代理提供与主机之间的必需通信。 半主机接口对 ARM 公司提供的所有调试代理都是通用的。 在无需移植的情况下使用 RealView ARMulator ISS、指令集系统模型 (ISSM)、实时系统模型 (RTSM)、RealView ICE 或 RealMonitor 时,会执行半主机操作,请参阅Figure 8.1。 在很多情况下,半主机由库函数内的代码调用。 应用程序还可以直接调用半主机操作。 有关 ARM C 库中的半主机支持的详细信息,请参阅《库和浮点支持指南》中的第 2 章 C 和 C++ 库。】 下面是51单片机通过printf()与串口结合发送数据到串口调试工具的代码如下: #include #include #define uchar unsigned char #define uint unsigned int void uart_init(); uint i = 0; //UART发送串口数据 void UART_SendData(char dat) { ES=0; //关串口中断 SBUF=dat; while(TI!=1); //等待发送成功 TI=0; //清除发送中断标志 ES=1; //开串口中断 } //UART 发送字符串 void UART_SendString(char *s) { while(*s)//检测字符串结束符 { UART_SendData(*s++);//发送当前字符 } } //重写putchar函数 char putchar(char c) { UART_SendData(c); return c; } void main() { uart_init(); while(1) { UART_SendString("qqqqqqqqqqqqqqqqqqqqqqrn"); printf("i = %drn",i++); } } void uart_init() { TMOD=0x20; //定时器的工作方式2; TH1=0xfd; //波特率9600 TL1=0xfd; TR1=1; //启动定时器1; SM0=0; // 方式一:10位(8位数据位,1,一个起始位,1个停止位) SM1=1; REN=1; //先允许串口接收 EA=1; //全中断(总中断) ES=1; // 串口中断 } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1658 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1571 浏览 1 评论
998 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
695 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1617 浏览 2 评论
1877浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
663浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
529浏览 3评论
547浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
517浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-29 10:24 , Processed in 0.788995 second(s), Total 47, Slave 40 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号