打印
[STM32F1]

STM32F103C8T6的ADC

[复制链接]
206|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-10-14 14:16 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
STM32F103C8T6的ADC:ADC1、ADC2

实际通道:共10个,ADC1与ADC2共引脚,PA0~PA7,PB0~PB1

F1系列最多输入通道:共18个通道,16个外部,2个内部(温度传感器、内部参考电压)



不同引脚所对应的ADC通道不同!!!

只改变引脚而不改变通道的话,会导致ADC转换无效。

也就是ADC12_INx的x就是不同引脚对应的通道。(24.10.11晚)



ADC工作模式:

        ①独立模式(常用):单个ADC进行工作。

        ②多重模式:多个ADC进行工作,就是近似能同时读取不同通道的值,能够提高转换效率,。

        (不甚了解多重模式,目前已知是一个ADC作为主ADC,其他ADC作为从ADC,从ADC在主ADC工作一段时间后(大约是一个采样周期后)才会启动)

ADC工作步骤:

采样——>保持——>量化——>编码

        采样:接收传感器传输的数据

        保持:保存数据。定格数据,不再接收新的数据,避免一直采样导致数据一直波动,无法正常量化的情况。

        量化:将连续的模拟信号值近似为有限多个离散值。量化精度与分辨率有关。

        编码:将量化后的数字值转换为二进制数字的过程。

分辨率:ADC的分辨率是指其能够分辨量化的最小信号的能力,一个12位的ADC,其分辨率就是12位。

        对于3.3v供电且参考电压(VREF–、VREF+)与电源(VDDA 和、VSSA )相接的板子而言,也就是可以把电源电压3.3v用0~4095范围内的值来量化。

ADC工作原理:逐次逼近。

        逐逼与二分法类似,实现方式是从最高位起开始判断置1或0后,硬件的值与输入值的大小关系。

        若置1大则0,若置1小则1,然后下一位,直至最低位也操作完成。

        (样例供参考:5位二进制数,值18)



        在ADC的逐次逼近型寄存器,就会从高位开始置位,并根据置位不同产生的不同电压来匹配外部输入的电压(0v~3.3v),要是接近的话,那么此时的置位结果从二进制转化为十进制数就是ADC的转换结果(会自动放在对应组别的数据寄存器里)。多少位的ADC,就要判断多少次


ADC通道分组:

        规则组(Regular Group):

                最多有16个通道。

                但由于只有1个规则组数据寄存器,对于多次转化或扫描转换,需要配合DMA使用,否则新数据会覆盖旧数据,最终只能读取到最新的数据。

        注入组(Injected Group):

                最多有4个通道。

                犹豫刚好有4个注入组数据寄存器,因此可以保证不同通道同时转换,而数据不被覆盖。

        区别:注入组可以中断规则组的转换,优先转自己的。



通道的操作:既可以同时开启多个注入组通道,然后同时读取;也可以逐个开关规则组通道,实现读一个关一个,开另一个,然后再开始读。两种方式都可以实现对不同通道数据的转换。


ADC转运模式:

扫描模式:在扫描模式下,ADC可以设置多个输入通道进行连续转换,按照通道号的顺序对这些通道进行转换,并将结果按顺序保存在对应的数据寄存器中。

连续模式:在连续模式下,ADC在完成一次转换后会自动开始下一次转换,无需外部触发。

        ①单次非扫描:对一个通道转一次停一次置一次EOC,不更改通道。结束后需要等待下一次触发

        ②单次扫描:转完所有通道后才停止置位EOC。需要用DMA,否则前面通道的数据会被后面通道的覆盖。结束后需要等待下一次触发

        ③连续非扫描:一直对一个通道进行转换,不停。

        ④连续扫描:一直对好几个通道进行扫描,不停。

        ⑤间断模式:扫几次就停,需要触发。

相关标志位:

                EOC是转换完成标志位,完成1,未完0。中断使能标志位是EOCIE

                AWD是模拟看门狗中断标志位。中断使能标志位是AWDIE

                JEOC是注入组转换结束标志位。中断使能标志位是JEOCIE

                START是开启转换标志位,置1表示开始转换。

如果开启了对应的NVIC的中断通道,那么产生中断标志的时候就会触发中断

