Stm32 ADC学习

摘要:
stm32的ADC是一个12位逐次逼近模数转换器;它包括18个通道,可用于测量16个外部通道和2个内部通道。ADC转换的结果存储在16位数据寄存器(ADC常规数据寄存器、ADC_DR和ADC注入数据寄存器ADC_JDCx)中,可以设置为左对齐或右对齐的ADC通道和GPIO对应表(图片来自整个点原子STM32F1开发指南库的功能版本)、常规通道组和注入通道组

stm32 ADC 简介

stm32的ADC是 12位逐次逼近型 模拟数字转换器;它包括18个通道,可以用来测量16个外部通道2个内部通道.ADC转换的结果存放在16位数据寄存器(ADC规则数据寄存器,ADC_DR 和 ADC注入数据寄存器,ADC_JDCx)中,这个数据寄存器可以设置对齐方式为左对齐或右对齐.

ADC通道与GPIO对应表(图片来自整点原子STM32F1开发指南库函数版本)

Stm32 ADC学习第1张


规则通道组注入通道组

注入通道可打断规则通道的转换

所谓规则通道组和注入通道组其实应该就是通道的分组吧,按照OOP的思想来理解,通道组是一个基类,注入通道组和规则通道组派生自通道组这个基类,通道组这个基类中包含了一个保存各个通道的数组.

为什么要对通道进行分组呢,这个有待深究,以后再说.


ADC相关的寄存器

ADC_CR1

各个位描述如下图:

Stm32 ADC学习第2张

  • scan位:
    设置扫描模式,1为使用扫描模式,0则关闭.扫描模式下,有ADC_SQRx或ADC_JSQRx寄存器选中的通道被转换,此时如果设置了EOCIE或JEOCIE,则只有在最后一个通道转换完毕后才会产生EOC或JEOC中断
  • DUALMOD位:
    设置ADC的操作模式,详细的看下面的来自<<stm32中文参考手册>>截图
    Stm32 ADC学习第3张

ADC_CR2

各个位描述如下图:

Stm32 ADC学习第4张

  • ADON位:用于开关AD转换器
  • CONT位:用于设置是否进行连续转换,使用单次转换CONT位必须设置为0.
  • EXTSEL[2:0]:用于选择启动规则转换组转换的外部事件
    Stm32 ADC学习第5张
    如果需要使用软件触发,就将这三个位设置为 111

ADC采样事件寄存器(ADC_SMPR1和ADC_SMPR2)

各个位描述如下图:

Stm32 ADC学习第6张

这两个寄存器用来设置通道0~17的采样时间,每个通道要占3位.

Stm32 ADC学习第7张

对于每个要转换的通道,采样时间尽量长一点,以获得较高的准确度,但是会降低ADC的转换速率.ADC的转换时间可以由以下公式计算:

Tconv = 采样时间 + 12.5周期

ADC规则序列寄存器(ADC_SQR1~3)

这几个寄存器功能都差不多,不一一详细说明了.

Stm32 ADC学习第8张

  • L[3:0]:用于存储规则序列的长度

ADC数据寄存器(ADC_DR)

这个没什么好说的,用来存放AD转换后的结果

要注意可以通过ADC_CR2的ALIGN位设置这个寄存器是左对齐还是右对齐

ADC状态寄存器(ADC_SR)

没啥好说的,保存了各种状态,看图吧.

Stm32 ADC学习第9张


通过库函数配置ADC1通道1进行AD转换

查看手册可以知道ADC1通道1对应着PA1,如下图
Stm32 ADC学习第10张


1.外设使能

  • STM32F103ZET6的ADC通道1在PA1上所以我们先要使能 PORTA的时钟 和 ADC1时钟,然后设置 PA1为模拟输入.

2.复位ADC1,同时设置ADC1的分频因子

  • 开启了ADC1的时钟后,要复位ADC1,将ADC1的全部寄存器重设位缺省值,然后通过RCC_CFGR设置ADC1的分频因子,并且分频因子要确保ADC1的时钟不超过14MHz!
    //ADC复位 ADC_DeInit();
    RCC_ADCCLKConfig(RCC_PCLK2_DIV6); //设置分配因子的库函数

3.初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息.
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);// ADC初始化

4.使能ADC并校准
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState); //使能指定的ADC
void ADC_ResetCalibration(ADC_TypeDef* ADCx);//复位校准
while(ADC_GetResetCalibrationStatus(ADCx));//等待复位校准结束
void ADC_StartCalibration(ADC_TypeDef* ADCx);//执行ADC校准
while(ADC_GetCalibrationStatus(ADCx));//等待AD校准结束

