stm32 ADC模数转换 ADC多通道 ADC DMA

发布者:冰心独语u最新更新时间:2022-05-05 来源: eefocus关键字:stm32  ADC  模数转换  DMA 手机看文章 扫描二维码
随时随地手机看文章

1 2


通过调节电位器,改变AD转换值和电压值


STM32F1 ADC 配置步骤


1.使能GPIO时钟和ADC时钟

2.配置引脚模式为模拟输入

3.配置ADC的分频因子

4.初始化ADC参数,ADC_InitTypeDef

5.使能ADC

6.执行ADC校准

7.设置ADC软件启动

8.读取ADC转换值

9.设置ADC规则,采样时间等

10.使能ADC的软件转换

11.读取ADC转换结果


举例


u16 ADC_value(u8 time)

{

    u8 i = 0;

    u16 value;


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

    {

        ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能ADC的软件转换


        while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) != SET);


        value += ADC_GetConversionValue(ADC1); //读取ADC转换结果

    }


    return value/time;

}


typedef struct

{

    uint32_t ADC_Mode; //双模式选择

    FunctionalState ADC_ScanConvMode; //扫描模式 

    FunctionalState ADC_ContinuousConvMode; //连续转换

    uint32_t ADC_ExternalTrigConv;  //注入通道的外部触发转换模式

    uint32_t ADC_DataAlign; //数据对齐

    uint8_t ADC_NbrOfChannel; //规则通道序列长度

}ADC_InitTypeDef;


void ADC_init()

{

    GPIO_InitTypeDef gpio = 

    {

        GPIO_Pin_1,

        GPIO_Speed_50MHz,

        GPIO_Mode_AIN //模拟输入

    };


    ADC_InitTypeDef adc =

    {

        ADC_Mode_Independent, //独立模式

        DISABLE, //关闭扫描模式

        DISABLE, //单次转换模式

        ADC_ExternalTrigConv_None, //不用外部事件启动转换

        ADC_DataAlign_Right, //右对齐

        1, //通道数目1

    };


    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); //使能GPIO时钟和ADC时钟


    GPIO_Init(GPIOA, &gpio); //配置引脚模式


    RCC_ADCCLKConfig(RCC_PCLK2_Div6); //配置ADC的分频因子 72/6=12(通常)


    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5); //设置ADC规则,采样周期


    ADC_Init(ADC1, &adc); //初始化ADC参数


    ADC_Cmd(ADC1, ENABLE); //使能ADC


    ADC_ResetCalibration(ADC1); //执行ADC复位校准

    while(ADC_GetResetCalibrationStatus(ADC1) == SET); //等待校准完成


    ADC_StartCalibration(ADC1); //执行ADC校准

    while(ADC_GetCalibrationStatus(ADC1) == SET);


    ADC_SoftwareStartConvCmd(ADC1, ENABLE); //ADC软件启动

}


int main(void)

{

    ADC_init();


    while(1)

    {

        adc = ADC_value(15); //15次平均值

        printf("ADC_value is %d.n", adc);

        printf("vol is %.3fV.n", adc * (3.3 / 4096)); //电压值

        delay_ms(500);

        led1 = ~led1;

    }

}


电压计算


vol = ADC * (3.3 / 4096);


ADC的参考电压VREF+为3.3V。ADC为12位转换精度, 2^12为4096


DMA方式

ADC_DMACmd开启DMA,在ADC初始化之后

ADC_RegularChannelConfig通道配置,在ADC初始化之后

DMA_MemoryInc要设置为DMA_MemoryInc_Enable,存储器地址递增


DMA_BufferSize大小,是定义DMA_MemoryBaseAddr内存的大小。根据DMA_MemoryDataSize存储器数据宽度,HalfWord占16bit


#define CHANNEL_NUM 4


volatile u16 AD_Bufer[4];

volatile u8 adc1_ok;


//多通道配置。4路输入

void ADC_init()

{

    ...


    ADC_InitTypeDef adc =

    {

        ADC_Mode_Independent, //独立模式

        ENABLE, //开启扫描模式

        ENABLE, //开启连续转换模式

        ADC_ExternalTrigConv_None, //不用外部事件启动转换

        ADC_DataAlign_Right, //右对齐

        CHANNEL_NUM, //通道数目4

    };


    ADC_Init(ADC1, &adc);


    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_55Cycles5);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_55Cycles5);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 4, ADC_SampleTime_55Cycles5);


    DMA_adc_init(ADC1, (u32)AD_Bufer, CHANNEL_NUM);


    ...

}


