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

基于STM32开发串口DMA空闲中断经验分享

[复制链接]
攻城狮Melo 发布时间:2023-3-29 18:42
  做STM32开发,串口可以说真的是无处不在,芯片与芯片之间的通信可以用TTL电平,多机通信可以用RS485工控总线,对外上位机需要RS232串口通信,那么作为一款经典的单片机系列STM32,应该怎么处理串口报文最有效快捷呢,无数的实践证明,大量的项目经验告诉我们答案永远是串口空闲中断。8 N% _) F: V" I, R

2 g5 \% i8 x" I      那么什么是串口空闲中断呢,大家都知道串口在空闲的时候默认是高电平,在发数据的时候有起始位,数据位,结束位等等,传统的串口处理数据的方式是一个个字节接收,这样做猛地一看好像没有啥问题,但却留下很多隐患,比如:1.固定的报头,一个个字节接收少接收一字节,导致报文接收异常;2.同时开两个115200波特率的串口,因为两个串口本身是独立的,一个个字节接收数据导致频繁进入中断,存在中断嵌套的风险;3.驱动底层代码会非常繁琐,把一个STM32硬生生玩成一个FPGA,判断报头报尾,CRC校验还需要C语言做成类似Verilog状态机的逻辑等等,笔者在这里不在赘述了,因为不是这篇博客的重点。
" F4 t9 t: B# g# I

# W7 v; _$ V7 v/ Y) \       串口空闲中断可以简单地理解成,当串口不发数据的时候产生中断,然后我们可以巧妙地把这些数据通过DMA搬运到指定变量地址上,这样当主机不发数据的时候,即可以得到整条报文的数据,和报文的长度,之后再对整条报文进行处理,包括CRC校验,逻辑层赋值,应用层控制等其他相关操作,这样就极大地减少了频繁进入中断的次数,也优化了底层逻辑,因为收到是一整条报文而不是一个个字节,如图1所示,笔者这里用到的STM32F103RCT6芯片,PCB上把STM32的PB6和PB7作为UART1,查阅芯片手册可以看到如图2所示,DMA1的通道4和通道5是UART1的对应的DMA通道,所以我们在编写完初始化USART1_Init后,还需要如图3所示打开两个通道的中断。% A$ x- t$ _1 P+ ]- l+ Z

, \5 B, F  y4 o9 v- d) y
5d3d67356ae948beb6b1b6a58b458b93.png
" o$ p" j* Q8 x9 x3 Y      
! ^# V3 T6 s% L- y; M: u# u' D dc864cbe53864d6494b50e8781e92fae.png 2 q: b; |. R7 p; C5 i

# k1 w7 W+ B: Z$ D; l: ~# t 3b9049c2eefa4930aa49ee867aea090a.png   Z# c# e, w) q4 G& s! x( j8 n1 _( P
* V# d8 u9 Z* o3 u. p
e8bddc9a676d4c13a1f75e352057c499.png
6 E- d, u) l  t9 m. V8 `" g d08ba5f61bf24d60b590d9a47f476a8e.png
5 w+ E  o+ \- O2 _- j$ h+ e
) |5 S2 q- `2 s
2 i, p# z8 K' U( z" V5 C& n: u 02a09f5becc44467ad864b90381815e5.png . q& q6 v# {+ C$ S, m

% ^  M- |9 y# U( [8 \
2 ~/ V; ?8 o1 J/ y 图1 USART1的初始化函数
) o# m1 v7 l* A% M' e' v$ I* [6 _# a$ M$ E# e7 ^
a51b018d5ee14acd936a9ca32026cf88.png / J  I0 q# i2 B9 c( v. o. r: T$ A

' V9 v( A+ p) b8 W 图2 STM32F103系列的DMA通道示意图
' V- c) F' i# ^7 g( ?, \7 }6 P* S
. }  }! T! z% b& Y' r
e492323adc7447ac9ffb411698907d27.png 1 M* F. B( {+ t( Y! v5 o4 v$ @

' f; m- \9 T; l, J6 Z0 V 图3 DMA通道4和通道5中断开启! A) i( i  i4 B2 Q2 h& q0 _9 M
8 j  ^- p* m- y
       如图4所示,定义了串口收发的数据报文,这里面flag在串口空闲中断里置位,表示接收到一包数据,在主函数里再进行数据解包处理操作,切记在STM32中断里不要做过多的判断和等待或者其他复杂操作,假设来了一个中断,CPU处理了10秒钟,那么大家都知道STM32也好,ARM LIUNX也好运行的原理,中断来了要压栈保护现场,屏蔽IRQ等其他中断,如果一个中断处理太长时间,那么对于用户来说体验会非常差,其他操作都不被CPU响应,仿佛是死机了一样,毫无实时性可言,如图5所示是串口空闲中断处理函数,这里需要说明几个地方:1.因为开始DMA接收的数据长度设定的是2048个字节,所以USART1_Type.RX_Count = 2048-Uart1Handle.hdmarx->Instance->CNDTR这句话,代表把整包报文的数据字节长度赋值给USART1_Type.RX_Count;2.需要在空闲中断里先关DMA,再使能DMA才能在下一次串口空闲中断产生的时候触发;3.可以在串口空闲中断处简单地判断报头,简化了逻辑层的设计。. J8 f2 D; B  q: y6 b$ g" a* [
8 x8 D" N: C" S' k
1fbe428cb2e745cfb11dfc888d6501d0.png
% K' H0 ?5 s! `# d6 w

& N& L( p# z8 S' m3 |  M  H图4 串口收发数据报文定义
  N% e% O2 w2 \# A
5 X* B1 N$ u1 Z$ X# J( J( p
a05524e5329f4be8965e7037444c3c6d.png # ^# `$ q+ _3 Q2 r
图5 串口空闲中断处理函数! U' V8 Y* Z  u& ^
————————————————; Q, c' O" J/ ?' T) ]: m9 R
版权声明:青青豌豆/ R" ?0 `; I/ Z
如有侵权请联系删除
* F) k. w( a8 K. _& Z) {
' w, F4 b% A$ ^# }. F- t1 u/ C. x
46009ea4ae2542119d017ef8bcb49abc.png
收藏 评论0 发布时间:2023-3-29 18:42

举报

0个回答

所属标签

相似技术帖

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