目录
在STM32F中,ADC可配置分辨率 有12位,10位,8位,6位
ADC供电要求为 2.4V~3.6V
输入方式:
-- 外部GPIO口16路输入
-- 内部温度传感器输入
-- 内部参考电压输入
--- 外部电池VBAT输入
模拟看门狗功能:
AWD模拟看门狗功能由在ADC_CFGR1寄存器的AWDEN位置位来开启,它可用于监控所选的单一通道或所有使能通道所配置的电压范围。
如果模拟电压转换由ADC高于高阈值或低于低阈值时,AWD模拟看门狗的状态为被置位,模拟看门狗中断可用设置ADC_IER寄存器中的AWDIE位来使能。
ADC中断
ADC中断可由一下任意事件产生

配置一个Demo
要求如下:配置ADC1IN1,ADC1IN2,ADC1IN3,使用内部专用14Mhz振荡器,过采样为7.5个ADC周期,由TIM1中断作为触发信号,DMA搬运
并且开启模拟看门狗监控ADC1IN1,阈值为3.3v~3.0v并且开启模拟看门狗中断。
设置时钟
1.首先要设定ADC的时钟,需要注意的是ADC是双时钟架构,可以选择以下任意一个
选项1:专用的14MHz内部振荡器
选项2:PCLK时钟/2 或/4 最大不能超过14MHz
选项1的优势是ADC一直具有最佳的ADC采样频率,它还提供了为了节能,可自动打开/关闭内部14MHz振荡器的能力。

可以看到选项1的优点为快速,选项2优点为无抖动
从RCC的图里也可以看到HSI14为内部14Mhz专用振荡器独立于任何时钟

HSI14在SystemInit的时候已经被关掉了所以需要在用的时候再开启,在我上篇博客里有解释

控制HSI14的寄存器为RCC_CR2

通过寄存器可以看到HSI14也需要校准,步骤为
1.HSI14ON=1,使能HSI14
2.等待HSI14DRY=1,等待HSI14就绪
3.HSI14DIS=0,允许ADC打开HIS14振荡器
经过这三步,HSI14就已经被打开而且可由ADC使用了。
使用HSI14需要注意ADC的这个功能
自动关断模式 (AUTOFF)
ADC 含有一个本身电源自动管理的功能,该功能为自关断模式。当设置 ADC_CFGR1 寄存器中的 AUTOFF=1 时,开启该功能。
当AUTOFF=1时, 无转换时ADC经常自断电;转换开始(由软件或硬件触发)时ADC自动唤醒。一个启动时间在触发开始转换与采样之间自动插入。一旦序列转换结束后 ADC 自动关闭。自动关断模式可大大降低应用的功耗, 其适用于需要相对较少转换或转换请求的时间间隔足够长 ( 如低频的硬件触发 ) 的应用。
自校准
2.注意在开启ADC之前需要进行自校准,否则无法使用ADC ,在校准期间,ADC计算一个用于ADC校准的7为校准因子(ADC掉电后丢失),在ADC校准期间和校准未完成前,不能使用ADC模块。
校准是由软件设置ADCAL=1 来初始化,且只能在ADC禁用(ADEN=0)时完成初始化,校准完成后,ADCAL被硬件清0,校准完成后可由ADC_DR的[6:0]读出校准因子。
使用ADC_CR寄存器完成自校准


软件过程
确认ADEN=0
设置ADCAL=1
等待ADCAL=0
校准完成(可由ADC_DR的[6:0]读出校准因子)

在ADC配置过程中需要注意
通道选择
通道可以选择:
●16个从GPIO引脚引入的模拟输入
●3个内部模拟输入(温度传感器ADC_IN16,内部参考电压ADC_IN17,VBAT通道ADC_IN18)
ADC可以选择单个或者多个序列
被转换的ADC在通道选择寄存器ADC_CHSELR 中编程选择

ADC扫描的通道顺序由ADC_CFGR1 中 SCANDIR 位的配置来决定:
● SCANDIR=0: 向前扫描 : 从通道 0 到通道 18.
● SCANDIR=1: 回退扫描:从通道 18 到通道 0

采样时间选择
启动ADC之前,ADC需要在被测电压源 和内嵌采样电容 间建立一个直接连接,采样时间必须足够长以便输入电压源对内嵌电容充电到输入电压水平。
ADC采样事件对所有通道都适用,通过修改ADC_SMPR来确认采样时间


转换模式选择
单次转换模式

连续转换模式

寄存器如下


断续模式
该模式由设置 ADC_CFGR1 寄存器中的 DISCEN 位来开启。 在这个模式(DISCEN=1)下,需要硬件或软件的触发事件去启动定义在一个序列中的每次转换。 相反,DISCEN=0 时 , 一个硬件或软件的触发事件就可以启动定义在一个序列中的所有转换。
即序列不是一次转换,而是一个一个转换,在每次触发的时候转换一个。



