STM32——关于printf重定向到串口的问题

发布者:Aq123456258最新更新时间:2018-10-21 来源: eefocus关键字:STM32  printf重定向  串口 手机看文章 扫描二维码
随时随地手机看文章

简单地说:想在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 */ 

 while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); 

 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“-》”Code 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()以避免使用半主机模式   

///

  

///   

///   

_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 code 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 code 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); 

returnch; 

} 

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

 

第二个问题,路径:D:\Keil3.80\ARM\Examples\ST\STM32F10xFWLib\Example

关键字:STM32  printf重定向  串口 引用地址:STM32——关于printf重定向到串口的问题

上一篇:ARM裸机程序之LED灯
下一篇:STM32的RTC晶振不起振的原因及解决方法

推荐阅读最新更新时间:2024-03-16 16:17

STM32驱动W5100实现udp通信
环境: 主机:WIN7 开发环境:MDK4.72 MCU:STM32F103ZE 源代码: 驱动层代码: drv_w5100.h /********************************************************************* * w5100驱动层头文件 * (c)copyright 2013,jdh * All Right Reserved *文件名:drv_w5100.h *程序员:jdh *修改日期:2013/10/22 * 2013/10/23 * 2013/10/24 ************************
[单片机]
通过STM32 UART及DMA修改TIMER占空比示例
现在有人谈到这样一个需求,他使用STM32F429芯片做开发,其中用到TIM2做3路PWM输出。另外有个上位机跟STM32的UART接口相连,上位机可能不定期地需要通过UART接口给STM32发送新的占空比参数,而且每次都发送3个输出通道的比较参数。如何快捷地实现这个功能呢?要求收到数据后尽快修改3个比较通道的参数。 STM32F429的TIM2是32位定时器,3个通道的CCR寄存器也是32位的。那么上位机每次发3个通道的参数对应12字节的数据。 显然,整体上功能不算复杂。我们可以先通过UART收到12字节数据,稍加整理后手动将数据逐字写到3个CCR寄存器来改变PWM输出。说实在的,这个方案的实现过程还是很清晰的,相信也是
[单片机]
通过<font color='red'>STM32</font> UART及DMA修改TIMER占空比示例
stm32使用中出现的警告
使用keill编写了一个程序 如下: uint8_t Count_Init(uint16_t sing) { if(sing mode72) { return 72; }else if(sing mode60) { return 60; }else if(sing mode48) { return 48; } } 这样在编译的时候会出现这样的警告 :count.c(51): warning: #940-D: missing return statement at end of non-void funcTIon Count_Init 这个警
[单片机]
STM32中对SysTick_Init()函数和Delay_us()的理解
STM32中对SysTick_Init()函数(sysTick_Config()、TimingDelay_Decrement()自定义)和Delay_us()的理解: 实验:3个LED灯以500ms的频率闪烁。
[单片机]
一个简单逆向stm32固件程序的实例分享
本文主要跟大家分享一个简单逆向stm32固件程序的实例,为了让大家在一款成熟的产品中去考虑加密这一块的技术,不然分分钟被别人copy! 1、情景再现 咬金,你们公司固件程序有加密处理吗 ? 额~,算了吧,我们公司的单片机程序炒鸡简单的,还加啥子密。 你这想法不对,假如产品卖得很好,如果没有任何加密措施,那岂不人家随便复制售卖。 没关系吧,反正他们没源码,应该也没那么容易复制吧 一点加密都没有,盗取还是比较简单的。 我才不信~~ 那行,把你的板子给我,不用你的源码,跟你把波特率改了! 直接读取固件 这里以stm32单片机进行演示,如果MCU没有做flash读取或者熔断保护,则可以通过jlink等烧写工具直接读取其Flash上的固
[单片机]
一个简单逆向<font color='red'>stm32</font>固件程序的实例分享
STM32库函数void USART_SendData的缺陷和解决方法
问题及现象( STM32F103系列 : http://www.y-ec.com/cpcp/class/?32.html ) 使用USART_SendData()函数非连续发送单个字符是没有问题的;当连续发送字符时(两个字符间没有延时),就会发现发送缓冲区有溢出现象。若发送的数据量很小时,此时串口发送的只是最后一个字符,当发送数据量大时,就会导致发送的数据莫名其妙的丢失。 如: for(TxCounter = 0;TxCounter RxCounter; TxCounter++) USART_SendData(USART1, RxBuffer ); 原因 此API函数不完善,函数体内部没有一个判断一个字符是否发送完毕
[单片机]
STM32 DMA学习
一个简单的例子 transfer a word data buffer from FLASH memory to embedded SRAM memory. 在V3.1.2库的位置 STM32F10x_StdPeriph_Lib_V3.1.2\Project\STM32F10x_StdPeriph_Examples\DMA\FLASH_RAM /* DMA1 channel6 configuration */ DMA_DeInit(DMA1_Channel6); //peripheral base address DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SRC_
[单片机]
<font color='red'>STM32</font> DMA学习
基于STM32的平衡小车设计过程分享(3)
一、简介 续上文,电机驱动、MPU6050驱动均已完成,接下来我们给他加上PID让它站起来 二、PID控制 我们将小车PID控制函数放到MPU6050中断函数中,每当MPU6050有数据输出时,引脚INT有相应的电平输出。依次来触发外部中断作为控制周期。保持MPU6050数据的实时性。 2.1直立环控制 通过传入的KP、KD参数,让平衡车的pitch轴保持在水平位置。 直立环是用于控制机械系统中垂直方向运动的一种控制器。在这些应用中,垂直方向的运动通常是非常稳定的,因此I控制器的积分作用并不是必需的。而PD控制器可以提供足够的控制性能,同时避免了可能出现的积分饱和问题,因此在直立环中通常只使用PD控制器,而不使用I控
[单片机]
基于<font color='red'>STM32</font>的平衡小车设计过程分享(3)
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved