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

如何使用CubeMX实现STM32的串口通信以及对printf等函数的重定向

[复制链接]
攻城狮Melo 发布时间:2024-6-15 13:03
串口UART,作为基础的一种通信协议应该是我们接触的最早的通信协议,有许多芯片和模块可以利用串口来进行通信。
: {( V6 D) d; k, u& c, E本期我们介绍如何使用CubeMX实现STM32的串口通信以及对printf等函数的重定向。% K* c9 Q5 P9 G: ^3 E
% n+ l* A6 u, u3 C) U* P1 L
微信图片_20240615130239.png / E9 c, n1 g# [

- k  O( @2 _: D- A$ C2 V$ n: t, }$ F* n* h" ?
微信图片_20240615130232.png
" }) g9 \! E8 b* R+ x
+ y" H' _; K! S) n, U首先打开CubeMX,配置时钟树和时钟源。
% ~' @( p5 V6 N8 _, }. }+ \: X
5 \7 ?1 W8 t8 v/ r' s" e, u 微信图片_20240615130228.png
3 w* n& e. B. S) M/ t- A( g; o" m

- a+ d5 x& r9 Y1 i" ^" H接着配置我们的串口,设置相对应的波特率。2 l6 _  H9 g5 F, B0 W8 ^7 `4 C

4 W- m. \5 g" S, M: ~ 微信图片_20240615130224.png $ I9 \5 X  C9 u* t
7 l+ O4 E8 v( N3 N
打开串口的中断。- L) Z5 W3 ?, q& ~* B* b

5 n" u& H; m2 ^3 o( ]
然后创建工程。
2 C# a( F  d/ P4 q& _# u7 H7 O# ?& d9 W- r
微信图片_20240615130221.png
, H! K* d+ a1 [

+ @* e4 U! F$ ~在魔术棒中勾选Use MicroLIB4 M. F' W' z# p; z% ]
  1. unsigned char ReciveBuffer;
复制代码
$ X' J2 t: l4 a6 D" Q; Q
在全局定义一个缓存用以存储中断接收到的数据。
6 `+ ~! H7 u  v% c. Q: i2 V' q
  1. HAL_UART_Receive_IT(&huart1,&ReciveBuffer,sizeof(ReciveBuffer));
复制代码
" Z2 p: I4 z( ~2 g0 Y  a2 P2 |3 Y
初始化的时候需要启动串口中断。- \% B5 v' G; }; @3 a6 O
  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    - K6 N: d' L. B
  2. {
    * |" M+ }( K1 M
  3.     if (huart->Instance == USART1)  // 判断是哪个UART触发了中断
    % g# i: r2 E. s3 t& f3 U4 C
  4.     {8 d6 ?+ V% }5 ?2 I1 p6 E* y
  5.         // 处理接收到的数据
    ; H7 x; i+ M8 o7 j! I9 g! U
  6.         HAL_UART_Transmit(&huart1,&ReciveBuffer,sizeof(ReciveBuffer),0);//将接收到的数据发送出去: z: Y3 ?/ i( E& D# P0 b6 S3 l
  7.         // 可以再次启动中断接收. {/ N5 F$ X. H3 i$ W3 V
  8.         HAL_UART_Receive_IT(huart, &ReciveBuffer, sizeof(ReciveBuffer));
    % J$ ]( W2 x' a* p0 b$ _
  9.     }% [/ A! u8 C6 p" I; |6 Z9 c* f- u  E
  10. }
复制代码
) S" f4 m! [8 I' W% p
接着编写串口的中断回调函数,我们将接收到的数据发送回PC机。% \0 W9 B! M  p

& {& a' J, K0 I' C* r 微信图片_20240615130217.png 6 L1 X# }/ g% r# i( t
' w* F& o+ j0 Y+ r
可以看到,我们发送的数据被原原本本的发送回来了。0 p: e; o$ Y8 O

4 h, G: X; D  F4 Z
串口的重定向

  E" @9 n, {- `9 c重定向在计算机科学中是一个常见概念,特别是在操作系统和编程语言中。在C语言中,标准输入输出库(stdio.h)提供了标准的输入输出流,如 stdin, stdout, 和 stderr。这些流默认连接到键盘和显示屏(或者命令行控制台),但是C语言也提供了机制来重定向这些流到其他的输入输出源,比如文件、管道或者其他设备。, R6 a% k+ `( _' G0 f8 G5 T0 U
+ V; L) d9 B! V: r0 }$ E) I
串口的重定向可以非常方便的让我们解决发送的格式问题,可以看到,其实使用HAL_UART_Transmit发送文本是比较麻烦的,C语言的标准库中有printf函数可以方便的让我们实现指定格式的发送,那么如何将printf函数和串口结合到一起呢?. [( F' [5 r) s5 T' x( G* f' d
  1. #include <stdio.h>
复制代码

1 p- l' t8 P' ]. Q* [+ S我们首先需要导入C语言标准输入输出库,这样子我们就可以使用printf函数了。
% k. a. F& Z/ E# ~, B  y1 p; q
1 U# g) x; O- y" p2 U! U
通过重写 fputc 函数,可以控制 printf 函数的输出,因为 printf 最终会调用 fputc 来逐个字符地写入输出。通过将这些字符发送到串口,实现了将标准输出重定向到串口的目的。
) S* p* ]! N$ a
  1. int fputc(int ch, FILE *f) {) E2 s6 f" `6 r4 u4 u; C5 t
  2.     // 发送单个字符3 K5 u2 b3 w7 d
  3.     HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
    ' M4 m5 |; o1 e  \  e
  4.    
    $ j+ i3 f' I# |, f3 x7 O
  5.     // 返回发送的字符
    3 z' S6 T# u; z
  6.     return ch;
    : s  ^2 S9 _2 P2 m, P0 e
  7. }
