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

【经验分享】STM32H7系列其二

[复制链接]
STMCU小助手 发布时间:2021-12-18 17:43
printf重定向介绍5 |1 l2 k' \" {# J6 W
在学C语言的时候,会经常用标准库<stdio.h>中printf(), scanf()这两个函数, 来实现数据的输入与输出. 格式化输入输出的功能还是挺强大的, 那已经有了现成的轮子, 就要寻思一下如何进一步在单片机上使用它.
6 f' w2 X1 c/ n% \5 m7 c. ^4 ?下面是ARM Compiler6文档中对printf的介绍:$ k! M4 o, m- j( V
, \/ o3 D% S- O  E* j
The printf family consists of _printf(), printf(), _fprintf(), fprintf(), vprintf(), and vfprintf().
" ~: p, j& j% p4 \( h1 ]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.
0 X* W3 H2 j% TThe standard output functions of the form _printf(…) are equivalent to:) E, [7 A/ b% X6 _4 T. O
fprintf(& __stdout, …)where __stdout has type __FILE.- V: F) @. j1 i4 O7 P7 Y
& }4 U" |7 r! m
大致是说printf家族有这么些函数<_printf(), printf(), _fprintf(), fprintf(), vprintf(), and vfprintf()>, 这些函数都隐式的使用__FILE<文件流>, 并且只依靠fputc(), ferror()这两个函数.
! t% J6 L) @0 n: W
( L0 i2 a. \. cIf 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.
  ^% d: i3 E8 C7 O* }
, L! B7 K1 ?  l4 @1 m9 j重新定义__FILE, fputc(), ferror(), __stdout, 就可以使用printf()家族的各种函数了.' t4 \3 U0 L) n& Q

1 H: @0 _$ w. s8 rSTM32中printf重定向

