[STM32F1] 一文解决STM32F103双通道ADC_DMA采集,可拓展多通道

对于STM32F103来说,它的ADC是12位,一共18个通道,其中16个外部通道,2个内部通道。支持单次,连续以及间断模式扫描。
12位ADC
指的是STM32F103的ADC分辨率具有12位,位数越高采集到的ADC越精准。12位是相对于二进制数来说,也就是“111111111111”,转换为十进制就是4095,其实是0-4095,实际上是4096个数,STM32F103的引脚电压是0-3.3V,12位的ADC就会把0-3.3V切割成4096份。这样转换器得到的ADC值便可以转换为相应电压,设转换器采集到的ADC值为x,实际所求电压为y。那么公式为:y=x/4096*3.3V。
16个外部通道:
f103的芯片上有16个引脚是接到模拟电压上可以进行电压检测的,这16个通道会分给3个转换器,这三个转换器是独立的,也就是我们常见的ADC1,ADC2,ADC3。引脚和通道的对应关系可通过手册或者芯片引脚定义查询。

GPIO_InitTypeDef GPIO_InitStructure;

 RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA ,ENABLE);

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

        GPIO_Init(GPIOA, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_5;

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

        GPIO_Init(GPIOA, &GPIO_InitStructure);



首先还是走老路,初始化所用的GPIO,此次所用的是PA4和PA5。通过手册可以看到这两个口对应的是ADC1和ADC2,对应通道是通道4和通道5。

ADC_InitTypeDef ADC_InitStructure;       

RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1 ,ENABLE);

RCC_ADCCLKConfig(RCC_PCLK2_Div6);//12M  最大14M

ADC_DeInit(ADC1);  //将外设 ADC1 的全部寄存器重设为缺省值

        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;

        ADC_InitStructure.ADC_ScanConvMode = ENABLE;        //连续多通道模式

        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;   //连续转换

        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换不受外界决定

        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //右对齐

        ADC_InitStructure.ADC_NbrOfChannel = 2;//扫描通道数

        ADC_Init(ADC1, &ADC_InitStructure);

        /* ADC1 regular channel10 configuration */

       

        ADC_RegularChannelConfig(ADC1, ADC_Channel_4,1, ADC_SampleTime_71Cycles5);

        ADC_RegularChannelConfig(ADC1, ADC_Channel_5,2, ADC_SampleTime_71Cycles5);          

                  

        /* Enable ADC1 */

        ADC_Cmd(ADC1, ENABLE);

        ADC_DMACmd(ADC1, ENABLE);

        /* Enable ADC1 reset calibaration register */              

        ADC_ResetCalibration(ADC1);          //复位指定的ADC1的校准寄存器           

        /* Check the end of ADC1 reset calibration register */           

        while(ADC_GetResetCalibrationStatus(ADC1));//获取ADC1复位校准寄存器的状态,设置状态则等待

        /* Start ADC1 calibaration */           

        ADC_StartCalibration(ADC1);                //开始指定ADC1的校准状态         

        /* Check the end of ADC1 calibration */         

        while(ADC_GetCalibrationStatus(ADC1));     //获取指定ADC1的校准程序,设置状态则等待

        /* Start ADC1 Software Conversion */

        ADC_SoftwareStartConvCmd(ADC1, ENABLE);

       

        ADC_SoftwareStartConvCmd(ADC1, ENABLE);

        DMA_Cmd(DMA1_Channel1, ENABLE);  //启动DMA通道



参数 ADC_Mode :是用来设置 ADC 的模式  ,ADC的模式很多(如下图),这里选择独立模式:ADC_Mode_Independent

DMA_InitTypeDef DMA_InitStructure;

        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能DMA时钟

        DMA_DeInit(DMA1_Channel1);

        DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&ADC1->DR;  //DMA外设ADC基地

        DMA_InitStructure.DMA_MemoryBaseAddr =(u32)&ADCConvertedValue;//内存地址

        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//dma传输方向单向

        DMA_InitStructure.DMA_BufferSize = 100*2;//设置DMA在传输时缓冲区的长度 word

        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//设置DMA的外设递增模式,一个外设

        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//设置DMA的内存递增模式,

        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据字长

        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//内存数据字长

        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//设置DMA的传输模式:连续不断的循环模式

        DMA_InitStructure.DMA_Priority = DMA_Priority_High;//设置DMA的优先级别

        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//设置DMA2memory中的变量互相访问

        DMA_Init(DMA1_Channel1, &DMA_InitStructure);

       

        DMA_Cmd(DMA1_Channel1, ENABLE);

因为我在代码中做了备注,这里踢几个人比较重要的点:
参数DMA_BufferSize :设置DMA在传输时缓冲区的长度 ,这里要提一下我的数据储存数组u16 ADCConvertedValue[100][2];因为采用两个通道,所以需要两个缓冲保存数据,100*2=200,DMA在运行是就会采集200个ADC值保存在数组中,100个通道4的值,100个通道5的值。取值处理会在后面介绍。
此项设置完之后DMA就回不停地采集这两个ADC通道中的ADC值并保存在数组中。我们只需要在需要的时候读取数组中的值便可。
读取ADC值并做处理

   int sum;

                int sum1=0;

                int sum2=0;

        

                int value1[10];

                int value2[10];

                int isSorted,temp1,temp2,k,p;

                float a;

                int i,j,c;

                float ADC_Value[2];//用来保存经过转换得到的电压值

        

     for(c=0;c<10;c++){

                        for(i=0;i<2;i++)

                        {

                                sum=0;

                                for(j=0;j<100;j++)

                                {

                                        sum+=ADCConvertedValue[j][i];

                                }

                                ADC_Value[i]=(float)sum*3.3/4096/100;//求平均值并转换成电压值

                        }

                        value1[c]=(int)(ADC_Value[0]*100);//4通道电压值扩大100

                        value2[c]=(int)(ADC_Value[1]*100);//5通道电压值扩大100

                }
---------------------
作者:呐咯密密
链接:https://bbs.21ic.com/icview-3070640-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

                        

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: STM32F103R6是一款基于ARM Cortex-M3内核的单片机,具有多个模拟数字转换器(ADC)通道,可用于电压信号的采集。 首先,我们需要在STM32F103R6上配置ADC模块。首先选择要使用的ADC通道,并设置ADC模式(单通道或扫描模式)。接下来,我们可以设置ADC的采样时间和采样顺序。采样时间决定了ADC在转换过程中将信号采样多少次,采样顺序确定了ADC转换的顺序。 接下来,我们可以初始化ADC模块并对其进行配置。我们可以设置ADC的分辨率(8位、10位或12位)、工作模式(单次转换或连续转换)、对齐方式(左对齐或右对齐)等。我们还可以配置DMA(直接内存访问)来自动传输ADC转换结果。 当ADC模块配置好后,我们可以开始进行电压采集。首先,我们需要启动ADC模块,这将启动转换过程。然后,我们可以使用适当的函数来读取ADC通道的转换结果。转换结果将根据所选的分辨率进行缩放,以获得正确的电压值。 最后,根据应用需求,我们可以对电压进行进一步的处理。例如,我们可以使用电压值进行数据显示、数据记录、控制逻辑等。在处理电压值时,我们还可以使用运算和校准来提高测量的准确性和精度。 总之,使用STM32F103R6的ADC模块,我们可以轻松地进行电压信号的采集和处理,为应用程序提供准确和可靠的电压测量功能。 ### 回答2: STM32F103R6是一款32位ARM Cortex-M3内核的微控制器,具有多个模拟数字转换器(ADC)通道,可用于采集电压信号。 STM32F103R6的ADC模块可以将物理世界中的模拟电压信号转换为数字信号,并通过内部控制器进行处理和分析。它可以采集范围在0至3.3V之间的电压信号。 在使用STM32F103R6进行ADC采集电压时,首先需要初始化ADC模块,并配置所需的通道和采样率。通常需要设置ADC时钟频率、采样时间和参考电压等参数。 然后,可以通过编程指令启动ADC的转换过程。转换过程中,ADC会将电压信号进行采样和转换,并将结果以数字形式存储在寄存器中。用户可以通过读取这些寄存器来获取转换结果。 另外,STM32F103R6还提供了中断和DMA两种方式来处理ADC转换完成的事件。用户可以根据需要选择合适的方式来获取采集到的电压值。 需要注意的是,由于ADC转换的精度有限,可能存在一定的误差。因此,在实际应用中,可能需要进行校准和调整以提高测量的准确性。 总而言之,通过STM32F103R6的ADC模块,我们可以方便地进行电压信号的采集,为后续的数据处理和分析提供基础。这为电子设计和物联网等领域的应用提供了很大的便利。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值