STM32F4如何通过外部ADC输出连续读取16位并行数据
STM32F4 GPIOA->IDR 16位并行数据存储与连续读取方案
1. GPIOA->IDR的16位数据存储方式
- STM32F4的GPIO IDR是32位寄存器,但GPIOA仅包含PA0-PA15共16个引脚,因此寄存器低16位对应PA0-PA15的输入电平状态,高16位为保留位,读回值固定为0。
- 引脚与寄存器位一一对应:PA0对应IDR的bit0,PA1对应bit1,……,PA15对应bit15。
- 若外部ADC的16位并行输出(D0-D15)分别连接到PA0-PA15,读取
GPIOA->IDR后,直接截取低16位即可得到ADC输出的完整数据(数据位序取决于硬件接线,比如D0对应LSB、D15对应MSB)。
2. 持续访问输入数据寄存器实现连续采样
方法1:轮询读取(适合低速率场景)
在循环中重复读取IDR,直接获取采样数据:
uint16_t adc_samples[1000]; uint32_t sample_cnt = 0; while (sample_cnt < 1000) { // 屏蔽高16位,仅保留有效数据 adc_samples[sample_cnt] = (uint16_t)GPIOA->IDR; sample_cnt++; // 可选:添加延时控制采样间隔,或根据ADC时序要求等待稳定 }
方法2:DMA无CPU干预采样(适合高速连续场景)
利用DMA直接将IDR数据搬运到内存,无需CPU参与,大幅提升采样效率:
- 配置DMA通道:外设地址设为
&GPIOA->IDR,内存地址指向采样数组首地址 - 设置数据宽度为半字(16位),内存地址递增,外设地址固定,开启循环模式
- 启动DMA后,自动完成连续采样并存储数据
核心配置代码(HAL库示例):
uint16_t adc_dma_buf[4096]; DMA_HandleTypeDef hdma_gpio_idr; void DMA_Init(void) { hdma_gpio_idr.Instance = DMA2_Stream0; hdma_gpio_idr.Init.Channel = DMA_CHANNEL_0; hdma_gpio_idr.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_gpio_idr.Init.PeriphInc = DMA_PINC_DISABLE; hdma_gpio_idr.Init.MemInc = DMA_MINC_ENABLE; hdma_gpio_idr.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_gpio_idr.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma_gpio_idr.Init.Mode = DMA_CIRCULAR; hdma_gpio_idr.Init.Priority = DMA_PRIORITY_HIGH; HAL_DMA_Init(&hdma_gpio_idr); // 启动DMA传输,设置采样总数 HAL_DMA_Start(&hdma_gpio_idr, (uint32_t)&GPIOA->IDR, (uint32_t)adc_dma_buf, 4096); }
方法3:外部中断同步采样(确保数据有效性)
若ADC提供转换完成(EOC)信号,可将其接入STM32外部中断引脚,在中断服务函数中读取IDR,保证每次读取的都是转换完成后的有效数据:
uint16_t current_adc_sample; void EXTI1_IRQHandler(void) { if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_1) != RESET) { current_adc_sample = (uint16_t)GPIOA->IDR; __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_1); } }
内容的提问来源于stack exchange,提问作者Akash kumar
相关产品推荐
相关产品推荐

