DMA+ADC实现多通道采集自学笔记

DMA+ADC实现多通道采集

这个程序的效果是要采集分别采集电位器、光敏模块、热敏模块和红外对射模块的ADC采集,通过使用ADC的扫描模式和DMA数据转运来实现ADC多通道采集

一、ADC结构图

在这里插入图片描述

二、DMA结构图

在这里插入图片描述

三、ADC和DMA初始化函数的配置步骤

  1. 开启ADC外设、GPIO外设和DMA外设的RCC时钟

  2. 配置GPIO,初始化结构体

  3. 配置ADC的时钟

    • 配置ADC时钟需要调用一个RCC的库函数,这个函数在stm32f10x_rcc.h文件中被定义:

      void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);//配置ADCCLK的分频器
      

      在跳转到这个函数的源码,知道他可以对APB2总线的72MHz时钟选择2、4、6、8分频输入到ADCCLK,在参考手册中的第11节ADC介绍中有提到ADC的输入时钟不得超过14MHz,所以这里可以选择6分频或者8分频
      在这里插入图片描述

  4. 配置GPIO到ADC转换器的多路开关,选择AD转换器的输入通道

    • 由于要对ADC进行四个通道的多通道采集,所以这个输入通道选择就应该是要分别选择四个通道,调用一个ADC的库函数

      void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
      

      在STM32入门教程资料的参考文档的STM32F103xx固件函数库用户手册中的4.2.15节有这个函数的详细解释
      在这里插入图片描述

  5. 配置ADC,初始化结构体

    • 结构体的详细配置配置在在STM32入门教程资料的参考文档的STM32F103xx固件函数库用户手册中的4.2.2节

    • (可选)如果要使用模拟看门狗,有函数来配置阈值和监测通道

    • (可选)如果要开启中断,配置NVIC

  6. 配置DMA,初始化结构体

    • 结构体的详细配置配置在在STM32入门教程资料的参考文档的STM32F103xx固件函数库用户手册中的7.2.2节
  7. 开启DMA

  8. 开启ADC到DMA的输出,选择DMA的硬件触发源

    • DMA1的通道1的要选择使用哪个硬件触发源就需要对其使能
      在这里插入图片描述
  9. 开启ADC

  10. ADC校准

    • 校准的流程就是开始复位校准、等待复位校准完成、开始校准、等待校准完成

四、程序代码

一、使用ADC单次转换扫描模式,DMA单次转运
  1. AD.c文件

    #include "stm32f10x.h"                  // Device header
    /* 
    	//一、开启GPIO外设和ADC外设RCC时钟
    	//二、配置GPIO,初始化结构体
    	//三、配置ADCCKL,调用一个函数
    	//四、选择规则组的输入通道
    	//五、配置ADC,初始化结构体
    		(可选)模拟看门狗,有函数来配置阈值和监测通道
    		(可选)开启中断,配置NVIC
    	//六、配置DMA,初始化结构体
    	//七、开启DMA
    	//八、开启ADC到DMA的输出,选择DMA的硬件触发源
    	//九、开启ADC
    	//十、ADC校准
    */
    
    uint16_t AD_Value[4];
    
    void AD_Init(void)
    {
         
         
    	//一、开启GPIO外设和ADC外设RCC时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
    	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    	
    	//二、配置GPIO,初始化结构体
    	GPIO_InitTypeDef GPIO_InitStruct;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
    	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 |  GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
    	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA, &GPIO_InitStruct);
    	
    	//三、配置ADCCKL,调用一个函数
    	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
    	
    	//四、选择规则组的输入通道
    	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
    	ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);
    	ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5);
    	ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5);
    	
    	//五、配置ADC,初始化结构体
    	ADC_InitTypeDef ADC_InitStruct;
    	//ADC转换模式选择(独立模式或双ADC模式),只有“ADC_Mode_Independent”是独立模式其他都是双ADC模式
    	ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
    	ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//对齐方式
    	ADC_InitStruct.
### STM32 DMA ADC 多通道数据采集实现方法 在STM32微控制器中,通过DMA(Direct Memory Access)与ADC(Analog-to-Digital Converter)配合使用,可以高效地完成多通道模拟信号的数字化处理。以下是具体的实现方法以及示例代码。 #### 1. 配置硬件资源 为了使能DMA功能并配置ADC进行多通道采集,需先初始化相关外设。这通常包括以下几个方面: - **启用时钟**:确保ADC模块及其关联GPIO端口的时钟已开启。 - **配置GPIO引脚**:将用于输入模拟信号的GPIO引脚设置为模拟输入模式。 - **初始化ADC参数**:定义采样时间、分辨率以及其他必要的属性。 - **绑定DMA流**:指定哪个DMA通道负责管理数据传输,并将其连接至目标存储区。 这些操作可以通过标准固件库或更现代的HAL驱动来执行[^1]。 #### 2. 编写软件逻辑 下面展示了一段典型的程序片段,它展示了如何利用STM32 HAL库创建一个多通道ADC采集流程: ```c #include "stm32f4xx_hal.h" // 定义全局变量保存结果缓冲区大小等于预期测量次数乘以每组样本数 #define NUM_CHANNELS 4 uint16_t adcResults[NUM_CHANNELS]; int main(void){ // 初始化系统时钟和其他基础服务... MX_ADC_Init(); MX_DMA_Init(); // 开始校准过程以减少误差影响 if(HAL_ADCEx_Calibration_Start(&hadc, ADC_SINGLE_ENDED)!= HAL_OK){ // 错误处理机制省略 } // 启动带有DMA支持下的连续转换模式 if(HAL_ADC_Start_DMA(&hadc,(uint32_t *)adcResults ,NUM_CHANNELS )!= HAL_OK ){ // 如果失败则调用错误处理器 } } void MX_ADC_Init(){ ADC_ChannelConfTypeDef sConfig = {0}; hadc.Instance = ADC1; hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; hadc.Init.Resolution = ADC_RESOLUTION_12B; hadc.Init.ScanConvMode = ENABLE; // 扫描多个信道 hadc.Init.ContinuousConvMode = ENABLE;// 连续获取新数值而非单一触发事件后停止 hadc.Init.NbrOfConversion = NUM_CHANNELS ; hadc.Init.DiscontinuousConvMode = DISABLE; hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV; if (HAL_ADC_Init(&hadc) != HAL_OK){ // 初始失败响应策略待补充 } for(int i=0;i<NUM_CHANNELS ;i++){ sConfig.Channel = i+1; // 假定四个连续编号的物理接口作为源 sConfig.Rank = i+1; // 排序顺序应匹配实际布线情况 sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; if(HAL_ADC_ConfigChannel(&hadc,&sConfig)!= HAL_OK ){ // 添加适当异常捕获措施 } } } ``` 上述代码片段涵盖了从设备初始化直至启动具体任务的主要步骤[^5]。值得注意的是,在真实应用场景里可能还需要考虑诸如中断优先级分配、电源管理模式调整等因素的影响。 ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值