启动转换
软件触发

需要注意在硬件触发情况下也需要第一次开启ADSTART
ADSTART在


外部触发
一次转换或一个序列的转换可由软件或外部事件 ( 例如:定时器捕获、输入引脚 ) 触发。
输入引脚触发为:

定时器触发为:

设置触发位于



转换结束


状态寄存器会改变


关于DMA
对于减轻CPU负担,建议使用DMA 来等待和搬运ADC数据
因为所有通道的转换结果数据存放到一个单一的数据寄存器中,故当转换通道超过 1 个时用
DMA 方式会更有效。这样可以避免丢失存在 ADC_DR 寄存器中的转换结果。
DMA 模式开启时 (ADC_CFGR1 寄存器中的 DMAEN =1), 每次转换结束时都会产生一个
DMA 请求。这样就允许把在 ADC_DR 寄存器中的转换数据传送到软件指定的目标地址中。
尽管如此,因 DMA 不能够及时为 DMA 请求服务而产生的过冲 (OVR=1) 时,ADC 就会停止
产生 DMA 请求且相应结果是新的转换数据也不会再由 DMA 进行传输 ( 当 OVR=0 时,会继
续传输 )。这也可以认为所有传输到 RAM 中的数据都是有效的 ( 因无效的数据再也不传输了 )。也就是DMA 传输请求会被阻止直到软件清除 OVR 位。
根据 OVRMOD 位的配置,ADC_DR 寄存器中的数据可选择为:保持或覆盖。
有两种不同的 DMA 模式,其取决于ADC_CFGR1 寄存器中的DMACFG 位的配置:
● DMA 一次模式 (one shot mode)(DMACFG=0 ).
当 DMA 编程用于传输固定长度的数据时,可选用该模式。在该模式下,每次使能仅进行一轮传输,一旦计数器的值减至0时,DMA传输会停止。想要再次传输,必须重新设置计数器CNDTR的数值。
●DMA 循环模式 (DMACFG=1 )
当 DMA 编程为循环模式或双缓冲模式时,可选用该模式。主要处理连续的数据传输,每进行一轮传输,计数器会被自动恢复为初始值,同时DMA传输进入下一轮,非常适合同ADC多通道(扫描)模式一起工作。

寄存器如下:



模拟看门狗
这里选择模拟看门狗监控通道
模拟看门狗中断在这里配置
模拟看门狗阈值寄存器:
ADC数据位置
以上是ADC的所有介绍,接下来开始写Demo
cpp
/*要求如下:配置ADC1IN1,ADC1IN2,ADC1IN3,使用内部专用14Mhz振荡器,过采样为7.5个ADC周期,由TIM1中断作为触发信号,DMA搬运
并且开启模拟看门狗监控ADC1IN1,阈值为3.3v~3.0v并且开启模拟看门狗中断。ADC分辨率为默认的12位*/
void Demo(void){
//打开HSI14时钟
RCC->CR2 |= 0x00000001;//开启HSI14
while(!(RCC->CR2 |= 0x00000002));//等待HSI14稳定
RCC->CR2 |= 0x00000004;//允许ADC打开HSI14
//ADC自校准
ADC1->CR |= 0x00000001; //ADC禁用
ADC1->CR |= 0x80000000; //开启自校准
while((ADC1->CR |= 0x80000000)); //等待自校准完成
//ADC通道选择
ADC1->CHSELR |= 0x0000000E; //选择通道1 2 3
ADC1->CFGR1 |= 0X00000004; //前向扫描
//ADC采样时间选择
ADC1->SMPR |= 0x00000001; //7.5个采样周期
//转换模式选择
ADC1->CFGR1 &= 0XFFFFDFFF; //单次转换模式
ADC1 ->CFGR1 &= 0xFFFFF3FF; //外部触发禁止
ADC1 ->CFGR1 &= 0xFFFFFE3F;//使用TIM1_TRGO作为触发事件源
//开启模拟看门狗
ADC1->ISR |= 0x00000080;//开启模拟看门狗中断
ADC1->IER |= 0x00000080;//模拟看门狗中断使能
ADC1 ->CFGR1 |= 0x4C00000;//模拟看门狗监视通道1 模拟看门狗使能 在单一通道上使能模拟看门狗
ADC1->TR |=0xE8C0FFF;//阈值为 4095~3723 即3.3v~3.0v
//DMA设置
ADC1 ->CFGR1 |= 0x00000003;//DMA使能 循环模式
//开始转换
ADC1->CR &= 0xFFFFFFFE; //ADC解除禁用
ADC1->CR |= 0x00000004; //开始转换
}
具体DMA配置见下篇博客介绍