STM32G431外部GPIO中断触发DMA的形式连续读取5次GPIO组数据
时间: 2025-03-26 08:14:15 浏览: 32
### 配置 STM32G431 使用外部 GPIO 中断触发 DMA 连续读取 5 次 GPIO 组的数据
#### 初始化配置
为了使STM32G431能够响应外部GPIO中断并通过DMA连续读取5次GPIO组数据,需先完成必要的初始化设置。这包括但不限于GPIO、EXTI(External Interrupt)、NVIC(Nested Vectored Interrupt Controller)以及DMA控制器的初始化。
#### EXTI与GPIO配置
针对需要作为中断源使用的GPIO引脚,在`MX_GPIO_Init()`函数内将其设定为输入模式,并启用上拉或下拉电阻以稳定电平。对于每一个欲关联至EXTI线路上的GPIO端口位,均要调用`HAL_NVIC_SetPriority()`和`HAL_NVIC_EnableIRQ()`来调整优先级并激活对应的中断请求。
```c
void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Configure the GPIO pin as input */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
```
#### NVIC配置
确保在启动文件(`startup_stm32g431xx.s`)中的向量表已正确定义了相应的中断服务程序(ISR),接着利用CubeMX工具自动生成的部分代码进一步细化这些ISR的具体行为逻辑。
#### DMA配置
参照提供的资料[^2],这里采用半字(Half Word)宽度来进行DMA传输操作;而关于DMA的方向,则是从外设到内存(Peripheral to Memory)。具体来说就是在发生一次有效的边沿检测之后,由DMA负责搬运来自选定GPIO寄存器内的值直至预定义好的缓冲区位置处。
```c
static void MX_DMA_Init(void)
{
hdma_gpio.Instance = DMA1_Channel1;
hdma_gpio.Init.Request = DMA_REQUEST_0;
hdma_gpio.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_gpio.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_gpio.Init.MemInc = DMA_MINC_ENABLE;
hdma_gpio.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_gpio.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_gpio.Init.Mode = DMA_CIRCULAR; // 循环模式
hdma_gpio.Init.Priority = DMA_PRIORITY_HIGH;
if (HAL_DMA_Init(&hdma_gpio) != HAL_OK)
{
Error_Handler();
}
}
```
#### 启动DMA传输
当一切准备就绪后,可通过如下方式开启DMA传输过程:
```c
/* Start DMA transfer after interrupt occurs */
if (__HAL_GPIO_EXTI_GET_FLAG(GPIO_PIN_0))
{
uint16_t* dst_addr = buffer_for_dma_transfer;
HAL_DMA_Start(&hdma_gpio, (uint32_t)&GPIOA->IDR, (uint32_t)dst_addr, 5); // 读取5次
__HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_0);
}
```
上述代码片段展示了如何在外围设备触发事件时立即启动DMA事务,其中目标地址指向了一个预先分配给接收GPIO状态信息的地方——即`buffer_for_dma_transfer`数组变量。同时注意清除可能存在的挂起标志以免造成重复触发问题。
#### 数据处理
一旦DMA完成了预定数量的数据搬移动作,就可以着手于后续的数据解析工作了。通常情况下会注册一个回调函数以便及时获知当前进度状况或是错误发生的时刻。
```c
__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM2)
{
// Process data here...
}
}
// Register callback function for DMA complete event.
__weak void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
{
if(hdma->Instance==DMA1_Channel1){
// Handle completion of DMA transfers and process received data.
}
}
```
阅读全文
相关推荐


