void DMA_adc_init(ADC_TypeDef *ADCx, u32 mem_addr, u32 size)

{

   DMA_InitTypeDef DMA_InitStructure;

   NVIC_InitTypeDef NVIC_InitStructure;


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


   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

   NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;

   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

   NVIC_Init(&NVIC_InitStructure);


   DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADCx->DR; //外设地址

   DMA_InitStructure.DMA_MemoryBaseAddr = mem_addr; //内存地址

   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

   DMA_InitStructure.DMA_BufferSize = size; //4个缓存大小

   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;

   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //循环模式

   DMA_InitStructure.DMA_Priority = DMA_Priority_High;

   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

   DMA_Init(DMA1_Channel1, &DMA_InitStructure);


   DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1, ENABLE); //开启中断


   DMA_Cmd(DMA1_Channel1, ENABLE);


   ADC_DMACmd(ADCx, ENABLE); //开启ADC1 DMA采集

}


void DMA1_Channel1_IRQHandler(void)

{

    if(DMA_GetITStatus(DMA1_IT_TC1) != RESET)

    {

        DMA_ClearITPendingBit(DMA1_IT_TC1);

        adc1_ok = 1;

    }

}


int main(void)

{

    ADC_init();


    while(1)

    {

        if(adc1_ok == 1)

        {

            v0 = AD_Bufer[0];

            v1 = AD_Bufer[1];

            v2 = AD_Bufer[2];

            v3 = AD_Bufer[3];


            printf("v0 is %.3fV.n", v0 * (3.3 / 4096)); //电压值

            printf("v1 is %.3fV.n", v1 * (3.3 / 4096));

            printf("v2 is %.3fV.n", v2 * (3.3 / 4096));

            printf("v3 is %.3fV.n", v3 * (3.3 / 4096));


            led1 = ~led1;

            adc1_ok = 0;

        }


        delay_ms(500);

    }

}


关键字:stm32  ADC  模数转换  DMA 引用地址:stm32 ADC模数转换 ADC多通道 ADC DMA

上一篇:linux搭建stm32开发环境
下一篇:stm32F1 DMA

推荐阅读最新更新时间:2024-10-30 11:31

