STM-32-ADC模拟数字转换(AD单通道转换)

文章目录

  • ADC模拟数字转换
  • 一、ADC模拟->数字转换
  • 1. ADC的基本介绍
  • 2. ADC的输入通道和两个转换单元
  • 3.ADC的触发源
  • 4. ADC连续转换or单次转换,非扫描or扫描模式
  • 5. ADC的数据对齐
  • 6. ADC的转换时间
  • 二、ADC的配置
  • 1. RCC开启时钟
  • 2. 配置GPIO
  • 3. 选择规则组或注入组的输入通道
  • 4.配置ADC初始化
  • 5.开关控制ADC
  • 6. 开启软件触发ADC
  • 7. 校准ADC
  • 8. 读取ADC转换后的数据
  • 测试及程序的现象
  • 三、 总结

  • ADC模拟数字转换

    本文主要介绍STM32ADC模拟数字转换,对STM32中的ADC资源外设做一个总结,也算是对前期知识的一个复习,其中包括AD单通道采集,AD多通道采集。


    一、ADC模拟->数字转换

    1. ADC的基本介绍

    ADC可以将模拟信号转换为数字信号,是模拟电路到数字电路的桥梁。

    STM32的ADC

    当ADC对I/O的引脚读取转换时,读取引脚上的电压,转换为一个数字数据,存放在ADC->DR寄存器里。这就完成了模拟到数字的转换。我们只需要读取ADC-DR寄存器中的值就可以获取到转换后的数字。同时产生一个EOC转换结束标志位,可以通过这个标志触发中断。

    下图为ADC的时序图:可以看到,ADC转换结束后就产生了一个ADC转换标志位EOC。

    几个重要特征:

  • 12位连续逼近型的ADC。这里的逐次逼近型指的是ADC的工作模式。12位指的是ADC的分辨率,一般使用多少位来表示,12位AD值,对应的范围就是0-2^12-1。即0-4095,也就是转换为数字信号所表示的范围。
  • 1us的转换时间。转换时间即为转换的频率,1us表示从AD转换开始到产生结果需要花费1us的时间。
  • 输入电压的范围0-3.3v。转换的结果为0-4095

  • 2. ADC的输入通道和两个转换单元

    1. STM32里的ADC拥有18个输入通道,其中包括16个外部通道2个内部的信号源

  • 16个外部通道,即16个GPIO口,可以直接接模拟信号,引脚直接测量电压。
  • 2个内部的信号源,包括内部温度传感器和内部参考电压。其中内部温度传感器可以测量cpu的温度。内部参考电压是一个1.2v左右的基准电压,不随外部电压的变化而变化。
    1. 两个转换单元即为规则组和注入组两个转换单元

    16个外部通道可以在任意多个通道上以任意顺序进行的一系列转换构成成组转换。

  • 规则组由多达16个转换组成。即规则组的通道有16个,可以在ADC连续转换的模式下连续转换16个通道。这个组最为常用。
  • 而且通常与DMA配合使用即ADC转换后的数据存放在ADC->DR寄存器里,当一个通道的数据被转换后,存放在DR寄存器里之后,上一个数据没有被读走,下一个数据就会覆盖上一次的数据。这样就导致数据的丢失。

  • 注入组有4个通道,多用于突发事件,最多为4通道。
  • 可以看下方的图,即为上方讲解的ADC的输入通道和两个转换单元。


    3.ADC的触发源

    ADC的触发源,包括硬件触发和软件触发

  • 软件触发,软件触发可以直接使用软件进行触发,即在软件中进行使用库函数,所以在使用软件触发之后,ADC就可以开始进行转换。一般没有特别的需求,都使用的是软件触发。
  • 硬件触发,包括注入组和规则组的信号。例如定时器捕获,外部中断引脚来触发,以及定时器的各个通道,还有TRGO的定时器主模式的输出所引发的触发信号。

  • 4. ADC连续转换or单次转换,非扫描or扫描模式

    连续转换or单次转换

    主要是看ADC转换后需不需要触发源再次触发通道,进行ADC转换。

  • 连续转换,指的是一次ADC转换结束后并不会停止,而是立即开启下一轮的转换,然后一直持续下去。即只需要触发一次,之后就可以一直转换。
  • 单次转换,在一次ADC转换结束后需要再次触发,才可以继续进行ADC转换。
  • 非扫描模式or扫描模式

  • 非扫描模式,在该模式下,转换的通道只有序列1位置有效。即只有第一个通道有效,能够进行ADC转换
  • 扫描模式下,序列X位置是有效的,可以直接选择多个序列进行ADC转换,而且在选择通道时可以重复,即序列X可以多选,在序列中可以选择重复的通道。

  • 5. ADC的数据对齐

    大家都知道,数据寄存器为16位的寄存器。而ADC是12位

    ADC转换结束后,产生的数据就是一个十二位的数据。这样转换完成后保存在ADC->DR数据寄存器里的值也就是一个十二位的数据。所以就产生了数据是左对齐还是右对齐。

  • 数据左对齐ADC->DR数据寄存器十六位,即高
    位数据为转换后的ADC数据,低四位为0
    相应的DR就比实际的结果大十六倍。
  • 数据右对齐ADC->DR数据寄存器的低12为ADC转换后的数据,高四位为0.对应的DR就是ADC转换后的数据一般使用数据右对齐

  • 6. ADC的转换时间

    ADC转换的步骤:采样->保持->量化->编码

    ADC转换的时间即在量化编码之前设置一个采样开关,收集外部电压。当外部电压被存储好后,断开采样开关,再进行AD转换。(在量化编码的过程中,电压始终保持不变。)

    所以打开采样开关收集外部电压到断开采样开关进行AD转换的时间就为ADC的转换时间。

    其中总转换时间:TCONV = 采样时间+ 12.5个周期

    当ADCCLK=14MHz,采样时间为1.5周期
    TCONV = 1.5 + 12.5 = 14周期 = 1μs


    二、ADC的配置

    经过了上述部分的学习,对ADC有了一个整体的了解,下面就是如何配置ADC,写程序来实现ADC模拟到数字的转换。

    1. RCC开启时钟

    首先我们需要开启ADC、ADC分频时钟ADCCLK以及选择通道对应的GPIO。

    	RCC_ADCCLKConfig(RCC_PCLK2_Div6);  //6分频
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);  //ADC分频时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  //开启GPIOA时钟
    

    注意ADC对应的GPIO口要根据手册的引脚定义图来配置。


    2. 配置GPIO

    这里我选择ADC1的通道6,对应的GPIO口就是GPIOA6

    这里引脚的模式要配置为模拟输入

    	GPIO_InitTypeDef GPIO_InitStruct;
    	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;   	//模拟输入
    	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;		//GPIOA6
    	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; 
    	GPIO_Init(GPIOA,&GPIO_InitStruct);
    

    3. 选择规则组或注入组的输入通道

    选择规则组的输入通道,我这里选择的是ADC1,ADC1的通道6,采样时钟为55,当配置其他通道时,同理。

    //配置ADC转换通道  选择ADC1通道6 序列1  采样时钟为55
    	ADC_RegularChannelConfig(ADC1,ADC_Channel_6,1,ADC_SampleTime_55Cycles5);
    

    4.配置ADC初始化

    ADC的初始化,通过ADC_Init()完成。

    我们来说说,这几个参数

  • ADC_ContinuousConvMode,ADC是否连续转换?可选单次转换(DISABLE)或者连续转换(ENABLE)。
  • ADC_DataAlign,转换后的数据对齐方式。可选左对齐或右对齐。
  • ADC_ExternalTrigConv 是否外部触发ADC,可选择硬件触发或者软件触发。
  • ADC_Mode,ADC的模式,我们一般使用单ADC转换。当然也可以使用双ADC转换。
  • ADC_ScanConvMode,ADC是否连续扫描?ADC的连续扫描可以和DMA配合使用,效果极佳!留在下篇。
  • ADC_NbrOfChannel,指定扫描模式下会用到几个通道。这个参数在非扫描模式下,默认是序列1。这个参数仅在扫描模式下有用。
  • //ADC初始化
    	ADC_InitTypeDef ADC_InitStruct;
    	ADC_StructInit(&ADC_InitStruct);
    	ADC_InitStruct.ADC_ContinuousConvMode=ENABLE;		//连续转换 否 单次转换
    	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=6;    			//选择ADC1的6号通道
    	ADC_InitStruct.ADC_ScanConvMode=DISABLE;			//连续扫描  否 单次扫描
    	ADC_Init(ADC1,&ADC_InitStruct);
    

    5.开关控制ADC

    开启ADC,即使能ADC

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

    6. 开启软件触发ADC

    一般都是选择软件触发ADC,这里直接使用库函数就可以啦。

    //软件触发ADC
    ADC_SoftwareStartConvCmd(ADC1,ENABLE);
    

    7. 校准ADC

    校准可大幅减小因内部电容器组的变化而造成的准精度误差

    	//校准ADC
    	ADC_ResetCalibration(ADC1);
    	while(ADC_GetResetCalibrationStatus(ADC1)==SET);
    	ADC_StartCalibration(ADC1);
    	while(ADC_GetCalibrationStatus(ADC1)==SET); 
    

    8. 读取ADC转换后的数据

    当经过了上述配置,ADC读取端口的模拟输入,将其转换成了数字,存放在ADC->DR寄存器内。我们只需要读取DR寄存器,就可以知道ADC转换的值啦。

    uint16_t AD_GetValue(void)
    {
    	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);	//规则组转换完成标志位 EOC为RESET时 转换未完成 EOC为空,执行空循环
    	return ADC_GetConversionValue(ADC1);
    }
    
    

    测试及程序的现象

    我选择在串口调试数据,即把转换后的数据发送给串口助手,读取AD转换后的数据。

    具体使用串口有关文章可以看我上一篇:STM32-串口通信(串口的接收和发送)

    程序现象

    可以看到AD转换后的值有波动,产生跳变。


    三、 总结

    上述就是关于ADC模拟数字转换的相关内容,是自己学习后的一个总结

    ADC转换的功能非常强大,使用起来也很方便

    主要明确以下几点

    1. ADC的通道,根据引脚定义表来选择
    2. ADC的触发源,软件触发or硬件触发
    3. ADC的模式选择,单次转换or连续转换。扫描模式or非扫描模式。
    4. EOC标志位的理解

    行文仓促,如有误,欢迎指正。

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM-32-ADC模拟数字转换(AD单通道转换)

    发表评论