我们介绍过了 STM32F1 的 USART 串口通信,本文我们来学习如何在STM32上使用 printf 输出函数。相信只要学习过 C 语言的朋友, 都会使用printf函数。本章要实现的功能是:通过 printf 函数将信息打印在串口调试助手上显示。 % Y! ?0 f& \2 @$ a( I% v
printf重定向简介 我们知道 C 语言中printf 函数默认输出设备是显示器,如果要实现在串口 或者 LCD 上显示,必须重定义标准库函数里调用的与输出设备相关的函数。比如使用 printf 输出到串口, 需要将 fputc 里面的输出指向串口,这一过程就叫重定向。 那么如何让 STM32 使用 printf 函数呢?很简单,只需要将 fputc 里面的输出指向 STM32 串口即可,fputc 函数有固定的格式,我们只需要在函数内操作STM32串口即可,代码如下: - int fputc(int ch,FILE *p) //函数默认的,在使用 printf 函数时自动调用* B7 [3 p) m8 L+ v& x5 e
- {7 \+ Y8 F5 I/ }1 I4 n
- USART_SendData(USART1,(u8)ch);
) d* r# P, o# ~- z - while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); G" S R2 D% G. q/ g& W; O% N8 ], W( s6 n
- return ch;
0 `7 g6 W, ~3 u5 j& x - }
复制代码. L7 E$ G) L7 E, W
如果要让其他的串口也使用 printf 函数,只需要修改下串口号即可。
6 ^! H) z5 f4 \4 b( d
' ~5 ^. `# _' L
printf函数格式 printf 函数调用格式如下: - printf("<格式化字符串>", <参量表>);
复制代码 # q( r5 ]" a: g- Y4 `5 P6 H* ~
其中格式化字符串包括两部分内容: 一部分是正常字符, 这些字符将按原+ L. Q$ i, ? ?3 F# ^' i
样输出; 另一部分是格式化规定字符, 以"%"开始, 后跟一个或几个规定字符, 用来确定输出内容格式。 参量表是需要输出的一系列参数, 其个数必须与格式化字符串所说明的输 出参数个数一样多, 各参数之间用","分开, 且顺序一一对应, 否则将会出现意 想不到的错误。 常用格式化规定字符如下: - %d 按照十进制整型数打印
: J$ { h" G! J# c& Y" T - %6d 按照十进制整型数打印,至少 6 个字符宽6 p9 v1 A1 M, ], B1 F. Q( z
- %f 按照浮点数打印
: Q3 e: Y5 U$ B - %6f 按照浮点数打印,至少 6 个字符宽
; ?+ n, p& \, Y9 Y - %.2f 按照浮点数打印,小数点后有 2 位小数, f! ]+ e' G6 Y+ C
- %6.2f 按照浮点数打印,至少 6 个字符宽,小数点后有 2位小数
5 H* h% t7 H; `; ` - %x 按照十六进制打印1 |0 b$ q7 F; _9 q0 ?
- %c 打印字符
$ C9 n: B( {; I4 J! t5 Y2 H% w - %s 打印字符串
复制代码
# z+ y7 m: a0 d, N1 P% n
例如:使用 printf函数输出一个整型数据 1234,则调用格式如下: - int data=1234;
+ A5 L" q0 P' L+ W8 V - printf(“输出整型数据data=%d\r\n”,data);
复制代码
v6 @* p& P. n, Y 在KEIL 中使用 printf一定要勾选“微库”选项,否则不会输出。配置如下:
1 ^! p8 w8 o a6 B0 _" M1 B, R& J ) k- s$ t s* K
在STM32 程序开发中 printf 应用是非常广的,当我们需要查看某些变量数 值或者其他信息等,都可以通过 printf 打印到串口调试助手上查看。 & Y' e% J' {( A- l9 J1 S
硬件设计 本章硬件电路与上一章串口通信实验一样,使用到了 STM32F1的串口1和D1 指示灯,这里不多说。 所要实现的功能是:通过 printf 函数将信息打印在串口调试助手上显示,同时 D1 指示灯不断闪烁,表示系统正常运行。程序框架如下: (1)初始化 USART1 (2)编写 printf 重定向程序 (3)编写主函数 本章软件部分非常简单,只需要在上一章串口通信程序基础上,加上一个 printf 重定向函数即可。下面我们打开“printf重定向”工程。 USART1 串口初始化程序同上一章串口通信实验一样。
3 P( @) P- H J) s$ Y- v
printf重定向函数 初始化 USART1 后,就需要将 fputc 里面的输出指向STM32 的串口,代码如下: - int fputc(int ch,FILE *p) //函数默认的,在使用 printf 函数时自动调用3 V1 s/ V& n0 E8 ` x( ^
- {2 [0 e- f. Z' G A4 l; v, U
- USART_SendData(USART1,(u8)ch);
" G$ g; l3 ?# S/ v* ~ - while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);7 K4 A+ s/ U( n5 B/ D/ e9 A }
- return ch;( \7 m Q2 o1 _' X) j3 F" w% n/ j
- }
复制代码
3 x9 H b5 B" m
当使用 printf 函数时,自动会调用 fputc 函数,而 fputc 函数内又将输出设备重定义为 STM32 的 USART1,所以要输出的数据就会在串口 1上输出。 主函数 编写好前面几部分程序后,接下来就可以编写主函数了,代码如下: - /****************************************************************7 l2 i0 ^2 h/ K: H) T
- * 函 数 名 : main9 B) k" y5 Y( A& O
- * 函数功能 : 主函数
" C* b. c. n7 O# t$ v ^0 d4 b - * 输 入 : 无( A" d: x7 q% X) ~
- * 输 出 : 无& G7 P& B4 O5 g& s/ z& r
- *****************************************************************/( |5 _5 a: c* Q Q6 Q
- int main()! a- ]9 v! e" P% o; v
- {/ D3 M5 g, b9 T) A; G' F
- u8 i=0;( u$ k" p4 U: O- k7 V; x7 Z3 d& ?
- u16 data=1234;
$ c* s' ^" W. a; N - float fdata=12.34;5 B: } [8 V; N
- char str[]="Hello World!"; v p5 Z5 U8 ]- Q+ [$ {* l
- SysTick_Init(72);
& _) k. L4 N. k7 {2 A - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2 组8 B' N5 D# U5 {! f2 Z
- LED_Init();- r5 ~5 ~" q; _; O
- USART1_Init(9600);* E: b5 T8 `0 i+ `
- while(1)* I0 a8 ]! d* Y6 [/ T
- {" q' D9 f* E, Z- n; E3 h' f
- i++;* ?/ u3 o4 l1 {
- if(i%20==0)$ P+ {5 l) R( C# Q6 z: X
- {; X$ ^7 E L3 V- F/ N
- led1=!led1;
' ~* h9 E% ]1 a - printf("输出整型数 data=%d\r\n",data);
( w- i1 ?% }" h/ T, i - printf("输出浮点型数 fdata=%0.2f\r\n",fdata);
" ?9 A4 O- ^* w" ^ - printf("输出十六进制数 data=%X\r\n",data);2 X& [& l. P+ Y) y) N$ B* I
- printf("输出八进制数 data=%o\r\n",data);
8 t8 k% }* t% C- [, Y6 ^7 ^ - printf("输出字符串 str=%s\r\n",str);
% @/ H. { i" n, ~' A - }. u% f) r$ n' J" p* k# K2 |" `! [
- delay_ms(10);
2 Z. d/ g& }! P9 x - } 9 U+ D3 `; D8 a: A
- }
复制代码0 M0 Z: [5 |' D- e) X! Z
主函数实现的功能很简单,首先调用之前编写好的硬件初始化函数,包括
! Z5 ], ]% x v ^; u SysTick 系统时钟,中断分组,LED 初始化等。然后调用我们前面编写的USART1初始化函数,这里我们设定串口通信波特率为 9600。最后进入 while 循环语句,不断让D1 指示间隔 200ms闪烁,同时通过串口 1 输出一连串字符信息。 其实如果你学会了重定向到 USART1,对于其他的串口重定向都是类似的。 将工程程序编译后下载到开发板内,可以看到 D1 指示灯不断闪烁,表示程序正常运行。打开“\5--开发工具\4. 常用辅助开发软件\串口调试助手”,首 先勾选下标号 1 DTR 框,然后再取消勾选。这是因为此串口助手启动时会把系统复位住,通过 DTR 状态切换下即可。然后设置好波特率等参数后,串口助手上即会收到 printf 发送过来的信息。(前提一定要连接好线路,USB 线一端连接电脑,另一端连接开发板“USB 转串口模块”上的 USB 下载口。先勾选下标号1 DTR框,然后再取消勾选)如下图所示:
+ f: R N0 A9 y |