STM32F407 标准库 串口usart2 dma 乒乓缓冲接收到的数据实例
时间: 2023-06-25 10:06:32 浏览: 351
以下是一个基于STM32F407标准库的串口USART2 DMA乒乓缓冲接收数据的示例代码:
```c
#include "stm32f4xx.h"
#include <stdio.h>
#include <string.h>
#define RX_BUFFER_SIZE 128
uint8_t rx_buffer[RX_BUFFER_SIZE][2]; // 乒乓缓冲区
volatile uint8_t rx_index = 0; // 当前使用的缓冲区下标
volatile uint8_t rx_length[2] = {0, 0}; // 缓冲区数据长度
void USART2_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
// USART2 Tx PA.2 and Rx PA.3 pins configuration
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Connect USART2 pins to AF
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
// USART2 configuration
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_Mode_Tx;
USART_Init(USART2, &USART_InitStructure);
// Enable USART2 DMA RX request
USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);
// DMA1 Stream5 Channel4 configuration
DMA_InitStructure.DMA_Channel = DMA_Channel_4;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)rx_buffer[0];
DMA_InitStructure.DMA_BufferSize = RX_BUFFER_SIZE;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(USART2->DR);
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);
// Enable DMA1 Stream5
DMA_Cmd(DMA1_Stream5, ENABLE);
// Enable USART2
USART_Cmd(USART2, ENABLE);
}
void DMA1_Stream5_IRQHandler(void)
{
if (DMA_GetITStatus(DMA1_Stream5, DMA_IT_TCIF5))
{
DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TCIF5);
// 切换到另一个缓冲区
rx_index ^= 1;
// 计算数据长度
rx_length[rx_index] = RX_BUFFER_SIZE - DMA_GetCurrDataCounter(DMA1_Stream5);
}
}
int main(void)
{
USART2_Config();
while (1)
{
// 处理接收到的数据
if (rx_length[rx_index] > 0)
{
// 处理rx_buffer[rx_index][0]~rx_buffer[rx_index][rx_length[rx_index]-1]中的数据
// ...
// 清空缓冲区
memset(rx_buffer[rx_index], 0, RX_BUFFER_SIZE);
rx_length[rx_index] = 0;
}
}
}
```
这个代码中,使用了一个`rx_buffer`数组来实现乒乓缓冲区,由DMA控制器在两个缓冲区之间进行自动切换。当一个缓冲区中的数据接收完成后,会触发DMA中断,在中断处理函数中切换到另一个缓冲区,并计算出当前缓冲区中接收到的数据长度。在主函数中,可以通过判断`rx_length[rx_index]`是否大于0来判断是否有新的数据到来,然后对当前缓冲区中的数据进行处理,并清空缓冲区。
阅读全文