版权声明:原创文章,请持怀疑态度阅读,欢迎转载,但请注明文章出处。 https://blog.csdn.net/qq_29344757/article/details/75363639

在前面学习了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;
_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上了。

--------------------- 本文来自 bright261 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/qq_29344757/article/details/75363639?utm_source=copy

https://shequ.stmicroelectronics.cn/forum.php?mod=viewthread&tid=598294

https://www.keil.com/support/man/docs/armlib/armlib_chr1359122859512.htm

http://openedv.com/thread-266440-1-1.html

STM32的printf函数重定向相关推荐

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

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

  2. STM32 在PC端串口助手上打印中文字符----printf()函数重定向

    前言 本博文基于STM32F103ZET6和MDK5.2.6和库函数V3.5.0开发: 本博文采用七星虫德飞莱开发板,USB-TTL电路,USART1和串口调试助手: 如有不足,多指教: 针对STM3 ...

  3. STM32中关于串口通信的printf()函数重定向问题

    在STM32串口通信程序中使用printf()函数发送数据非常方便,但是需要先进行简单的配置,下面介绍两种配置方法. 方法一.对工程属性进行配置 第1步:在main.c中包含"stdio.h ...

  4. 这两种printf()函数重定向方法,太实用了

    作者:echobright 原文链接:https://blog.csdn.net/qq_29344757/article/details/75363639 在前面学习了STM32的串口编程,通过USA ...

  5. 【STM32学习5】STM32使用printf函数 打印到电脑串口助手

    本文所使用的方法与代码参考自正点原子,如果想要详细了解这方面的知识,请阅读正点原子官方提供的文档. 一.背景 在开发STM32应用时,将一些信息通过串口打印到电脑上是常用的调试手段.C语言标准库中的p ...

  6. STM32使用printf函数的步骤和注意事项

    第一种方法: 使用微库: 1,在KEIL中勾选 Use MicroLIB . 即使用微库. 2, 在代码中添加 如下代码 (目的是为了调用stdio库中的print 函数) #include &quo ...

  7. STM32的printf函数串口重定义(HAL库和标准库都适用)

    1. 打开或创建工程 打开或者创建自己要用到的工程,配置串口相关的GPIO.时钟.波特率等,本次使用STM32CubeMX创建工程,打开串口1,配置波特率为115200,数据位为8,停止位为1,无奇偶 ...

  8. printf函数的重定向

    为什么要重定向printf函数? printf函数是底层函数,含于stdio.h头文件.因为在C语言中printf函数已经定义为默认输出到显示器的,若要想在串口上显示,那就需要重定向printf.例如 ...

  9. C语言printf重入,单片机中printf函数的重映射

    单片机中printf函数的重映射 一.源自于:大侠有话说 1.如果你在学习单片机之前学过C语言,那么一定知道printf这个函数.它最最好用的功能 除了打印你想要的字符到屏幕上外,还能把数字进行格式化 ...

最新文章

  1. Python bytes 的使用
  2. Leetcode 143. 重排链表
  3. 国内数十位NLP大佬合作,综述预训练模型的过去、现在与未来
  4. JavaScript操作DOM对象
  5. Linux中存储相关的命令,Linux存储管理命令与HAB相关命令
  6. css label 居中布局_用好这20个css技巧快速提升你的CSS技能
  7. 头条账号权重被降低后会导致点赞推荐兑换率会下降
  8. 红巨星视频调色AE插件 Red Giant Magic Bullet Suite 16.0.0 WIN
  9. html中居中方法,HTML中5种常见的居中方法
  10. 4G基站软件产品测试,4G TD-LTE测试解决方案全方位解读 - 全文
  11. linux系统在当前目录下创建子目录,linux根目录下一级子目录
  12. 表达式的LenB(123程序设计ABC)的值是20吗
  13. div元素(css)定位
  14. ajax获取jsp数据,如何使用ajax调用从servlet到jsp获取arraylist数据
  15. ChinaSkills技能大赛网络系统管理Debian模块||AppSrv的CA(证书颁发机构)配置详解
  16. kafka日志清理策略,compact和delete
  17. 如何在SuperMap中打开谷歌卫星地图
  18. 【网络协议详解】——GNS3的使用(学习笔记)
  19. C语言实现移位密码体制
  20. ProCAST 2021反算教程

热门文章

  1. jdk,jre,jvm的区别以及联系
  2. navicat 将自增长字段重置(重新从1开始)的方法
  3. Effective C++ 笔记(1)让自己习惯c++
  4. match和exec
  5. Makefile的几个赋值运算符(转:笔记)
  6. 在.NET环境中实现每日构建(Daily Build)--ccnet,MSBuild篇
  7. 2021-10-25 Vue异步操作
  8. 什么是Web渗透测试
  9. 使用Python自由切分pdf文件提取任意页面
  10. 微课|玩转Python轻松过二级(2.1节):常用内置对象