Debugging revealed that it was a hardware bug of the serial port interrupt:
1. USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); The receive interrupt is enabled, and the ORE interrupt is also enabled at the same time.
2. The ORE interrupt can only be read using USART_GetFlagStatus(USART1, USART_FLAG_ORE) (when USART_IT_ERR interrupt is not enabled)
Solution:
1. Enable interrupts during initialization
USART_ITConfig(USART1, USART_IT_PE, ENABLE); //Enable PE error reception interrupt Bit 8PEIE: PE interrupt enable
//CR2 enables ERR interrupt
USART_ITConfig(USART1, USART_IT_ERR, ENABLE);
2. Add USART_IT_ORE and other exception interrupt processing to the STM32 interrupt function!
//Enable EIE of CR3, bit0: Error interrupt enable, handle USART_IT_ERR, USART_IT_ORE_ER, USART_IT_NE, USART_IT_FE error
if(USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET)
{//Same as @arg USART_IT_ORE_ER: OverRun Error interrupt if the EIE bit is set
ushTemp = USART_ReceiveData(USART1); //Take out and throw away
USART_ClearFlag(USART1, USART_FLAG_ORE);
}
if(USART_GetFlagStatus(USART1, USART_FLAG_NE) != RESET)
{//Same as @arg USART_IT_NE: Noise Error interrupt
USART_ClearFlag(USART1, USART_FLAG_NE );
}
if(USART_GetFlagStatus(USART1, USART_FLAG_FE) != RESET)
{//Same as @arg USART_IT_FE: Framing Error interrupt
USART_ClearFlag(USART1, USART_FLAG_FE);
}
if(USART_GetFlagStatus(USART1, USART_FLAG_PE) != RESET)
{//Same as @arg USART_IT_PE: Parity Error interrupt
USART_ClearFlag(USART1, USART_FLAG_PE);
}
There is also an article on the Internet that explains it in more detail, please take a look!
http://bbs.21ic.com/viewthread.php?tid=160999&highlight=USART
Today, I encountered some problems when using the USART module and solved them, so I posted them to share.
Problem description:
When using USART for serial communication, I only turned on the receive interrupt and set the preemption priority to the lowest level. The previous priority of the receive interrupt handles more things, which may take up 2ms. When I use 9600 baud rate to send data to the lower computer, the speed is very fast, just keep pressing enter to send! The problem comes out. In less than 1 minute, the communication is unresponsive. The USART configuration code is as follows:
void uart_config(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = UART_GetBaud(BaudRate);
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_Init Structure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode
= USART_Mode_Rx | USART_Mode_Tx; OL
= USART_CPOL_Low;
USART_InitStructure.USART_CPHA = USART_CPHA_2Edge;
USART_InitStructure.USART_LastBit = USART_LastBit_Enable;
/* Configure USART1 */
USART_Init(USART1, &USART_InitStructure);
/* Enable USART1 receive interrupt */
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
/* Enable the USART1 */
USART_Cmd(USART1, ENABLE);
}
Analysis of the problem:
1. Why is there no communication?
Through the emulator simulation, it is found that the program has been entering the receive interrupt. Since I did not use the interrupt to send, the program died in the receive interrupt, and no data was sent to the computer. The receive interrupt code is as follows:
void UART_Receive(void)
{
//Processing the previous communication, do not process the received data
if(bRecieveOK)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
return;//processing receive data,don't receive again
}
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
if(MoudBusExpir == 0)
{
ucRcePtr = 0;
MoudBusExpir = 20;//50ms
}
else
MoudBusExpir = 20;
/* Read one byte from the receive data register */
ucRS485Buff[ucRcePtr++] = USART_ReceiveData(USART1);
/* Clear the USART1 Receive interrupt */
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
2. Why does it keep running to the receive interrupt?
After the breakpoint, I found that (USART_GetITStatus(USART1, USART_IT_RXNE)==RESET, which means that the interrupt was entered even though no data was received, and I only turned on the receive interrupt in the USART configuration! It should be impossible to enter the interrupt without data sent!
3. What interrupt was responded to?
I wanted to read all the interrupt status through the function (USART_GetITStatus(), but failed. All interrupt status of USART_IT_XXX are RESET! That is to say, it entered this interrupt service routine even without an interrupt! ?
4. Looking for information
STM32F10x Microcontroller Reference Manual (10th Edition, December 2009) P541 found the following description:
That is to say, as long as the receive interrupt is turned on, that is, RXNEIE is set to 1, then the ORE interrupt is automatically turned on.
But USART_GetITStatus(USART1, USART_IT_ORE )== RESET!!!!
Found the USART_GetITStatus(USART1, USART_IT_RXNE) function and found that the ORE interrupt can only be read when the USART_IT_ERR interrupt is enabled.
Here I want to point out this BUG: the ORE interrupt is generated, but the USART_GetITStatus() function cannot read that the interrupt is SET!
5. Clear the ORE interrupt flag bit
Since we have found what interrupt it is, it should be OK to clear the corresponding interrupt flag bit, right?
USART_ClearITPendingBit(USART1, USART_IT_ORE);
However, the result is that there is no effect! After clearing, read the ORE interrupt status immediately, USART_GetITStatus(USART1, USART_IT_ORE)==RESET. The program still runs dead on the receiving interrupt. Use another function USART_GetFlagStatus(USART1,USART_FLAG_ORE) = SET, it turns out that the ORE flag bit has not been cleared.
6. Problem Solved
Why can't it be cleared? I was troubled, so I looked for more information and found that on page P523, as shown below:
The receive interrupt program is changed to:
void UART_Receive(void)
{
if (USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET) // Note! Cannot use if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) to judge
{
USART_ReceiveData(USART1);
}
//Processing the previous communication, do not process the received data
if(bRecieveOK)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
return;//processing receive data,don't receive again
}
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
if(MoudBusExpir == 0)
{
ucRcePtr = 0;
MoudBusExpir = 20;//50ms
}
else
MoudBusExpir = 20;
/* Read one byte from the receive data register */
ucRS485Buff[ucRcePtr++] = USART_ReceiveData(USART1);
/* Clear the USART1 Receive interrupt */
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
Summary:
Note: 1. USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); enables the receive interrupt, so the ORE interrupt is also enabled.
2. The ORE interrupt can only be read using USART_GetFlagStatus(USART1, USART_FLAG_ORE) (when the USART_IT_ERR interrupt is not enabled)
BUG suggestion: 1. In the STM32 library, can the USART_GetITStatus() function be modified to handle the USART_IT_ORE interrupt? In other words, as long as I turn on the receive interrupt, I can also use USART_GetITStatus(USART1,USART_IT_ORE) to read it when there is an ORE interrupt.
Previous article:STM32 USART library function USART_SendData bug
Next article:Regular garbled characters encountered in STM32 serial communication
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Do you know all the various motors commonly used in automotive electronics?
- What are the functions of the Internet of Vehicles? What are the uses and benefits of the Internet of Vehicles?
- Power Inverter - A critical safety system for electric vehicles
- Analysis of the information security mechanism of AUTOSAR, the automotive embedded software framework
- Brief Analysis of Automotive Ethernet Test Content and Test Methods
- How haptic technology can enhance driving safety
- Let’s talk about the “Three Musketeers” of radar in autonomous driving
- Why software-defined vehicles transform cars from tools into living spaces
- How Lucid is overtaking Tesla with smaller motors
- Wi-Fi 8 specification is on the way: 2.4/5/6GHz triple-band operation
- Taking a “family-first” approach to op amp design
- Who knows the name of the chip?
- How to realize 12864 display of 430f149 MCU AD sampling waveform
- Pre-match training FAQ: Detailed explanation of ON Semiconductor's ultra-low power RSL10 Bluetooth SoC development board
- How to start with PCB layout and wiring to avoid noise caused by improper switching power supply layout
- EEWORLD University ---- Type-C end-to-end solution
- Diary of the trouble of building TMS320F28379D project with css6.0
- ESP32-S2 Development Pitfalls (4) -- USB Pitfalls
- Analysis of several components of switching power supply that "seriously affect the cost"!
- Three differential amplifier circuits, available for actual testing