我们介绍过了 STM32F1 的 USART 串口通信,本文我们来学习如何在STM32上使用 printf 输出函数。相信只要学习过 C 语言的朋友, 都会使用printf函数。本章要实现的功能是:通过 printf 函数将信息打印在串口调试助手上显示。
* M" Z/ f- c1 W X9 j2 i. f/ ~0 w
printf重定向简介 我们知道 C 语言中printf 函数默认输出设备是显示器,如果要实现在串口 或者 LCD 上显示,必须重定义标准库函数里调用的与输出设备相关的函数。比如使用 printf 输出到串口, 需要将 fputc 里面的输出指向串口,这一过程就叫重定向。 那么如何让 STM32 使用 printf 函数呢?很简单,只需要将 fputc 里面的输出指向 STM32 串口即可,fputc 函数有固定的格式,我们只需要在函数内操作STM32串口即可,代码如下: - int fputc(int ch,FILE *p) //函数默认的,在使用 printf 函数时自动调用
( ]1 D. r" T* Q1 y6 Q+ ? - {2 w4 E4 G: K0 M/ F7 K: D) G8 H2 D% ]
- USART_SendData(USART1,(u8)ch);4 b$ B7 Q9 H0 ?
- while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);( X* A+ @5 @$ V8 K$ ~, a9 r4 T6 H
- return ch;0 p1 N( ^ F5 g/ v! j" Z& w I. N
- }
复制代码
! Q5 O2 r P+ j" E
如果要让其他的串口也使用 printf 函数,只需要修改下串口号即可。
& j3 A$ A" Q0 }7 T& A. B8 q! {' A , E2 Z* j$ K' Q8 f4 E# W
printf函数格式 printf 函数调用格式如下: - printf("<格式化字符串>", <参量表>);
复制代码 . r5 M) H; M+ i; V7 e3 y
其中格式化字符串包括两部分内容: 一部分是正常字符, 这些字符将按原
; n$ e2 z: n' F) s, Q# @ 样输出; 另一部分是格式化规定字符, 以"%"开始, 后跟一个或几个规定字符, 用来确定输出内容格式。 参量表是需要输出的一系列参数, 其个数必须与格式化字符串所说明的输 出参数个数一样多, 各参数之间用","分开, 且顺序一一对应, 否则将会出现意 想不到的错误。 常用格式化规定字符如下: - %d 按照十进制整型数打印
' x1 D6 l# q0 g( j: s0 t - %6d 按照十进制整型数打印,至少 6 个字符宽0 r7 Q' [3 ?6 t* }. X8 F
- %f 按照浮点数打印* {- ?) d8 Y1 X& K4 I
- %6f 按照浮点数打印,至少 6 个字符宽
% Z4 p0 Q7 d h - %.2f 按照浮点数打印,小数点后有 2 位小数
! B" } e: @1 G. j* R' P - %6.2f 按照浮点数打印,至少 6 个字符宽,小数点后有 2位小数& N. x2 N$ V) | i5 {' a# P
- %x 按照十六进制打印
# l8 E! E/ A, N6 b& x7 o - %c 打印字符! \3 \/ O! A) y* G0 g" T( Q
- %s 打印字符串
复制代码
2 V* c7 d4 ^8 c% F- X
例如:使用 printf函数输出一个整型数据 1234,则调用格式如下: - int data=1234;
/ K5 _9 {- \; z$ \ C/ e# ^5 T3 d - printf(“输出整型数据data=%d\r\n”,data);
复制代码
- y: a1 `9 G: H8 w# @* T) G 在KEIL 中使用 printf一定要勾选“微库”选项,否则不会输出。配置如下: F* Q1 F& x: r5 g. w/ I* _
" l9 q6 k2 K; U
在STM32 程序开发中 printf 应用是非常广的,当我们需要查看某些变量数 值或者其他信息等,都可以通过 printf 打印到串口调试助手上查看。
$ g/ G* v: m& }- J* l3 @9 v8 @# E
硬件设计 本章硬件电路与上一章串口通信实验一样,使用到了 STM32F1的串口1和D1 指示灯,这里不多说。 所要实现的功能是:通过 printf 函数将信息打印在串口调试助手上显示,同时 D1 指示灯不断闪烁,表示系统正常运行。程序框架如下: (1)初始化 USART1 (2)编写 printf 重定向程序 (3)编写主函数 本章软件部分非常简单,只需要在上一章串口通信程序基础上,加上一个 printf 重定向函数即可。下面我们打开“printf重定向”工程。 USART1 串口初始化程序同上一章串口通信实验一样。
$ c' E) i' w+ V% o
printf重定向函数 初始化 USART1 后,就需要将 fputc 里面的输出指向STM32 的串口,代码如下: - int fputc(int ch,FILE *p) //函数默认的,在使用 printf 函数时自动调用
- n) f9 \. ~$ Q- r t# ] - {
5 w& y8 r! Q8 P; X - USART_SendData(USART1,(u8)ch);5 C5 s! V) O' Y. d
- while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
$ i2 y3 r# h. a. \6 K8 v - return ch;4 W0 N c& g! r
- }
复制代码
3 a/ K8 g5 K, d% ~7 j
当使用 printf 函数时,自动会调用 fputc 函数,而 fputc 函数内又将输出设备重定义为 STM32 的 USART1,所以要输出的数据就会在串口 1上输出。 主函数 编写好前面几部分程序后,接下来就可以编写主函数了,代码如下: - /****************************************************************
: I& s: p- g) u( L$ k5 c( ^) m" d - * 函 数 名 : main
; Z: ]; T9 ]1 R* h" }# w) T - * 函数功能 : 主函数5 O6 T0 J* N2 [- Z3 v
- * 输 入 : 无
O M& O( b) C* y5 t$ U1 s - * 输 出 : 无9 |( L( V' ?6 o! G* e, ~
- *****************************************************************/8 l+ z- p. a" s, \
- int main()
4 g0 R; H2 A9 k" y+ L- s; C - {
0 k) ]0 ^$ p# c9 y$ M4 P+ g - u8 i=0;! V) q, T: m9 T# R1 e: I
- u16 data=1234;
0 d. e3 x" n6 ^- Z) O4 v - float fdata=12.34;. h+ j; C, w `
- char str[]="Hello World!";
6 K- \9 @& ^, K/ { R- G5 C& M6 l - SysTick_Init(72);( T% p4 I# F6 f2 c# ]
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2 组; k5 e: j7 E) @1 i% X
- LED_Init();
) X% U4 @2 A& V% s& o - USART1_Init(9600);
$ Z& b% Y ~0 n, D' x, l - while(1)
' `! B6 p6 H2 D' A3 n7 a, S - {
# A9 T/ @' L5 E Y Y1 S - i++;8 v7 x) h" D& m4 f; ]" \
- if(i%20==0)& p2 v* d2 i; Q* T* V9 l
- {+ p* w6 w$ }/ S% y* e! h
- led1=!led1;
% x9 G) ~, g; T; N- V& B - printf("输出整型数 data=%d\r\n",data);* M; t; L1 Z/ x/ \+ Y f
- printf("输出浮点型数 fdata=%0.2f\r\n",fdata);
& S( K/ m/ ?9 E( K/ D) r - printf("输出十六进制数 data=%X\r\n",data);
, ^5 M& [+ P5 P" B/ k( u) T - printf("输出八进制数 data=%o\r\n",data);( p: o, n. } ^. g- y
- printf("输出字符串 str=%s\r\n",str);: F& p7 ~% n* }- u* V
- }
9 O% n( c1 f, `3 T9 ~ - delay_ms(10);
" |) C) ~0 ]+ N! N* Z% E; Y, ~ - }
" b9 v9 B: W5 j8 [! j - }
复制代码
Z$ h D5 o( P, |1 c8 q' @
主函数实现的功能很简单,首先调用之前编写好的硬件初始化函数,包括. U! h% _5 F- J/ A0 U& h% I: x
SysTick 系统时钟,中断分组,LED 初始化等。然后调用我们前面编写的USART1初始化函数,这里我们设定串口通信波特率为 9600。最后进入 while 循环语句,不断让D1 指示间隔 200ms闪烁,同时通过串口 1 输出一连串字符信息。 其实如果你学会了重定向到 USART1,对于其他的串口重定向都是类似的。 将工程程序编译后下载到开发板内,可以看到 D1 指示灯不断闪烁,表示程序正常运行。打开“\5--开发工具\4. 常用辅助开发软件\串口调试助手”,首 先勾选下标号 1 DTR 框,然后再取消勾选。这是因为此串口助手启动时会把系统复位住,通过 DTR 状态切换下即可。然后设置好波特率等参数后,串口助手上即会收到 printf 发送过来的信息。(前提一定要连接好线路,USB 线一端连接电脑,另一端连接开发板“USB 转串口模块”上的 USB 下载口。先勾选下标号1 DTR框,然后再取消勾选)如下图所示:
6 n4 J( J% k! B8 u |