18.ADC模数转换

1.STM32ADC简介:

ADC(Analog to Digital Converter)即模数转换器,它可以将模拟信号转换成数字信号。按照其转换原理主要分为逐次逼近型、双积分型、电压频率转换型三种。

STM32 ADC主要特性:        

  • 12位分辨率;
  • 转换结束、注入转换结束和发生模拟看门狗事件时产生中断;
  • 单次和连续转换模式;
  • 从通道0到通道n的自动扫描模式;
  • 自校准;

1)STM32一般都有3个ADC,这些ADC可以独立的使用,可以使用双重或三重的模式,这种模式是为了提高ADC采样率;

2)STM32的ADC一般是12位的逐次逼近型的模拟转换器,多达18个复用通道可以测量16个外部的模拟通道和2个内部的信号源;

3)这些AD转换可以是单次连续扫描或间断模式执行,ADC结果可以左对齐或右对齐存放在16位的一个数据存储器中;

4)ADC还具有模拟看门狗的特性,运行应用程序来检测输入电压是否超出用户定义的阀值上限和下限,如果超过则触发模拟看门狗中断;

2.STM 32介绍:

  • 带内嵌数据一致性的数据对齐;
  • 采样间隔可以按通道分别编程;
  • 规则转换和注入转换均有外部触发选项;
  • 间断模式;
  • 双重模式(带2个或以上ADC的器件);
  • ADC转换时间;
  • ADC供电要求:2.4V到3.6V;
  • ADC输入范围:VREF-≤VIN≥VREF+;
  • 规则通道转换期间有DMA请求产生;
STM ADC结构框图:

​ 

① 第一部分:电压输入引脚:

在设计电路中,将VEF+连接到基准电压源中,基准电压源实现的方法有很多种如TL431,将基准电压设置为固定的2.5V,实现高精度测量;

② 第二部分:输入通道(18个=16外+2内):

ADC2和ADC3不具有内部通道,ADC具有2个内部通道(内部温度传感器+内部参考电压VREF);

③ 第三部分:通道转换顺序(注入通道(最多4路)+规则通道(最多16路)):

  • 如果在规则通道进行转换的时候,有注入通道插入进来,就要先执行注入通道转换等注入通道转换完成之后,再回到规则通道往下继续转换;
  • 每组包含一个转换序列,序列可以按任意序列在任意的通道上进行完成,通过这个转换序列可以将要转换的通道进行排序;
  • 规则通道组序列寄存器有3个(SQR3、SQR2、SQR1),SQR3(控制1到6的转换),SQR2(控制7到12的转换),SQR1(控制13到16的转换);
  • 注入通道组序列寄存器只有1个,最多支持4个通道(JSQR(00->1次转换,01->2次转换,10->3次转换,11->4次转换));
  • 如果在转换期间修改了SQR或JSQR寄存器中的值,将复位当前转换,并向ADC发送一次新的启动脉冲以转换新选择的通道;

④ 第四部分:触发源:

触发极性(4个):禁止触发检测、上升沿触发检测、下降沿触发检测、上升沿和下降沿触发检测;

⑤ 第五部分:ADC时钟(APB2最大支持14M):

  • 72/6=12M;
  • 采样的周期,可以通过ADC的采样时间寄存器来设置,ADC采样时间寄存器(SMPRE(10~17通道)+SMPR2(0~9通道));
  • 每个通道可以分别用不同的采样时间,每个通道采样时间可以独立设置,采样周期最小是1.5个TCLK;
  • Tcon(总的转换时间)=采样时间+12.5周期;

⑥ 第六部分:数据寄存器:

  • ADC是12位,数据寄存器都是16位,因此存在左对齐和右对齐;
  • 规则通道中(只有1个寄存器,容易出现数据覆盖),当转换完成之后,就立刻将数据取走,可以开启DMA将数据自动的搬到其他地方去;

⑦ 第七部分:中断:

只有在ADC1和ADC3中,才可以产生DMA请求;        

3.ADC配置步骤:

ADC相关库函数在stm32f10x_adc.c和stm32f10x_adc.h文件中;
  1. 使能端口时钟和ADC时钟,设置引脚模式为模拟输入:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
  2. 设置ADC的分频因子:RCC_ADCCLKConfig(RCC_PCLK2_Div6);
  3. 初始化ADC参数,包括ADC工作模式、规则序列等:void ADC_Init();
  4. 使能ADC并校准:void ADC_Cmd()、ADC_ResetCalibration(ADC1) 复位校准、ADC_StartCalibrationStatus(ADC1) 开启校准;
  5. 读取ADC转换值:void ADC_RegularChannelConfig()、                                                     void ADC_SoftwareStartConvCmd()、ADC_GetConversionValue()、ADC_GetFlagStatus()

