历史上的今天
返回首页

历史上的今天

今天是:2024年10月30日(星期三)

正在发生

2020年10月30日 | STM32(MDK)中不能使用printf()函数的问题

2020-10-30 来源:eefocus

简单地说:想在mdk 中用printf,需要同时重定义fputc函数和避免使用semihosting(半主机模式),

标准库函数的默认输出设备是显示器,要实现在串口或LCD输出,必须重定义标准库函数里调用的与输出设备相关的函数.


例如:printf输出到串口,需要将fputc里面的输出指向串口(重定向),方法如下:

#ifdef __GNUC__

/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar()*/

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)

#else

#define 

PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

#endif /* __GNUC__ 

*/

PUTCHAR_PROTOTYPE

{

/* Place your implementation of fputc here */

/* e.g. write a character to the USART */

USART_SendData(USART1, (uint8_t) ch);

/* Loop until the end of transmission */

return ch;

}


因printf()之类的函数,使用了半主机模式。使用标准库会导致程序无法运行,以下是解决方法:

方法1.使用微库,因为使用微库的话,不会使用半主机模式.


方法2.仍然使用标准库,在主程序添加下面代码:

#pragma import(__use_no_semihosting) 

_sys_exit(int x) 

x = x; 

struct __FILE 

int handle; 

/* Whatever you require here. If the only file you are using is */ 

/* standard output using printf() for debugging, no file handling */ 

/* is required. */ 

}; 

/* FILE is typedef’ d in stdio.h. */ 

FILE __stdout;


如果使用的是MDK,请在工程属性的“Target“-》”Co de Generation“中勾选”Use MicroLIB;今天参考了一下论坛,使用微库可以很好的解决这个问题。


2.另一种方法:(其实大同小异)  

需要添加以下代码 

(论坛里应该有完整介绍这个的帖子,但是我没搜到,也许是沉了。)

#pragma 

import(__use_no_semihosting)  

/******************************************************************************  

*标准库需要的支持函数  

******************************************************************************/  

struct __FILE  

{  

int handle;  

/* Whatever you require here. If the only file you are using is */  

/* standard output using printf() for debugging, no file handling */  

/* is required. */  

};  

/* FILE is typedef’ d in stdio.h. */  

FILE __stdout;  


///

  

/// 

定义_sys_exit()以避免使用半主机模式  

///

  

/// name="x">  

/// 

  

_sys_exit(int x)  

{  

x = x;  

}  



int fputc(int ch, FILE *f) 

