STM32的printf函数重定向

2023-05-16

在前面学习了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 <stdio.h>
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, "HelloWorld\n");
	//USART_SendChar(USART1, 'h');
	printf("\r\nstm32f103rct6\r\n");
	printf("\r\nCortex-M3\r\n");
	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上了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32的printf函数重定向 的相关文章

  • 【C语言】使用函数指针实现状态机软件框架

    文章目录 回调函数实现例子四则运算的简单回调函数例子状态机实现例子 函数返回值类型 指针变量名 函数参数列表 回调函数实现例子 span class token keyword int span span class token funct
  • 【嵌入式Linux】MBR分区表 和 GPT分区表

    文章目录 GUID以及分区表MBR分区方案GPT 分区方案GPT分区表结构 GPT分区表LBALBA0 xff08 MBR兼容部分 xff09 LBA1LBA 2 33python生成GPT分区表gpt分区表实例 gpt分区表查看查看百问网
  • 【目录】Buildroot学习记录

    Buildroot 学习记录 xff08 1 xff09 简介与理论 Buildroot 学习记录 xff08 2 xff09 配置注解 Buildroot 学习记录 xff08 3 xff09 其他功能 Buildroot 学习记录 xf
  • 【目录】Yocto学习记录

    Yocto 学习记录 xff08 1 xff09 理论知识 Yocto 学习记录 xff08 2 xff09 资源资料 Yocto 学习记录 xff08 3 xff09 实际操作
  • 【Buildroot】学习记录(2)配置注释

    文章目录 一 前言二 Buildroot目录结构三 Buildroot配置选项四 Target options 目标选项 五 Build options 编译选项 六 Toolchain 工具链 七 System configuration
  • oracle alter table详解

    建测试表 create table dept deptno number 3 primary key dname varchar2 10 loc varchar2 13 create table employee info empno nu
  • 【目录】音视频开发笔记

    音视频开发 基础知识 xff1a 音频基础 音视频开发 基础知识 xff1a 视频简介 音视频开发 基础知识 xff1a 视频封装格式和编码格式 音视频开发 基础知识 xff08 1 xff09 音视频开发 基础知识 xff08 2 xff
  • 串口通信之(一)获取传感器数据(modbus rtu master)

    一天领导拿了几个传感器设备丢给我 xff0c 给我把这些数据取到 我一看 xff0c 好家伙 这是要搞硬件了啊 那就搞他丫的 可是 xff0c 怎么搞是个问题 我是一头雾水 还好 xff0c 和传感器丢给我的 xff0c 还有传感器厂家一起
  • 小觅深度版-realsense系列,深度相机对比

    本文为CSDN原创文章 xff0c 转载请注明出处 本文为CSDN原创文章 xff0c 转载请注明出处 本文对比了目前小觅生产的深度版 xff08 120 xff09 相机 Realsense D435以及 Realsense ZR300
  • VIO单目评测算法:A Benchmark Comparison of Monocular Visual-Inertial Odometry Algorithms for Flying Robots

    A Benchmark Comparison of Monocular Visual Inertial Odometry Algorithms for Flying Robots 飞行器单目VIO算法测评 算法方面总结 xff1a MSCK
  • LVM调整home剩余空间到root分区

    注意 xff1a 1 此方法为LVM逻辑卷调整 xff0c 请确认是否为逻辑卷分区 xff0c 且文件系统格式为ext4或者xfs 2 减少home分区会将home分区格式化 xff0c 请先备份home分区 xff0c 但是放心增加的ro
  • git clone 指定某个分支而不是整个版本仓库

    最近在搭建Gitblit内网仓库时发现一个问题 xff0c git clone 只能clone整个仓库 xff0c 但是如果我只需要仓库里面的某一个分支 xff0c 这时还需要clone整个仓库就很头疼 xff0c 下面用这个命令就可实现c
  • 十九、I2C驱动及应用

    一 概述 1 Linux主机驱动和外设驱动分离思想 外设驱动 API 主机驱动 板级逻辑 具体的i2c设备 xff08 camera xff0c ts xff0c eeprom等等 xff09 主机驱动 xff1a 根据控制器硬件手册 xf
  • 内核驱动的本质——模块

    内核驱动的本质 模块 在Linux中 xff0c 驱动的本质就是一个模块 模块可以被选择 静态编译 或 模块化编译 1 静态编译 xff1a 链接入内核镜像 xff0c 默认永远被加载 2 模块化编译 xff1a 需要在内核运行时动态加载
  • 【STM32知识点】关于串口接收中断(回调函数)

    串口使用流程 xff1a 1 初始化串口 2 使能中断 xff08 在非阻塞模式下接收一定量的数据 xff09 HAL UART Receive IT UART HandleTypeDef huart uint8 t pData uint1
  • 最近看书少了,以后要多看书

    最近两周的oracle学习都是围绕csdn上oracle板块中遇到的问题 xff1b 看书少了 xff0c 遇到不懂的知识 xff0c 查询书籍 xff0c 查询网络的次数多了 xff1b 于是与电脑一起度过的时间 xff0c 占了大约9
  • 【STM32Cube HAL】定时器中断(四)

    实验内容 xff1a 使用基本定时器 xff0c 实现LED灯以1S间隔进行亮灭切换 一 原理图 二 CubeMX配置 Step1 打开 STM32CubeMX xff0c 点击 New Project xff0c 选择芯片型号 xff0c
  • 【STM32Cube HAL】输入捕获(六)——PWM测量

    对于PWM的捕获 xff0c 我这里一共使用两种方法实现 xff1a 第一种是PWM输入模式 xff0c 采用一个定时器的两个通道 xff08 通道一和通道二 xff09 xff0c 配置从模式为复位模式 xff0c 没有进行溢出处理 xf
  • 【STM32知识点】关于不同外设中断标志位清除的使用笔记(更新中)

    在使用中断函数的时候 xff0c 我们往往忘记在中断服务函数内清除中断标志位而导致一些未知错误 以下我总结了几个外设关于中断标志位的清除问题 定时器 xff1a 1 在程序有使用到中断的情况下 xff0c 定时器在使能之前需要先清除更新中断
  • 【FreeRTOS 应用开发笔记】软件定时器(九)

    一 软件定时器的基本概念 1 硬件定时器和软件定时器的主要区别 定时器 xff0c 是指从指定的时刻开始 xff0c 经过一个指定时间 xff0c 然后触发一个超时事件 xff0c 用户可以自定义定时器的周期与频率 硬件定时器 xff1a

