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

【经验分享】STM32CubeMX—串口空闲中断+DMA接收

[复制链接]
STMCU小助手 发布时间:2022-5-16 10:35
一、实验说明  H1 o" f- b3 D' [- ^) ^
实验平台:STM32F103C8T6
. ?6 }: s! ~9 d9 h实验内容:使用串口一空闲中断结合DMA 完成不定长数据接收
( _2 V, i. |6 {7 {% F3 x1 J+ }* N! r$ g9 W# _3 s# _& y
STM32的串口接收数据的方式
0 Y" s" F( A* W+ Z0 S" A1、轮询接收
5 Y. _: c  H1 m% O0 q  所谓轮询,就是在主函数中判断接收完成的标志位。举个不太恰当例子,就比如,此时你正在考试作弊,手机藏在兜里,你的队友再给你发答案,但是你的手机静音,所以你不得不写一会题看一会手机,有的时候答案已经发来了但是你此时在假装写,没有看,导致你没能及时看到答案浪费了时间(仅仅为了举例而已。。。。)。轮询接收数据也是这样。/ W- E- H$ y1 N. G. Z

* Z7 O3 u% B. D6 G2、中断接收
. S5 v, l4 I1 H/ z1 I( o  串口接收配置为中断模式,当有数据收到时,进入到串口接收中断中读取数据。继续上面的例子(你为了不浪费时间且及时抄到答案,你把手机开了震动,消息一来立马看,这是就比上面好多了,能够及时发现消息。但是又出了一个问题,你的猪队友,写一个选择给你发一次,不停的震动,完全扰乱了你的节奏)。其实也就是,串口接收数据时,一次接收一个字节,当数据量较大时,显然这样频繁的进入中断,打断主程序,严重影响系统性能。/ W4 ]/ j# V  A: @9 n2 J
8 p# n, T; y# w" m$ y
3、空闲中断接收

' p6 F- u$ I7 X4 p4 T  空闲中断接收,当一帧数据接收完成之后,串口会进入到空闲中断中去,然后在空闲中断中处理收到的数据。这种模式对处理不定长数据帧带来很大的便利,我们不必频繁的进入接收中断处理数据,但是弊端也是明显的,由于每次都要接收完一个完整的数据帧后才空闲中断,所以当一帧数据出错时,我们也不得不接收这帧错误的数据。在通讯可靠的场合,使用空闲中断接收模式接收串口数据,将会大大提高系统的性能。" `* N  w- B0 _
5 ~/ }" d3 g# U4 t
二、实验步骤
" ~$ i8 q- x0 S1、基础配置

' {# p# Z* {1 f* q5 s8 X5 c1)、sys中,选好调试方式,例如jtag-4pin。
6 C- T& ^+ F( R# x9 e* ^2)、RCC时钟,晶振选择。
3 |5 \& K% H6 k+ I3)、时钟树配置。
- t' s- D. O5 w+ K, F9 y4)、中断分组配置。+ ]( D" y  p4 t0 ?0 ]
以上步骤可以参考串口中断实验。# F; \' J/ o8 b* G

- r! Z! i9 |: x+ H8 W7 @串口中断实验配置7 X3 {' Q- e& n
本实验要配置好printf函数便于演示效果
9 ]4 _5 a! v1 z6 g: s- g/ ]2 H# B& `6 E! f$ ~
2、串口和DMA配置% W( Q) p! B0 n6 L- N, E
1)、串口一配置。
2 h% }" f* ~! u3 x8 V: M- V, G5 n( |. Z+ E% Y& R6 ~. }" f4 p: c
]CXMGGO%(~CVM(]Z)3~HG(Y.png ( W6 h2 L3 f5 U
" i$ w9 ]5 ~. [, R0 ]
2)、DMA选择, l& g  I$ n% f
T(MA7CJTGMUHRZZU~9F.png
4 x0 C; K6 v! S' _
( A, B3 e+ f' E3 ?7 C9 g/ A 71CDS@LW]C_6GUJ7RXXP@XN.png # Z2 U& t! e0 l6 b# e6 V

& F9 a3 T, x# T8 N+ Y" L9 i) W6 P3)、生成工程代码
. s5 ~6 n9 A& ?. w9 X5 ]( p, O3 }+ ~9 [3 Z) q0 p5 }$ U3 D
IZOO[@GPHC5O@UK9ASY]IDI.png
0 z) b9 i3 ^: @4 g) `1 ~. @: C: J; p3 b* K, R
然后生成代码。
& U5 A. ]* M5 H& E' X: K; J4)、添加代码/ x% r# i) ?. l) w2 h6 X

5 y# @, [8 e5 Z 3@8(I63`AXKHYAEVQ4QLC30.png 6 ^. T% Z+ Y+ @* n2 G" f% e" V
, H) u& l" w' ~2 @% D& z% w
  1. // 这里没有使用中断回调函数,这样写更直接一点。* x7 s6 V6 j/ x; ]# _
  2. extern volatile uint8_t rx_len;//接收到的数据长度
    5 `5 }3 L3 H/ _
  3. extern volatile uint8_t recv_end_flag; //接收完成标志位9 k8 j0 e3 @( U! d5 n+ R* q( i9 [
  4. extern uint8_t rx_buffer[200]; //数据缓存数组, U2 u1 m7 ~5 ]: A
  5. void USART1_IRQHandler(void)* c: S' U0 o) L0 T
  6. {
    & s, t% S4 m5 }6 [" d3 `- l% V
  7.   /* USER CODE BEGIN USART1_IRQn 0 */
    . K# q& n4 U& S. c& N$ b7 Y
  8.     uint32_t tmp_flag = 0;- @3 r. G' e& c2 k6 g  O9 @! L
  9.     uint32_t temp;
    9 d( i$ p; k: e$ C8 t
  10.     tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE);
    % o8 w9 p, R+ |( i+ O
  11.     if((tmp_flag != RESET))
    ! y* W0 q' G7 W! q9 B
  12.     {
    & p2 K2 H3 n5 d7 V; p: X1 L* ?
  13.         __HAL_UART_CLEAR_IDLEFLAG(&huart1);* ^* b- \! H+ d; A' b# r: W- L8 W" ?
  14.         temp = huart1.Instance->SR;  7 f5 U) k9 g2 S/ R8 [% y
  15.         temp = huart1.Instance->DR; 3 q2 k: u. @" C8 Z
  16.         HAL_UART_DMAStop(&huart1);
    ' V% R- J, Q' {) x3 \% b* D/ `
  17.         temp  = hdma_usart1_rx.Instance->CNDTR;2 N& K: G: z- Q4 K
  18.         rx_len =  200 - temp; / B, a, L1 H; i, ?3 C3 H0 W
  19.         recv_end_flag = 1;               
    $ d# f) V" _. {/ c+ ~
  20.     }& e0 Y  I# s$ N5 k* @
  21.     HAL_UART_IRQHandler(&huart1);        # b" M4 D  {+ t
  22. }
复制代码

8 n: [% m4 H; z. Y如下图,在usart.c 文件中先把变量定义上,同时把支持printf的函数添加上。/ V8 c9 h7 t5 `& l$ Q1 e
! k' d9 r7 j) Y& o
  1. //注:**这三个变量 需要在stm32f1xx_it.c和main.c中外部声明**
    + L% o: A2 C9 M2 q/ t
  2. volatile uint8_t rx_len=0;  //接收到的数据长度
    $ s& o; T& Y; ~5 Q# m9 n
  3. volatile uint8_t recv_end_flag=0;//接收成功标志位
    1 n9 d# p6 v, E2 a" K
  4. uint8_t rx_buffer[200];//缓存数组
复制代码

9 k2 W9 Q1 @5 a; h. u0 a+ d. B- J# g ZD3I8)}08`}Y`@Y]W5QGW19.png
/ a( f( c* ?. J( o5 i) |4 N. w: h1 @+ U% B7 D* y( h  p& `) q
10BJGM%V~TYC4W]DN6F1ALW.png # }5 a6 l( b( o3 M1 Q- {

7 B( {$ M8 y4 L# S: j
  1.         __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);" }' v" Y8 D4 J" X' s9 d) `( q
  2. HAL_UART_Receive_DMA(&huart1,rx_buffer,200);
复制代码
& L, h) I6 o& l5 `
3_4M~T~TU3DS7MZDRB24~GL.png 7 D% A+ U8 v- Y8 ?1 [: U
# N; q; f6 @( [$ K& q( ?7 N; o
  1. int main(void)
    - O4 P% R  `. k$ z
  2. {
    $ f4 p4 p3 m% a6 q  x& ]
  3.         HAL_Init();. f, l+ x; ]. Z- @9 e3 f$ U
  4.         SystemClock_Config();  L5 `$ G, t. w$ @5 y
  5.         MX_GPIO_Init();; L7 C  m0 q0 ~, [- {2 A! B
  6.         MX_DMA_Init();" b3 M  P8 N; O2 @  q
  7.         MX_USART1_UART_Init();! ]3 A" Q' w( E
  8.         /* USER CODE BEGIN WHILE */
    6 x1 x+ |9 M! a: s, k! Z
  9.         printf("DMA_TEST");$ K. }0 J( L- _
  10.         while (1)
    , U# a: [2 d& Z4 }; C9 M
  11.         {
    ' k6 q4 G8 s. U+ F
  12.                 if(recv_end_flag ==1)                        
    6 p7 l( C8 J7 V# [4 X2 D
  13.                 {        
    2 ?" e# g8 i7 ^3 b, U+ p  u3 e
  14.                         printf("接收到的数据长度为%d\r\n",rx_len);/ I8 u2 ~. a- [
  15.                         HAL_UART_Transmit(&huart1,rx_buffer, rx_len,200);
    5 ]8 G3 n- Y' T% I6 y7 e/ D/ Y9 l
  16.                         for(uint8_t i=0;i<rx_len;i++)
    / I4 p8 ]2 @* I
  17.                         {  K  z1 [1 j* T
  18.                                 rx_buffer<i>=0;
    & B3 f4 Y7 c  D, P6 D5 J/ L# Y! }
  19.                         }
    ! _4 l4 J0 c8 f. h' r. f8 I
  20.                         printf("\r\n");3 n1 d6 Q3 K. S; A; I0 G
  21.                         rx_len=0;8 x% W  Q* v6 R, s0 K7 L. N: o
  22.                         recv_end_flag=0;" A: [* ?* E$ t7 E5 o$ e+ [
  23.                 }/ \1 R! S! V$ P9 v" T1 _
  24.                 HAL_UART_Receive_DMA(&huart1,rx_buffer,200);        , E5 z& n. o% W: q9 }- D
  25.                 /* USER CODE END WHILE */, E; g( Q) Z8 G4 Z- A
  26.         }
    % C1 O  _! [6 a$ i
  27. }# n8 M( f- n2 E* z/ _; d
  28. </i>
复制代码

" E+ A1 ^2 e0 e# b3 烧录调试
) T: j" x) q' f9 a添加链接描述& f. e% f! h3 v  }1 ^" _/ l
. O! m. J2 M. R
2E6(L5`BW[C2NM5)0UHR3PC.png 2 T& b: y2 F, L' E; a" ^- G
赞 收藏 评论0 发布时间:2022-5-16 10:35

举报

0个回答

所属标签

相似技术帖

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