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

【经验分享】STM32H7系列其二

[复制链接]
STMCU小助手 发布时间:2021-12-18 17:43
printf重定向介绍$ m  o: x- p6 O7 I' P# Q- u( S
在学C语言的时候,会经常用标准库<stdio.h>中printf(), scanf()这两个函数, 来实现数据的输入与输出. 格式化输入输出的功能还是挺强大的, 那已经有了现成的轮子, 就要寻思一下如何进一步在单片机上使用它.) u8 G6 P' K' N; q4 V
下面是ARM Compiler6文档中对printf的介绍:
0 e, u: ^. I  G1 ]5 h1 w) R9 X3 ~
3 B/ i* z3 z2 X7 k" @The printf family consists of _printf(), printf(), _fprintf(), fprintf(), vprintf(), and vfprintf().7 L4 u$ b& m; w6 |4 e
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.
2 ^5 v1 W% ~- k, r; vThe standard output functions of the form _printf(…) are equivalent to:, \0 ^1 g+ b8 b. V8 |3 u1 s
fprintf(& __stdout, …)where __stdout has type __FILE.0 W$ K0 D% ]/ A9 \2 I$ x

) o; D/ p$ b. W4 q! @/ Y大致是说printf家族有这么些函数<_printf(), printf(), _fprintf(), fprintf(), vprintf(), and vfprintf()>, 这些函数都隐式的使用__FILE<文件流>, 并且只依靠fputc(), ferror()这两个函数.
: x$ r1 M2 X  o  U9 v0 y7 b) p% K: k- g, i! X4 ?# m
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.
" I& ^1 [# U$ M" c, i( x
0 h6 _# T6 b/ [3 a+ y4 Y重新定义__FILE, fputc(), ferror(), __stdout, 就可以使用printf()家族的各种函数了.1 r) E, D7 h# H( w

* |5 m4 `7 E! ^8 u  `0 g4 mSTM32中printf重定向
, t! H8 Z! n1 r- l6 R
下面是官方给出的重映射模板:9 t6 _; H: I, D
<遇到不会的先看看文档往往能得到最直接的答案>
% S1 u3 y3 C, h& L# L% U5 G! S7 G. {( F6 m
  1. #include <stdio.h>
    9 @8 \7 Z( d6 [; d2 d) I
  2. struct __FILE
    6 ~& Q  C2 A" s# @# a; j6 T9 y
  3. {
    " w4 `6 A( \7 l
  4.   int handle;
      c+ A6 T( a3 f5 r. r
  5.   /* Whatever you require here. If the only file you are using is */
      K2 e0 E' ?/ Z5 I' ]! X
  6.   /* standard output using printf() for debugging, no file handling */! h4 Z# L) a, s4 o. D
  7.   /* is required. */
    . ^1 P6 d0 j; V: l" a3 ^0 L
  8. };* G* f. a- f0 U6 Q3 r1 T
  9. /* FILE is typedef’d in stdio.h. */
    6 y0 t4 l3 ~7 d0 l. e# V
  10. FILE __stdout;+ d8 k- A2 ~" ?* f+ B
  11. int fputc(int ch, FILE *f) ' e8 a  O" ^0 d3 s3 v
  12. {
    , S) X- @4 D$ O' k( j
  13.   /* Your implementation of fputc(). */
    . ]. [* A3 R* S& q( E8 E
  14.   return ch;- U" L: J5 S( ]% m! n8 {
  15. }
    $ ^. H7 [' V1 s; l3 @
  16. int ferror(FILE *f)
    ; F" B6 C6 R' Q8 }! X( M7 w
  17. {
    ( w" h* V& ?+ G! M
  18.   /* Your implementation of ferror(). */5 s  r! g, V7 C4 ^, `, b% H! _
  19.   return 0;
    ' U6 h- ?- p- c$ M
  20. }
复制代码
" B" e9 _6 E4 ~( h1 r
要将printf()重定向到STM32中的串口, 只需要重新实现 fputc() 函数即可, 在fputc()中通过串口发送一个char. 在上一次的工程上进行修改, 将printf()重定向到串口3.
" |& f0 W; F% a; p4 M5 V: Y/ G
& B& E  P, I& [+ E$ H% J0 |9 n2 q
  1. #include <stdio.h>8 \: A0 r% o; q0 ~1 {
  2. struct __FILE
    $ m) |9 T' O5 Y! i+ z( o7 k: O; Q
  3. {: `3 J$ x: N0 X  z$ \0 q- ~
  4.   int handle;& {( Y) n* k, b7 R
  5.   /* Whatever you require here. If the only file you are using is */; ]4 O" T; S& G
  6.   /* standard output using printf() for debugging, no file handling */
    / j/ U1 A* \& G( ?; }; _- Q
  7.   /* is required. */
    , s+ ?' t- C- l6 @
  8. };
    / c  G7 B/ k' u, }9 Z$ {& e2 b$ U
  9. /* FILE is typedef’d in stdio.h. */
    " U7 H7 {% T1 }/ d# x0 X
  10. FILE __stdout;/ k7 w4 F0 N, X- W5 `
  11. int fputc(int ch, FILE *f)
    " E, T5 e4 S" R% u
  12. {
    9 s# ]2 y- c) [+ t4 z
  13.   /* Your implementation of fputc(). */
    ' V! G! P. I# e5 C1 T8 f. y
  14.   HAL_UART_Transmit( &huart3, ( uint8_t* )&ch, 1, 0xFFFF );! {" m! l; w: u
  15.   return ch;( c3 E8 I% o" h8 r3 V
  16. }
    ! d0 |% w* _4 U
  17. int ferror(FILE *f)) I. X) l" _) o0 r7 P! ]7 G
  18. {9 r( A( Y* `; b
  19.   /* Your implementation of ferror(). */
    : T/ }2 W7 V* ?+ f
  20.   HAL_UART_Transmit( &huart3, ( uint8_t* )"Printf Error\n", 13, 0xFFFF );// 可选: h( O& m0 }  M2 M1 t- l8 M
  21.   return 0;
    " v/ T/ U% A, H2 y- ^& E
  22. }
复制代码
$ D7 b, W' M. U  u2 v
写个简单的程序试一试:2 T% T/ H0 S; w$ }. g  z4 d
& u( O$ v2 q5 {" [" ~
  1. int main(void)! L; D6 w' F7 Z6 F  ~5 ]
  2. {
    ) \6 u1 Y# n  X+ C. S# R
  3.     MPU_Config();
    . V* G) a0 T7 i8 e8 Y+ @
  4.     SCB_EnableICache();
    ( m: E: A( V8 c* y5 X
  5.     SCB_EnableDCache();
    . q' M) |9 ?" a. v+ k1 u! z2 z
  6.     HAL_Init();) Y8 |8 C$ u! w# m- {6 S. [  r
  7.     SystemClock_Config();, b5 E7 v6 G0 q; {. P( F& u+ Q, @
  8.     MX_GPIO_Init();
    : O  W! f* [/ a7 L
  9.     MX_ETH_Init();+ u# q/ M0 m) O/ T
  10.     MX_USART3_UART_Init();
    ( e1 {3 a% F5 v4 o7 r( A+ f
  11.     /* USER CODE BEGIN 2 */# A. W) @2 ~1 [5 {. ?
  12.         double d = 1.234;
    6 Q$ F; \# h4 _( T) P8 j5 Y% a
  13.         int i = 60;
    5 W% K+ S$ _# M# ?
  14.         char str[] = "Do not be lazy.\n";5 J0 K$ {) ~+ x  p9 e" t
  15.         printf("Hello World\n");" g/ c' E' h% F3 h; x" N
  16.         printf("d = %lf\ni = %d\n", d, i);* ]) `( t7 @9 ?( F# J0 r5 l1 Q
  17.         printf("this is a string : %s", str);
    ; X8 R! m2 f; Q. {
  18. ' O: u; w/ }* j) |" q9 b+ a2 X! U
  19.     while (1){}! D5 x4 R! I+ v. O
  20. }
复制代码
% ?) {  h# u" W/ @
输出结果:/ ]! m0 U* ]7 C" W1 F# e
20190313212812741.png

+ B  ]2 c8 I; X7 f7 X% b
" M6 D& z1 C. I+ p# X7 d可以开始愉快的使用printf()了.
: h6 a! f. q& q' ~9 j3 Z4 w
, R- q- }; v% N% _8 |+ i2 v. B1 p, K& y
3 f! U9 Q! k$ z0 ?) @. C5 ~
赞 收藏 评论0 发布时间:2021-12-18 17:43

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版