随机推荐

  • 【STM32知识点】STM32基础知识总结

    目录 认识STM32 GPIO外设 一 GPIO的八种工作模式 二 总结在STM32中选用IO模式 RCC时钟 NVIC是嵌套向量中断控制器 一 优先级定义 二 优先级分组 EXTI外部中断 事件控制器 SysTick系统定时器 通讯的基本
  • 【数据结构】排序

    本文主要选取了桶排序 xff0c 冒泡排序 xff0c 以及快速排序 当然还有其他几种 xff0c 可以根据需要进行学习 一 桶排序 1 什么是桶排序 xff1f 桶排序是计数排序的升级版 它利用了函数的映射关系 xff0c 高效与否的关键
  • 【数据结构】栈,队列,链表

    一 队列 队列 xff0c 顾名思义 xff0c 就像排队一样 xff0c 我们只能在队首删除 xff0c 在队尾增加 队列是一种先进先出 xff08 FIFO xff09 的数据结构 队列的存储方式可以使用线性表进行存储 xff0c 也可
  • 【数据结构】树

    一 树 1 什么是树 xff1f 树状图是一种数据结构 xff0c 它是由n xff08 n gt 61 1 xff09 个有限节点组成一个具有层次关系的集合 把它叫做 树 是因为它看起来像一棵倒挂的树 xff0c 也就是说它是根朝上 xf
  • 【专题2: 嵌入式stm32】 之 【6.中断和异常】

    嵌入式工程师成长之路 系列文章 总目录系列文章总目录希望本是无所谓有 xff0c 无所谓无的 xff0c 这正如脚下的路 xff0c 其实地上本没有路 xff0c 走的人多了 xff0c 也便成了路原创不易 xff0c 文章会持续更新 xf
  • workerman-chat启动失败解决办法

    该教程是在官方文档的基础上再加上本人的踩坑经验进行的优化 在开始搭建环境之前 xff0c 先要确认你要搭建聊天室的站点的PHP版本 xff0c 为什么要确认PHP版本 xff1f 等下会解释 下面以PHP5 6为例 1 环境检测 官网方法
  • oracle 分区和面向对象数据库系统的学习

    在过去的一周里面 xff0c 学习了oracle表分区 xff0c object relational database system简介 1 oracle分区 oracle分区是在oracle 8 0中引入的 xff0c 这个过程是将一个
  • 非线性系统线性化过程

    线性化 在对非线性系统进行建模分析时 xff0c 对模型进行线性化处理可以简化分析过程 例子 xff1a 磁悬浮系统建模 系统非线性模型 xff1a m a 61 m g k f i z 2 m a 61 m g
  • ECMAScript 6学习笔记(六)数组的扩展

    数组的扩展 1 扩展运算符 含义 扩展运算符 xff08 spread xff09 是三个点 xff08 xff09 它好比 rest 参数的逆运算 xff0c 将一个数组转为用逗号分隔的参数序列 该运算符主要用于函数调用 span cla
  • vs2022 x64 C/C++和汇编混编

    vs2022环境x64 C C 43 43 和汇编混编 vs64位程序不支持 asm内嵌汇编 xff0c 需要单独编写汇编源文件示例如下1 新建空的win32项目 xff0c 新建main cpp xff0c 示例代码如下2 新建asm64
  • python学习:解决如何在函数内处理数据而不影响原列表

    python学习 xff1a 解决如何在函数内处理数据而不影响原列表 关于一个如何在函数内修改三阶矩阵 在python里 xff0c 如果想要定义一个函数 xff0c 把列表当c 43 43 里的形参传进去 xff0c 显然是不可能的 在p
  • 有关树莓派驱动1.3寸IPS屏幕的一点经验

    有关树莓派驱动1 3寸IPS屏幕的经验 前言CS引脚按键显示效果 后记 分享最近我用树莓派驱动IPS屏幕及微雪1 3inch LCD HAT的经验 前言 我的树莓派zero w已经吃灰很久了 xff0c 趁着今年电赛留校集训期间玩一玩 注意
  • tensorflow采坑系列-InvalidArgumentError: Shape [-1,784] has negative dimensions

    问题描述 xff1a InvalidArgumentError Traceback most recent call last d span class hljs command Anaconda span 3 span class hlj
  • 在旧版本Ubuntu系统中使用“apt-get update”出现“404 Not Found”错误的解决办法

    每一个Ubuntu发布版本都有它的结束时间 xff0c 通常 xff0c Ubuntu发布版本支持18个月 xff0c 而LTS Long Term Support xff08 长期支持 xff09 版本分别支持3年 服务器版 和5年 桌面
  • 使用 ROS中的插件

    URDF 文件完成后 xff0c 可以在 rviz 中显示机器人的模型 xff0c 如果要在 gazebo 中进行物理环境仿真 xff0c 还需要为 URDF 文件加入一些 gazebo 相关的标签 既然是仿真 xff0c 那么机器人应该像
  • linux杀毒软件

    0x00前言 linux或者Unix系统经常被用作服务器 xff0c 并且安全性往往比windows高 xff0c 但是在linux查杀病毒往往得依靠管理员执行find grep等命令查看文件以确认文件是否为病毒 xff0c 但由于本身li
  • 使用LVM对根分区进行扩容

    使用LVM对根分区进行扩容 1 df h 查看当前根分区大小 可以看到我们当前根分区的大小为66G 2 创建PV物理卷 pvcreate span class token operator span dev span class token
  • 毕业了,投入的工作

    2012年7月1日 xff0c 一个全新的开始 大学毕业了 xff0c 结束了学生时代 xff0c 走向社会 xff0c 开始工作 开始挣钱 xff0c 在一个熟悉的城市里 xff0c 面对陌生的面孔 使用未曾听过见过的语言 xff0c 技
  • vscode配置git

    首先下载git 下载完成后复制git路径 xff0c 如 xff1a D Software Git cmd git exe 也可以打开cmd窗口输入 where git 然后打开vscode xff0c 打开设置 xff0c 搜索git p
  • STM32的printf函数重定向

    在前面学习了STM32的串口编程 xff0c 通过USART1向计算机的串口调试助手打印数据 xff0c 或者接收计算机串口调试助手的数据 xff0c 接下来我们可以实现STM32工程上的printf 函数了 xff0c 方便用于程序开发中