5.设置规则序列1里面的通道,读取ADC的值
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); //设置规则序列通道以及采样周期
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//允许软件开启ADC转换
while(!ADC_GetFlagStatus(ADCx,ADC_FLAG_EOC));//等待转换结束
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);//获取转 换结果数据

MDK5中实现代码

  • 配置stm32f103库函数编程环境,我用的是正点原子的那一套,不多记录了;

  • ADC1_Init() 函数

    void ADC1_Init(void)
    /* ---------------------------------------------
        ADC1_IN1 -> PA.1
    --------------------------------------------- */
    void ADC1_Init(void)
    {
        GPIO_InitTypeDef gpioInitStruct;
        ADC_InitTypeDef adcInitStruct;
        //Enable periph clock
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
        //配置ADC的时钟,不要超过14MHz;
        RCC_ADCCLKConfig(RCC_PCLK2_Div6);	
        //Congfig PA.1
        gpioInitStruct.GPIO_Mode = GPIO_Mode_AIN;	//设置PA.1的输入模式为模拟输入
        gpioInitStruct.GPIO_Pin = GPIO_Pin_1;
        gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA,&gpioInitStruct);
        //ADC1 复位
        ADC_DeInit(ADC1);
        //initialize adc1
        adcInitStruct.ADC_Mode = ADC_Mode_Independent;	//ADC模式:ADC独立模式
        adcInitStruct.ADC_DataAlign = ADC_DataAlign_Right;	//ADC_DR寄存器的数据对齐方式:右对齐
        adcInitStruct.ADC_ScanConvMode = DISABLE;	//是否允许连续扫描模式:不允许,使用单通道模式
        adcInitStruct.ADC_ContinuousConvMode = DISABLE;	//单次转换模式
        adcInitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//ADC触发方式:不需要外部触发源,由软件触发
        adcInitStruct.ADC_NbrOfChannel = 1;	//进行转换的ACD通道数目
        ADC_Init(ADC1,&adcInitStruct);
        //Enable ADC1
        ADC_Cmd(ADC1,ENABLE);
        //ADC1校准
        ADC_ResetCalibration(ADC1);	//复位校准
        while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准完成
        ADC_StartCalibration(ADC1); //ACD校准
        while(ADC_GetCalibrationStatus(ADC1));	//等待ADC校准完成
    }
    
  • ADC_GetConvValue()

    u16 ADC_GetConvValue(u8 channel)
    /**
    * 获取指定的通道adc的转换结果
    * @param channel: 指定adc的通道,必须在1~3之间
    */
    u16 ADC_GetConvValue(u8 channel)
    {
        //Config sample channel
        //采样周期尽量设置长一些,以确保精度
        ADC_RegularChannelConfig(ADC1,channel,1,ADC_SampleTime_239Cycles5);
        //使能软件转换
        ADC_SoftwareStartConvCmd(ADC1,ENABLE);
        while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
        return ADC_GetConversionValue(ADC1);
    }
    
  • ADC_GetAverageConvValue()

    u16 ADC_GetAverageConvValue(u8 channel,u8 times)
    u16 ADC_GetAverageConvValue(u8 channel,u8 times)
    {
        u8 i = 0;
        u32 temp = 0;
        for(;i < times;i++)
        {
            temp += ADC_GetConvValue(channel);
        }
        return (u16)(temp/times);
    }
    
  • ADC_SampleValue2ReadableValue()

    double ADC_SampleValue2ReadableValue(u16 sampleValue)
    /**
        * 描述:将AD转换后存放在ADC_DR寄存器中的值转换为有意义的值,
        * 		 可以通过宏定义 REF 来设置参考电压
        * @param sampleValue : 要转换的值
        * @retval 转换的结果,是一个double类型的浮点数
        */
    double ADC_SampleValue2ReadableValue(u16 sampleValue)
    {
        return (double)sampleValue*((double)REF/4096.0);
    }
    
  • main.c文件代码

    main.c
    #include"ADC.h"
    #include"delay.h"
    #include"usart.h"
    

    void Init(void);
    void Loop(void);

    int main(void)
    {
    Init();
    while(1)
    Loop();
    }

    void Init(void)
    {
    delay_init();
    USART_Debug_Init();
    ADC1_Init();
    USART_WriteLine("系统初始化完成!将开始AD采集.");
    }

    void Loop(void)
    {
    u16 sampledValue;
    sampledValue = ADC_GetAverageConvValue(1,5);
    USART_WriteLine("采样值: %d ; 计算所得电压值: %.2f ",sampledValue,ADC_SampleValue2ReadableValue(sampledValue));
    delay_ms(250);
    }

  • 在main.c中使用的 USART_WriteLine(const char*str,...)函数 是我自己封装的串口函数,也可以使用正点原子 System文件夹 下提供的printf()函数;