8 S1 {1 B# ?( L+ h* x0 k* Z下面是官方给出的重映射模板:
, _, m8 G3 H# K6 a; }7 U<遇到不会的先看看文档往往能得到最直接的答案>6 d: {. `' g9 w& w. K

6 ]2 n/ h) T; F
  1. #include <stdio.h>6 V4 A$ v0 H6 V5 d7 L
  2. struct __FILE- v3 T  O/ j7 S6 s' p1 {  a+ y1 a/ D2 l' P
  3. {
    . T" B0 y& b+ S" A' }
  4.   int handle;# d, n- w& w9 G* O# ?# c  k
  5.   /* Whatever you require here. If the only file you are using is */
    0 }0 l' i0 y1 o5 a( |! V5 T
  6.   /* standard output using printf() for debugging, no file handling */
    ) E  r6 o( W" U
  7.   /* is required. */
    " P" C+ g; [; Y  w2 B7 E9 b
  8. };3 u, g* u8 y  S
  9. /* FILE is typedef’d in stdio.h. */- i/ o, i2 {) S- N
  10. FILE __stdout;4 d2 W3 ]* O  |# G
  11. int fputc(int ch, FILE *f)   G' e( ^, R7 a
  12. {
    6 d6 O$ r' f  O
  13.   /* Your implementation of fputc(). */5 n8 x2 N- Z1 [$ ~6 K4 l
  14.   return ch;
    8 b9 }2 c6 h( v. k" E+ G9 [
  15. }+ h1 n# M( ]5 A& ~) O; O: i
  16. int ferror(FILE *f)( e; Y, y* E9 o: f! Q" F% f+ H
  17. {+ F: ^6 @! k% S  T. \1 _. b
  18.   /* Your implementation of ferror(). */
    1 z' a  w' i9 C4 P* V- o
  19.   return 0;
    0 ~! ?# j* C6 n$ c/ N+ f
  20. }
复制代码
# ^( u3 R8 K1 z- `
要将printf()重定向到STM32中的串口, 只需要重新实现 fputc() 函数即可, 在fputc()中通过串口发送一个char. 在上一次的工程上进行修改, 将printf()重定向到串口3.! ]* o" G% v+ p% s
6 D! i9 ^( x5 h* ^3 J4 k7 q
  1. #include <stdio.h>
    * f& w8 n0 A5 Q9 [- P/ \
  2. struct __FILE
    3 d/ s2 J6 p) r/ e. i9 A  R
  3. {* g$ v( B8 v# {/ G1 c0 p2 R/ Z
  4.   int handle;
    2 T# X( c9 D, Z. C
  5.   /* Whatever you require here. If the only file you are using is */
    # \( a6 v, t* M/ ?9 ]& l. ~
  6.   /* standard output using printf() for debugging, no file handling */+ Y* M+ P2 W. N- G; }# C: _5 p" L
  7.   /* is required. */& V6 ^5 k( S* G
  8. };% U9 }# d/ x3 g0 A" k% w2 r
  9. /* FILE is typedef’d in stdio.h. */
    # A# h, e$ v  d: j
  10. FILE __stdout;6 I$ W" ^* a/ z9 |0 m
  11. int fputc(int ch, FILE *f) : l6 {% j5 h+ T
  12. {
    ' t! a0 |" O+ g! W4 Q
  13.   /* Your implementation of fputc(). */. W$ m/ I$ T9 R) X* ^2 C
  14.   HAL_UART_Transmit( &huart3, ( uint8_t* )&ch, 1, 0xFFFF );' M& {, H4 v1 y
  15.   return ch;
    ( d9 i8 \- [3 c
  16. }
    + E/ H7 D; A& F8 G
  17. int ferror(FILE *f)
    % ^! J) K/ H2 o
  18. {9 s/ Q1 c- w& y2 G) [
  19.   /* Your implementation of ferror(). */
    , J7 W; G9 d0 N1 g5 r+ k5 Y' G
  20.   HAL_UART_Transmit( &huart3, ( uint8_t* )"Printf Error\n", 13, 0xFFFF );// 可选) O- Q6 |2 S. m: X/ I7 v9 M
  21.   return 0;
    9 t% V( n: ~1 f0 S1 Y) N
  22. }
复制代码
, H( f( u! y; H2 u, p7 F
写个简单的程序试一试:* S- ]3 ~& s  H
- C/ L! r+ s% S8 r- e% l" C# V5 R! t
  1. int main(void)
    % {. _  n# d- O
  2. {
    : G# B; d! z; C& i
  3.     MPU_Config();
    # ?. s8 G2 ]$ w  H
  4.     SCB_EnableICache();) x2 t/ y: {/ a$ d( x$ d5 S
  5.     SCB_EnableDCache();) ], p2 B0 i0 p$ m2 A7 G
  6.     HAL_Init();  `$ z1 _1 P7 ?. R  a- ~
  7.     SystemClock_Config();
    $ r1 C4 h7 G9 r5 t2 P1 X6 b$ s
  8.     MX_GPIO_Init();
    ! ?7 a  o7 ]1 H; K, s- H
  9.     MX_ETH_Init();
    3 @+ u9 c0 f+ s" F& x+ m
  10.     MX_USART3_UART_Init();) P) k+ V. E  k8 A3 M" h% V
  11.     /* USER CODE BEGIN 2 */
    , M% \- E0 x# ^8 b6 k
  12.         double d = 1.234;
    6 {/ L+ `, L  `0 k* n
  13.         int i = 60;
    # }; h8 c$ s# _! b3 P
  14.         char str[] = "Do not be lazy.\n";
    ) p, r& s( R1 W0 v$ C+ I
  15.         printf("Hello World\n");0 _( P* J) R- h$ R# Z7 Z
  16.         printf("d = %lf\ni = %d\n", d, i);& I* d* U8 j" r0 v, ^# e5 A& x
  17.         printf("this is a string : %s", str);+ U" _9 y0 `' G" c+ Q, ^. z
  18. # }2 T$ B$ J. v
  19.     while (1){}
    0 }, \+ d8 h- Y0 P# L
  20. }
复制代码
, \! w, ~7 a  e- K' R1 y
输出结果:- |' z4 E+ I! e# P% C# H+ h" T
20190313212812741.png

6 y0 ]2 |- c0 Y2 ?1 I  _; l
3 _- P! o  D: t) r- Q可以开始愉快的使用printf()了.
& J- A6 F0 M( C% U1 |) y: z+ v
0 M- H% s# ]/ F1 O7 L4 @# y8 i+ t8 e* j% H$ b2 u
3 S1 W) C& [9 X) D' ^
收藏 评论0 发布时间:2021-12-18 17:43

举报

0个回答

所属标签

相似技术帖

官网相关资源

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