复制代码
  1. while (1)# c* d0 b6 @. g) }. {  v
  2.   {
    6 w+ |* [: U7 w3 ^) @9 J. Y% ?
  3.     /* USER CODE END WHILE */
    - l5 M6 G+ M# p6 R
  4.     printf("Hello\r\n");* P; C3 f+ A8 h. y, F! r
  5.     /* USER CODE BEGIN 3 */1 R5 t' k1 Z: q
  6.   }  g4 I) v; u% w0 a" C8 G
  7.   /* USER CODE END 3 */
复制代码

) o6 R, g5 z, |: w2 Q 微信图片_20240615130212.png 4 l; e% U, T+ B8 b

3 U3 \8 l4 D+ I7 K' z

+ K' |/ ]& O" q9 B正弦波; F" F9 e; C: W. A( m. m1 a$ M
  1. while (1)
    ( ~: e: ]4 f. `! W
  2.   {& n: D7 R7 N. v* U7 P( ^
  3.     float t = 0;0 N$ O/ |: F; U( C3 F
  4.     /* USER CODE END WHILE */
    4 _" Z  x1 `/ o4 r' v3 I
  5.     printf("A:%lf\r\n",sin(t));//正弦波4 C6 @+ h3 U/ z7 {" E
  6.     t+=0.01;
    * V* j* ^" z6 e. `- @
  7.     /* USER CODE BEGIN 3 */
    2 k* g% Y* d+ H. H
  8.   }
复制代码

7 s+ I; N" A* C 微信图片_20240615130207.png
1 \1 K3 p& l6 E7 }2 u: b& i& j4 X1 P# S) V

0 k* Y  a/ C" N! y/ d' m: ^& Y正弦波相加
# B; L) H3 B8 K7 i' T# p% b9 E
  1. while (1)
    9 C, ^& T. o# j6 z' {' N8 u$ z
  2.   {
    1 F, r$ R+ N7 b2 `5 M, V' d
  3.     static float t = 0;
    # E9 A* Q+ s3 G- x* p8 b
  4.     /* USER CODE END WHILE */
    2 J6 R1 V( p+ }2 Q. Y/ N
  5.     printf("A:%lf\r\n",sin(t)+sin(10*t));//正弦波相加
    ; R) p' Z4 L) ^4 G9 N
  6.     t+=0.01;8 q' w4 ?- B& W
  7.     /* USER CODE BEGIN 3 */
    & g: `8 y9 T- f# z2 A
  8.   }
复制代码
- ~- I9 a( H% q4 w( s, b
微信图片_20240615130159.png ( S' R+ _+ U& P" x

8 n& ?# A6 }$ {1 ?/ w& ?3 Z8 N- B: r+ E7 q+ i
正弦波相乘) W- |0 ]: R8 M% c& b/ |
  1. while (1)
    ' Z" X$ ~2 W$ G0 m* ?/ `, d
  2.   {. F5 N, y/ U+ z
  3.     static float t = 0;& B5 M6 o# N7 M/ I! k
  4.     /* USER CODE END WHILE */
    + U/ V6 \6 q6 `! f7 K
  5.     printf("A:%lf\r\n",sin(t)*sin(100*t));; e0 _0 N* _( Q0 Z4 _, u/ U
  6.     t+=0.001;
    9 z  A. X! {9 }: |' w: `4 B
  7.     /* USER CODE BEGIN 3 */
    , @  k2 [% O* S( p" P
  8.   }
复制代码
1 g& _8 ~6 A( c( t& t# b' M4 T8 [+ k
微信图片_20240615130130.png
9 P2 F! F" S! s% J4 u: {1 V( t( u/ R9 b
转载自: 电路小白3 t/ a" @% b) D  {0 h

. L/ p  m2 G; O- {: J如有侵权请联系删除4 S5 b! i" P$ f

+ E) {1 X' ]2 |+ B0 A( J# J
4 @4 }+ E$ T# W
5 v" N! L& k$ h& z
# j1 n8 m3 G# D9 M( ^7 ?7 S2 l0 E6 m/ J6 _: g2 G

6 p* M% c6 c; P2 _/ n7 ~
收藏 评论0 发布时间:2024-6-15 13:03

举报

0个回答

所属标签

相似技术帖

官网相关资源

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