This method uses a timer to periodically query the data received by DMA. If it exceeds the set period, it is considered that the data packet has ended, and the data is copied to the buffer and handed over to other programs for processing. It can receive data packets of any size, especially suitable for protocols such as MODBUS. It has been used for GPS, GPRS, etc., and is very practical. This method takes up very little CPU time, especially when the baud rate is very high, the effect is more obvious.
When the data reception of a serial port times out, the data is copied to the buffer in the timer interrupt. The data flag UART1_Flag can be judged in the main program. When it is greater than 0, it means that data has been received and can be processed. After processing, this variable can be cleared.
When the interval between two data packets is small, the timer period can be shortened.
//Timeout definition
#define UART1_TimeoutComp 2 //20ms
#define UART2_TimeoutComp 10 //100ms
#define UART3_TimeoutComp 10 //100ms
#define SRC_USART1_DR (&(USART1->DR)) //Serial port receive register as source
#define SRC_USART2_DR (&(USART2->DR)) //Serial port receive register as source
#define SRC_USART3_DR (&(USART3->DR)) //Serial port receive register as source
extern u16 UART1_Flag,UART2_Flag,UART3_Flag;
extern u8 uart1_data[200],uart3_data[500],uart2_data[500];
u8 UART1_Timeout,UART2_Timeout,UART3_Timeout;
u16 UART1_FlagTemp,UART2_FlagTemp,UART3_FlagTemp;
u8 uart1_data_temp[200],uart2_data_temp[500],uart3_data_temp[500];
u16 uart1_Flag_last=0,uart2_Flag_last=0,uart3_Flag_last=0;
//Timer initialization
void TimerInit(void)
{
//Timer initialization data structure definition
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
//Initialize timer for timeout reception, 20ms
//Reset counter
TIM_DeInit(TIM2);
TIM_TimeBaseStructure.TIM_Period = 100; //Count upper limit, 100*100us = 10000us = 10ms
TIM_TimeBaseStructure.TIM_Prescaler = 4799; //Pre-divided 4800, 48MHz main frequency, divided clock period 100us
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //No frequency division
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //Count up
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
//Initialize
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
//Clear interrupt
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
//Enable timer interrupt
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
TIM_UpdateDisableConfig(TIM2,DISABLE);
//Timer clear
TIM_SetCounter(TIM2,0);
//Timer start
TIM_Cmd(TIM2,ENABLE);
}
//DMA initialization, only one channel is listed, the other two channels are the same
void DMA5_Init(void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel5); //Reset DMA channel 1 register to default value
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)SRC_USART1_DR; //Source BUF is (&(USART1->DR))
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)uart1_data_temp; //Destination BUF is to be written into which array DMA_InitStructure.DMA_DIR
= DMA_DIR_PeripheralSRC; //Peripheral as source //Is the peripheral the destination or source of data transmission
DMA_InitStructure.DMA_BufferSize = 200; //The size unit of DMA buffer is set below
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //Peripheral address register does not incrementDMA_InitStructure.DMA_MemoryInc
= DMA_MemoryInc_Enable; //Memory address incrementDMA_InitStructure.DMA_PeripheralDataSize
= DMA_PeripheralDataSize_Byte; //Peripheral bytes are in unitsDMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte
; //Memory bytes are in unitsDMA_InitStructure.DMA_Mode
= DMA_Mode_Circular; //Work in circular cache modeDMA_InitStructure.DMA_Priority
= DMA_Priority_High; //One of the 4 priorities (high priority) VeryHigh/High/Medium/Low
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //Non-memory to memoryDMA_Init
(DMA1_Channel5, &DMA_InitStructure); //Initialize DMA channel 1 register according to the parameters specified in DMA_InitStructDMA_ITConfig
(DMA1_Channel5, DMA_IT_TC, ENABLE); //DMA5 transfer completion
interruptUSART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); //Enable USART1 receive DMA requestDMA_Cmd
(DMA1_Channel5, ENABLE); //Formally allow DMA
}
//Serial port initialization, only one channel is listed, the other two channels are
the samevoid USART1_Configuration(void)
{
//Serial port initialization data structure definitionUSART_InitTypeDef
USART_InitStructure;
//Initialize the serial port to 38400,n,8,1
USART_InitStructure.USART_BaudRate = 38400 ;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ; USART_InitStructure.USART_HardwareFlowControl
= USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
//Initialize
USART_Init(USART1, &USART_InitStructure);
//Start the serial port, no need to receive interrupt
USART_Cmd(USART1, ENABLE);
//Default is set to input state
DMA5_Init();
}
//Timer interrupt service routine
void TIM2_IRQHandler(void)
{
u16 i;
//Clear timer interrupt
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update);
UART1_Timeout++;
UART2_Timeout++;
UART3_Timeout++;
//------------------------------------------------------------------
i=DMA_GetCurrDataCounter(DMA1_Channel5);
DMA_ClearITPendingBit(DMA1_IT_GL5); //Clear all interrupt flagsif
(i!=uart1_Flag_last) //Unfinished transmission
{
UART1_Timeout=0;
uart1_Flag_last=i;
}
else
{
if(UART1_Timeout>UART1_TimeoutComp) //Timeout
{
if(i<200) //Data received
{
UART1_FlagTemp=200-i; //Get the number of bytes receivedfor
(i=0;i
uart1_data[i]=uart1_data_temp[i];
UART1_Flag=UART1_FlagTemp;
DMA_ClearFlag(DMA1_FLAG_TC5);
DMA_Cmd(DMA1_Channel5, DISABLE); //Formally allow DMA
DMA5_Init();
}
UART1_Timeout=0;
}
}
//------------------------------------------------------------------
i=DMA_GetCurrDataCounter(DMA1_Channel6);
DMA_ClearITPendingBit(DMA1_IT_GL6); //Clear all interrupt flags
if(i!=uart2_Flag_last) //Unfinished transmission
{
UART2_Timeout=0;
uart2_Flag_last=i;
}
else
{
if(UART2_Timeout>UART2_TimeoutComp) //Timeout occurs
{
if(i<500) //Data is received
{
UART2_FlagTemp=500-i; //Get the number of bytes receivedfor
(i=0;i
[i]=uart2_data_temp[i];
UART2_Flag=UART2_FlagTemp;
DMA_ClearFlag(DMA1_FLAG_TC6);
DMA_Cmd(DMA1_Channel6, DISABLE); //Formally allow DMA
DMA6_Init();
}
UART2_Timeout=0;
}
}
//------------------------------------------------------------------
i=DMA_GetCurrDataCounter(DMA1_Channel3);
DMA_ClearITPendingBit(DMA1_IT_GL3); //Clear all interrupt flagsif
(i!=uart3_Flag_last) //Unfinished transmission
{
UART3_Timeout=0;
uart3_Flag_last=i;
}
else
{
if(UART3_Timeout>UART3_TimeoutComp) //Timeout occurs
{
if(i<500) //Data received
{
UART3_FlagTemp=500-i; //Get the number of bytes receivedfor
(i=0;i
[i]=uart3_data_temp[i];
UART3_Flag=UART3_FlagTemp;
DMA_ClearFlag(DMA1_FLAG_TC3);
DMA_Cmd(DMA1_Channel3, DISABLE); //Formally allow DMA
DMA3_Init();
}
UART3_Timeout=0;
}
}
}
Keywords:STM32
Reference address:STM32 serial port DMA timeout reception method can greatly save CPU time
When the data reception of a serial port times out, the data is copied to the buffer in the timer interrupt. The data flag UART1_Flag can be judged in the main program. When it is greater than 0, it means that data has been received and can be processed. After processing, this variable can be cleared.
When the interval between two data packets is small, the timer period can be shortened.
//Timeout definition
#define UART1_TimeoutComp 2 //20ms
#define UART2_TimeoutComp 10 //100ms
#define UART3_TimeoutComp 10 //100ms
#define SRC_USART1_DR (&(USART1->DR)) //Serial port receive register as source
#define SRC_USART2_DR (&(USART2->DR)) //Serial port receive register as source
#define SRC_USART3_DR (&(USART3->DR)) //Serial port receive register as source
extern u16 UART1_Flag,UART2_Flag,UART3_Flag;
extern u8 uart1_data[200],uart3_data[500],uart2_data[500];
u8 UART1_Timeout,UART2_Timeout,UART3_Timeout;
u16 UART1_FlagTemp,UART2_FlagTemp,UART3_FlagTemp;
u8 uart1_data_temp[200],uart2_data_temp[500],uart3_data_temp[500];
u16 uart1_Flag_last=0,uart2_Flag_last=0,uart3_Flag_last=0;
//Timer initialization
void TimerInit(void)
{
//Timer initialization data structure definition
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
//Initialize timer for timeout reception, 20ms
//Reset counter
TIM_DeInit(TIM2);
TIM_TimeBaseStructure.TIM_Period = 100; //Count upper limit, 100*100us = 10000us = 10ms
TIM_TimeBaseStructure.TIM_Prescaler = 4799; //Pre-divided 4800, 48MHz main frequency, divided clock period 100us
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //No frequency division
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //Count up
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
//Initialize
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
//Clear interrupt
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
//Enable timer interrupt
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
TIM_UpdateDisableConfig(TIM2,DISABLE);
//Timer clear
TIM_SetCounter(TIM2,0);
//Timer start
TIM_Cmd(TIM2,ENABLE);
}
//DMA initialization, only one channel is listed, the other two channels are the same
void DMA5_Init(void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel5); //Reset DMA channel 1 register to default value
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)SRC_USART1_DR; //Source BUF is (&(USART1->DR))
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)uart1_data_temp; //Destination BUF is to be written into which array DMA_InitStructure.DMA_DIR
= DMA_DIR_PeripheralSRC; //Peripheral as source //Is the peripheral the destination or source of data transmission
DMA_InitStructure.DMA_BufferSize = 200; //The size unit of DMA buffer is set below
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //Peripheral address register does not incrementDMA_InitStructure.DMA_MemoryInc
= DMA_MemoryInc_Enable; //Memory address incrementDMA_InitStructure.DMA_PeripheralDataSize
= DMA_PeripheralDataSize_Byte; //Peripheral bytes are in unitsDMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte
; //Memory bytes are in unitsDMA_InitStructure.DMA_Mode
= DMA_Mode_Circular; //Work in circular cache modeDMA_InitStructure.DMA_Priority
= DMA_Priority_High; //One of the 4 priorities (high priority) VeryHigh/High/Medium/Low
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //Non-memory to memoryDMA_Init
(DMA1_Channel5, &DMA_InitStructure); //Initialize DMA channel 1 register according to the parameters specified in DMA_InitStructDMA_ITConfig
(DMA1_Channel5, DMA_IT_TC, ENABLE); //DMA5 transfer completion
interruptUSART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); //Enable USART1 receive DMA requestDMA_Cmd
(DMA1_Channel5, ENABLE); //Formally allow DMA
}
//Serial port initialization, only one channel is listed, the other two channels are
the samevoid USART1_Configuration(void)
{
//Serial port initialization data structure definitionUSART_InitTypeDef
USART_InitStructure;
//Initialize the serial port to 38400,n,8,1
USART_InitStructure.USART_BaudRate = 38400 ;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ; USART_InitStructure.USART_HardwareFlowControl
= USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
//Initialize
USART_Init(USART1, &USART_InitStructure);
//Start the serial port, no need to receive interrupt
USART_Cmd(USART1, ENABLE);
//Default is set to input state
DMA5_Init();
}
//Timer interrupt service routine
void TIM2_IRQHandler(void)
{
u16 i;
//Clear timer interrupt
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update);
UART1_Timeout++;
UART2_Timeout++;
UART3_Timeout++;
//------------------------------------------------------------------
i=DMA_GetCurrDataCounter(DMA1_Channel5);
DMA_ClearITPendingBit(DMA1_IT_GL5); //Clear all interrupt flagsif
(i!=uart1_Flag_last) //Unfinished transmission
{
UART1_Timeout=0;
uart1_Flag_last=i;
}
else
{
if(UART1_Timeout>UART1_TimeoutComp) //Timeout
{
if(i<200) //Data received
{
UART1_FlagTemp=200-i; //Get the number of bytes receivedfor
(i=0;i
UART1_Flag=UART1_FlagTemp;
DMA_ClearFlag(DMA1_FLAG_TC5);
DMA_Cmd(DMA1_Channel5, DISABLE); //Formally allow DMA
DMA5_Init();
}
UART1_Timeout=0;
}
}
//------------------------------------------------------------------
i=DMA_GetCurrDataCounter(DMA1_Channel6);
DMA_ClearITPendingBit(DMA1_IT_GL6); //Clear all interrupt flags
if(i!=uart2_Flag_last) //Unfinished transmission
{
UART2_Timeout=0;
uart2_Flag_last=i;
}
else
{
if(UART2_Timeout>UART2_TimeoutComp) //Timeout occurs
{
if(i<500) //Data is received
{
UART2_FlagTemp=500-i; //Get the number of bytes receivedfor
(i=0;i
UART2_Flag=UART2_FlagTemp;
DMA_ClearFlag(DMA1_FLAG_TC6);
DMA_Cmd(DMA1_Channel6, DISABLE); //Formally allow DMA
DMA6_Init();
}
UART2_Timeout=0;
}
}
//------------------------------------------------------------------
i=DMA_GetCurrDataCounter(DMA1_Channel3);
DMA_ClearITPendingBit(DMA1_IT_GL3); //Clear all interrupt flagsif
(i!=uart3_Flag_last) //Unfinished transmission
{
UART3_Timeout=0;
uart3_Flag_last=i;
}
else
{
if(UART3_Timeout>UART3_TimeoutComp) //Timeout occurs
{
if(i<500) //Data received
{
UART3_FlagTemp=500-i; //Get the number of bytes receivedfor
(i=0;i
UART3_Flag=UART3_FlagTemp;
DMA_ClearFlag(DMA1_FLAG_TC3);
DMA_Cmd(DMA1_Channel3, DISABLE); //Formally allow DMA
DMA3_Init();
}
UART3_Timeout=0;
}
}
}
Previous article:STM32 serial port DMA mode receives data
Next article:Use of STM32 SPI DMA
Recommended ReadingLatest update time:2024-11-16 15:19
STM32 - interrupt priority
Interrupts are an important type of system resource, which can play an indispensable role in the operation of hardware. Basically, every hardware will have corresponding interrupts, but it is just a matter of the type and number of interrupts. For example, the hardware of the 51 single-chip microcomputer has relati
[Microcontroller]
stm32 Flash read and write
The programming operation of stm32 can be realized by reading and writing the flash inside stm32.
The built-in programmable Flash of stm32 is of great significance in many occasions. For example, its support for ICP features allows developers to debug and develop stm32, and can prog
[Microcontroller]
The transplantation process of generating no less than 64 bytes of transmission based on STM32 HID routines
Preface
This article briefly introduces how to use the ST USB HID (MOUSE) routine to generate a transplant process that can input and output any length less than or equal to 64 bytes.
Problem description:
HID is widely used in USB, but many applications are not simple mouse or keyboard operations, but some customiz
[Microcontroller]
STM32 serial port obtains ammonia sensor data
Sensor: ZE03 electrochemical module NH3NH3 (0-100ppm) This is similar to the previous blog post about the STM32 serial port receiving laser dust sensor. Because this sensor provides serial port output data, other configurations can remain the same as the dust sensor. The main thing to do is to modify the serial port
[Microcontroller]
stm32-Serial port uses IDLE interrupt to accept variable length data method
Method 1: The serial port receives data, and the timer is used to determine whether the data reception is completed after the timeout. Method 2: DMA accept + IDLE interrupt Implementation idea: Use the serial port 1 of STM32F103, configure it to the idle interrupt IDLE mode and enable DMA reception, and set the re
[Microcontroller]
STM32 APB1 bus clock configuration problem
When debugging the carrier communication system, I encountered such a problem: two devices, A and B, both used timers 2~4 for communication, PCLK1 of device A was configured as HCLK, and PCLK1 of device B was configured as 1/2HCLK. During the communication process, it was found that A and B could communicate occasional
[Microcontroller]
STM32 interrupt vector nesting NVIC understanding
1. Interrupt priority:
The concept of priority in STM32 (Cortex-M3)
There are two concepts of priority in STM32 (Cortex-M3) - preemptive priority and response priority. Some people call response priority 'sub-priority' or 'sub-priority'. Each interrupt source needs to be assigned these two priorities.
An interrup
[Microcontroller]
- Popular Resources
- Popular amplifiers
Recommended Content
Latest Microcontroller Articles
He Limin Column
Microcontroller and Embedded Systems Bible
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
MoreSelected Circuit Diagrams
MorePopular Articles
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
MoreDaily News
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
Guess you like
- I'm a newbie. I don't understand. I'm asking for help on the problem I encountered when making a spi receiving module in Verilog.
- How feasible is it for the United States to skip 5G and go directly to 6G?
- 77 GHz Radar Solutions
- Showing Goods (7) - Open Source Development Board
- New version of IAR installation problems and solutions
- arm assembly instructions WFI and WFE
- IMX6 EK200 RTL8188EUS WIFI AP
- Methods for supporting national encryption algorithms in embedded devices
- Discussion: 5G and the Internet of Things, have they moved your cheese?
- Matlab Machine Learning (English and Chinese subtitles)