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

【经验分享】STM32H7系列其二

[复制链接]
STMCU小助手 发布时间:2021-12-18 17:43
printf重定向介绍7 g* u" m' O  a, s9 t5 j
在学C语言的时候,会经常用标准库<stdio.h>中printf(), scanf()这两个函数, 来实现数据的输入与输出. 格式化输入输出的功能还是挺强大的, 那已经有了现成的轮子, 就要寻思一下如何进一步在单片机上使用它.
; ^; c9 R$ y. a. ?* p1 A下面是ARM Compiler6文档中对printf的介绍:
( y& k, P" [) k3 T3 R' K: S
  u1 A' K# s+ q8 i# x6 h/ m( YThe printf family consists of _printf(), printf(), _fprintf(), fprintf(), vprintf(), and vfprintf().
3 f5 i8 M+ W; f/ j% r2 ]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.. B( [- K! ?7 W4 G/ p7 V; I; U. C
The standard output functions of the form _printf(…) are equivalent to:
  Z8 }/ ?8 _5 V, v+ Z; U# u" I! sfprintf(& __stdout, …)where __stdout has type __FILE.* g; l8 j0 S  t

, u: C& j- P) T7 G/ `; Y/ L0 |大致是说printf家族有这么些函数<_printf(), printf(), _fprintf(), fprintf(), vprintf(), and vfprintf()>, 这些函数都隐式的使用__FILE<文件流>, 并且只依靠fputc(), ferror()这两个函数.1 p7 R6 z2 a4 y- Q  I) T

6 p+ @: Q' i. I0 }( R: h, U9 GIf 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., y4 _1 }/ ]" Z  E& W; ~. F. k  p( q

0 @$ b- O4 x1 N" Q) Y/ U( q6 u重新定义__FILE, fputc(), ferror(), __stdout, 就可以使用printf()家族的各种函数了.
. P$ v3 U" }$ w% i4 O& Q4 q8 N
( Z+ u: d: [1 m7 Z7 XSTM32中printf重定向
' v0 H5 }* @$ l9 {  O; m
下面是官方给出的重映射模板:
+ h) q% X0 I( R& {9 ?7 v) x' J* K<遇到不会的先看看文档往往能得到最直接的答案>
7 ]4 B! I8 J0 _+ i, X, C% j7 P2 u, f# L; W5 s. P
  1. #include <stdio.h>* F3 c+ M, P7 u* F6 g% _
  2. struct __FILE% \8 v) Q# v9 b2 `) @8 ^
  3. {
    4 c- [( i* g" j6 y3 n
  4.   int handle;7 C; T9 d% O  h1 S% T) F
  5.   /* Whatever you require here. If the only file you are using is */8 k2 ]. |7 h9 U- ~& y9 b
  6.   /* standard output using printf() for debugging, no file handling */( g$ Y3 e# w2 ?  {5 I; B8 H
  7.   /* is required. */
    6 U( y( }; k% O9 y2 ]4 w* D( |
  8. };
    9 f+ g4 q# {) e
  9. /* FILE is typedef’d in stdio.h. */
      {3 Y) B% m* k- C
  10. FILE __stdout;
    * h7 T$ [8 K; h3 q5 m( c/ z6 T
  11. int fputc(int ch, FILE *f)
    ' n  {; L/ }; y$ u
  12. {) u) M3 q* K- e7 L! q& I. k
  13.   /* Your implementation of fputc(). */$ ^# c0 T1 d; M6 V3 j  ?
  14.   return ch;4 c! F1 ^; ^; {, M2 L( f- t# D
  15. }
    1 Q5 O$ w% {  w& J1 B( V
  16. int ferror(FILE *f)
    " M% k+ }4 X* m( m, \9 o
  17. {- ~6 h) l: M$ a" e) w- i+ [
  18.   /* Your implementation of ferror(). */
    8 u! ~; e9 ^# p) [
  19.   return 0;
    + T( e/ |7 z: N) M3 b
  20. }
复制代码

4 Z! H8 t4 i; o0 Q5 n+ \# f. M要将printf()重定向到STM32中的串口, 只需要重新实现 fputc() 函数即可, 在fputc()中通过串口发送一个char. 在上一次的工程上进行修改, 将printf()重定向到串口3.9 B4 v9 z0 s# p! [( U2 B9 b
) ^3 v) i: x$ `: P
  1. #include <stdio.h>- I) L& E2 T$ V1 ]9 n4 W
  2. struct __FILE; g" T4 l& u$ T5 \
  3. {+ W5 o- v2 s& j/ C3 W7 q
  4.   int handle;
    . T* M, U: s4 M$ Z8 f/ i' e' g
  5.   /* Whatever you require here. If the only file you are using is */6 v$ j! `6 |1 j2 B: b# v
  6.   /* standard output using printf() for debugging, no file handling */3 s$ z8 \9 v$ V8 S6 q# q! ^! ~
  7.   /* is required. */$ [) v7 q- m+ C' [+ K
  8. };/ [- t2 m( @( H4 }6 R4 a
  9. /* FILE is typedef’d in stdio.h. */- L' X" b) c( F' t
  10. FILE __stdout;
    ; s3 T" i% [  c8 j+ A& j: W( n
  11. int fputc(int ch, FILE *f) / ?1 l8 E0 W) t/ t) ?6 M
  12. {
    * b% |' S/ [( p& H8 [
  13.   /* Your implementation of fputc(). */
    : p1 N4 \) E6 U* k" x, ^
  14.   HAL_UART_Transmit( &huart3, ( uint8_t* )&ch, 1, 0xFFFF );/ P3 @7 `1 J. \% |) P
  15.   return ch;
    6 u- b( v0 o8 S% D
  16. }
    - W% A# a, r% @. [
  17. int ferror(FILE *f)
    1 B# u' v0 A+ B; G0 y9 d
  18. {
    1 r1 P+ U* y- r0 }
  19.   /* Your implementation of ferror(). */6 \* M. L7 q! z1 j' A5 A! A4 s
  20.   HAL_UART_Transmit( &huart3, ( uint8_t* )"Printf Error\n", 13, 0xFFFF );// 可选
    ( t0 a) T0 G6 k7 v; y6 e/ a" C: p
  21.   return 0;
    ; ]2 e" m+ E, Q/ b
  22. }
复制代码

5 J) e! m0 m1 Y1 [2 n& z1 p写个简单的程序试一试:
3 c& h' N2 L6 [2 S# Z9 f( A( ^8 z. V4 Z# M  w
  1. int main(void)
    * F. S$ f4 G6 a3 Z+ R
  2. {
    . J6 u9 G0 l0 T
  3.     MPU_Config();
    0 |& C  P3 J4 I, w9 B% K: U% ~
  4.     SCB_EnableICache();
    9 K0 T( f2 U1 o' W8 G3 m/ h$ k9 K
  5.     SCB_EnableDCache();' }) w3 a9 Z& u# Q2 c' E8 @" d2 j
  6.     HAL_Init();1 @- W; b6 v9 m8 Q* r
  7.     SystemClock_Config();3 R3 m$ Y8 @2 b, p+ q. F
  8.     MX_GPIO_Init();; f! O4 }6 G# m9 u% j
  9.     MX_ETH_Init();; [- z7 `5 ]/ |* C+ {0 M' @
  10.     MX_USART3_UART_Init();
    * c1 ?$ q; o; D/ r7 M! V- w5 d9 C
  11.     /* USER CODE BEGIN 2 */  C6 r1 {5 h" t: b
  12.         double d = 1.234;
    * x+ m/ r2 J9 ^6 v% ^; r
  13.         int i = 60;
      Q, R- A* e) U4 g# k$ Z
  14.         char str[] = "Do not be lazy.\n";
    % C# q3 a" I. {2 @: Y& z
  15.         printf("Hello World\n");
    , ], I# u5 [' P4 D( }0 e4 B
  16.         printf("d = %lf\ni = %d\n", d, i);1 S/ M6 k/ g; p4 c3 o# M3 l8 [  z4 T
  17.         printf("this is a string : %s", str);
    9 R# b5 v- p& V, A, v

  18. ' k- x% C4 D) B& B
  19.     while (1){}6 E, l1 \/ Q& n8 k- z( h7 z3 s) P6 p
  20. }
复制代码

1 }: l8 F! Y7 M输出结果:
% s  C7 G6 z, c) T
20190313212812741.png
0 u! k  M9 g' q2 h1 {& D4 G$ c

" y# d- R0 L2 C5 f+ X  _可以开始愉快的使用printf()了.
* }3 D4 y& C6 ~% v, p4 j. C2 x3 _5 n
) g7 @+ Q9 k1 x# X0 q5 s& m) d

& c3 b/ i7 ]/ j. F/ P
收藏 评论0 发布时间:2021-12-18 17:43

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版