STM32F407使用标准库实现串口USART2通过DMA使用乒乓缓冲来接收和发送数据
时间: 2023-06-26 22:05:52 浏览: 125
好的,下面是使用标准库实现串口USART2通过DMA使用乒乓缓冲来接收和发送数据的步骤:
1. 配置USART2串口,使其能够使用DMA传输。这涉及到GPIO和USART的配置,具体步骤如下:
```c
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // 使能GPIOA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); // 使能USART2时钟
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); // 配置PA2为USART2的TX引脚
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); // 配置PA3为USART2的RX引脚
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure;
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);
USART_DMACmd(USART2, USART_DMAReq_Rx | USART_DMAReq_Tx, ENABLE); // 使能USART2的DMA传输
```
2. 配置DMA,使其能够在USART2的接收和发送过程中传输数据。这里使用了两个DMA通道(DMA1_Stream5和DMA1_Stream6),分别用于接收和发送数据。
```c
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); // 使能DMA1时钟
DMA_InitTypeDef DMA_InitStructure;
// 配置DMA1_Stream5作为USART2的接收通道
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) & receiveBuffer[0];
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_VeryHigh;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream5, &DMA_InitStructure);
// 配置DMA1_Stream6作为USART2的发送通道
DMA_DeInit(DMA1_Stream6);
DMA_InitStructure.DMA_Channel = DMA_Channel_4;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & (USART2->DR);
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) & sendBuffer[0];
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
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_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream6, &DMA_InitStructure);
DMA_Cmd(DMA1_Stream5, ENABLE); // 使能DMA1_Stream5
DMA_Cmd(DMA1_Stream6, DISABLE); // 禁用DMA1_Stream6
```
3. 实现DMA传输完成的中断处理函数,在接收和发送完成后触发相应的事件。
```c
void DMA1_Stream5_IRQHandler(void) {
if (DMA_GetITStatus(DMA1_Stream5, DMA_IT_TCIF5)) { // 接收完成
DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TCIF5);
receiveComplete = true;
}
}
void DMA1_Stream6_IRQHandler(void) {
if (DMA_GetITStatus(DMA1_Stream6, DMA_IT_TCIF6)) { // 发送完成
DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TCIF6);
sendComplete = true;
}
}
```
4. 实现发送和接收函数,使用乒乓缓冲来存储数据。
```c
void USART2_SendData(const uint8_t *data, uint16_t length) {
while (sendComplete == false); // 等待上一次的发送完成
sendComplete = false;
memcpy(sendBuffer[currentSendBuffer], data, length); // 将待发送的数据拷贝到当前的发送缓冲区
DMA_SetCurrDataCounter(DMA1_Stream6, length); // 设置DMA传输的数据长度
DMA_Cmd(DMA1_Stream6, ENABLE); // 启动DMA传输
currentSendBuffer = (currentSendBuffer + 1) % 2; // 切换发送缓冲区
}
bool USART2_ReceiveData(uint8_t *data, uint16_t length) {
if (receiveComplete == false) { // 如果没有接收到数据,则返回false
return false;
}
memcpy(data, receiveBuffer[currentReceiveBuffer], length); // 将接收到的数据拷贝到指定的缓冲区
receiveComplete = false;
DMA_SetCurrDataCounter(DMA1_Stream5, BUFFER_SIZE); // 重新设置DMA传输的数据长度
currentReceiveBuffer = (currentReceiveBuffer + 1) % 2; // 切换接收缓冲区
return true;
}
```
以上就是使用标准库实现串口USART2通过DMA使用乒乓缓冲来接收和发送数据的全部步骤。
阅读全文