STM32 --- ADC

本文详细介绍了STM32的ADC工作原理,包括ADC结构、GPIO选择、通道配置、DMA触发转换、标志位、转换频率、模拟看门狗和校准过程。同时提供了STM32ADC的实验配置和代码示例,供开发者参考。
摘要由CSDN通过智能技术生成

ADC简介

        ADC(Analog-Digital Converter)模拟-数字转换器,ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁。

STM32—ADC

简介

整体结构图:

GPIO端口选择:

        通过选取外部GPIO口,作为模拟信号量的输入,根据STM32不同型号引脚来选取ADC模拟输入引脚。(PS:以STM32F103R8T6为例,有ADC1,ADC2,并且有0~9十个ADC输入引脚复用在下图对应GPIO引脚,不同型号会有所不同,具体可以查看具体型号的引脚定义表)

通道选择:

        STM32有16个多路通道。可以把转换组织成两组:规则组(最多16)和注入组(最多4)。在任意多个通道上以任意顺序进 行的一系列转换构成成组转换。(PS:可以如下顺序完成转换:通道3、通道8、通道2、通道 2、通道0、通道2、通道2、通道15。)

        ● 规则组由多达16个转换组成。规则通道和它们的转换顺序在ADC_SQRx寄存器中选择。规 则组中转换的总数应写入ADC_SQR1寄存器的L[3:0]位中。

        ● 注入组由多达4个转换组成。注入通道和它们的转换顺序在ADC_JSQR寄存器中选择。注入 组里的转换总数目应写入ADC_JSQR寄存器的L[1:0]位中。

        如果ADC_SQRx或ADC_JSQR寄存器在转换期间被更改,当前的转换被清除,一个新的启动脉冲将发送到ADC以转换新选择的组

 通道寄存器:

        注入通道数据寄存器一共四个(4*16),对应注入通道每一个注入通道对应一个数据寄存器

        规则通道数据寄存器就一个(1*16)。(这里需要注意当选择多规则通道时,需要DMA配合转运数据寄存器的值,如果转移不及时数据将会覆盖。

DMA触发转换:

         根据规则组与注入组的不同对应的触发源不同(具体触发源如下图,大部分的触发源是多定时器,这些触发源有硬件支持可以不需要进入中断(需要根据触发源配置不同定时器的更新事件),也可以选择定时器到达时选择进入中断进行ADC转换),ADC经常需要每隔一段时间来触发转换,这样我们可以根据对应通道的定时器触发源,设置定时时间来申请中断触发ADC转换。除了这些触发源我们也可以选择软件触发ADC,需要我们在程序当中调用触发转换的代码即可。

DMA完成标志位:

        根据不同的通道有着不同的标志位,规则组对应的标志位是EOC,通道组对应的标注位是JEOC,当对应的标志位为1,表示转换完成。

 ADC转换频率:

        ADC转换频率,来自RCC,通过ADC预分频器分频最大可以达到14MHZ

 模拟看门狗:

        通过模拟开门狗对ADC转换结果进行监听(通过让ADC转换结果即数据寄存器的值与模拟看门狗的阈值对比),如果不在阈值内就会产生看门狗相应中断标志位触发NVIC中断可以在中断进行相应的处理。

 ADC基本结构图:

ADC转换模式:

        1、单次转换,非扫描模式:只有一个通道,触发一次转换一次。

        2、单次转换,扫描模式:只有一个通道,触发一次连续转换(数据需要及时取出否则容易被覆盖,可以使用DMA转移数据)。

        3、多次转换,非扫描模式:有多个通道,触发一次每个通道转换一次(PS:这里是多通道所以需要DMA协调转运数据,否则数据容易覆盖)。

        4、多次转换,扫描模式:有多个通道,触发一次每个通道转换一次,然后轮询每个通道转换一次(PS:这里是多通道所以需要DMA协调转运数据,否则数据容易覆盖)。

ADC校准:

        ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。在校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换 中每个电容器上产生的误差。

         通过设置ADC_CR2寄存器的CAL位启动校准。一旦校准结束,CAL位被硬件复位,可以开始正 常转换。

        建议在上电时执行一次ADC校准。校准阶段结束后,校准码储存在ADC_DR中。

        注意:

        1 建议在每次上电后执行一次校准。

        2 启动校准前,ADC必须处于关电状态(ADON=’0’)超过至少两个ADC时钟周期。 

ADC实验 

实验工具:

        软件:win10、keil

        硬件:STM32F103C8T6、OLED(4引脚)、电位器、杜邦线、串口烧录工具、螺丝刀。

实验现象:

        通过螺丝刀调节电位器,产生不同模拟信号量通过ADC1通道0输入STM32F03C8T6,STM32通过ADC转换将模拟型号转换成数据信号通过OLED显示。

 

实验代码书写:
开启时钟:

        这里我们需要使用ADC1,与GPIOA_Pin_0,使用我们需要开始ADC1与GPIOA的时钟。

/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);	//开启ADC1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOA的时钟
配置ADC采集时钟:

        配置ADC采集时钟,来自RCC系统时钟(系统时钟72MHz)通过ADC分配器分频系数可以选择RCC_PCLK2_Div2: ADC clock = PCLK2/2、RCC_PCLK2_Div4: ADC clock = PCLK2/4、RCC_PCLK2_Div6: ADC clock = PCLK2/6、 RCC_PCLK2_Div8: ADC clock = PCLK2/8。(PS:ADC采集时钟最大可以达到14MHz,所以只能选择6分频与8分频,达不到最大的采用频率)

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

        因为我们需要配置GPIO口为ADC模拟信号输入,所以我们需要将对应的端口配置为模拟输入的模式。

/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);		//将PA0引脚初始化为模拟输入
通道组选择配置:

        这里我们选择规则组通道,根据自己的要求可以选择ADC的端口(ADC1~ADC3)、输入频道(ADC的输入口具体看GPIO口,这里我使用的是GPIOA_Pin_0,对应ADC_Channel_0)、放入的通道序号(1~16一共16个通道)、以及优先级(安装自己的需求)。(PS:这里我们选择的是规则组通道,我们也可以选择注入组通道,使用ADC_InjectedChannelConfig(),可以根据自己的选择进行配置,这里通道只能选择1~4四个通道,其他同注入组相同)

/*规则组通道配置*/
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);	//规则组序列1的位置,配置为通道0
ADC初始化:

        通过一个结构体来配置模式、数据对齐方式、触发方式,是否连续转换、是否扫描模式、通道个数。

/*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之前需要使能ADC。

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

        开始使用ADC转换之前需要ADC校准,防止误差,具体步骤固定。

/*ADC校准*/
ADC_ResetCalibration(ADC1);							//固定流程,内部有电路会自动执行校准
while (ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
ADC软件触发函数: 

        通过ADC_SoftwareStartConvCmd(ADC1, ENABLE)软件触发ADC转换,通过while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET)等待EOC标志位(EOC为1时表示转换完成,0没有转换完成),如果选择的是注入通道应该判断JEOC标志位。

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转换的结果
}

工程文件分享:

        http://链接:https://pan.baidu.com/s/1r5dbjqI26ntK15U8znWE-A 提取码:xqct

  • 30
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值