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

【经验分享】STM32H7系列其二

[复制链接]
STMCU小助手 发布时间:2021-12-18 17:43
printf重定向介绍
/ l. }' R2 ^1 p! `4 ]3 N5 u在学C语言的时候,会经常用标准库<stdio.h>中printf(), scanf()这两个函数, 来实现数据的输入与输出. 格式化输入输出的功能还是挺强大的, 那已经有了现成的轮子, 就要寻思一下如何进一步在单片机上使用它.
+ v% f+ Z6 R/ Z下面是ARM Compiler6文档中对printf的介绍:
: z, X% W# \* O. p6 G: ^: E+ I. r) [9 _" _$ ~
The printf family consists of _printf(), printf(), _fprintf(), fprintf(), vprintf(), and vfprintf().4 ^4 ^) z2 Y; a% v4 N' w* a
All these functions use __FILE opaquely and depend only on the functions fputc() and ferror(). The functions _printf() and _fprintf() are identical to printf() and fprintf() except that they cannot format floating-point values.' r9 C$ ^+ E8 e9 T
The standard output functions of the form _printf(…) are equivalent to:/ a$ Q2 p$ _( V+ _9 w# t
fprintf(& __stdout, …)where __stdout has type __FILE.
( m  W4 {4 _3 _% g! P; y+ c  z
% h2 o' r" Y& k0 r大致是说printf家族有这么些函数<_printf(), printf(), _fprintf(), fprintf(), vprintf(), and vfprintf()>, 这些函数都隐式的使用__FILE<文件流>, 并且只依靠fputc(), ferror()这两个函数.2 z% P1 e1 N" w# x
  f7 i# H) P+ F$ A7 Y
If you define your own version of __FILE, your own fputc() and ferror() functions, and the __stdout object, you can use all of the printf() family, fwrite(), fputs(), puts() and the C++ object std::cout unchanged from the library.1 _: |- y6 W  w, L5 g7 G5 W
9 V" R6 p( K, K# e) C! U
重新定义__FILE, fputc(), ferror(), __stdout, 就可以使用printf()家族的各种函数了.3 g9 ^2 H  f5 {6 i) ~/ r2 `! [1 E
% q- I' O, c* Q- |. y
STM32中printf重定向
' b; `( P% o) r: r" L0 [
下面是官方给出的重映射模板:
4 {. R" m* x7 y) \" F9 Y/ a# Y<遇到不会的先看看文档往往能得到最直接的答案>
. ?" E8 I. M2 o, }0 m% v/ W8 |: S$ J# X7 c1 @6 X. _3 p0 p
  1. #include <stdio.h>
    " k* A0 _2 R; x# r( a
  2. struct __FILE6 x1 J2 @+ y% p
  3. {
    " `" }2 c- Z- A4 T# f$ f- e+ l
  4.   int handle;$ c5 w' C: [1 ^" M2 q
  5.   /* Whatever you require here. If the only file you are using is */
    ; R& j: H, d/ z5 T! c6 A! Y: N. n
  6.   /* standard output using printf() for debugging, no file handling */0 h; o1 e* B( j& |
  7.   /* is required. */6 |6 Y8 O6 Q7 {: U- S
  8. };3 d4 {  S' I& U9 C
  9. /* FILE is typedef’d in stdio.h. */5 J2 b- k  ~  }
  10. FILE __stdout;% w# t1 |' Z! W7 d4 u8 k2 v! b
  11. int fputc(int ch, FILE *f)
    0 N. r# [* _: I- G; E
  12. {
    8 B: x; i" w0 R
  13.   /* Your implementation of fputc(). */2 q1 I9 V( ~4 E/ @/ d$ Q
  14.   return ch;4 |$ @) \* }9 k# q2 ^! V5 a
  15. }  \3 c5 \/ s8 Z7 Y1 N/ E7 |
  16. int ferror(FILE *f)" t$ Y% `- Q. w+ W0 z# o
  17. {
    . J" D+ \9 n& ~% O) K- e
  18.   /* Your implementation of ferror(). */1 n1 D( |' K0 y/ h7 u& A
  19.   return 0;' e# N7 c: I- d, L+ |
  20. }
复制代码

  X- ~7 r3 E" Z$ U  N  v要将printf()重定向到STM32中的串口, 只需要重新实现 fputc() 函数即可, 在fputc()中通过串口发送一个char. 在上一次的工程上进行修改, 将printf()重定向到串口3.* P* c. @  q2 ~) j; a- g
9 D& L0 L( X  X0 ?; e0 o& r# A
  1. #include <stdio.h>
    5 @9 A9 {+ |% m7 V/ i  \4 O1 ]8 y: G
  2. struct __FILE; ^& t# o7 I1 B' T) G( i
  3. {
    3 L" M! y; A! s) W  @' l
  4.   int handle;# C6 R! e2 E, n
  5.   /* Whatever you require here. If the only file you are using is */0 H/ `/ p' p# z8 K; r- g2 m( {1 \
  6.   /* standard output using printf() for debugging, no file handling */0 d5 {' r6 ~& L8 K9 t* U
  7.   /* is required. */4 s2 v! l. K" R6 i3 n
  8. };7 S% ^* m+ l% T
  9. /* FILE is typedef’d in stdio.h. */
    1 r6 v3 d- ^9 y- X1 H3 B
  10. FILE __stdout;1 R7 V+ Y9 o2 S4 ]
  11. int fputc(int ch, FILE *f) : ], G( W$ x% Q
  12. {
    4 ]! H; x/ l0 U, l$ t3 K' E
  13.   /* Your implementation of fputc(). */" \- ~* b: p; s
  14.   HAL_UART_Transmit( &huart3, ( uint8_t* )&ch, 1, 0xFFFF );6 w. R% G& U5 n7 h* d! V2 U2 b
  15.   return ch;" f7 N- d. q: l8 Y2 B; U
  16. }
    2 v0 f& Z" q  |  B
  17. int ferror(FILE *f)) ^- v% e% y7 E  r- Q0 R7 m
  18. {
    7 x3 Q- m  ]8 R4 S9 b
  19.   /* Your implementation of ferror(). */
    : @4 ]! d3 M( y+ L4 @+ I/ e' u
  20.   HAL_UART_Transmit( &huart3, ( uint8_t* )"Printf Error\n", 13, 0xFFFF );// 可选
    # ]1 ]% u) N! g; ~
  21.   return 0;4 [$ f( _! ^! Y9 W2 Y$ [
  22. }
复制代码
5 i2 j- @4 |$ R( o8 j, Z6 p
写个简单的程序试一试:& B& W$ ?3 Q4 u' c0 |& k+ j) K

0 f6 r( I5 r' t6 q
  1. int main(void)
    $ G. e  |* E" U
  2. {
    5 X, I" M" z  R. r  H9 c% o
  3.     MPU_Config();3 Y% q) g8 z* `% A) {
  4.     SCB_EnableICache();
    " T& p7 z$ u* ^' k) v7 c
  5.     SCB_EnableDCache();
    - [: a* P' B+ _8 \" i4 g! m# x( k
  6.     HAL_Init();
      `8 I/ S. Q! j7 E( H6 @0 d: ~
  7.     SystemClock_Config();' Q0 ?6 u7 d5 E- J( M$ Y
  8.     MX_GPIO_Init();* q6 S- n* A; l. i, W8 Q8 Y
  9.     MX_ETH_Init();
    $ \0 j, `6 i! y; h, R8 P1 S
  10.     MX_USART3_UART_Init();& P$ h$ `: v6 K
  11.     /* USER CODE BEGIN 2 */
    & k0 O) V8 T  Q& B8 E
  12.         double d = 1.234;
    6 A  c9 b5 A5 ]9 R+ w
  13.         int i = 60;
    ; }' I2 L& k6 [* _
  14.         char str[] = "Do not be lazy.\n";
      C3 ?" a9 I4 ?' x' `8 ~! U' [" B
  15.         printf("Hello World\n");
    3 w0 k) L1 z, g" R. A+ a
  16.         printf("d = %lf\ni = %d\n", d, i);$ I, _( O+ r2 d
  17.         printf("this is a string : %s", str);
    0 U: i" n' B) V, {% W7 W& B

  18. 8 z2 A" ~! v! g9 b1 m+ y: D
  19.     while (1){}' g+ O: i6 l3 B% ~
  20. }
复制代码
1 E' q- `- b+ b- t
输出结果:: f1 e  c& T- h' Z- w/ L# X, q
20190313212812741.png

5 |* u4 b- |+ w9 B/ o8 }  y; }. }" }  p' c6 [( s; o% ?
可以开始愉快的使用printf()了.
& w/ ~$ ?1 r, O/ N. x- i7 k
( K4 N1 I1 B6 m4 K4 r$ _" W! _- `* [- t. [8 \' \' i

8 s4 b! V# M, u( _
收藏 评论0 发布时间:2021-12-18 17:43

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版