基于STM32的无线通讯终端系统的设计方案
1.引言 目前仪器设备多数采用RS232接口与计算机通信,但是随着计算机技术的发展,支持热插拔的USB标准接口将取代RS232接口,因此计算机将越来越少配置甚至不配置RS232接口。 实验证明,该系统的设计具有低成 本、高集成度和设计简单等优点,实现无线联网和组网功能,适于便携式电子设备的文件远端下载和上传,为诸如无线切割机、各类物联网掌上终端等设备的数据传输提供了解决方案。 RS232接口与USB接口虽然都属于串行接口,但它们的数据格式、通信协议、信号电平以及机械连 接方式则不同。这样计算机不能控制现有仪器设备,解决这一问题就得把现有的仪器设备的RS232接口转换成USB接口。实现这种转换可以采用 USB/RS232桥接器件如C
[电源管理]
基于<font color='red'>STM32</font>的无线通讯终端系统的设计方案
STM32时钟,外部16M设置
一般的时钟设置是外部8M的时钟,但是当设置为外部16M的时候,需要配置如下: (1)stm32f103xx的芯片,在stm32f10x.h库中修改大概119行的HSE_VALUE 为16000000(自带的是8000000),然后在system_stm32f10x.c中设置,大概在1054行,位于SetSysClockTo72(void)函数中,添加2分频(RCC_CFGR_PLLXTPRE_HSE_Div2|),然后在1056处添加同样的句子(RCC_CFGR_PLLXTPRE_HSE_Div2|),编译就可以了。 (2)stm32f40xx的芯片,在stm32f4xx.h库中修改大概122行的修改为16M如下 #if !def
[单片机]
降低设计复杂度并减少设计时间的ΔΣ ADC电路
采用Easy Drive技术的增量累加(Δ-Σ)模数转换器(ADC)不仅功能丰富,而且易于使用。Easy Drive功能简化或免除了输入端的有源放大或滤波 电路 ,软件 接口 也比其它类型的ADC简单得多。它消除了传统ADC应用设计的复杂性(例如需要外部器件和软件),可大幅节省设计时间。 表1给出了18款可供货的Easy Drive器件的特点,包括具有I2C或SPI接口的单通道、4通道或16通道版本。24位器件适合非常高性能的应用,而16位器件的通用性更好。在16位器件上还提供一个可编程增益放大器(PGA),以满足中间要求或者用在需要适应多种输入范围的场合。 简化高阻抗 传感器 测量电路 Δ-Σ ADC具有很高的准确度和
[模拟电子]
STM32下载方法
一、JLINK下载方法 1、硬件设置 Boot0,Boot1 = 0,*(测试通过) Boot0,Boot1 = 1,0或者0,1(未测试) 2、软件设置 MDK设置 ① 选择Project - Options for Target ... - Debug ② 点击Settings Debug子选项   注意速度不能太高,如果选的太高,在下载程序或者调试时可能出现“cannot load flash programming algorithm !”错误。 Flash Download子选项 二、ISP下载方法--使用串口下载   Boot0,Boot1 = 1,0,芯片从系统闪存里启动Bootloader,执行系统预设
[单片机]
<font color='red'>STM32</font>下载方法
基于W5500的NetBIOS应用实例
一 实例背景 最近一个做智能家居的朋友面临这样的一个烦恼,他想让用户通过智能手机在家里方便地控制家居设备,又想让用户免除下载安装App的麻烦,通过浏览器直接打开设备内嵌的网页便可实现控制。但是设备的IP地址都是通过家里的路由器自动获得的,设备上又没有屏幕来显示其IP地址。问我有没有办法不输入IP地址来实现浏览器访问该设备网页的办法,就是类似DNS之类,但是无需连外网,只在家庭网络内能访问即可。 这使我想起一个古老的协议,NetBIOS(Network Basic Input/Output System)。这个在上世纪80年代由IBM开发的协议,主要用于数十台左右计算机组成的小型局域网,该协议的主要用途之一就是把计算机名称解
[单片机]
基于W5500的NetBIOS应用实例
STM32——PWM输出总结
学习后发现stm32的定时器功能确实很强大,小总结一下方便以后使用的时候做参考。Stm32定时器一共分为三种:tim1和tim8是高级定时器,6和7是基本定时器,2 5是通用定时器。从名字就可以看得出来主要功能上的差异。今天我主要是用定时器做pwm输出,所以总结也主要是针对pwm方面的。 先大致说下通用和高级定时器的区别。通用的可以输出四路pwm信号互不影响。高级定时器可以输出三对互补pwm信号外加ch4通道,也就是一共七路。 所以这样算下来stm32一共可以生成4*5+7*2=30路pwm信号。接下来还有功能上的区别:通用定时器的pwm信号比较简单,就是普通的调节占空比调节频率(别的不常用到的没去深究);
[单片机]
STM32 进阶教程 5 - 内联函数
前言 在计算机科学中,内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展);也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省了每次调用函数带来的额外时间开支。但在选择使用内联函数时,必须在程序占用空间和程序执行效率之间进行权衡,因为过多的比较复杂的函数进行内联扩展将带来很大的存储资源开支。另外还需要特别注意的是对递归函数的内联扩展可能引起部分编译器的无穷编译。 内联扩展是一种特别的用于消除调用函数时所造成的固有的时间消耗方法。一般用于能够快速执行的函数,因为在这种情况下函数调用的时间消耗显得更为突出。这种方法对于很小的
[单片机]
<font color='red'>STM32</font> 进阶教程 5 - 内联函数
stm32库函数FSMC_NORSRAMInit()解析
这是一段对nor存储器的时序进行编程的函数,函数形式为void FSMC_NORSRAMInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct),里面只有一个参数,这个参数为指针类型,指向一段数据结构,这个数据结构就保存着对时序进行配置的的各个参数,这个结构的详细内容为 typedef struct { uint32_t FSMC_Bank;//nor被分为四块,其中这个参数是说明对那个块编程 uint32_t FSMC_DataAddressMux;//地址数据是否复用 uint32_t FSMC_MemoryType;//存储器类型 uint3
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved