请选择 进入手机版 | 继续访问电脑版

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

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

[复制链接]
donatello1996 发布时间:2019-1-7 09:38
    串口不定长接收在项目中经常用到,像MODBUS串口服务器中就会经常传来一大帧数据,数据的长度不定,通常人们的做法是采用环形队列接收的方式,以特定的结束标志位如0x0d 0x0a等用以判断一帧数据的结束,但实际上STM32这种高级的ARM单片机是带有空闲中断和DMA的,不需要用环形队列这种纯软件的做法实现不定长接收,直接用空闲中断+DMA就可以实现了,非常简单,小白也能一看就懂。1 j# ?9 `* v- M" D) @
    首先是要初始化串口不定长接收,比如打开空闲中断,打开DMA,这里我选的是板上的USB转TTL串口即串口3,对应的接收DMA为DMA1流1:
' M4 w# L  q* z( T. \# z4 r8 g. u 12.jpg 13.jpg , e- `1 q5 D% m
代码如下:0 O1 Z7 ]; y% c
7 M) r' y& z6 B( `+ F8 d0 G

( K$ x: ~8 _* S( Q; tvoid UART3_Init(int baud)6 m  @4 I4 @, o8 F' s
{4 U- ]/ D8 S* f! m: ^
        __HAL_RCC_GPIOB_CLK_ENABLE();8 F' {; N8 u" \6 ?# d1 @* u
        __HAL_RCC_USART3_CLK_ENABLE();
9 g- L0 K8 A2 z& w0 D        __HAL_RCC_DMA1_CLK_ENABLE();6 T& X! j8 S% i' o1 X
       
7 \/ x4 r- W1 }7 h2 ]  ~  q! U        GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
# l# Y/ x$ x: Y2 I& J4 P  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
$ M/ a- a* W$ E& u! _9 L  GPIO_InitStruct.Pull = GPIO_PULLUP;1 S3 D- E5 E) U( `
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ f, c2 }9 n' z% A% n3 n2 K  GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
1 x6 P9 K, e* e  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);5 M9 I% x4 N9 b
       
, ?5 [1 h7 F4 e: v1 H  Q  huart3.Instance = USART3;
/ g: g" A0 x/ ?6 J$ l* e! v3 Z, t  huart3.Init.BaudRate = baud;
0 M7 p) o4 m- q. G* E  huart3.Init.WordLength = UART_WORDLENGTH_8B;! t' ^' D+ h' U& \6 z
  huart3.Init.StopBits = UART_STOPBITS_1;5 g6 D1 I* z1 _- b  b" s+ Y
  huart3.Init.Parity = UART_PARITY_NONE;
4 d( P0 |0 S0 ?3 s$ a% V& i  huart3.Init.Mode = UART_MODE_TX_RX;9 I% T/ @. C4 H+ i
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
; |) o$ x: a) N3 U7 F  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
0 M4 s' i/ Z. g: I" t/ Q8 P  HAL_UART_Init(&huart3);7 D9 Y# t- x$ ~3 {# I* X4 ]5 Q! ~3 x3 Y
        __HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE);0 s9 @9 a' \4 V& `" z9 m
        HAL_NVIC_SetPriority(USART3_IRQn,0,0);' V9 m& b, S1 g3 u; K* G: @+ W
  HAL_NVIC_EnableIRQ(USART3_IRQn);
( ?+ s( ~7 B+ s7 p3 |       
6 ]$ o% J+ f; w4 i: G7 Z        hdma_usart3_rx.Instance = DMA1_Stream1;6 C9 x) T/ {: g
  hdma_usart3_rx.Init.Channel = DMA_CHANNEL_4;! S; a3 N- P9 R) s" Q
  hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
9 T- {( ^# s% l9 ^8 k8 c  hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE;, P8 Y: D2 r. w- d
  hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE;' w3 y: }1 B* ?
  hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
! H  T( ]5 Q9 B% }+ K; T* A8 p  hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;& `/ X$ ]+ N1 s9 H2 a; F/ k
  hdma_usart3_rx.Init.Mode = DMA_NORMAL;
9 @. ?! p$ H7 `/ q4 _" k  hdma_usart3_rx.Init.Priority = DMA_PRIORITY_LOW;
7 V4 k) n8 ?9 |. k9 z$ }  hdma_usart3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;' d! ?% @( p8 X8 g# |0 V+ i( ]3 ]' L
  HAL_DMA_Init(&hdma_usart3_rx);
