[其他ST产品]

STM32初识及运用—ADC

[复制链接]
203|8
手机看帖
扫描二维码
随时随地手机跟帖
l63t89|  楼主 | 2023-5-29 23:34 | 显示全部楼层 |阅读模式
基于stm32f103c8t6(48引脚))
ADC初识——理论讲解

    Analog-to-Digital Converter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字
    ADC跟其名字一样完成的是一个模拟量转换为数字量的过程,为什么要把模拟信号转换为数字信号呢,这是因为在显示生活中很多模拟信号太抽象,不好定性分析,如果将其按一定方式转化为容易分析的数值信号,就会变得很容易。

基本原理:

总共有三个ADC控制器,最多能支持23个通道,21个外部和2个内部
Vref+ Vref-分别ADC采集正负参考电源,输入采集的电压不能超过这两个值。

804216474c5e57c105.png

关于32的讲解在官方的技术手册中讲解的很清楚,我这里对其中一些难理解的词做一些注释,方便大家能够更容易看懂技术手册
名词讲解:
规则通道:顾名思义就是最普通,最常用的通道,平时大多数ADC转化都是利用规则通道实现的。
注入通道:注入通道是相对于规则通道而言的,注入通道可以在规则通道转化时,强行插入转换,当有注入通道需要转换时,规则通道的转换会停止,优先执行注入通道的转换,当注入通道的转换执行完毕后,再回到之前的规则通道进行转换。(相当于中断吧)
转换顺序:规则通道只有一个数据寄存器,当多个通道进行转换时就涉及到一个优先级的问题,通过SQRX寄存器可以对进行设置。
注入通道的顺序寄存器为JSQR(只有当JL=4的时候,注入通道的转换顺序才会按照JSQ1、JSQ2、JSQ3、JSQ4的顺序执行。当JL<4时,注入通道的转换顺序恰恰相反,也就是执行顺序为:JSQ4、JSQ3、JSQ2、JSQ1。)


使用特权

评论回复
l63t89|  楼主 | 2023-5-29 23:34 | 显示全部楼层
触发源:ADC转化的触发方式 其一就是通过直接配置寄存器CR2的ADON位,写1的时候开始转换,写入0的时候停止转换。此外还可以通过内部定时或外部IO触发,定时器触发就是利用内部时钟让ADC进行周期性的转换;也可以利用外部IO在使ADC在需要的时候进行转换,都是通过配置CR2寄存器来决定的。
转换时间:转换时间 = 采样时间+12.5个周期
采样时间可以通过寄存器设置为多少个周期(例如1.5个周期),用这个周期时间乘以ADC的一个时钟周期即可
数据寄存器(注意):
数据寄存器分为规则数据寄存器和注入数据寄存器。值得注意的是使用多个通道的时候,会产生多个转换数据,但是数据寄存器就一个,所以在一个通道完成转换后就看立刻将数据取出来,方便下一个数据存储。
对于规则数据寄存器而言:总共有32位,当使用ADC独立模式(只使用一个ADC,可以使用多个通道),数据存放在低16位中,使ADC多模式时高16位存放ADC2的数据。
此外ADC传回来的数据是12位的,而数据寄存器预留的空间为16位的,所以说还需要设置字节对齐模式,是左对齐还是右对齐。(但注入通道的数据寄存器是12位的所以就不用设计)

使用特权

评论回复
l63t89|  楼主 | 2023-5-29 23:35 | 显示全部楼层
寄存器配置讲解

(1)ADC状态寄存器(ADC_SR)
此寄存器主要存储ADC采集时的各种状态信息
记录当前时间 ADC转换是否开始或者结束,以及一个模拟看门狗标志位。
(2)ADC控制寄存器1(ADC_CR1)
(3)ADC控制寄存器2(ADC_CR2)
这两个寄存器主要完成ADC的基本配置与模式设定。
其中我们所用到的有
CR1:
工作方式的设定(多ADC还是单ADC)
扫描模式的设定(单通道还是多通道)
CR2:
转换模式的设定(单次转换模式还是连续转换)
触发方式的设定(外部,时钟,软件)
数据对齐方式的设定(左对齐还是右对齐)
使能AD转换器
开启校准

(4)ADC采样时间寄存器1(ADC_SMPR1)
(5)ADC采样时间寄存器2(ADC_SMPR1)
采样时间的设定

(6)ADC注入通道寄存器数据偏移寄存器x(ADC_ JOFRx)

(7)ADC看门狗高/低阈值寄存器(ADC_HTR/ADC_LTR)

