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

【经验分享】STM32 UART收发-中断方式接收-重定向printf函数

[复制链接]
STMCU小助手 发布时间:2022-4-12 10:00
环境:2 N- `) d/ `1 e% t
1、STM32CubeMX 5.3
: `* i" Y3 ^4 C' }; P' z! t7 {2、Atollic TrueSTUDIO for STM32 9.3.0
6 V3 W0 O1 i% g7 B4 R* @, t3、战舰迷你板(stm32f103rb)

( G, o) w4 x* Q& ~6 S* w& Q# P9 S( L5 M
(一)配置串口, j( u8 h& Y/ ]  X3 G4 l
波特率:115200& T2 `( [: M. ~$ o7 X! o2 K6 `
数据长度:8bit
/ M0 K6 ~+ G/ U0 d. F3 o2 V6 ?停止位:1位+ }( J1 k' A$ C& O- r
校验位:无
# A% B% m! q6 b! `& B
4 Z% K- D0 m  T" k
0{CJ5]DZVE1SQVJQX3`1F@5.png
  O0 {: D% R7 Q
6 O5 q+ ~* }# _1 w(二)配置串口接收中断

* D/ M0 L, Q) `1 G/ S, H设置中断分组为第二组,使能串口中断,串口中断优先级设置成主优先级3,次优先级0:
+ t! i, f; |/ H& r( Q6 \1 m8 t+ Q4 D1 l
6F{DR2XXAH_GHB~YD(PCZZA.png
0 y6 E9 O5 v4 c2 t9 K% x: V7 j# R$ J2 \8 ]( W, X6 H
(三)修改代码

3 y7 Y4 q' N1 m" Y! W在函数MX_USART1_UART_Init中添加如下代码,使能串口中断:0 ?) w/ s; ~& Z3 R7 l# ~1 L- I

% y' y/ P8 }& x2 w. g1 b& d
  1. HAL_UART_Receive_IT(&huart1, RecvBuffer, 1);                // 使能接收中断
复制代码
* ~, W) B! b' V! n1 N2 d# |9 K+ F
然后覆写接收中断回调函数:- P8 |0 z# Q! o  ]$ a, a, t  y
! t; v4 X% I% u0 n4 V' G: q
  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    ; }! X! |( z8 L6 v$ N
  2. {
    : B0 f( H+ b% U( C$ x/ `$ F
  3.         if (huart->Instance == huart1.Instance)( H. M8 S6 Y  v5 i; n
  4.         {: U% L4 [- e) n
  5.                 HAL_UART_Transmit(&huart1, RecvBuffer, 1, 0xFFFF);                // 将收到的数据在发回去
    / Q; r$ F) Y0 a
  6.                 HAL_UART_Receive_IT(&huart1, RecvBuffer, 1);                        // 再次使能接收中断4 P/ \+ y% h: V4 Q" G7 x. D
  7.         }# C7 @0 P* l, b! O) u, h% c( d
  8. }
复制代码

) j7 J' y$ ?$ U: T4 s; D) I然后添加如下代码重定向printf函数:- p1 E4 r5 ~" O# C' Y

8 G: n4 U. k( z0 B
  1. #ifdef __GNUC__, T/ z: ?- D: x! c9 K
  2. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)( {/ |6 R$ I. T
  3. #else) q& L. A( t, O1 `% v
  4. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)# j* r% h& q3 @
  5. #endif; C) [8 T' T- b  W! F2 I
  6. PUTCHAR_PROTOTYPE
    5 Y/ Z. e: A; h, H/ O4 s2 M: L& u
  7. {8 i5 E: c, D6 @. D! o) y8 u/ H8 f  R
  8.         HAL_UART_Transmit(&huart1, (uint8_t *) &ch, 1, 100);
    # c1 |: ~7 [& y4 y4 U3 ^
  9.         return ch;! |9 G2 {( u9 j( g4 `. ^" o8 W
  10. }! K* n8 R# f/ i1 w  R  B6 Z' m
复制代码

) j" Y. Z- a* F' r: D. h0 K效果如下图:: L" l3 u- V6 t' S

% O* l$ E6 I; g* e/ e @LBDZDCKVOQRN}7Y7NR[$K1.png
- \! B4 [; T+ E5 t" j
6 Z( y  z! w* Q9 q5 S% k( f1 B3 f(四)使printf函数可以打印浮点数
+ A4 R% L- Q4 V9 G, A项目->属性:
6 p" M- O5 d7 R2 g- k
) S' x1 T) _% R0 Y; I0 \4 k
20191018092753343.png " g3 [4 a' N/ u8 h
# Q3 d( {* Q3 B. [: i
(五)重新实现printf函数! @9 Z7 a# R# K5 V2 Z
  1. void debug_printf(const void* fmt, ...)! P% Z6 H/ ~$ m4 I6 q, b
  2. {
    / v6 U$ ?" p) o7 A+ s5 R" j: B7 I
  3.         static char buf[1024];% q2 g/ R& S& s# U% H
  4.     va_list ap;
    " B* }! ], m" T7 a1 B% F
  5.     va_start(ap, fmt);' g4 ?8 N! ]  v/ F. J' C- Z; c
  6.     vsprintf(buf, (char *)fmt, ap);
    ; A4 V* T" c  f( U- L, ^& ^" I; \
  7.     va_end(ap);
    ; [5 p8 c  P. G1 u$ ?5 c
  8.     HAL_UART_Transmit(&huart1, (uint8_t *)buf, strlen(buf), 100);: ?6 P4 E0 ?. F# q
  9. }
复制代码
. y' \) K3 ~+ E2 m+ g, J* J
(六)串口接收与处理
5 H! B! `9 }' T8 Q$ T
  1. #define UART1_RX_LEN 0xFF                                 // 串口一次接受数据的最大长度
    3 Q% ~1 P5 M5 q0 ]% M  e% Z
  2. uint8_t UART1_RX_BUF[UART1_RX_LEN];                // 串口接收缓存
    3 J, C# j5 ^- a- j, y) s+ I
  3. uint8_t UART1_RX_BYTE = 0;                                // 串口中断接收一个字节
    ' @2 M( J$ K" W2 T% r, a
  4. uint16_t UART1_RX_STA = 0;                                // 串口接受状态,第15位表示接收到了换行符,第14为表示接收到了回车符,第0~7位表示本次接收到的数据长度
复制代码
  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)( [5 ]+ Q9 b. U) }1 G' ^/ H
  2. {% ^  U2 B- v) |) X2 L; G* c) T
  3.         if (huart->Instance == huart1.Instance)0 q* ?' s1 j+ o8 t% g5 Q  J2 ]
  4.         {! D7 q: N/ h# L
  5.                 if ((UART1_RX_STA & 0x8000) == 0)                        // 接收未完毕
    , X6 k& u" C, X
  6.                 {4 L- H; k$ l2 |( z* h) b; m5 U0 m
  7.                         if (UART1_RX_STA & 0x4000)                                // 接收到了回车符, H# [5 |) W# H. g
  8.                         {% \9 M( b/ d& Z0 r$ D3 H5 F
  9.                                 if (UART1_RX_BYTE == '\n')                        // 本次接受到的是换行符9 ?; m& Z$ t5 v( E8 F" w
  10.                                         UART1_RX_STA |= 0x8000;                        // 标记接收结束) E! H9 b) m5 s# a
  11.                                 else3 V" ]/ i- {& e3 o/ _7 T
  12.                                         UART1_RX_STA = 0;                                // 否则接收错误,状态置为初始
    / r( g8 F% x- v; w
  13.                         }
    ) ~8 _! }. y; P- _$ \# }
  14.                         else" [0 s1 _8 K% |, J/ o4 W8 d3 D+ F9 @
  15.                         {
    - l+ N* i/ n9 j9 d
  16.                                 if (UART1_RX_BYTE == '\r')                        // 本次接收到的是回车符2 w& A$ E& l% b  r
  17.                                         UART1_RX_STA |= 0x4000;                        // 标记接收到了回车符
    * O) B2 S4 V4 B) a% r4 ~
  18.                                 else
    6 k. c5 Q' ~& c$ i' Q( r3 N, Y
  19.                                 {: v) d& W2 d; W$ \
  20.                                         UART1_RX_BUF[UART1_RX_STA & 0x3FFF] = UART1_RX_BYTE;        // 本次接收到的是数据! T: s0 @5 Z8 e3 N
  21.                                         if (UART1_RX_STA++ >= UART1_RX_LEN)                                                // 连续接收到的数据高于最大接收长度,则视为接收错误7 I$ q; o, l0 X. r4 w
  22.                                                 UART1_RX_STA = 0;                                                                        // 状态置为初始' H2 t' W% q! ~+ k+ G5 E
  23.                                 }
    " E0 R* G6 f: u* J- z
  24.                         }
    % t* K( }) u0 H6 B* \2 H' J
  25.                 }& L+ [4 l6 G# o% v3 M
  26.                 HAL_UART_Receive_IT(&huart1, &UART1_RX_BYTE, 1);                                        // 再次使能接收中断& w# m' [4 H: Z6 d
  27.         }0 u: r' |* k3 [. `' v5 h
  28. }
    ( v# d6 q8 v2 `' Y( \, p, s1 |
  29. . t0 |; w# e1 W' h5 a  q* e: n
  30. /**0 n: Y2 O9 `# {
  31. * 串口1接收处理函数
    8 i7 i$ {' r6 ]3 c% A
  32. */
    " T5 U8 p, L) `% Y; h) A
  33. void UART1_RecvHandler(void)7 o1 T% W9 B$ Q- d2 e
  34. {) S8 E/ Q( s! ~: y& h  l
  35.         if (UART1_RX_STA & 0x8000)                                                        // 有数据收到
    9 _4 n( v- b* @, @0 Y
  36.         {
    & o- A  O8 N5 g1 b! X4 j
  37.                 UART1_RX_BUF[UART1_RX_STA & 0x3FFF] = '\0';                // 添加结束符& z. h. i9 W* o# z6 s
  38.                 printf("%s\r\n", UART1_RX_BUF);                                        // 串口打印出来. u. L; d5 t' _9 J$ j: q
  39.                 UART1_RX_STA = 0;                                                                // 状态置为初始2 I7 o2 ]! v1 W! d% a
  40.         }
    % I1 }4 v) @; |6 ]/ S6 a
  41. }
复制代码
# G) G1 j- ~) }! o- ~# u, y
ends…
% U6 o! {4 I% Q- \( |6 Z3 g0 p6 w  I! K/ a) o
% G) v6 V& O, B, w3 W
赞 收藏 评论0 发布时间:2022-4-12 10:00

举报

0个回答

所属标签

相似技术帖

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