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

【经验分享】STM32H7系列其二

[复制链接]
STMCU小助手 发布时间:2021-12-18 17:43
printf重定向介绍
: M: I0 ]" _* k( B+ b( p( Q在学C语言的时候,会经常用标准库<stdio.h>中printf(), scanf()这两个函数, 来实现数据的输入与输出. 格式化输入输出的功能还是挺强大的, 那已经有了现成的轮子, 就要寻思一下如何进一步在单片机上使用它.6 y( ^# n& |8 k; F# h, L
下面是ARM Compiler6文档中对printf的介绍:4 x4 g9 k7 S2 A% u8 @6 x

# p( u& V+ W9 \& U* R/ PThe printf family consists of _printf(), printf(), _fprintf(), fprintf(), vprintf(), and vfprintf().0 M# i( ^6 A- c
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.
. x7 k; |5 Q. s- MThe standard output functions of the form _printf(…) are equivalent to:  E0 A" g% f; |, D
fprintf(& __stdout, …)where __stdout has type __FILE.& f7 G) K$ Q+ U# j6 e

& r, N3 P: C% k  K& j/ g大致是说printf家族有这么些函数<_printf(), printf(), _fprintf(), fprintf(), vprintf(), and vfprintf()>, 这些函数都隐式的使用__FILE<文件流>, 并且只依靠fputc(), ferror()这两个函数.
/ \$ ~  ^! o3 B4 s/ n0 Q7 R/ k& s$ y( Z/ h$ @. N4 O2 V3 c
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.
( o; y  `# f1 w9 Z3 Q4 ]
4 x' }* ]1 f  Q重新定义__FILE, fputc(), ferror(), __stdout, 就可以使用printf()家族的各种函数了.
4 z  K3 C/ t* S9 O& Z+ ?2 S4 W: a
STM32中printf重定向

  f2 _3 t. U, O6 P% J下面是官方给出的重映射模板:" |- D3 X0 Y2 W$ ^. C. x# ^4 n
<遇到不会的先看看文档往往能得到最直接的答案>/ ^, Z6 a' O4 y
+ I, ~. P2 N6 D; k! u
  1. #include <stdio.h>, d6 a$ }! P' [( b# s
  2. struct __FILE
    ' I; O8 @3 a$ [+ @# E8 G
  3. {
    & }2 V  ~) g3 ~
  4.   int handle;
    6 O7 i; S' @/ q9 ]# u$ d- B
  5.   /* Whatever you require here. If the only file you are using is */$ `- _/ k' H+ A+ e  _+ p8 ]
  6.   /* standard output using printf() for debugging, no file handling */& t1 m' o3 F6 J" [' z0 q3 F; ]1 s
  7.   /* is required. */
    , G# n# t9 ]; c4 U1 K6 g
  8. };
    % k7 C- D1 I$ D% g' E
  9. /* FILE is typedef’d in stdio.h. */
    * \* m' v8 n) |. \* B
  10. FILE __stdout;! ?# ^1 q  [5 I
  11. int fputc(int ch, FILE *f) : B4 {9 E/ Y1 d7 w. w8 R3 ?7 W
  12. {
    % T8 ~: q/ U3 P
  13.   /* Your implementation of fputc(). */
    ' C  F5 y6 Y% p
  14.   return ch;
    , V7 W$ ]& V9 G1 n, t
  15. }. s" k: k. v- y0 w2 @( J
  16. int ferror(FILE *f)2 J' n: y/ w3 \7 k, y' B0 C
  17. {- Z3 h6 `6 q' M/ m% g8 \
  18.   /* Your implementation of ferror(). */! ?- V1 n. j. u  s  Q/ a) K
  19.   return 0;
    8 j3 R  x. ?0 Y  E% ^2 J; q" J
  20. }
复制代码

# T9 f# u" _3 {( K/ l- R要将printf()重定向到STM32中的串口, 只需要重新实现 fputc() 函数即可, 在fputc()中通过串口发送一个char. 在上一次的工程上进行修改, 将printf()重定向到串口3.
' A& o2 C# i1 a, E3 d% Z8 p! a7 ~5 f
  1. #include <stdio.h>
    % U+ y  O) p1 o! X8 R. l
  2. struct __FILE
    3 y. f8 K5 I( B/ }6 f
  3. {$ ~8 D: v, C- o" X* Y5 o
  4.   int handle;3 q  B9 T8 Y2 K! c# Y
  5.   /* Whatever you require here. If the only file you are using is */
    8 G- w) ]! p. R1 X" f
  6.   /* standard output using printf() for debugging, no file handling */
    * G/ B, {! v! d4 i
  7.   /* is required. */5 y( K* \7 Y$ g1 i
  8. };
    8 U7 j5 F9 ?% M* n8 y
  9. /* FILE is typedef’d in stdio.h. */8 r# D7 S; D/ s' ]% N$ g
  10. FILE __stdout;
    / o1 h0 K, p+ f8 _
  11. int fputc(int ch, FILE *f)
    ( l# s) K# H1 K, a9 w7 G0 h/ {
  12. {
    5 d4 g# ~9 J- a& S8 ^9 |* H/ h
  13.   /* Your implementation of fputc(). */
    . b# u' @/ t& A$ Z/ ?/ l. r
  14.   HAL_UART_Transmit( &huart3, ( uint8_t* )&ch, 1, 0xFFFF );
    # G. Y0 F! b, j# T
  15.   return ch;
    $ Y, ]# b8 ^" {. [4 E
  16. }. ]9 Y4 n5 }8 Z" X
  17. int ferror(FILE *f)* x8 ?3 L& c$ X4 G3 \! C- X
  18. {  ?! {8 q) I+ q: ]7 H' G
  19.   /* Your implementation of ferror(). */0 \( M: v+ s. D. x% m
  20.   HAL_UART_Transmit( &huart3, ( uint8_t* )"Printf Error\n", 13, 0xFFFF );// 可选. @) A( H' s; c9 H
  21.   return 0;! o5 D2 T$ `0 y' q! ~! l# {+ T
  22. }