总结库函数配置ADC的步骤

1.使能需要用到的GPIO 和 ADC的时钟;
2.配置ADC的时钟分频:
void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);
2.配置IO口,输入模式为 GPIO_Mode_AIN,模拟输入模式;
3.调用 ADC_DeInit(); 对ADC进行复位;
4.调用 ADC_Init();初始化ADC
5.调用 ADC_Cmd(ADCx,ENABLE);,使能ADC
6.校准ADC:
ADC_ResetCalibration(ADC1); //复位校准 while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准完成 ADC_StartCalibration(ADC1); //ACD校准 while(ADC_GetCalibrationStatus(ADC1)); //等待ADC校准完成
7.获取AD转换的结果

  </div>
  • 相关阅读:
    宋宝华: Linux内核编程广泛使用的前向声明(Forward Declaration)
    朱辉(茶水): Linux Kernel iowait 时间的代码原理
    宋宝华:Linux设备驱动框架里的设计模式之——模板方法(Template Method)
    宋宝华:论程序员的时代焦虑与焦虑的缓解
    邵国际: C 语言对象化设计实例 —— 命令解析器
    让天堂的归天堂,让尘土的归尘土——谈Linux的总线、设备、驱动模型
    宋宝华:关于Ftrace的一个完整案例
    php采集页面指定标签里面的内容
    js调用video的播放时长
    php解析url并得到url中的参数
  • 原文地址:https://www.cnblogs.com/Laggage/p/10406118.html
  • 免责声明:文章转载自《Stm32 ADC学习》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

    上篇VBA 字符串处理CodeBblock 常用快捷键 (最常用)下篇

    宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

    相关文章

    STM32学习笔记——AFIO时钟的配置问题

    最近在写程序时发现设置外部中断出了问题,之前的程序好好的怎么就不能用了呢?经过了一晚上的折腾发现问题出在AFIO时钟的配置上,我没有使能AFIO时钟。 什么时候要开启AFIO呢?参考手册:  说的很明白,操作AFIO的三类寄存器时需要开启:  1.事件控制寄存器(AFIO_EVCR) 2.复用重映射和调试I/O配置寄存器(AFIO_MAPR) 3.外部...

    STM32 + UIP + ENC28J60 实现TCP 简单通讯

    MCU: STM32F103C6T6 背景 上次介绍了怎么把UIP移植到STM32中来,并最后实现一个ping操作,这次在上次基础上实现MCU当TCP服务端,电脑当客户端通过TCP端链接MCU,实现通讯。 为保证程序尽量精简,程序在接受到TCP数据后,会原封不动返回给客户端(电脑), 并通过串口打印。 在使用UIP TCP功能前,需要可以让MCU获取当前时...

    STM32定时器输入捕获功能应用——超声波模块

    一、工作原理 输入捕获是STM32单片机定时器的一项重要的功能,应用很广泛,常用于测量脉冲宽度,周期等。 超声波模块测距的原理是:单片机给超声波模块(我用到的超声波模块型号是HC-SR04,下面简称HC-SR04)发送一个大于10us的高电平,触发HC-SR04发出8个40kHz的方波,并自动检测是否有信号返回,如果有信号返回,就会通过Echo对单片机输出...

    STM32代码自动生成工具使用说明

    1.什么是“代码自动生成工具” 为了降低开发者的开发门槛,缩短开发周期,降低开发资源投入,机智云推出了代码自动生成服务。云端会根据产品定义的数据点生成对应产品的设备端代码。 自动生成的代码实现了机智云通信协议的解析与封包、传感器数据与通信数据的转换逻辑,并封装成了简单的API,且提供了多种平台的实例代码。当设备收到云端或APP端的数据后,程序会将数据转换成...

    JLINK、ULINK和STlink仿真器详解

    JLink仿真器 德国SEGGER公司推出基于JTAG的仿真器。简单地说,是给一个JTAG协议转换盒,即一个小型USB到JTAG的转换盒,其连接到计算机用的是USB接口,而到目标板内部用的还是jtag协议。它完成了一个从软件到硬件转换的工作。 ULINK仿真器 现在普遍用到的是ULINK2,它是ARM公司最新推出的配套RealViewMDK使用的仿真器,是...

    一、STM32简介、选型及其目标

    STM32简介 STM32系列是由意法半导体公司推出的ARM Cortex-M内核单片机,从字面上来看,ST为意法半导体公司的缩写,M是Microcontrollers即单片机的缩写,32代表32位 芯片系列 STM32系列芯片分类 STM32后缀的型号说明 模块准备 STM8S103F3P6 STM8S芯片,20引脚,8KB闪存,TSSOP封装,工...