STM32F407 usart2通过DMA进行数据的接收,接收缓冲区使用乒乓缓存
时间: 2023-06-25 09:03:47 浏览: 269
使用DMA进行数据接收可以大大提高数据传输效率,而乒乓缓存则可以避免接收数据过程中数据覆盖的问题。
具体实现步骤如下:
1. 配置USART2为DMA接收模式,并开启DMA时钟。
2. 配置USART2的接收缓冲区地址和大小,同时开启USART2的接收中断(用于通知DMA传输完成)。
3. 配置DMA传输的目的地址和大小,以及传输模式(循环传输或单次传输)。
4. 创建两个缓冲区,用于存储接收到的数据。这两个缓冲区可以交替使用,即当一个缓冲区满了之后,另一个缓冲区开始接收数据。
5. 在USART2的接收中断中,切换当前使用的缓冲区,并通知DMA传输新的目的地址和大小。
6. 在需要使用接收到的数据时,读取当前未使用的缓冲区。
代码示例:
```
#define BUFFER_SIZE 128
uint8_t buffer1[BUFFER_SIZE];
uint8_t buffer2[BUFFER_SIZE];
uint8_t *current_buffer = buffer1;
void USART2_DMA_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
/* 配置USART2 */
USART_InitStructure.USART_BaudRate = 115200;
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_Init(USART2, &USART_InitStructure);
USART_Cmd(USART2, ENABLE);
/* 配置DMA传输 */
DMA_DeInit(DMA1_Stream5);
DMA_InitStructure.DMA_Channel = DMA_Channel_4;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(USART2->DR);
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)buffer1;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream5, &DMA_InitStructure);
/* 配置USART2接收中断 */
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
/* 启动DMA传输 */
DMA_Cmd(DMA1_Stream5, ENABLE);
}
void USART2_IRQHandler(void)
{
if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) {
/* 切换缓冲区 */
if (current_buffer == buffer1) {
DMA1_Stream5->M0AR = (uint32_t)buffer2;
current_buffer = buffer2;
} else {
DMA1_Stream5->M0AR = (uint32_t)buffer1;
current_buffer = buffer1;
}
/* 通知DMA传输新的目的地址和大小 */
DMA1_Stream5->NDTR = BUFFER_SIZE;
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
}
}
/* 读取当前未使用的缓冲区中的数据 */
void read_data(void)
{
uint8_t *unused_buffer = current_buffer == buffer1 ? buffer2 : buffer1;
/* 处理接收到的数据 */
/* 清空缓冲区 */
memset(unused_buffer, 0, BUFFER_SIZE);
}
```