你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32实例-printf 重定向

[复制链接]
STMCU小助手 发布时间:2022-6-29 15:00
    我们介绍过了 STM32F1 的 USART 串口通信,本文我们来学习如何在STM32上使用 printf 输出函数。相信只要学习过 C 语言的朋友, 都会使用printf函数。本章要实现的功能是:通过 printf 函数将信息打印在串口调试助手上显示。
4 R& x* T  _$ }7 ^# X9 L( y
printf重定向简介
    我们知道 C 语言中printf 函数默认输出设备是显示器,如果要实现在串口
或者 LCD 上显示,必须重定义标准库函数里调用的与输出设备相关的函数。比如使用 printf 输出到串口, 需要将 fputc 里面的输出指向串口,这一过程就叫重定向。
    那么如何让 STM32 使用 printf 函数呢?很简单,只需要将 fputc 里面的输出指向 STM32 串口即可,fputc 函数有固定的格式,我们只需要在函数内操作STM32串口即可,代码如下:
  1. int fputc(int ch,FILE *p) //函数默认的,在使用 printf 函数时自动调用' P8 M/ d4 I% G3 W! p5 v+ A
  2. {
    ' _$ g7 w1 }1 V" _: }" L4 E; V
  3.   USART_SendData(USART1,(u8)ch);. C! o( A: s( q
  4.   while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
    ' {. k, c( h' q# n3 p) n' s
  5.   return ch;
    ) [2 N! l2 k" Z4 E6 s+ `
  6. }
复制代码

8 r+ ^( W$ Y  Y* w, G. O
    如果要让其他的串口也使用 printf 函数,只需要修改下串口号即可。
, O5 c3 M- t$ d  n( |0 v

, w1 g9 ?/ G3 H+ D; P0 r7 Z6 |
printf函数格式
    printf 函数调用格式如下:
  1. printf("<格式化字符串>", <参量表>);
复制代码

( A8 O9 u; ?; I$ h; l1 o
    其中格式化字符串包括两部分内容: 一部分是正常字符, 这些字符将按原# Y4 C0 Q! C1 X9 B8 g+ l
样输出; 另一部分是格式化规定字符, 以"%"开始, 后跟一个或几个规定字符,
用来确定输出内容格式。
    参量表是需要输出的一系列参数, 其个数必须与格式化字符串所说明的输
出参数个数一样多, 各参数之间用","分开, 且顺序一一对应, 否则将会出现意
想不到的错误。
    常用格式化规定字符如下:
  1. %d 按照十进制整型数打印
    * w0 E3 @, E* P& h" d3 r
  2. %6d 按照十进制整型数打印,至少 6 个字符宽1 [( }! I/ D1 y
  3. %f 按照浮点数打印! K5 f& e8 ]9 i0 J& s% y. Q6 h
  4. %6f 按照浮点数打印,至少 6 个字符宽
    2 z, w9 l$ `% f" t6 v' j- @- E
  5. %.2f 按照浮点数打印,小数点后有 2 位小数
    & J4 G: Y0 k/ z( i% Z+ N
  6. %6.2f 按照浮点数打印,至少 6 个字符宽,小数点后有 2位小数
    . T* ~1 o7 Y6 c5 e
  7. %x 按照十六进制打印2 Y0 n  _# B2 h& H$ \' f
  8. %c 打印字符
    : S- t3 V  t5 d+ v* p+ n
  9. %s 打印字符串
复制代码

' M, h/ B) |. C+ I$ m* Q: Y5 j5 X
    例如:使用 printf函数输出一个整型数据 1234,则调用格式如下:
  1. int data=1234;
    2 \9 H4 M6 \0 r5 X
  2. printf(“输出整型数据data=%d\r\n”,data);
复制代码
1 ]5 k4 E; A+ x! |
    在KEIL 中使用 printf一定要勾选“微库”选项,否则不会输出。配置如下:
4 t4 o  A  |, R* @9 b. g
微信图片_20220628154543.jpg
1 P8 p9 J, _, E5 t
    在STM32 程序开发中 printf 应用是非常广的,当我们需要查看某些变量数
值或者其他信息等,都可以通过 printf 打印到串口调试助手上查看。
  M7 W8 J2 N9 O$ F7 D
硬件设计
    本章硬件电路与上一章串口通信实验一样,使用到了 STM32F1的串口1和D1 指示灯,这里不多说。
    所要实现的功能是:通过 printf 函数将信息打印在串口调试助手上显示,同时 D1 指示灯不断闪烁,表示系统正常运行。程序框架如下:
(1)初始化 USART1
(2)编写 printf 重定向程序
(3)编写主函数
    本章软件部分非常简单,只需要在上一章串口通信程序基础上,加上一个
printf 重定向函数即可。下面我们打开“printf重定向”工程。
    USART1 串口初始化程序同上一章串口通信实验一样。
, k1 ^8 h9 Z3 C( K9 c9 K
printf重定向函数
    初始化 USART1 后,就需要将 fputc 里面的输出指向STM32 的串口,代码如下:
  1. int fputc(int ch,FILE *p) //函数默认的,在使用 printf 函数时自动调用4 P4 C: s2 u  Y% L. b( H& D
  2. {* r" b: c7 ], S7 i& g9 n3 {2 U! u
  3.   USART_SendData(USART1,(u8)ch);  ]; \" a4 C; y7 P2 R* }
  4.   while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);, G5 w# ~# h; D- ]5 s" Z$ O  ]
  5.   return ch;
    6 K3 ?' b3 @; P- I  J/ f& g
  6. }
复制代码
, L4 c# }5 a+ ~: D
    当使用 printf 函数时,自动会调用 fputc 函数,而 fputc 函数内又将输出设备重定义为 STM32 的 USART1,所以要输出的数据就会在串口 1上输出。
主函数
    编写好前面几部分程序后,接下来就可以编写主函数了,代码如下:
  1. /****************************************************************
    + l! n) N$ |+ u1 }8 Q
  2. * 函 数 名 : main
    ) W# z# p) e" }9 }/ l8 v
  3. * 函数功能 : 主函数
    2 @; M0 d4 w9 \. y/ ^
  4. * 输 入 : 无
    " b  L7 h5 T9 t) I" l* j9 b
  5. * 输 出 : 无& y, G. |" r8 ~* a. t( N8 j
  6. *****************************************************************/, t9 K8 ^7 q+ b7 \- z
  7. int main()
    5 F8 \3 O# _0 k+ ~1 e! A
  8. {
    * e. E& q5 W( a
  9.   u8 i=0;
    & S' Y9 [+ }; K" F3 G1 ~
  10.   u16 data=1234;; o9 s* ~. N. w$ D/ n' a
  11.   float fdata=12.34;
    * a% H3 I) s$ W$ Y; W
  12.   char str[]="Hello World!";
    . v5 B  s" |9 \4 ]" a- z0 D
  13.   SysTick_Init(72);( u5 q: L2 f9 O+ l; U" B
  14.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2 组; E# f' e# P; n. B3 e/ `. U9 n% Z
  15.   LED_Init();
    1 m8 w; @& c6 [; y. o
  16.   USART1_Init(9600);
    * _$ ~* l. M( x, J) u
  17.   while(1)6 Q* X% m3 x) \9 W
  18.   {
    4 h" R9 O" [; G) X
  19.     i++;
    # P5 D/ |3 c' Q& Z, X; g9 O2 Y
  20.     if(i%20==0)
    0 T* U/ K: ^( E3 e' j5 ^
  21.     {8 X! @- r* J( Y0 i% I, b% f; u
  22.       led1=!led1;
    # [+ H- {* ~8 d8 c; ^6 H
  23.       printf("输出整型数 data=%d\r\n",data);" T. y( f) T1 O4 {" b! Z+ G
  24.       printf("输出浮点型数 fdata=%0.2f\r\n",fdata);' i2 |* K% h4 G4 c* ]7 u
  25.       printf("输出十六进制数 data=%X\r\n",data);
    4 y* [  c! D, L9 U; K
  26.       printf("输出八进制数 data=%o\r\n",data);9 g% }- e# l0 O  G! g' f; R
  27.       printf("输出字符串 str=%s\r\n",str);# b' `$ F  W/ Y7 h, n7 C; d% R
  28.     }; n& p' \% \% Z3 R, `7 \; o
  29.   delay_ms(10);
    ' m  |' A1 P- q, k
  30. }  
    / o, b, W4 n$ x( @  f* h  x
  31. }
复制代码

$ J/ S5 v' g, B; X2 w/ q5 R) _; O
    主函数实现的功能很简单,首先调用之前编写好的硬件初始化函数,包括; O. Z5 K% h/ U; u( y3 K
SysTick 系统时钟,中断分组,LED 初始化等。然后调用我们前面编写的USART1初始化函数,这里我们设定串口通信波特率为 9600。最后进入 while 循环语句,不断让D1 指示间隔 200ms闪烁,同时通过串口 1 输出一连串字符信息。
    其实如果你学会了重定向到 USART1,对于其他的串口重定向都是类似的。
    将工程程序编译后下载到开发板内,可以看到 D1 指示灯不断闪烁,表示程序正常运行。打开“\5--开发工具\4. 常用辅助开发软件\串口调试助手”,首
先勾选下标号 1 DTR 框,然后再取消勾选。这是因为此串口助手启动时会把系统复位住,通过 DTR 状态切换下即可。然后设置好波特率等参数后,串口助手上即会收到 printf 发送过来的信息。(前提一定要连接好线路,USB 线一端连接电脑,另一端连接开发板“USB 转串口模块”上的 USB 下载口。先勾选下标号1 DTR框,然后再取消勾选)如下图所示:
微信图片_20220628154549.jpg

4 U7 Y  U# _% q$ S" X
赞 收藏 评论0 发布时间:2022-6-29 15:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版