Stm32怎么用串口DMA中断方式接收发送
时间: 2023-08-09 12:10:11 浏览: 263
使用串口 DMA 中断方式接收发送可以大大降低 CPU 的占用率,提高系统的响应速度。下面我简单介绍一下 STM32 使用串口 DMA 中断方式接收发送的步骤。
1. 初始化串口
首先需要初始化串口,设置波特率、数据位、停止位等参数。这里我们以 USART1 为例:
```
// 使能 USART1 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// 初始化 USART1
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(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
```
2. 配置 DMA
接下来配置 DMA,设置 DMA 的传输方向、数据宽度、缓冲区地址等参数。这里我们以 USART1 的 DMA 接收为例:
```
// 使能 DMA1 时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// 配置 DMA1_Channel5(USART1_RX)为普通模式,从外设接收数据,内存地址自增,传输数据宽度为 8 位
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)rx_buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = RX_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_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure);
// 使能 DMA1_Channel5(USART1_RX)传输完成中断
DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
// 使能 DMA1_Channel5(USART1_RX)传输
DMA_Cmd(DMA1_Channel5, ENABLE);
```
3. 配置中断
最后配置中断,使能串口和 DMA 的中断。这里我们以 USART1 的 DMA 接收中断为例:
```
// 使能 USART1 的中断
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 使能 DMA1_Channel5(USART1_RX)的中断
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
```
4. 接收数据
现在我们可以通过 DMA 接收数据了。当 DMA 接收到数据后,会触发 DMA1_Channel5 的传输完成中断,我们可以在中断处理函数中读取接收到的数据:
```
uint8_t rx_buffer[RX_BUFFER_SIZE];
void DMA1_Channel5_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC5))
{
// 读取接收到的数据
uint16_t rx_length = RX_BUFFER_SIZE - DMA_GetCurrDataCounter(DMA1_Channel5);
for(int i = 0; i < rx_length; i++)
{
uint8_t ch = rx_buffer[i];
// 处理接收到的数据
}
// 清除传输完成中断标志
DMA_ClearITPendingBit(DMA1_IT_TC5);
}
}
```
5. 发送数据
除了接收数据以外,我们也可以使用 DMA 发送数据。这里我们以 USART1 的 DMA 发送为例:
```
// 配置 DMA1_Channel4(USART1_TX)为普通模式,从内存发送数据,外设地址自增,传输数据宽度为 8 位
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)tx_buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = tx_length;
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_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
// 使能 DMA1_Channel4(USART1_TX)传输完成中断
DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);
// 使能 DMA1_Channel4(USART1_TX)传输
DMA_Cmd(DMA1_Channel4, ENABLE);
// 等待 DMA1_Channel4(USART1_TX)传输完成
while(DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET);
// 清除传输完成标志
DMA_ClearFlag(DMA1_FLAG_TC4);
```
以上就是 STM32 使用串口 DMA 中断方式接收发送的基本步骤。需要注意的是,配置 DMA 时,要根据实际情况选择传输模式和优先级,以保证数据的正确传输。另外,在中断处理函数中,要及时清除相应的中断标志,以免影响下一次的中断处理。
阅读全文