作者:echobright

原文链接:https://blog.csdn.net/qq_29344757/article/details/75363639

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

法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();printf("\r\nstm32f103rct6\r\n");printf("\r\nCortex-M3\r\n");while (1);  return 0;
}

printf()函数的使用方法跟之前一样,运行结果:

法2:不使用MicroLIB库

2.1 半主机模式

半主机模式是ARM的一种机制,实现将来ARM应用程序代码的输入/输出请求传送至运行着调试器的主机。例如设置使用半主机模式下的ARM应用程序,可以使用printf()和scanf()来使用主机的显示器和键盘,而不需要在ARM系统上搭配显示器和键盘。

半主机通过一组定义好的软件指令(如SVC)来实现的,这些指令在程序控制下产生异常,ARM应用程序调用半主机对应的异常处理函数,然后调试代理处理该异常。

第二段话感觉理解起来有点模糊,但是第一段还是懂它在讲什么的。一般的ARM应用程序中并不需要半主机操作,在这里为确保ARM应用程序中没有链接MicroLib的半主机相关函数,我们要取消ARM的半主机工作模式。

2.2 实现代码

在工程中加上如下代码:

#pragma import(__use_no_semihosting)
struct __FILE { int handle;
};
FILE __stdout;
_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上了。

推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎转发,在看,评论~

这两种printf()函数重定向方法,太实用了相关推荐

  1. JS两种声明函数的方法以及调用顺序

    两种声明方法: 1. var a = function () {...}; 2. function a() {...}; 第一种方式必须先声明后调用,而第二种方式函数调用在声明之前之后都可以. //第 ...

  2. 归一化mysql函数_数据归一化和两种常用的归一化方法

    数据归一化和两种常用的归一化方法 一.总结 一句话总结: min-max标准化:x* =(x-min)/(max-min):新数据加入,需重新计算max和min Z-score标准化:x* =(x-μ ...

  3. 函数指针--Nginx和Redis中两种回调函数写法

    1.Nginx和Redis中两种回调函数写法 #include <stdio.h>//仿Nginx风格 //结构外声明函数指针类型 typedef void (*ngx_connectio ...

  4. 英雄无敌6服务器在哪个文件夹,Win7系统无法运行英雄无敌6的两种原因和解决方法...

    英雄无敌6作为一款策略模拟类游戏,深受高端玩家的喜爱.但最近有Win7旗舰版系统用户在玩英雄无敌6时,却出现了无法运行的情况,重启好多次还是一样,不太清楚是哪里出问题,网上相关解决方案也比较少,针对此 ...

  5. 快排的两种partition函数

    partition函数就是快排的关键部分,作用是将数组划分成两部分,左边小于基数,右边大于基数 但实际上它也不仅仅用于快排,在求top(K)问题中也常常会用到. 下面介绍两种partition函数,他 ...

  6. 两种Random函数的使用

    Java中的Random()函数 Java中存在着两种Random函数(java.lang.Math.Random以及java.util.Random): 因为在日常的使用中,常常会涉及到随机数的产生 ...

  7. PIC单片机printf()函数重定向

    基本信息: 系统:Windows10 编译器:MPLAB X IDE V3.26 + XC8 V1.45 单片机:PIC18F66K22 下载器:PICKit3 一.串口初始化 /*函数名:void ...

  8. 数据归一化和两种常用的归一化方法

    数据标准化(归一化)处理是数据挖掘的一项基础工作,不同评价指标往往具有不同的量纲和量纲单位,这样的情况会影响到数据分析的结果,为了消除指标之间的量纲影响,需要进行数据标准化处理,以解决数据指标之间的可 ...

  9. win10与linux 开机黑屏,win10系统开机黑屏进不去的两种原因及解决方法

    win10电脑用久了总会会遇到某些故章,较为普遍的属于黑屏了.黑屏的故障就可以分为多种状况,比如开机黑屏,只有鼠标出现.或者是驱动不兼容导致电脑黑屏等,造成黑屏的原因也有很多,所以不同情况,修复方法也 ...

最新文章

  1. requests不容易注意到的细节收集~
  2. java dataurl_java url参数去重
  3. 【Python】如何在Excel中调用Python脚本,实现数据自动化处理
  4. jquery 判断是否有类名_Day037-JS、jQuery
  5. Gradle入门:创建Web应用程序项目
  6. Python之Numpy入门实战教程(1):基础篇
  7. LightOj 1027 A Dangerous Maze
  8. 开机动画适配方案_小米CC开机动画首曝光:7月2日在北京水立方发布
  9. html制作苹果手机屏幕,iphone怎么录屏幕点击动作(苹果手机的屏幕录制步骤)...
  10. ttl备份机顶盒固件_机顶盒刷机TTL教程,任意安装安卓软件,免费看电视直播
  11. wincc 服务器授权型号,WinCC V7.5 SP1软件安装及授权方法
  12. 读取图像数据:通过append方法
  13. 图片画圈画箭头用什么软件_什么软件可以在编辑图片中画圈圈,如裁图时需要特..._网络编辑_帮考网...
  14. TDD实践之实用主义
  15. 4大主流CPU处理器技术架构详解
  16. android手机常用分辨率
  17. 静态存储器(SRAM)工作原理
  18. Jlink命令行烧录
  19. Tableau用多线图展示多个指标
  20. goip设备的特点_架设通讯网络设备为境外诈骗集团服务 3男子被田东警方抓获...

热门文章

  1. Oracle+ASM单机环境下,开启归档的最简单的方法
  2. 为ESXI 添加ISCSI存储设备 Linux服务器系统
  3. VMware HA与VMotion的部署与搭建
  4. SQL server挂了之后
  5. Django博客--3.创作后台开启
  6. 调整标志位方法oracle,面试题(二)(示例代码)
  7. 深度学习之卷积神经网络 GoogleNet
  8. Hive的基本操作总结
  9. python 单例模式的四种实现方法
  10. stm32c语言设计以及注释,13个基于STM32的经典项目设计实例,全套资料~-嵌入式系统-与非网...