
问题表现, C- d6 ]+ e e$ N- G$ n8 F 在MCU系统负载较重、串口收发数据频率很高、多个中断存在(如同时有定时器更新中断、外部中断、DMA中断、串口接收中断)的情况下,容易出现串口溢出错误(ORE)。该错误的主要显现形式是:程序莫名卡死在串口中断之中(单片机失去响应)。" b; B% \- i1 P' m / O. k/ T& O4 u3 a 解决方法 ORE标志位在USART_SR寄存器,当我们打开串口接收中断时,同时也就打开了ORE中断,串口的overload错误会导致程序反复进入串口中断服务程序。在中断服务程序中增加处理overload的处理,顺序执行对USART_SR和USART_DR寄存器的读操作可以复位ORE位,以防止程序反复进入串口中断服务程序。示例代码如下:' k; y( z0 ]' a 在STM32中断函数增加USART_IT_ORE等异常中断的处理,执行USART_GetFlagStatus(USART1, USART_FLAG_ORE),会对USART_SR进行了一次读操作,然后再执行USART_ReceiveByte(USART1),会对USART_DR进行一次读操作,从而复位了ORE位。% n0 f0 p. L( ? /** * @brief Checks whether the specified USART flag is set or not. * @param USARTx: Select the USART or the UART peripheral. % S" O/ B: F9 O1 Z * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5./ f- I- |8 B; b) [ * @param USART_FLAG: specifies the flag to check. * This parameter can be one of the following values:+ o6 ?0 i: Q% q6 Y# Z. ~ * @arg USART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5); k8 o" D9 R2 A2 z; A) P8 E! O3 ^ * @arg USART_FLAG_LBD: LIN Break detection flag2 N) ~- Z' F% X& V8 d * @arg USART_FLAG_TXE: Transmit data register empty flag1 ?% V& Z* g, o% S' d( v; j * @arg USART_FLAG_TC: Transmission Complete flag * @arg USART_FLAG_RXNE: Receive data register not empty flag * @arg USART_FLAG_IDLE: Idle Line detection flag; I6 ?" C* _0 \& W3 |! K0 f2 N * @arg USART_FLAG_ORE: OverRun Error flag * @arg USART_FLAG_NE: Noise Error flag \( h L+ ~* |" e, n6 a * @arg USART_FLAG_FE: Framing Error flag * @arg USART_FLAG_PE: Parity Error flag * @retval The new state of USART_FLAG (SET or RESET).4 r/ I2 @: q, t+ x. S! S/ ^; z7 q: s */ FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG) { FlagStatus bitstatus = RESET; /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx));- y* b/ b; U& P8 ~, i$ H assert_param(IS_USART_FLAG(USART_FLAG)); /* The CTS flag is not available for UART4 and UART5 */ if (USART_FLAG == USART_FLAG_CTS); i# G0 q& Y9 f9 X/ B {, Z3 }3 j% B% [% H8 d) d assert_param(IS_USART_123_PERIPH(USARTx)); } & ]0 i9 y* v2 w/ e5 K0 C; ]6 M if ((USARTx->SR & USART_FLAG) != (uint16_t)RESET) {3 R. t) a+ b4 } bitstatus = SET;4 ]6 P J5 h- i$ h. m } else {4 O T/ f" x% h& f" S5 K bitstatus = RESET; }7 p; G7 l2 O5 w. u, @8 p0 y4 j return bitstatus; } + ]8 T8 r- A: _2 s+ N( r /**% m8 M# y \2 U: x/ z' G * @brief Returns the most recent received data by the USARTx peripheral.4 T: L# g6 d' e! l * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values:4 `0 ~: j; i% p$ u; k7 e* ] * USART1, USART2, USART3, UART4 or UART5.* F6 F# ^, I* C* x * @retval The received data. */" e( O/ z8 {* Z) v! Z3 X uint16_t USART_ReceiveByte(USART_TypeDef* USARTx) {* _6 q4 S6 \ V /* Check the parameters */: N5 T/ s9 o3 }: E assert_param(IS_USART_ALL_PERIPH(USARTx)); N5 ~% L& U+ j# S, ` 7 k5 t3 p9 w" w S2 j9 b% Y n0 _ /* Receive Data */ return (uint16_t)(USARTx->DR & (uint16_t)0x01FF);9 j4 Y* ~+ n g% b. V } * e- p( P N" F$ L , P0 y7 Z+ O" `: q( T1 K$ B9 K3 Z 1 c$ d4 N {8 j void USART1_IRQHandler(void)& }$ p5 \' Q- O. v { /**1 s3 o1 j1 M$ p& @) ?1 d * 如果使能串口接收中断,那么ORE为1时也会产生中断。 * 在应用中对ORE标志进行处理,当判断发生ORE中断的时候, * 我们再读一次USART_DR的值,( ^" w7 Y3 z) [& B: D5 o/ ]( r * 这样如果没有新的Overrun 溢出事件发生的时候,ORE会被清除,+ G, I6 ~1 \# C2 R1 `+ x8 Z * 然后程序就不会因为ORE未被清除而一直不断的进入串口中断 */ //没有使能USART_IT_ERR中断时,ORE中断只能使用USART_GetFlagStatus(USART1, USART_FLAG_ORE)读到4 _. y' p$ Z$ L' Z. ? if(USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET): D' P$ |: s- {- j& D { //(void)USARTx->SR; //(vois)USARTx->DR; //先读SR再读DR寄存器$ [2 \' T i; c( v$ m+ F- V* c USART_ReceiveByte(USART1);3 N) E( w+ p4 O" `7 W) ~1 f - t4 T2 E: p0 G! _! X, D //USART_ClearFlag(USART1, USART_FLAG_ORE); }8 E8 b9 i& j D) R! b% y. r //处理接收到的数据(示例为FIFO缓冲队列), `+ t) p; H! l2 l, Q! x if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { USART_ClearITPendingBit(USART1, USART_IT_RXNE);& H( T$ w# u* i- \ *USART_RevPointer[0][0] = (u8) USART_ReceiveByte(USART1);" _) @/ S! x6 p- g% a& q USART_RevPointer[0][0]++; USART_RevCount[0]++;6 Z7 v& u% ^0 y4 m4 c* e ) Q5 K$ {) ?1 g& G+ g! h! i7 a if (USART_RevPointer[0][0] >= USART_RevBuffer[0] + USART_BufferSize[0]) USART_RevPointer[0][0] = USART_RevBuffer[0];& q: \4 X; C! F1 y7 F7 N0 R2 X }0 D$ X" u0 T; v% I/ @ }( }7 M5 U8 k4 E7 N. t2 k' n$ q' t* V / {) N2 a5 z! j$ }/ a |
实战经验 | Keil工程使用NEAI库的异常问题
STM32 ISP IQTune:真正零门槛的免费ISP调整软件
【经验分享】STM32 新建基于STM32F40x 固件库的MDK5 工程
意法半导体MCU双供应链策略,打消中国客户后顾之忧
【经验分享】基于STM32使用HAL库实现USB组合设备CDC+MSC
2024意法半导体工业峰会:赋能智能电源和智能工业,构筑可持续未来
ST推出灵活、面向未来的智能电表通信解决方案,助力能源转型
意法半导体 x Qu-Bit Electronix:推动新一轮的数字声音合成革命
从STM32 MPU产品看嵌入式系统中微处理器的新变化
【Hot!】STM32全系列开发板都支持Arduino开发,你知道吗?