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

【经验分享】STM32H7系列其二

[复制链接]
STMCU小助手 发布时间:2021-12-18 17:43
printf重定向介绍
; h% ?3 e$ ]4 {在学C语言的时候,会经常用标准库<stdio.h>中printf(), scanf()这两个函数, 来实现数据的输入与输出. 格式化输入输出的功能还是挺强大的, 那已经有了现成的轮子, 就要寻思一下如何进一步在单片机上使用它.
* `/ H: F4 v' a4 |0 R, U下面是ARM Compiler6文档中对printf的介绍:
* c0 H) S0 ?2 P& C; R2 W. A4 ^! f: N& b: B+ l- T# Q* ~
The printf family consists of _printf(), printf(), _fprintf(), fprintf(), vprintf(), and vfprintf().5 W6 u: t# D  ]: a2 ^* C1 E" b
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." j* u' I7 A- d+ ?
The standard output functions of the form _printf(…) are equivalent to:3 t/ e, U. L2 K4 \+ o
fprintf(& __stdout, …)where __stdout has type __FILE.  p' T- a0 E) C6 {9 N

  m% X7 ]4 A+ J  o大致是说printf家族有这么些函数<_printf(), printf(), _fprintf(), fprintf(), vprintf(), and vfprintf()>, 这些函数都隐式的使用__FILE<文件流>, 并且只依靠fputc(), ferror()这两个函数.
+ ?: t$ x& |$ O/ C5 z9 j/ \2 N; r! g3 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.
4 V5 D# ]& X+ }1 {; c
* Y+ ~4 R! R  Z. ?1 s重新定义__FILE, fputc(), ferror(), __stdout, 就可以使用printf()家族的各种函数了.. k. D% o1 O/ G/ {' Y; t

' {$ e- i# {2 U( P. F% {5 XSTM32中printf重定向
0 U& l0 C( A4 P! ?
下面是官方给出的重映射模板:
: A9 j& T8 C" T2 F1 m  X<遇到不会的先看看文档往往能得到最直接的答案>$ B: E: _# j* f! k6 l% l0 d

* n7 j. ?+ H6 `! D2 V
  1. #include <stdio.h>: U5 T% n. F7 a; |/ i; P7 A
  2. struct __FILE
      D: w7 s2 \1 W
  3. {
    # i8 }7 t* \( ^. c) o% J' o
  4.   int handle;' E7 W5 T* `& R3 ]8 U8 _9 |
  5.   /* Whatever you require here. If the only file you are using is */7 t; A! g* _* A# e% @
  6.   /* standard output using printf() for debugging, no file handling */
    * J- p2 h) ^: u4 a7 l
  7.   /* is required. */6 p  v/ @" d& W: y9 R7 s
  8. };/ G5 v# y& ~0 I5 |8 T* x
  9. /* FILE is typedef’d in stdio.h. */
    - v0 U' _; f. x" `1 m* Y4 m
  10. FILE __stdout;
    / \4 @- D0 T8 j) G* i/ W
  11. int fputc(int ch, FILE *f) ) f' N9 Q6 K( ~5 c6 p6 n
  12. {, B- \5 i. e( u8 [, r* x
  13.   /* Your implementation of fputc(). */# w, h; {* M" A# U
  14.   return ch;
    5 ]- @( ]  x8 P, n& D6 ~
  15. }) p# ~" s1 L  e' K
  16. int ferror(FILE *f)
      B6 Z1 i; i9 T+ }
  17. {4 @+ j- C$ T. X
  18.   /* Your implementation of ferror(). */2 X  D2 n5 o# j2 s6 v
  19.   return 0;3 q; D4 t1 X/ G, v
  20. }
复制代码