(8)ADC规则序列寄存器(ADC_SQRx)
(9)ADC注入序列寄存器(ADC_JSQR)
规则转换的顺序设定
规则转换的数目设定

(10)ADC注入数据寄存器(ADC_JDRx)
(11)ADC规则数据寄存器(ADC_DR)
存储采样返回值

使用特权

评论回复
l63t89|  楼主 | 2023-5-29 23:35 | 显示全部楼层
ADC初识——实际运用

注意:为了提高32在进行小项目开发的速度,本篇文章所用的代码都是笔者自己基于32标准库进行二次开发 ,方便能够快速调用单片机外设

    关于代码,工程文件会附在文章的末尾。

使用特权

评论回复
l63t89|  楼主 | 2023-5-29 23:35 | 显示全部楼层
ADC的初始化
//-------------------------------------------------------------------------------------------------------------------
//  [url=home.php?mod=space&uid=247401]@brief[/url]      ADC初始化
//  @param      adcn            选择ADC模块(ADC1,ADC2)
//  @param      ch              选择ADC通道
//  [url=home.php?mod=space&uid=266161]@return[/url]     void
//  Sample usage:               adc_init(ADC1, CH0_PA0);
//-------------------------------------------------------------------------------------------------------------------
void HYJ_ADC_Init(ADC_TypeDef* adc,chx_enum ch)
{
        ADC_InitTypeDef ADC_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1        , ENABLE );          //使能ADC1通道时钟
        RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

        HYJ_GPIO_Init(get_adc_pin(ch),GPIO_Mode_AIN,0);

        ADC_DeInit(adc);  //复位ADC
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC工作模式:ADC1和ADC2工作在独立模式
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;        //模数转换工作在单通道模式
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        //模数转换工作在单次转换模式
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        //转换由软件而不是外部触发启动
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐
        ADC_InitStructure.ADC_NbrOfChannel = 1;        //顺序进行规则转换的ADC通道的数目
        ADC_Init(adc, &ADC_InitStructure);        //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   
        ADC_Cmd(adc, ENABLE);        //使能指定的ADC
       
        ADC_ResetCalibration(adc);        //使能复位校准           
        while(ADC_GetResetCalibrationStatus(adc));        //等待复位校准结束       
       
        ADC_StartCalibration(adc);         //开启AD校准
        while(ADC_GetCalibrationStatus(adc));         //等待校准结束
}


使用特权

评论回复
l63t89|  楼主 | 2023-5-29 23:35 | 显示全部楼层
这里为了方便快速调用初始化,入口参数只设置了adc模块和通道,其他设置统一设置为
单通道,单次转换,时钟为12M

ADC的运用和实例

完成初始化后就可以调用
//-------------------------------------------------------------------------------------------------------------------
//  @brief      ADC转换一次
//  @param      adcn            选择ADC模块(ADC1、ADC2)
//  @param      ch              选择ADC通道
//  @return     void
//  Sample usage:               adc_convert(ADC1,CH0_PA0);
//-------------------------------------------------------------------------------------------------------------------
u16        HYJ_ADC_Getdata(ADC_TypeDef* adc,chx_enum        ch)
{
        //设置指定ADC的规则组通道,一个序列,采样时间
        ADC_RegularChannelConfig(adc, ch, 1, ADC_SampleTime_239Cycles5 );        //ADC1,ADC通道,采样时间为239.5周期                                      
       
        ADC_SoftwareStartConvCmd(adc, ENABLE);                //使能指定的ADC1的软件转换启动功能       
         
        while(!ADC_GetFlagStatus(adc, ADC_FLAG_EOC ));//等待转换结束

        return ADC_GetConversionValue(adc);        //返回最近一次ADC1规则组的转换结果
}

使用特权

评论回复
l63t89|  楼主 | 2023-5-29 23:36 | 显示全部楼层
示例:
 int main(void)
{       
                HYJ_ADC_Init(ADC1, CH0_PA0);
  while(1)               
        {
                HYJ_ADC_Getdata(ADC1,CH0_PA0);
        }
}

使用特权

评论回复
l63t89|  楼主 | 2023-5-29 23:36 | 显示全部楼层
工程文件链接地址:
链接:https://pan.baidu.com/s/1abTvUt44NiH5B_o7IiPa3Q
提取码:cxm6

使用特权

评论回复
海滨消消| | 2023-5-30 11:06 | 显示全部楼层
老铁,文章字数多也不要分成这么多段分发哟

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

67

主题

661

帖子

0

粉丝