关于stm32中串口重定向问题详解(找个时间好好理解下)

2023-05-16

usart这部分代码我也是从网上copy出来的,一下是作者的解释:
简单地说:想在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;  

/// <summary>   
/// 定义_sys_exit()以避免使用半主机模式   
/// </summary>   
/// <param name="x"></param>   
/// <returns></returns>   
_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\Examples
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于stm32中串口重定向问题详解(找个时间好好理解下) 的相关文章

  • ubuntu23.04安装gitbook

    wget https npm taobao org mirrors node v12 16 1 node v12 16 1 linux x64 tar gz tar zxvf node v12 16 1 linux x64 tar gz l

随机推荐

  • 使用OpenMV引导无人机飞行

    原文链接 xff1a http www nufeichuiyun com p 61 307
  • APM固件太大放不下,咋办?

    APM固件越来越大 xff0c 小容量单片机放不下咋办 xff1f 原文链接 xff1a APM固件太大放不下 xff0c 咋办 xff1f 怒飞垂云 无人机知识库
  • 怒飞垂云视频教程 二、基于waf编译飞控固件

    原文链接 xff1a http www nufeichuiyun com p 61 246 怒而飞 xff0c 其翼若垂天之云 xff01 我是怒飞 QQ xff1a 3500985284
  • 怒飞垂云视频教程 三、基于eclipse编译飞控固件

    基于eclipse编译飞控固件 xff0c 原文链接 xff1a http www nufeichuiyun com p 61 249
  • 怒飞垂云视频教程 四、建立软件仿真环境

    原文链接 xff1a http www nufeichuiyun com p 61 256 怒而飞 xff0c 其翼若垂天之云 xff01 我是怒飞 QQ xff1a 3500985284
  • docker:国内 hub 镜像地址

    七牛云
  • C++读取STL模型文件

    数据格式 二进制的数据格式 xff1a 二进制STL文件用固定的字节数来给出三角面片的几何信息 80 80个字节的文件头 xff0c 用于存贮文件名 4 4 个字节的int描述模型的三角面片个数 小端存储 50 n 一个三角面片占用固定的5
  • mNetAssist(arm64)linux下图形界面的网络调试助手

    linux下图形界面的网络调试助手mNetAssist 网上均为x86 amd处理器的 想在arm64上使用 所以 自己down了源码编译了一遍 方便大家使用 项目地址 码云 https gitee com justsure m net a
  • 激光SLAM建图过程中的问题MessageFilter [target=odom_combined ]:Dropped 100.00% of messages so far.,解决方案

    最近在和师弟用kobuki底盘进行SLAM建图的过程中遇到一个比较棘手的问题 xff0c 一直没有解决 xff0c 直到今天我在仿真环境中也碰到了 WARN 1618301922 711685031 2351 764000000 Messa
  • Linux 内核优化-调大TCP最大连接数

    一 tcp 概述 1 服务器如何标识tcp连接 xff1f 在tcp应用中 xff0c server事先在某个固定端口监听 xff0c client主动发起连接 xff0c 经过三路握手后建立tcp连接 在确定最大连接数之前 xff0c 先
  • 飞书妙记用法小结

    企业升级后 xff0c 可以到达10G 妙记的2G不是指代识别容量 xff0c 而是指代源文件容量 额度满了以后 选择权益数据 那么如果容量满了的话 xff0c 怎么释放呢 xff1f 需要删除回收站里面的所有文件 xff0c 才可以释放
  • 3-1利用文件流复制文件内容-Java

    题目 xff1a 编程利用文件流把一个文本文件中的内容复制到另外一个文件中 解答 xff1a Test类 xff1a package Experiment 3 Question 1 import java io public class T
  • C++强制类型转换运算符(static_cast、reinterpret_cast、const_cast和dynamic_cast)

    将类型名作为强制类型转换运算符的做法是C语言的老式做法 xff0c C 43 43 为保持兼容而予以保留 C 43 43 引入了四种功能不同的强制类型转换运算符以进行强制类型转换 xff1a static cast reinterpret
  • 字符数组的初始化与赋值

    代码编译运行环境 xff1a VS2017 43 Win32 43 Debug 1 字符数组的初始化方式 C语言中表示字符串有两种方式 xff0c 数组和指针 xff0c 字符数组是我们经常使用的方式 变量的定义包括指明变量所属类型 变量名
  • XML和HTML之间的差异

    XML 不是 HTML 的替代 XML 和 HTML 为不同的目的而设计 xff1a XML 被设计用来传输和存储数据 xff0c 其焦点是数据的内容 HTML 被设计用来显示数据 xff0c 其焦点是数据的外观 HTML 旨在显示信息 x
  • 线程、线程句柄、线程ID

    什么是句柄 xff1a 句柄是一种指向指针的指针 我们知道 xff0c 所谓指针是一种内存地址 应用程序启动后 xff0c 组成这个程序的各对象是住留在内存的 如果简单地理解 xff0c 似乎我们只要获知这个内存的首地址 xff0c 那么就
  • Modbus通信协议

    一 Modbus 协议简介 Modbus 协议是应用于电子控制器上的一种通用语言 通过此协议 xff0c 控制器相互之间 控制器经由网络 xff08 例如以太网 xff09 和其它设备之间可以通信 它已经成为一通用工业标准 有了它 xff0
  • 77组合

    给定两个整数 n 和 k xff0c 返回 1 n 中所有可能的 k 个数的组合 示例 输入 n 61 4 k 61 2 输出 2 4 3 4 2 3 1 2 1 3 1 4 最容易想到的应该是回溯 xff0c 更多题目思路及代码见 xff
  • 结构体内数据元素对齐

    默认情况下 xff0c 为方便结构体内元素的访问于管理 xff0c 当结构体内的数据元素的长度小于处理器的位数的时候 xff0c 便以结构体内的最长数据元素为对齐单位 xff0c 即结构体的长度一定为最长数据元素的长度的整数倍 如果结构体内
  • 关于stm32中串口重定向问题详解(找个时间好好理解下)

    usart这部分代码我也是从网上copy出来的 xff0c 一下是作者的解释 xff1a 简单地说 xff1a 想在mdk 中用printf xff0c 需要同时重定义fputc函数和避免使用semihosting 半主机模式 xff09