environment:
Host: WINXP
Development environment: MDK4.23
MCU:STM32F103CBT6
illustrate:
The serial port can be configured to receive data using DMA, but DMA requires a fixed length to generate a receive interrupt. How can we receive data of variable length?
There are three methods:
1. Connect the RX pin to an external clock pin. When a frame is sent by the serial port, this timer can be used to generate a timeout interrupt. This has high real-time performance and can achieve real-time monitoring of 1 byte.
2. Without changing the hardware, start a timer to monitor DMA reception, and generate an interrupt if it times out. This is not very real-time, because the timeout must be greater than the time required to receive the frame, and the accuracy is difficult to control.
3. Some serial ports of STM32 microcontrollers can monitor whether the bus is idle, and generate an interrupt if it is idle. It can be used to monitor whether DMA reception is completed. This method has high real-time performance.
This article adopts the third method. The impact of large data packets at a baud rate of 576000 proves to be feasible.
source code:
//Serial port receive DMA buffer
#define UART_RX_LEN 128
extern uint8_t Uart_Rx[UART_RX_LEN];
//Serial port receive DMA buffer
uint8_t Uart_Rx[UART_RX_LEN] = {0};
//---------------------Serial port function configuration---------------------
//Open the peripheral clock corresponding to the serial port
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//Serial port DMA configuration
//Start DMA clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
//DMA send interrupt setting
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//DMA1 channel 4 configuration
DMA_DeInit(DMA1_Channel4);
//Peripheral address
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);
//Memory address
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart_Send_Buffer;
//dma transmission direction is one-way
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
//Set the length of the DMA buffer during transmission
DMA_InitStructure.DMA_BufferSize = 100;
//Set the DMA peripheral increment mode, a peripheral
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
//Set DMA memory increment mode
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//Peripheral data word length
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
//Memory data word length
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
//Set DMA transfer mode
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
//Set the DMA priority level
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
//Set the variables in the two DMA memories to access each other
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4,&DMA_InitStructure);
DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);
// Enable channel 4
//DMA_Cmd(DMA1_Channel4, ENABLE);
//Serial port receiving DMA configuration
//Start DMA clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
//DMA1 channel 5 configuration
DMA_DeInit(DMA1_Channel5);
//Peripheral address
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);
//Memory address
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart_Rx;
//dma transmission direction is one-way
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
//Set the length of the DMA buffer during transmission
DMA_InitStructure.DMA_BufferSize = UART_RX_LEN;
//Set the DMA peripheral increment mode, a peripheral
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
//Set DMA memory increment mode
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//Peripheral data word length
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
//Memory data word length
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
//Set DMA transfer mode
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
//Set the DMA priority level
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
//Set the variables in the two DMA memories to access each other
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5,&DMA_InitStructure);
// Enable channel 5
DMA_Cmd(DMA1_Channel5,ENABLE);
//Initialization parameters
//USART_InitStructure.USART_BaudRate = DEFAULT_BAUD;
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;
USART_InitStructure.USART_BaudRate = DEFAULT_BAUD;
// Initialize the serial port
USART_Init(USART1,&USART_InitStructure);
//TXE send interrupt, TC transmission completion interrupt, RXNE receive interrupt, PE parity error interrupt, can be multiple
//USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
//Interrupt configuration
USART_ITConfig(USART1,USART_IT_TC,DISABLE);
USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
//Configure UART1 interrupt
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //Channel is set to serial port 1 interrupt
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //Interrupt preemption level 0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //Interrupt response priority 0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //Enable interrupt
NVIC_Init(&NVIC_InitStructure);
//Send using DMA
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
//Receive using DMA
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
//Start the serial port
USART_Cmd(USART1, ENABLE);
//Serial port 1 receive interrupt
void USART1_IRQHandler(void)
{
uint32_t temp = 0;
uint16_t i = 0;
if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
{
//USART_ClearFlag(USART1,USART_IT_IDLE);
temp = USART1->SR;
temp = USART1->DR; // Clear USART_IT_IDLE flag
DMA_Cmd(DMA1_Channel5,DISABLE);
temp = UART_RX_LEN - DMA_GetCurrDataCounter(DMA1_Channel5);
for (i = 0;i < temp;i++)
{
Data_Receive_Usart = Uart_Rx[i];
//Start the serial port state machine
usart_state_run();
}
//Set the transmission data length
DMA_SetCurrDataCounter(DMA1_Channel5,UART_RX_LEN);
//Open DMA
DMA_Cmd(DMA1_Channel5,ENABLE);
}
__nop();
}
Test Results:
Conditions: The microcontroller runs at 72M and communicates with the PC at a rate of 460800. The PC sends a 9-byte packet every 100ms: c5 5c 6 0 6F 10 5 4e f7.
Test: Each time the MCU receives this packet, an IO jumps to a level, and then processes and returns a packet.
Oscilloscope display:
Zoom in to show:
Previous article:STM32 serial port 1 send and receive DMA mode function configuration
Next article:STM32F407ZET6 USART DMA mode to send and receive data
Recommended ReadingLatest update time:2024-11-16 15:20
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- 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
- 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
- Working principle, functional characteristics and classification of photoelectric liquid level sensors
- EEWORLD University Hall--Detailed explanation of MATLAB image functions and their applications
- I need help, stlink v2 cannot be recognized and the firmware version cannot be seen
- FPGA Power Consumption
- Easily extend the battery life of the charging box of TWS true wireless Bluetooth headsets
- MSP430FR2355 LaunchPad Development Kit
- NUCLEO_G431RB Review - UART Questions
- Using a fuel gauge chip to achieve fast and intelligent charging of dual-series lithium batteries
- Here is a disassembly picture of ASUS Mars15 VX60GT9750
- 【GD32E231 DIY】Human infrared detection (EXTI)