复制代码
# A9 d6 [/ v  H, G! k
写个简单的程序试一试:
$ W* i0 v0 |! G3 Q9 O+ y9 P6 ?" ^9 V" u* f8 A2 Q
  1. int main(void)
    7 t1 q# E  ~' f; c; \/ _! q; L7 c
  2. {
    % j5 J, n+ S- g8 k
  3.     MPU_Config();
    ; C* m- a0 X, w+ p
  4.     SCB_EnableICache();  e) `5 ]* M6 H; Y
  5.     SCB_EnableDCache();. C5 H- u6 E0 _  E
  6.     HAL_Init();8 a4 |+ {1 b& F9 p( H
  7.     SystemClock_Config();) y- A9 d" e# D% K) H  \3 g
  8.     MX_GPIO_Init();
    ! P& w4 }) N5 g% h
  9.     MX_ETH_Init();6 H. o% D- E7 \  }* {  @- n' P9 W4 n
  10.     MX_USART3_UART_Init();
    1 M: r: m) P0 x) ]: A/ _$ Y& \' o6 }
  11.     /* USER CODE BEGIN 2 */! H& K$ h" J- O8 W2 ]
  12.         double d = 1.234;
    7 C/ [7 E" s: L; v: x
  13.         int i = 60;
    # A! I! C+ Y6 H& N( _
  14.         char str[] = "Do not be lazy.\n";! }' A& w5 H0 U
  15.         printf("Hello World\n");
    - B! v: |9 w' v! Y
  16.         printf("d = %lf\ni = %d\n", d, i);
    - U1 P* _9 Y7 W! }& Q0 d
  17.         printf("this is a string : %s", str);# \! l" r( d7 o  _  H2 K* o) n

  18. 6 x* q3 m5 h0 l
  19.     while (1){}
    ' `% X: q8 p, r0 g  N! _. I7 S5 C
  20. }
复制代码
+ [! d9 S$ L- t/ t- l) |  i0 t
输出结果:% ~: p4 {7 d) f' c
20190313212812741.png

. l/ c! ^" A4 D' c3 a0 o1 u4 W3 ?4 O" V) w8 `
可以开始愉快的使用printf()了.
% E) }& k+ b. D* A" A9 t2 G, r# R4 Y$ Z2 R# R' [. F" W

' K  f3 a- T! L# r& b/ e- G% Q
' f) h5 r+ G5 Y2 K/ G- t( d
收藏 评论0 发布时间:2021-12-18 17:43

举报

0个回答

所属标签

相似分享

官网相关资源

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