* w7 ^! o( Z6 Q要将printf()重定向到STM32中的串口, 只需要重新实现 fputc() 函数即可, 在fputc()中通过串口发送一个char. 在上一次的工程上进行修改, 将printf()重定向到串口3.
2 O; P% l+ l. q7 H2 M1 _2 }
! @) ]! H$ O$ h2 ]% v- u3 V3 X
  1. #include <stdio.h>0 [6 S  l2 p" `& V/ d8 O( K
  2. struct __FILE
    5 j0 ^+ l0 s9 `& Y. m4 Q
  3. {- U$ J4 p9 a8 N+ n' r0 z2 r' _
  4.   int handle;
    " _, C; X- y* R5 w* n$ Z) `- {4 E
  5.   /* Whatever you require here. If the only file you are using is */
    8 S' f; q9 ~* W" o
  6.   /* standard output using printf() for debugging, no file handling */: ]$ P- k* R( s) [
  7.   /* is required. */' [$ o& v0 `$ }% C
  8. };
    ' G( @: ]0 `) C6 ?9 b. C
  9. /* FILE is typedef’d in stdio.h. */
    ' i& G/ u0 P! r, a
  10. FILE __stdout;
    ' @+ b+ A2 ?: o, a' o, L
  11. int fputc(int ch, FILE *f) , J+ ^" r9 g0 R; `) D
  12. {
    # P0 C7 Y7 D: H+ G4 {
  13.   /* Your implementation of fputc(). */; y, U* H6 i6 n+ s! W6 a
  14.   HAL_UART_Transmit( &huart3, ( uint8_t* )&ch, 1, 0xFFFF );$ J/ @, m, h# p# o& `. v
  15.   return ch;
    " S7 L# u$ C+ ^
  16. }
    $ Y5 P( z' Y. Y$ U4 X
  17. int ferror(FILE *f)/ r0 G4 P  S8 l8 P% |8 B
  18. {% W4 E1 }* \, l/ j8 `4 _3 w
  19.   /* Your implementation of ferror(). */
    ) x- H6 G  c$ F4 _2 O9 N
  20.   HAL_UART_Transmit( &huart3, ( uint8_t* )"Printf Error\n", 13, 0xFFFF );// 可选0 T1 S+ c" ~- d
  21.   return 0;
    6 \3 d9 c# h; L5 W
  22. }
复制代码

* _/ N( L8 @' k  s写个简单的程序试一试:
7 g! g' a9 ~/ H+ ^9 C* b" a4 {0 e$ Q) Y* c% U9 W* j& r
  1. int main(void)- g8 o0 ?: y5 J" C
  2. {
    8 X- q# u: j, L/ E& F" G% M" t7 t
  3.     MPU_Config();+ Q, L) a2 Y5 b7 @; ^
  4.     SCB_EnableICache();
    0 i( z4 j0 x& L
  5.     SCB_EnableDCache();
    4 ~# j- a1 P4 C
  6.     HAL_Init();1 P% p  m9 r) p, D" J+ y& B
  7.     SystemClock_Config();
    $ e* o0 G* g* R2 _1 C2 F5 k
  8.     MX_GPIO_Init();
    4 M* r' C& v# M4 X
  9.     MX_ETH_Init();
    ! i. `' u( w6 R) n7 V
  10.     MX_USART3_UART_Init();) q  g9 X5 R) ^- l$ W
  11.     /* USER CODE BEGIN 2 */' Z' x' x4 t- Z2 ?
  12.         double d = 1.234;
    # y! R6 z/ q& \: y# b. `1 q/ D5 A
  13.         int i = 60;1 w' D1 M" F$ @) P
  14.         char str[] = "Do not be lazy.\n";  a; b: j' P, m% T9 D' @8 l
  15.         printf("Hello World\n");' X" S! u, q7 O6 w
  16.         printf("d = %lf\ni = %d\n", d, i);$ t5 B2 `, m5 d( P$ c" D
  17.         printf("this is a string : %s", str);
    8 w' N& z5 I' c$ [. c

  18. ; Q( S- g  C% `7 j$ O' j
  19.     while (1){}
    " N/ r; T- X! y/ e, b  U6 i! S; r3 e
  20. }
复制代码
3 [- J) ^1 D1 s& s0 v8 A( M
输出结果:, a. s* l6 Y# N2 v
20190313212812741.png
( [! e" ^. E* p; r: I+ L

0 h) y% a( z5 l$ t可以开始愉快的使用printf()了.! l( z- u* {  ?
& l2 t& r/ F4 `# U
6 h5 i: I: b. ?# |

# j3 U' D9 m/ C
收藏 评论0 发布时间:2021-12-18 17:43

举报

0个回答

所属标签

相似技术帖

官网相关资源

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