stm32f103空闲中断dma
时间: 2025-06-20 08:53:37 浏览: 14
### STM32F103空闲中断中使用DMA的实现方法
在STM32F103微控制器中,USART模块支持通过DMA方式传输数据。当USART处于空闲状态(即检测到IDLE线信号)时,可以触发一个中断事件,并结合DMA控制器完成数据的自动传输。以下是实现该功能的具体方法和代码示例。
#### 1. 配置USART的空闲中断
为了使能USART的空闲中断,需要配置USART的控制寄存器以启用IDLE中断。通过设置USART_CR1寄存器中的IDLEIE位为1,可以使能空闲中断[^1]。
```c
// 使能 USART0 的 IDLE 中断
USART_ITConfig(USART0, USART_IT_IDLE, ENABLE);
```
#### 2. 配置DMA控制器
DMA控制器需要配置为从USART接收缓冲区读取数据并存储到指定的内存区域。具体步骤包括选择DMA通道、配置传输方向、数据宽度以及使能DMA请求等。
```c
// 配置 DMA 控制器
DMA_InitTypeDef DMA_InitStruct;
DMA_InitStruct.DMA_Channel = DMA1_Channel5; // 选择 DMA 通道
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&USART0->DR; // 外设地址为 USART 数据寄存器
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)buffer; // 内存地址为目标缓冲区
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC; // 数据从外设到内存
DMA_InitStruct.DMA_BufferSize = BUFFER_SIZE; // 缓冲区大小
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址不递增
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; // 内存地址递增
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 数据宽度为字节
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 数据宽度为字节
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal; // 正常模式
DMA_InitStruct.DMA_Priority = DMA_Priority_High; // 高优先级
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable; // 禁用 FIFO 模式
DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; // FIFO 阈值
DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single; // 单次传输
DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; // 单次传输
DMA_Init(DMA1_Channel5, &DMA_InitStruct); // 初始化 DMA 通道
```
#### 3. 使能USART的DMA请求
为了将USART的数据传输与DMA关联,需要使能USART的DMA接收请求。
```c
// 使能 USART0 的 DMA 接收请求
USART_DMACmd(USART0, USART_DMAReq_Rx, ENABLE);
```
#### 4. 实现空闲中断处理函数
在空闲中断处理函数中,可以通过DMA控制器启动数据传输。当检测到IDLE线信号时,调用DMA控制器开始从USART接收数据。
```c
void USART0_IRQHandler(void) {
if (RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE)) { // 检查是否为 IDLE 中断
DMA_Cmd(DMA1_Channel5, ENABLE); // 启动 DMA 传输
while (DMA_GetCmdStatus(DMA1_Channel5) == ENABLE); // 等待 DMA 传输完成
usart_interrupt_flag_clear(USART0, USART_INT_FLAG_IDLE); // 清除 IDLE 中断标志
}
}
```
#### 5. 示例代码整合
以下是一个完整的代码示例,展示了如何配置USART和DMA以实现空闲中断的数据传输。
```c
#include "stm32f1xx.h"
#define BUFFER_SIZE 64
uint8_t buffer[BUFFER_SIZE];
void USART_Config(void) {
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// 配置 USART 引脚
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; // TX
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; // RX
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置 USART 参数
USART_InitStruct.USART_BaudRate = 115200;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStruct);
// 使能 IDLE 中断
USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);
// 使能 DMA 接收请求
USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
// 使能 USART
USART_Cmd(USART1, ENABLE);
}
void DMA_Config(void) {
DMA_InitTypeDef DMA_InitStruct;
DMA_InitStruct.DMA_Channel = DMA1_Channel5;
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)buffer;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStruct.DMA_BufferSize = BUFFER_SIZE;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
DMA_InitStruct.DMA_Priority = DMA_Priority_High;
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Channel5, &DMA_InitStruct);
DMA_Cmd(DMA1_Channel5, DISABLE);
}
void USART1_IRQHandler(void) {
if (RESET != usart_interrupt_flag_get(USART1, USART_INT_FLAG_IDLE)) {
DMA_Cmd(DMA1_Channel5, ENABLE);
while (DMA_GetCmdStatus(DMA1_Channel5) == ENABLE);
usart_interrupt_flag_clear(USART1, USART_INT_FLAG_IDLE);
}
}
int main(void) {
USART_Config();
DMA_Config();
while (1) {
// 主循环
}
}
```
阅读全文
相关推荐


















