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

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

[复制链接]
donatello1996 发布时间:2019-1-7 09:38
    串口不定长接收在项目中经常用到,像MODBUS串口服务器中就会经常传来一大帧数据,数据的长度不定,通常人们的做法是采用环形队列接收的方式,以特定的结束标志位如0x0d 0x0a等用以判断一帧数据的结束,但实际上STM32这种高级的ARM单片机是带有空闲中断和DMA的,不需要用环形队列这种纯软件的做法实现不定长接收,直接用空闲中断+DMA就可以实现了,非常简单,小白也能一看就懂。
# w2 ]1 x) H9 Q, {7 w2 S    首先是要初始化串口不定长接收,比如打开空闲中断,打开DMA,这里我选的是板上的USB转TTL串口即串口3,对应的接收DMA为DMA1流1:* l$ `& S4 D5 M- d+ F
12.jpg 13.jpg . q* u6 X" k/ ]% F$ B$ Z# ~
代码如下:* G9 d- F4 g1 f, @, W' L
4 I+ ?. X7 u/ D% a

) H+ P' w9 I( r- ], bvoid UART3_Init(int baud)
) K! r# d7 o5 _& g4 R8 d: X{+ K* ?1 X& J6 p5 |
        __HAL_RCC_GPIOB_CLK_ENABLE();2 K0 a5 s0 ?6 ^( M
        __HAL_RCC_USART3_CLK_ENABLE();
* w1 O* W' j0 e9 e- c        __HAL_RCC_DMA1_CLK_ENABLE();
  M! R  J% O# V3 S1 [       
! M1 F) X  J' V        GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
+ p+ C+ C0 R+ B' x5 b1 l3 s/ l  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;: M* A5 ]) d! k* L4 u
  GPIO_InitStruct.Pull = GPIO_PULLUP;. F. F2 s1 B! Z3 W: u
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
) [  Y0 C, [, `- H4 N8 C# Q- S  GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
7 J4 S; u5 B: I  S4 P8 n- P  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);: @; b7 h5 r% x; A* {
        & ~" M2 x3 z$ Q$ K* J6 w6 f
  huart3.Instance = USART3;0 H8 U6 `, t/ y9 n' Y* D
  huart3.Init.BaudRate = baud;
2 Z9 B6 M2 P) e+ E- Q/ v8 ?  huart3.Init.WordLength = UART_WORDLENGTH_8B;2 {: _) ?$ S9 y$ c
  huart3.Init.StopBits = UART_STOPBITS_1;+ Q6 R' O; @3 b& y
  huart3.Init.Parity = UART_PARITY_NONE;: q, {: w" a+ F8 x- B
  huart3.Init.Mode = UART_MODE_TX_RX;
; I+ Y$ G) M+ n3 a4 X  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;4 z! y$ G4 p2 l; c- w( [
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;6 O# v1 }# k1 O8 h3 a; L# [
  HAL_UART_Init(&huart3);
1 r; _6 w; |7 e" W/ ~( ?6 E        __HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE);! o5 W. G2 h+ J5 o% a4 R
        HAL_NVIC_SetPriority(USART3_IRQn,0,0);
- a# g3 Z% U7 U) E% Z1 v' r  HAL_NVIC_EnableIRQ(USART3_IRQn);+ {' r7 v, K  p" i. E. X  ?
        9 w% }7 t* U% O
        hdma_usart3_rx.Instance = DMA1_Stream1;2 |6 I: m! W# W; S' C
  hdma_usart3_rx.Init.Channel = DMA_CHANNEL_4;
4 D) ~1 Y/ ?/ J% r+ G- r, H6 O  hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
# A6 B+ B7 P9 [: ?  hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
7 e8 O8 Y9 j  R# `  hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE;
3 @  n5 F/ K& H  hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;' q$ m! r! F) d4 I4 E' `8 t' _5 m3 Q
  hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
8 L9 T) j0 y& n+ e3 y  hdma_usart3_rx.Init.Mode = DMA_NORMAL;
9 ?7 {3 P" ?( E" F  hdma_usart3_rx.Init.Priority = DMA_PRIORITY_LOW;
9 Q, w+ V6 ]/ w7 {! S5 N% T  hdma_usart3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;+ ]9 }* a6 u: A2 S* ^/ S) {3 @3 `( T
  HAL_DMA_Init(&hdma_usart3_rx);
* f9 w* y, x7 \! R) A) r       
9 T7 V6 s6 L+ }, x0 H9 p4 U( k5 G  __HAL_LINKDMA(&huart3,hdmarx,hdma_usart3_rx);
" t! B2 ~) X' \}! f) J* T* p' m3 y
3 i- l; p3 t* B
2 @' V, `) b* U( [. Z7 ^
void USART3_IRQHandler()  E/ ]" E& n' a
{6 T& t1 j* |, c. e
        int temp;
: Q9 z1 B! Y6 e& x& p        if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE))
  Z) i+ q1 t1 s/ f! e        {
" U- G5 g$ x" @7 V+ {2 M+ z                __HAL_UART_CLEAR_IDLEFLAG(&huart3);: I0 O! D5 v- _, |3 L; H2 H/ o
                HAL_UART_DMAStop(&huart3);
3 v! B8 y; R* a- z7 k4 d# U4 s% _  x                temp=__HAL_DMA_GET_COUNTER(&hdma_usart3_rx);- G: m% U% @4 r- T1 W3 s* L1 X- B
                rx_len_uart3=BUFFERSIZE-temp;
. Y# f" p5 w0 V- z/ b                rx_flag_uart3=1;: K% `. n; k/ s% ?4 d3 L; p
        }& K# t$ h3 z1 e4 P" {6 R. d2 M
}4 W1 p+ m8 w# Y5 c
在主循环中加入以下语句以让单片机轮询串口不定长接收的标志位,并在液晶彩屏上显示出来:
4 z4 O6 ^2 S1 K0 Evoid UART_DMA_Get()
# T/ \0 e4 i3 l, i' }: Q! A{
1 V2 i5 [7 g, q6 _0 g        int i;# ?4 ^5 d& E! P1 _/ W
        if(rx_flag_uart1==1)
* g. _- k' n& h        {
2 Q. ]; m: P; i/ e5 Y, J& B                printf("rx_len=%d\n\n",rx_len_uart1);: A. M6 c2 _, U! _. L* x
                printf("%s\n\n",rx_buf_uart1); , {0 V4 Q3 P2 t; Y6 h2 ?
                rx_len_uart1=0;8 k  M2 a/ x( b/ r9 C
                rx_flag_uart1=0;2 n. p2 R: x; l. y! \3 d. l' Y
        }
- t7 ]- j: f+ ~' U( s! K        if(rx_flag_uart3==1)
1 _* ~  h. F* V        {3 p- `5 h4 d. q! ~) `' H
                printf("rx_len=%d\n\n",rx_len_uart3);
1 x2 T; M" T$ D$ e2 V4 \                for(i=0;i<rx_len_uart3;i++)
( |  D! n& o) i7 n" p                {
3 r( `) d) \* D: k  c3 w# f                        if(rx_buf_uart3=='\r'||rx_buf_uart3=='\n')* _/ U, y5 o, d3 I; o. U1 P* u
                                rx_buf_uart3=0;
. y+ m( c$ ], P/ u9 y' Z$ J; H
* D0 `" k0 Z# H3 i& C3 \
1 P* W3 X" V9 ]! H1 V  q' D, v) Y
                }
