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

【屋脊雀F407开发板】串口空闲中断+DMA实现不定长接收&处理

[复制链接]
donatello1996 发布时间:2019-1-7 09:38
    串口不定长接收在项目中经常用到,像MODBUS串口服务器中就会经常传来一大帧数据,数据的长度不定,通常人们的做法是采用环形队列接收的方式,以特定的结束标志位如0x0d 0x0a等用以判断一帧数据的结束,但实际上STM32这种高级的ARM单片机是带有空闲中断和DMA的,不需要用环形队列这种纯软件的做法实现不定长接收,直接用空闲中断+DMA就可以实现了,非常简单,小白也能一看就懂。
# t2 W7 D. J3 }( B; ^3 V    首先是要初始化串口不定长接收,比如打开空闲中断,打开DMA,这里我选的是板上的USB转TTL串口即串口3,对应的接收DMA为DMA1流1:
" l$ T; h+ c* n1 U 12.jpg 13.jpg , T( I# k4 a; ~' _' z7 K) s
代码如下:
7 k* h5 q/ Z0 v% h' e8 {1 c% k% Z0 p

/ D6 g" d5 p  r2 n+ l) B) Uvoid UART3_Init(int baud)
, S$ H1 A1 Q# R) E8 X4 }% B% n{5 {: ^$ q7 k7 j5 J$ ]
        __HAL_RCC_GPIOB_CLK_ENABLE();
$ i" h- n6 o: x6 }" x  B% V, [8 s        __HAL_RCC_USART3_CLK_ENABLE();) A' T. [5 z6 }7 e  W* Y
        __HAL_RCC_DMA1_CLK_ENABLE();% M) ?8 F) U$ y* l7 O
       
/ Z4 Q, C' j' t4 n        GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;$ H# m, C) y! S0 F
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  f0 W) b% P- h8 ?  GPIO_InitStruct.Pull = GPIO_PULLUP;
5 m7 s$ V% c: L) h% s/ `1 l  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
( h7 J7 e/ W7 L  S9 F( ?" |  g  GPIO_InitStruct.Alternate = GPIO_AF7_USART3;5 X: m; c2 W( I; s8 B: z
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);. }2 V' h, C; _2 J' |5 F, \3 u8 q
        " s- K- t" G# o. I
  huart3.Instance = USART3;
2 V/ L$ y% w7 D# @) K  huart3.Init.BaudRate = baud;
" C& w# Y# \  O  S0 d! r7 J  huart3.Init.WordLength = UART_WORDLENGTH_8B;
+ P  ?8 w+ ]  ]& ]7 i( C2 I  huart3.Init.StopBits = UART_STOPBITS_1;# q3 z+ O) L, r: Y# C( d' P. G
  huart3.Init.Parity = UART_PARITY_NONE;. Z8 p) t2 f7 V& w( T3 s0 J4 k7 n. `
  huart3.Init.Mode = UART_MODE_TX_RX;
4 @7 g, j" r" J  h( N/ L  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;3 V7 e; k! Y; r9 l6 h& D. |7 }7 Q
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
5 L9 a0 f& q" X. H, P- _) h6 f. o  HAL_UART_Init(&huart3);
0 X0 v1 x. Z+ q  ?        __HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE);6 `2 b/ y( _7 _
        HAL_NVIC_SetPriority(USART3_IRQn,0,0);
- j: _2 m& D, p+ Q  HAL_NVIC_EnableIRQ(USART3_IRQn);7 p  W- K3 J  z: ]4 Z' }: t
       
8 ~6 ?7 C) y" U3 }        hdma_usart3_rx.Instance = DMA1_Stream1;* B  O- |. V$ z; o% M7 A
  hdma_usart3_rx.Init.Channel = DMA_CHANNEL_4;
8 _7 I! ]; J. j7 q1 ^4 C  hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;6 o$ R( N9 ^+ K% K' K2 H/ k  D
  hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE;; \7 Z& W+ P. ?! d* W
  hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE;
8 R* i6 v0 i5 A9 P2 D" o  hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
" ^! P$ E/ Z3 A* E- Q  hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;. K9 p$ y' W2 l& v: b# o. v
  hdma_usart3_rx.Init.Mode = DMA_NORMAL;) W' b) T1 k* O+ c
  hdma_usart3_rx.Init.Priority = DMA_PRIORITY_LOW;
3 P+ w. e, ^; Z  hdma_usart3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  a! j) w+ w. a  E* e- n( ~  HAL_DMA_Init(&hdma_usart3_rx);8 v- {& p" f: v. M0 @
       
1 H: M2 z- P9 d$ Z( K, k) E  __HAL_LINKDMA(&huart3,hdmarx,hdma_usart3_rx);8 A- s2 o" {7 r$ Q
}
9 q0 [) w8 i( P3 D9 q$ \( \& V  e; u+ G! [+ w! Y+ i

% q$ @) j1 l5 ~9 ^! ^4 Mvoid USART3_IRQHandler()
4 t* q8 Q2 R' T6 {{
: g2 c5 M, P+ F4 k( n        int temp;0 x+ z3 ^2 P3 c1 X
        if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE))
! V8 u/ N, |2 ?' m2 |0 i        {
9 M5 t; \2 C% O. w% U. `                __HAL_UART_CLEAR_IDLEFLAG(&huart3);- u* l2 |9 e' t
                HAL_UART_DMAStop(&huart3);