{   

//USART_SendData(USART1, (u8) ch); 

    USART1->DR = (u8) ch; 

  

   

    /* Loop until the end of transmission */ 

    

while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)

    {  

    return ch; 




semihosting的作用,介绍如下 

Semihosting is a mechanism for ARM targets to communicate input/output requests 

from application co de to a host computer running a debugger. This mechanism could be 

used, for example, to allow functions in the C library, such as printf() and scanf(), to use the screen and keyboard of the host rather than having a screen and keyboard on the target system. 

This is useful because development hardware often does not have all the input and 

output facilities of the final system. Semihosting allows the host computer to provide these facilities. 

Semihosting is implemented by a set of defined software interrupt (SWI) operations. 

The application invokes the appropriate SWI and the debug agent then handles the SWI 

exception. The debug agent provides the required communication with the host. 

In many cases, the semihosting SWI will be invoked by co de within library functions. The application can also invoke the semihosting SWI directly. Refer to the C library descriptions in the ADS Compilers and Libraries Guide for more information on support for semihosting in the ARM C library. 


按我的理解,这个模式是用来调试的,通过仿真器,使用主机的输入输出代替单片机自己的,也就是说即便单片机没有输出口也能printf到电脑上。反过来,由于这个模式更改了printf()等的实现方式,输入输出就不走单片机的外设了,所以只重定义fputc不起作用。 


用代码关闭此模式后,需要同时更新一下__stdout 和__stdin 的定义,所以有后面的语句。 

以上仅为个人理解,如有错误请指正。 


另外,勾选microlib之后,也许编译的时候就不把开启semihosting的文件包进去了,所以没事。


C库函数重定向:

用户能定义自己的C语言库函数,连接器在连接时自动使用这些新的功能函数。这个过程叫做重定向C语言库函数,如下图所示。


举例来说,用户有一个I/O设备(如UART)。本来库函数fputc()是把字符输出到调试器控制窗口中去的,但用户把输出设备改成了UART端口,这样一来,所有基于fputc()函数的printf()系列函数输出都被重定向到UART端口上去了。


下面是实现fputc()重定向的一个例子:

externvoidsendchar(char*ch);

intfputc(intch,FILE*f)

{/*e.g.writeacharactertoanUART*/

    chartempch=ch;

    sendchar(&tempch);

    return ch;


这个例子简单地将输入字符重新定向到另一个函数sendchar(),sendchar()假定是个另外定义的串口输出函数。在这里,fputc()就似乎目标硬件和标准C库函数之间的一个抽象层。


推荐阅读

史海拾趣

Advanced Thermal Products Inc公司的发展小趣事

Advanced Thermal Products Inc公司成立于XXXX年,由一群热衷于热管理技术的工程师创立。在初创期,ATP公司便以独特的技术视角,专注于研发高效、创新的热管理产品。他们针对当时电子设备散热效果不佳的痛点,成功开发出了一款新型的热管理解决方案,为公司在行业内树立了良好的口碑。

Ampire Co Ltd公司的发展小趣事

随着技术的不断积累,ATP公司开始加大产品创新的力度。他们推出了一系列具有竞争力的热管理产品,不仅满足了市场对于高效散热的需求,还凭借其优异的性能赢得了客户的青睐。同时,公司积极拓展市场,与多家电子设备制造商建立了长期合作关系,产品广泛应用于手机、电脑、服务器等领域。

Hei Inc Optoelectronic Division公司的发展小趣事
无触点操作减少了机械动作产生的噪音,并降低了电磁干扰,对工作环境和周边设备更为友好。
Bomar公司的发展小趣事

Bomar公司成立于1963年,最初是一家专注于石英晶体制造的公司。在当时的电子行业,石英晶体作为频率控制元件,对于无线通信和电子设备的稳定运行至关重要。Bomar公司通过不断的研发和技术创新,成功突破了石英晶振在宽频率范围内的高稳定性问题,满足了严格的FCC规范。这一技术突破使得Bomar公司的石英晶振在市场上获得了广泛的认可,并为公司的发展奠定了坚实的基础。

Electrolube公司的发展小趣事

在电子行业中,电池管理系统(BMS)的可靠性和耐用性一直是制造商关注的焦点。Electrolube公司凭借其在材料科学领域的深厚积累,成功推出了一款名为UVCL的新型UV固化涂层。这款涂层以其独特的特性迅速在市场中脱颖而出。

UVCL涂层采用先进的UV固化技术,能够在几秒钟内完成固化过程,大大提高了生产效率。同时,它还具有高效的湿气引发的二次固化机制,确保即使在阴影区域也能实现完全固化。这一特性对于BMS等复杂电子电路的保护至关重要。

为了将UVCL涂层推向市场,Electrolube公司的研发团队与客户紧密合作,克服了客户内部没有UV固化设施的难题。他们与信誉良好的供应商合作,提供了完整的解决方案,并成功为客户提供了原型样品单元进行现场测试。测试结果显示,UVCL涂层能够为电子电路提供最高水平的保护,且操作过程简单、应用速度快。

UVCL涂层的成功推出不仅提升了Electrolube公司在电子材料领域的地位,也为公司赢得了众多客户的信赖和好评。

ETL [E-Tech Electronics LTD]公司的发展小趣事

在国内市场取得一定成功后,ETL开始积极拓展国际市场。公司参加了多个国际电子展会,与全球各地的客户和合作伙伴建立了广泛的联系。同时,ETL还通过与国际知名企业的合作,不断提升自身的技术水平和产品质量。这些努力使得ETL的产品逐渐走向国际市场,为公司的发展注入了新的动力。

问答坊 | AI 解惑

语音单片机WT588D

Ü 外挂2M~32M的Flash,时间从32—1054秒。掩膜为内置ROM,最长支持400秒(@6K采样)。采样率支持6K~22K Ü DAC输出:13Bit,PWM输出:12Bit Ü 内置0.5W功放,可直接推动0.5W/8Ω扬声器 Ü 支持加载MP3/WAV/WMA三种音频 ...…

查看全部问答>

刚从京东订的主机就出问题了~

每次重启电源后开机,cpu、显卡风扇转一下就停了,主板无法上电,主板上的LED灯不亮,再按开机键就没有任何反应了,只能再次重启电源才能复现上述情况。 请问这是怎么回事啊?电源供电不足?还是主板烧了(为什么每次重启电源后风扇都能转一下呢) ...…

查看全部问答>

要做电源管理,有什么好的建议没?

功能一、    检测充电器的插拔         【我的想法:】可以用中断来做,这个好做 功能二、检测电池的电量:         只能用AD,将电压转成数字信号了, 就不知道怎么实 ...…

查看全部问答>

求教高手解决vxworks 启动盘制作问题

我在制作启动盘时如果选择bootrom_uncmp image则使用mkboot a: bootrom_uncmp指令时,弹出如下的对话框 D:\\Tornado2.2\\target\\config\\PCPENT~4>mkboot a: bootrom_uncmp VxSys 1.6 (c) Wind River 1993-2002 Boot sector installed OK. obj ...…

查看全部问答>

怎样用residentFlash保存用户数据

我用的是2410+wince4.2,flash用的是K9F1208UOM.在wince系统运行时,我能够看到ResidentFlash文件夹,而且好像用属性查看剩于空间也就是出去os镜像的大小.但是好像因为没有指定flash剩于空间的起始位置的原因吧,只要拷东西进这个文件夹,下次wince就别 ...…

查看全部问答>

早晨浏览见到个地铁应急灯大家看下,我看老好了

  这款地铁应急灯是为应付地铁突发状况准备的。当地铁突然停运,电源切断的时候,乘客们可以将把手取下,充当应急电筒使用。通过挤按把手上的按钮,就能够轻松将把手与带子分离。当然,只有在地铁熄灯之后才能启动这一按钮。   &n ...…

查看全部问答>

VHDL类属参数在verilog中怎么对应?

在VHDL中,类属参数可以在不同层次的模块间传递。可以在顶层修改这些参数,下面各层随之改变。 verilog中怎么实现这一功能? 谢谢!…

查看全部问答>

信号链基础知识合集2

  自《电源开关设计秘笈30例》推出以来,得到广大工程师的热烈反响, 已推出的由德仪资深工程师William P. (Bill) Klein 主笔的《信号链基础知识合辑》反响也非常好,   应大家的强烈要求,现隆重推出《信号链基础知识合辑2》   ...…

查看全部问答>