- q+ Q6 i& X' ]/ M$ r                printf("%s\n\n",rx_buf_uart3);
6 C# g1 f3 T4 _( l5 }' f                SPILCD_DrawString(0,128,"                              ",BLACK,CYAN,ZF32_NORMAL);3 o1 z8 t# {& Q0 P
                SPILCD_DrawString(0,128,rx_buf_uart3,BLACK,CYAN,ZF32_NORMAL);
. D3 v/ Q# c- s) F$ c8 y8 F3 [% i3 n! j! i
* n9 m  y+ Y1 z& {( \( v/ l! F
                rx_len_uart3=0;
! ^4 N2 R5 ?! v7 _                rx_flag_uart3=0;
$ q  n# I$ q$ Q        }
. L8 w; K" t7 u! b. B        HAL_UART_Receive_DMA(&huart1,(uint8_t*)rx_buf_uart1,BUFFERSIZE);2 |' K  S" s( O# y8 l5 @
        HAL_UART_Receive_DMA(&huart3,(uint8_t*)rx_buf_uart3,BUFFERSIZE);# o1 B6 S! l' r' A, R/ k
}, G- Z, ]2 I8 u0 K& M: I

) _/ c5 I$ }/ L6 a! o
3 L7 t# m4 M) v' T9 ?* ?
看看效果,可以看到,上位机串口程序那边发什么,显示屏就显示什么:$ g- h1 A, ]. t8 x8 ~& b
14.jpg 15.jpg % y2 Q/ Z3 g2 D" V7 z
IMG_20190106_183604.jpg IMG_20190106_183620.jpg IMG_20190106_183643.jpg 6 D  p& ~( z0 N6 P: w0 g4 b
上传工程文件:
) \6 H0 d/ Z# p2 K1 r" P! r* ?! Y; o 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
空闲中断是个思路,
" j9 f) s. ~8 {( _不过可靠性可能需要认真考虑。
  {4 v% h- r: P/ L: d0 ]串口属于硬件层,数据链路层协议还是需要考虑的。
0 v. K" [% A5 s. ]
david69chen 回答时间:2019-2-24 15:36:53
好东西,感谢分享!
q790198803 回答时间:2020-10-31 23:19:16
3 c2 x+ w. Z# s: K$ u  Z4 e3 Y" S7 y
好东西,感谢分享!

所属标签

相似分享

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