STM32F407使用标准库,串口USART2通过DMA进行数据接收使用乒乓缓冲的实例
时间: 2023-06-26 12:06:28 浏览: 108
好的,以下是使用标准库,串口USART2通过DMA进行数据接收使用乒乓缓冲的实例代码:
```c
#include "stm32f4xx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define RX_BUFFER_SIZE 512
volatile uint8_t rx_buffer[2][RX_BUFFER_SIZE];
volatile uint32_t rx_write_index = 0;
volatile uint32_t rx_read_index = 0;
volatile uint32_t rx_count = 0;
volatile uint8_t rx_active_buffer = 0;
void init_usart(void);
void init_dma(void);
void DMA1_Stream5_IRQHandler(void);
int main(void)
{
init_usart();
init_dma();
while (1) {
if (rx_count > 0) {
uint32_t i;
for (i = 0; i < rx_count; i++) {
printf("%c", rx_buffer[rx_read_index][i]);
}
rx_count = 0;
rx_read_index = (rx_read_index + 1) % 2;
}
}
}
void init_usart(void)
{
GPIO_InitTypeDef gpio_init;
USART_InitTypeDef usart_init;
// Enable GPIO clock
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
// Enable USART clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
// Configure USART pins
gpio_init.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
gpio_init.GPIO_Mode = GPIO_Mode_AF;
gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
gpio_init.GPIO_OType = GPIO_OType_PP;
gpio_init.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &gpio_init);
// Connect USART pins to AF
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
// Configure USART
usart_init.USART_BaudRate = 115200;
usart_init.USART_WordLength = USART_WordLength_8b;
usart_init.USART_StopBits = USART_StopBits_1;
usart_init.USART_Parity = USART_Parity_No;
usart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
usart_init.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART2, &usart_init);
// Enable USART
USART_Cmd(USART2, ENABLE);
}
void init_dma(void)
{
DMA_InitTypeDef dma_init;
NVIC_InitTypeDef nvic_init;
// Enable DMA clock
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
// Configure DMA channel
DMA_DeInit(DMA1_Stream5);
dma_init.DMA_Channel = DMA_Channel_4;
dma_init.DMA_PeripheralBaseAddr = (uint32_t)&USART2->DR;
dma_init.DMA_Memory0BaseAddr = (uint32_t)&rx_buffer[0];
dma_init.DMA_DIR = DMA_DIR_PeripheralToMemory;
dma_init.DMA_BufferSize = RX_BUFFER_SIZE;
dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
dma_init.DMA_Mode = DMA_Mode_Circular;
dma_init.DMA_Priority = DMA_Priority_VeryHigh;
dma_init.DMA_FIFOMode = DMA_FIFOMode_Disable;
dma_init.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
dma_init.DMA_MemoryBurst = DMA_MemoryBurst_Single;
dma_init.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream5, &dma_init);
// Enable DMA interrupts
DMA_ITConfig(DMA1_Stream5, DMA_IT_TC, ENABLE);
nvic_init.NVIC_IRQChannel = DMA1_Stream5_IRQn;
nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
nvic_init.NVIC_IRQChannelSubPriority = 0;
nvic_init.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_init);
// Start DMA transfer
DMA_Cmd(DMA1_Stream5, ENABLE);
}
void DMA1_Stream5_IRQHandler(void)
{
if (DMA_GetITStatus(DMA1_Stream5, DMA_IT_TCIF5)) {
DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TCIF5);
// Swap active buffer
rx_active_buffer = (rx_active_buffer + 1) % 2;
// Set DMA memory buffer address
DMA1_Stream5->M0AR = (uint32_t)&rx_buffer[rx_active_buffer];
// Update write index and count
uint32_t new_count = DMA_GetCurrDataCounter(DMA1_Stream5);
rx_count += RX_BUFFER_SIZE - new_count;
rx_write_index = rx_active_buffer;
}
}
```
以上代码中使用了两个缓冲区,即“乒乓缓冲”。DMA接收数据到一个缓冲区时,另一个缓冲区可以被处理。在中断处理程序中,交换缓冲区并更新读写索引和计数器。在主循环中,如果有数据可用,则打印出来。
希望对你有所帮助!
阅读全文