" _- p/ Z. \. g4 [- e9 L                temp=__HAL_DMA_GET_COUNTER(&hdma_usart3_rx);$ l% t( G$ Y$ ~( A0 t3 J) O
                rx_len_uart3=BUFFERSIZE-temp;
- {1 S- T* k6 A2 _. a9 _                rx_flag_uart3=1;
. B4 L% _" A: I& D( x" ~; W        }
: V: O4 w7 e6 h( K}
7 u6 V+ p# D/ u. [6 A& R' i在主循环中加入以下语句以让单片机轮询串口不定长接收的标志位,并在液晶彩屏上显示出来:
) [! w- O% k. P8 c  g; `void UART_DMA_Get()0 c$ S1 ~& m6 ~
{
! M0 d$ L9 N3 A7 T& \3 D1 K& }        int i;
) @+ t' t. m! g* R6 V( J# d        if(rx_flag_uart1==1)  o+ z6 W& O$ _$ |& e7 R( X
        {* ]* U! Q% T; o* |& n8 w; I% F! d
                printf("rx_len=%d\n\n",rx_len_uart1);
9 `2 X) z1 u, h6 S5 k1 U                printf("%s\n\n",rx_buf_uart1); 4 P; U( k% o8 T, w
                rx_len_uart1=0;4 ^8 _! C) w, s
                rx_flag_uart1=0;; W7 W" H8 A5 R* C4 O  u) u
        }
' K. v* U! C( c0 q8 Q        if(rx_flag_uart3==1)* z) o9 X3 S9 t) A% ^! [; f
        {
0 G: x! y9 o  ]4 V) @3 f                printf("rx_len=%d\n\n",rx_len_uart3);
* Y5 |) T$ I8 L; P6 D                for(i=0;i<rx_len_uart3;i++), c# `: M& M/ G- h+ o# j! }
                {
7 M( \0 r; Y4 a5 P( }                        if(rx_buf_uart3=='\r'||rx_buf_uart3=='\n')
" V* S5 v- `) |4 @# V( ^, a; w: P3 H$ m( f                                rx_buf_uart3=0;5 j+ W3 k( G* d+ A

& F0 M$ u3 i3 ^& N
7 k" v; @2 o4 ]$ H& \# A" @
                }6 V/ \* }# G1 I/ P
                printf("%s\n\n",rx_buf_uart3);' k5 {/ i6 v2 m7 L) ?. `  L$ I
                SPILCD_DrawString(0,128,"                              ",BLACK,CYAN,ZF32_NORMAL);; x# Q4 }. l; d$ X/ D
                SPILCD_DrawString(0,128,rx_buf_uart3,BLACK,CYAN,ZF32_NORMAL);
* q% T+ X3 ?7 G" u; H$ L) w6 Y
% U6 K8 p% H5 g' a

) R5 Q  t$ [- ?                rx_len_uart3=0;
: S  J9 w, S7 s8 ~. M% ]                rx_flag_uart3=0;6 x7 ?* N& R8 I
        }
6 i1 |- S  s& ?9 X" [) x        HAL_UART_Receive_DMA(&huart1,(uint8_t*)rx_buf_uart1,BUFFERSIZE);
& j# i1 _2 i, ]* v5 n4 k. X        HAL_UART_Receive_DMA(&huart3,(uint8_t*)rx_buf_uart3,BUFFERSIZE);
! L1 Y/ x, R( P}
" D  J/ [- \5 p4 G9 C; e$ G% v5 L3 _8 l, Z- ^5 i. y

. Y% z* c: V) _9 y看看效果,可以看到,上位机串口程序那边发什么,显示屏就显示什么:' K5 v: A% B8 ?# b! F
14.jpg 15.jpg
0 m; W2 W- H+ K4 @) U' C9 g IMG_20190106_183604.jpg IMG_20190106_183620.jpg IMG_20190106_183643.jpg 6 [9 H  h8 {) e. s
上传工程文件:2 e; k/ ^! b7 @, U( V. z
STM32F407ZGT6.zip (551.38 KB, 下载次数: 28)
收藏 2 评论6 发布时间:2019-1-7 09:38

举报

6个回答
Kevin_G 回答时间:2019-1-7 10:04:17
好文章!
STMCU-管管 回答时间:2019-1-7 10:39:15
支持支持
杨满意 回答时间:2019-1-7 13:07:33
有些外设模块不能用,会存在断帧问题
wujique 回答时间:2019-1-9 14:50:33
空闲中断是个思路,+ ~, {8 Q* [& `. F0 J8 s! k5 z/ E
不过可靠性可能需要认真考虑。
; h7 v' f; i" d串口属于硬件层,数据链路层协议还是需要考虑的。8 Q2 i# E4 V5 ]/ m
david69chen 回答时间:2019-2-24 15:36:53
好东西,感谢分享!
q790198803 回答时间:2020-10-31 23:19:16
& X, }5 c7 O, L$ J5 O7 Q
好东西,感谢分享!

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版