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

【经验分享】UART IDLE 中断使用-接收不定长串口数据

[复制链接]
STMCU小助手 发布时间:2022-2-15 22:07
前言
2 k+ P0 i" _& p- ?" B5 d在串口通信应用中,我们常使用接受和发送中断,相信大家都不陌生。这里有个非常有用的中断可能被大家所忽略,即总线IDLE 中断。当一帧数据传输结束之后,总线会维持高电平状态,此时,就可以触发 MCU 的 IDLE 中断。在本文中,将介绍使用该中断来进行不定长串口数据接收的办法。通过该中断,可以省却很多用于检测数据传输是否完成的判断动作。: X$ M, j- z9 p8 c! r) v. X$ u
实验环境, z) w' L& W$ X: {/ g
   STM32F411RE-NUCLEO7 j* v$ S  {' e$ V2 r, H) K# ~9 I
   STM32CubeMX( ?8 j+ |9 r  U2 @1 r
% W5 k% T! r8 n, D  i* H% U! |+ A
总线状态分析8 i3 K; E8 k; P; h
下图是发送 0xAA 0x55 的所抓取到的波形。从图中我们可以看到在发送该帧之前和之后,数据线处于 IDLE 的状态。在该帧中,字节与字节之间,没有 IDLE 状态出现,即不会出现 IDLE 误触发的情况。
* P* K$ r( S# }7 F/ a4 ], `8 f( |+ h$ ?& K3 l3 T, D4 B8 b
G_YB)_J~CWYDHOKQS]P0.png 1 A& q3 [  _+ E, w# x" t* h( z
) S  N  Z2 H$ D! W
不定长数据接收
4 v' X( m, X0 A( a8 k本次制作的工程是基于 HAL 库。在原生的 HAL 库中,并没有集成 IDLE 中断的处理。所以,在本文我们介绍的方法中,需要修改一些库文件来实现。. V" l6 i) }6 X# f

: w- |4 c+ U4 S# K6 t' m( m使用 STM32CubeMX 生成实验工程
6 Y' e5 Q9 b; E1 R5 C$ Y+ |% h工程的配置如下图:7 z  P# ]( Q& S2 @0 s( W
1. 系统始终配置为 100MHz
2 H! V1 x+ H' C2. 配置 USART2 为 Asynchrones,管脚配置为 PA2,PA3。7 A* j! p4 L. G9 N2 q9 N0 f
3. USART2 参数:9600Bits/s, 8bits, None,1Stop7 I6 R1 r! O0 T* B  v

) x1 Y. q; b) k2 A {NA4%H92Q97)J{D5LUGEWAE.png * C! F+ U8 [$ `. r* l% [
( g% _3 S$ |6 e& t- C* P
为了方便打印接收到的相关信息,需要对生成的工程做如下修改来映射 print 函数。% ]: V, K3 }/ X
main.c-声明
1 G8 O0 H; v, G! b! x+ v4 ]
  1. #ifdef __GNUC__
    ( ?+ |2 {2 r" I: U# J5 Z
  2. /* With GCC, small printf (option LD Linker->Libraries->Small printf3 F$ a1 ^3 N8 L# {! O3 Z5 G
  3. set to 'Yes') calls __io_putchar() */" t- u' m' w  e/ z9 R9 n. X$ i# A
  4. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)$ G0 q% g: O0 k9 L# J' y
  5. #else
    3 l% ]( I5 J: E! G+ S& a$ }
  6. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    , ~5 i# W( t4 V, p
  7. #endif /* __GNUC__ */
复制代码

" ~$ z0 N, |7 `6 T  I+ x
0 t7 n5 r  q1 _8 X: Qmain.c-Code4 R; f7 D( G, v" i3 U
  1. /**
    ; R, a9 h3 r  F( z/ I
  2. 7 g8 W6 E4 Y: B  E/ I
  3. * @brief Retargets the C library printf function to the USART.4 c" K  w0 z) b8 d
  4. * @param None
    & Y# A$ t7 N% @- Z9 _: k. v- Y7 M
  5. * @retval None
    * N' T2 K0 D' r; r+ j+ [. X# o
  6.   *// c0 @! p2 v  Z7 r
  7.   PUTCHAR_PROTOTYPE
    % t. W  C" {1 Y  ~2 g! J
  8.   {
    - T) V2 j  P; P- p+ K/ k
  9.   /* Place your implementation of fputc here */
    * B. z0 M( i& c" {4 _3 B7 H
  10.   /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
    7 p% e$ I8 N' q% K, _* L
  11.   HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);7 L5 s7 {+ y7 Q' e; m; g& |- t( Y
  12.   return ch;, G+ J( y! v& S7 }2 [# o. M! N
  13.   }
复制代码

, [9 v. k/ S* g8 V$ I' f  修改工程代码
9 y" F% D5 Z% G: |) m* F  增加接收 Buffer

/ y- Q9 @0 N, M' g* d7 T. j/ T& ^  main.c; Y$ Y: f$ H1 L- U+ \
  1.   //Modification 0" {7 `7 D2 L2 g* t, M
  2.   //Store the revceived bytes number
    " e! k* o1 e$ V$ R- w7 H
  3.   uint32_t Rev_Size = 0;
    + H% U7 r+ u) w, ^
  4.   //Receive buffer
      X& O5 I: T7 \: Q( ~7 c5 y6 F
  5.   uint8_t UART_RX_Buf[15];
复制代码
9 Q4 @' C! b6 e+ \# a  o* H
  stm32f4xx_hal_uart.c) y6 U7 |9 K0 C" \# Z. m0 m
  1.   //Modification 0
    5 M; x$ ?  X; n; y7 B3 Q, E3 S* V
  2.   extern uint32_t Rev_Size;
复制代码
6 w2 k* P0 i5 x4 d4 W
  在接收函数中使能 IDLE 中断
9 @+ [' W: y9 N) J' lstm32f4xx_hal_uart.c -> HAL_UART_IRQHandler ()函数
7 T$ K: X5 q8 R# o7 Q2 f
  1. //Modification 2
    & {! a1 `+ h, V8 E. L$ f
  2. if(((isrflags & USART_SR_IDLE) != RESET) && ((cr1its & USART_CR1_IDLEIE) != RESET))/ ]% q2 j6 ?$ P( D5 V# }
  3. {& [' e2 J' U* Q
  4. //Record the received bytes number
    0 l: Y9 W' {& n1 [  r
  5. Rev_Size = huart->RxXferSize - huart->hdmarx->Instance->NDTR;
    # Y( k5 v' M" G4 B, r# K6 D# g
  6. //clear the IDLE flag
    # U' A4 W% h8 U& D8 f# X. V' r/ p
  7. __HAL_UART_CLEAR_IDLEFLAG(huart);' M3 `+ p& r" T5 F, S' Z- S; C  h
  8. //Abord the received process" K; W' |, v, T  d- M7 B
  9. HAL_UART_AbortReceive_IT(huart);
    5 T6 A6 O: B5 O; y' o, E
  10. return;
    % ~" ]% ~4 N* ]/ ~- G. E; E" I9 t
  11. }
复制代码

# w0 D% Q- D% t" m! J, ]9 J

3 d8 r/ Z0 |9 O, w) V  J5 ]% _- F接收完成处理(IDLE 产生,一帧数据传输完成)
% B4 K! c0 @! T, v  Dstm32f4xx_hal_uart.c -> HAL_UART_AbortReceive_IT ()函数; }, r, D  k# }$ _; ]
  1. <div>//Modification 3</div><div>CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE| USART_CR1_IDLEIE));</div><div>// CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));</div>
复制代码

% J( Y, M, L8 |
) e8 Q! ~6 d; q2 f' omain.c+ f9 T7 ?% [8 _" `' S
  1. <div><div>//Modification 4</div><div>void HAL_UART_AbortReceiveCpltCallback (UART_HandleTypeDef *huart)</div><div>{</div><div> //Print received Bytes</div><div>printf("\n\r[IDLE]Received %d Bytes:",Rev_Size);</div></div><div><div>for(uint16_t i = 0; i < Rev_Size; i++)</div><div>{</div><div>printf(" 0x%02X", UART_RX_Buf[i]);</div><div>}</div><div>//Re-start receiving</div><div>HAL_UART_Receive_DMA(&huart2, UART_RX_Buf, 15);</div><div> /* NOTE : This function should not be modified, when the callback is needed,</div><div> the HAL_UART_AbortTransmitCpltCallback can be implemented in the user file.</div><div> */</div><div>}</div></div>
复制代码

3 `6 f5 P. J, \! p; \5 t; k3 E/ D; B1 [& w9 {

# g6 u# d( h! j% S' K使能接收
9 `1 |0 t* S8 |4 Q. v& Mmain.c; J/ Z! U8 h( `( r$ t8 x1 m
  1. <div>//Modification 5. ‘15’ is the total number to be received. Make sure it can cover the</div><div>longest frame.</div><div> HAL_UART_Receive_DMA(&huart2, UART_RX_Buf, 15);</div>
复制代码

2 h9 W' s( _/ ~! R& G

# ]1 O! }4 P2 w: ]% j# W实验结果3 E6 a; A5 L  e" B/ Q; P# G8 ~( K) \
使用串口调试串口,通过 STLINK 的虚拟串口发送数据,MCU 会返回接收多少个字节的数据,并将接收到的数据打印出来。
. r( S' C+ J# I& G) T下图是发送 0xAA 0x55 的实验结果。
# T1 j4 _2 F8 S$ e0 S7 d2 N. S7 k- u( G5 }! g2 H( b* t

6 k6 [9 H9 o  `$ } 24I%WL`B_XX29`0L0N}JQ]E.png
( z: t- l+ n  ~( @1 W3 c: \
6 G% V8 s' R4 e5 _) g小结
# E. D6 L% C" m8 l1 Z% kIDLE 作为指示总线空闲状态的中断,合理的使用能够很大程度的节省代码程序设计工作量。这里只是做个简单示范,抛砖引
! J8 R. E! x& @玉,实际应用中希望大家可以灵活使用满足所需。
0 N+ T1 \2 b) A0 Y
+ |% V+ d( _0 v! X( M! L
$ T$ W7 P  E1 }  L6 n: i  O; E4 A
赞 收藏 1 评论0 发布时间:2022-2-15 22:07

举报

0个回答

所属标签

相似技术帖

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