左右对齐:

        ADC是12位的,但是数据寄存器是16位的,也就是有4位空余,这导致了需要考虑左对齐还是右对齐。

        左对齐:直接读取会导致精度下降。(相当于读取值=原值 x 16)

        右对齐:直接读取就是目标值。(常用)

触发源:软件触发源--调用函数。

               硬件触发源-- 定时器、 外部中断

时钟:AHB——>APB2时钟(72MHZ)——>ADC预分频器(2、4、6、8分频)——>DACCLK

        由于ADC的时钟频率上限是14MHZ,而RCC的时钟是72MHZ,所以需要选择6、8分频,否则越界容易导致转换的结果会有误(超频 )。

转换周期:采样时间+12.5个ADC周期(12bit算一个ADC周期,余下0.5算硬件操作时间)

采样时间:看ADCCLK,如当ADC_CLK=14MHZ时,采样时间位1.5ADC周期,此时转换一次的时间时1us

校准:使用库配置好的代码,使ADC的采样防止电容变化导致的精度不准。需要ADC断电一段时间后才能校准,但在初始化后校准一下就可以了。

模拟看门狗:模拟看门狗检测某个输入通道的值,一旦高于或低于中断标志位AWD就是置位,就会申请中断。

配置要点:

        ①是否连续转换:转一次数据就结束一次,还是转多次数据才结束

        ⑥是否扫描模式:完成一个通道之后,是否接着转其他通道

        ②数据左右对齐:左对齐(降低精度,共12位,取高8,舍低4)

                                    右对齐(实际值,直接读取即可)

        ③ADC的触发方式(硬件、软件):一般软件触发

        ④单多ADC运行:一般单ADC运行

        ⑤ADC通道选择:就是GPIO口,看GPIO口的配置中将哪个口配置成了AIN模式

数据位数称呼及对应大小

STM32F103C8T6是一款基于ARM Cortex-M3内核的32位微控制器,其数据位数和其他数据大小称呼如下:

字(Word) :STM32F103C8T6的数据总线宽度为32位,因此一个字(Word)是32位(4字节)。

半字(Half Word) :半字通常指的是16位,即2字节。

字节(Byte) :字节是8位,即1字节。

主要代码(参考自江协)
ADC与GPIO口的初始化函数

void AD_Init(void)
{
    /*开启时钟*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);    //开启ADC1的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);    //开启GPIOA的时钟

    /*设置ADC时钟*/
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);                        //选择时钟6分频,ADCCLK = 72MHz / 6 = 12MHz

    /*GPIO初始化*/
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);                    //将PA0引脚初始化为模拟输入

    /*规则组通道配置*/

为所选ADC(ADC1)配置其对应的常规通道(ADC_Channel_0)、排序(1)、采样时间(ADC_SampleTime_55Cycles5)。
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);        //规则组序列1的位置,配置为通道0

    /*ADC初始化*/
    ADC_InitTypeDef ADC_InitStructure;                        //定义结构体变量
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //模式,选择独立模式,即单独使用ADC1
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;    //数据对齐,选择右对齐
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;    //外部触发,使用软件触发,不需要外部触发
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        //连续转换,失能,每转换一次规则组序列后停止
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;            //扫描模式,失能,只转换规则组的序列1这一个位置
    ADC_InitStructure.ADC_NbrOfChannel = 1;                    //通道数,为1,仅在扫描模式下,才需要指定大于1的数,在非扫描模式下,只能是1
    ADC_Init(ADC1, &ADC_InitStructure);                        //将结构体变量交给ADC_Init,配置ADC1

    /*ADC使能*/
    ADC_Cmd(ADC1, ENABLE);                                    //使能ADC1,ADC开始运行

    /*ADC校准*/
    ADC_ResetCalibration(ADC1);                                //固定流程,内部有电路会自动执行校准
    while (ADC_GetResetCalibrationStatus(ADC1) == SET);
    ADC_StartCalibration(ADC1);
    while (ADC_GetCalibrationStatus(ADC1) == SET);
}

获取ADC转换值的函数

uint16_t AD_GetValue(void)
{
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);                    //软件触发AD转换一次
    while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);    //等待EOC标志位,即等待AD转换结束
    return ADC_GetConversionValue(ADC1);                    //读数据寄存器,得到AD转换的结果
}
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/QL_SD/article/details/142791325

使用特权

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

本版积分规则

1931

主题

15650

帖子

12

粉丝