4.ADC模数转换实验:

功能实现:通过ADC1通道1采样外部电压值,将采样的AD值和转换后的电压值通过串口打印出来,同时LED0指示灯闪烁,提示系统正常运行。

(1)原理图:

(2)主函数:

#include "delay.h"
#include "led.h"
#include "usart1.h"
#include "adc.h"



int main(){
    
    u8 i=0;    
    u16 val=0;
    float vol=0.0f;
   
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);      //设置分组
    delay_init();                                        //延时初始化
    LED_Init();  
    usart1_Init(9600);                                   //串口通信初始化
    ADCx_Init();                                         //ADC1初始化
   
    while(1)
       {
          i++;
          if(i%20==0)
          {
             LED0=!LED0;
          }

           delay_ms(10);
          
          if(i%100==0)        //1s
          {
             val=Get_ADC_Value(ADC_Channel_1,20);     //获取转换并且滤波后的值;通道1,20次
             printf("检测的AD值=%d\r\n",val);
             
             //AD值 0~4095,电压采集范围:0~3.3V
             vol=(float)val*(3.3/4095);
             printf("检测的电压值=%2.f V\r\n",vol);
             printf("\r\n");
    
          }
       
      }       
}

(3)头文件:

#ifndef __ADC_H
#define __ADC_H

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;

void ADCx_Init(void);                     //ADC1初始化
u16  Get_ADC_Value(u8 ch,u8 times);       //读取ADC转换值 


#endif

(4)ADC模数转换功能函数:

#include "stm32f10x.h"
#include "delay.h"
#include "adc.h"


/*
   功能:ADC1初始化->ADC1(PA1)
   变量:无
   返回值:无
*/
void ADCx_Init(void)
{
   GPIO_InitTypeDef GPIO_InitStruct;
   ADC_InitTypeDef ADC_InitStruct;
   
   
   //1.使能端口时钟和ADC时钟,设置引脚模式
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
   
   GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;                          //模拟输入模式
   GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;                              //PA1
   GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;       
   GPIO_Init(GPIOA,&GPIO_InitStruct);
   
   //2.设置ADC的分频因子
   RCC_ADCCLKConfig(RCC_PCLK2_Div6);                                 //ADC最大不超过16M,(72/6=12)<16
   
   //3.初始化ADC参数,包括工作模式、规则序列等
   ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;                    //不连续转换
   ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;                 //对齐方式->右对齐
   ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;    //不使用外部触发,使用软件触发
   ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;                     //ADC工作模式设置为独立模式
   ADC_InitStruct.ADC_NbrOfChannel=1;                                //通道数
   ADC_InitStruct.ADC_ScanConvMode=DISABLE;                          //不扫描
   ADC_Init(ADC1,&ADC_InitStruct);
   
   //4.使能ADC校准
   ADC_Cmd(ADC1,ENABLE);                                             //使能ADC1
   ADC_ResetCalibration(ADC1);                                       //复位校准
   while(ADC_GetResetCalibrationStatus(ADC1));                       //复位校准完成标志,完成后退出循环
   ADC_StartCalibration(ADC1);                                       //开启校准
   while(ADC_GetCalibrationStatus(ADC1));                            //开启复位校准完成标志,完成后退出循环
   
   //5.开启软件触发方式
   ADC_SoftwareStartConvCmd(ADC1,ENABLE);
     
}



/*
   功能:读取ADC转换的值
   变量:ch:选择通道  times:读取的次数
   返回值:返回平均值(进行滤波后的值)

*/
u16  Get_ADC_Value(u8 ch,u8 times)
{
   u8 i=0;
   u32 temp_val=0;               //存储获取到的ADC转换值
   
   //ADC规则通道配置
   ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5);       //选择ADC、通道、通道数量、采样周期
   
   //读取数据
   for(i=0;i<times;i++)
   {
      ADC_SoftwareStartConvCmd(ADC1,ENABLE);             //开启ADC转换,因为使用的是单次转换,所以每次转换都需要开启
      while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));      //ADC_FLAG_EOC:规则组转换完成
      temp_val+=ADC_GetConversionValue(ADC1);            //获取转换的值
      delay_ms(10);
   }
   
   return temp_val/times;        //返回进过滤波后的数据
   
}


(5)实验结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

&jhan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值