; [) i+ w9 M4 l7 ^- u! |. K; `% ?& {        ; Q2 ^6 C" y1 y/ _& t- Y' y
  __HAL_LINKDMA(&huart3,hdmarx,hdma_usart3_rx);! m( Y3 v. K0 x# w3 y
}
7 h% m! c+ p0 p. G( U4 v9 g' R3 w/ x. Z( H/ f0 v" |

) x  H( l4 S( g0 w) [void USART3_IRQHandler(): x/ g& Y6 F3 p- ^4 P3 u) y
{
- ~" l8 Z7 o: Q9 q+ u* z        int temp;" M; s' |( g+ K7 d5 G. H
        if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE))
' I6 g7 i7 @7 m, c        {" ?$ F8 d# Q" a3 |- J
                __HAL_UART_CLEAR_IDLEFLAG(&huart3);
! D$ g# d* B' o% ^3 r( d. w                HAL_UART_DMAStop(&huart3);- a, ^8 W/ [5 Z% _% O& x& y
                temp=__HAL_DMA_GET_COUNTER(&hdma_usart3_rx);
( u9 E0 |. d) r6 k                rx_len_uart3=BUFFERSIZE-temp;
" }# Z% C$ k# K8 g7 q0 z# {" R                rx_flag_uart3=1;
$ w. J8 c# c5 f1 F        }8 }3 O9 H$ U( g$ s4 y9 ~# z
}
9 v0 k+ r8 q. N在主循环中加入以下语句以让单片机轮询串口不定长接收的标志位,并在液晶彩屏上显示出来:& u2 c0 i/ `: B" F
void UART_DMA_Get()* j' G. r& ~4 t) f) ^/ L6 h+ a
{' K2 B" C6 N! ?$ U# m5 F6 f8 V
        int i;7 r2 X- k' |$ E: b
        if(rx_flag_uart1==1)9 T) }# V3 F7 P" }0 f- Q8 ^. n. O
        {% y: ]+ f" p1 J# q! }
                printf("rx_len=%d\n\n",rx_len_uart1);4 F2 t  ]9 O8 d& d
                printf("%s\n\n",rx_buf_uart1); 2 F' O: Y6 K2 e. J
                rx_len_uart1=0;/ f' N3 r2 b( s7 G
                rx_flag_uart1=0;
4 b* S! j8 o6 n- f3 }4 T        }
; ~. m! Z$ E; c- ]3 V4 e        if(rx_flag_uart3==1): k% W3 F* c; k/ K/ u
        {
" J! a7 ?6 q* Q- o                printf("rx_len=%d\n\n",rx_len_uart3);7 h+ d& T4 t. L) F. p
                for(i=0;i<rx_len_uart3;i++)8 C: a( i: w9 Q! U1 u
                {) G% v4 A! b* k/ g7 l
                        if(rx_buf_uart3=='\r'||rx_buf_uart3=='\n')
% K4 P9 K# b% r: m& b                                rx_buf_uart3=0;
# e8 z% ]7 A$ @; f
; u- l8 ~& \2 C7 B/ m
: \- A& S  p  ~# P; ?* N) \
                }
6 C- m9 y& t: J7 g9 c( G                printf("%s\n\n",rx_buf_uart3);- |. h" J0 s2 i5 U8 o- k. i- [8 I
                SPILCD_DrawString(0,128,"                              ",BLACK,CYAN,ZF32_NORMAL);0 ?# L1 u0 p) Y: z: o' r; J- F
                SPILCD_DrawString(0,128,rx_buf_uart3,BLACK,CYAN,ZF32_NORMAL);) u; {! R1 k* N. y5 h) I3 V

7 Z% l. [( R+ }) s
  L7 y3 B5 e* U& {
                rx_len_uart3=0;
6 I+ {$ U/ O7 e- Y% w                rx_flag_uart3=0;4 W/ O) p+ T) R* L9 ]
        }
8 g" ?% l# f& }6 L        HAL_UART_Receive_DMA(&huart1,(uint8_t*)rx_buf_uart1,BUFFERSIZE);  a8 G/ i5 n5 s5 y$ z2 q7 ~
        HAL_UART_Receive_DMA(&huart3,(uint8_t*)rx_buf_uart3,BUFFERSIZE);7 K- \. {0 B: @0 E2 c/ N5 l" P2 [
}
" o$ p" v$ |+ A) X7 F1 {% F, C! ]/ c* c* ?, C. Q( T

" B$ g  e; n6 N3 j4 C, S. o* U看看效果,可以看到,上位机串口程序那边发什么,显示屏就显示什么:
: V* d' S6 r2 X. ?% G# L 14.jpg 15.jpg
+ c- l! u" b- q, R3 T- k IMG_20190106_183604.jpg IMG_20190106_183620.jpg IMG_20190106_183643.jpg ; ?8 q& \3 N/ b# k- T: m8 W
上传工程文件:' L' [  s2 }- e
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
空闲中断是个思路,
0 N. i5 Y8 ^$ J- ~5 R* ?/ h+ O不过可靠性可能需要认真考虑。
& _; h5 ]& _; y; a% I* Z串口属于硬件层,数据链路层协议还是需要考虑的。+ F" x: w) L0 l& E5 ~! z  @
david69chen 回答时间:2019-2-24 15:36:53
好东西,感谢分享!
q790198803 回答时间:2020-10-31 23:19:16
) l! a1 t  Y% L+ J
好东西,感谢分享!

所属标签

相似分享

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