12位逐次逼近型ADC,1us转换时间。
输入电压0-3.3v和转化范围0-2^12-1(0-4095)成线性关系。
2个ADC资源,ADC1和ADC2,10个外部通道。
有两种转换单元组:规则组和注入组。
模拟看门狗,会自动检测输入电压范围。
以ADC0809芯片为例:
![](https://img-blog.csdnimg.cn/a5d475dfbac9435bb3c03e4f3823a994.png)
通过地址所存和译码控制通道选择开关。通过2分法依次逼近未知测量电压,Vref(+)和Vref(-)即是VCC和GND,决定DAC的比较值和电压对应关系。EOC是转换完成信号,START是起始信号。
STM32ADC
![](https://img-blog.csdnimg.cn/63d2415122d345199bad9c1744826293.png)
规则组最多可以选择16个通道进行数据转化,但是只有1个16位的数据寄存器,根据通道顺序的值会覆盖数据寄存器的值,所以最好用DMA数据转运。
对于注入组,同时可以选择4个通道,因为有4个数据寄存器,所以不必担心数据覆盖问题。
触发ADC数据开始转化的方式有两种:软件写一条代码触发或硬件触发,主要是定时器和中断,如图所示。
ADC时钟来自RCC
![](https://img-blog.csdnimg.cn/177db2b837a943e7aed1452c27bc75bd.png)
![](https://img-blog.csdnimg.cn/135a0015f6bb47169449cb33c127a7b1.png)
对于初始化的72Mhz,我们只能选择6分频的12Mhz,或者8分频的9Mhz。
如果启动了模拟看门狗,看门狗会自动去比较阈值结果,超过的的话会将AWD位置高位,配置中断后可以申请中断。注入组和规则组转换完成也都会去置标志位。
ADC四种转化模式(单次转换和扫描组合)
1)单次转换,不扫描
![](https://img-blog.csdnimg.cn/2e950b4e16944b179875bec37f3c118e.png)
触发一次,转换一个序列1内的通道,置转换完成标志位。下次转换依旧还要发开始转换信号
2)连续转换,不扫描
![](https://img-blog.csdnimg.cn/c5dab09b95154c7d9443fe9861253793.png)
只发送一次转换信号,然后这个通道就不断转换
3)单次转换,扫描模式
![](https://img-blog.csdnimg.cn/2285afd863ab4a2a85712da3de75813d.png)
一次转换多个通道值,每次转换完后,下一次转换还要再次触发。注意,要指定通道数目。
4)连续转换,扫描模式
![](https://img-blog.csdnimg.cn/d3ffd08373344b7ca196ee08a8164229.png)
和单次不同的是,它会不段扫描通道的值,不需要重新触发开始转换。
数据对齐
ADC的数据只有12位,但是通道的数据寄存器却有12位,可以采用
右对齐方式:低位依次对齐,高位补零(常用),因为它读到的数据就是转换结果。
左对齐方式:高位对齐,低位补零。
ADC转换时间:
AD转换步骤:采样,保持,量化,编码
采样时间可配置。
STM32ADC总转换时间:T=采样时间+12.5个ADC周期
以14M的采样时钟为例:采样时间为1.5个ADC周期时:T=14个周期=1us
ADC校准
ADC内部自带校准,建议每次上电后执行一次校准。启动校准前,ADC必须处于关电状态超过至少2个ADC时钟周期。
STM32单通道程序
ADC单通道初始话程序如下
#include "stm32f10x.h" // Device header
void AD_Init(void)
{
//开时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//6分频=72/6=12Mhz
//GPIO
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_RegularChannelConfig(ADC1,ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);//输入通道:选ADC1,通道0,通道放入扫描列表的位置1,采样时间55.5个周期
//ADC
ADC_InitTypeDef ADC_InitStruct;
ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;
ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;
ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;
ADC_InitStruct.ADC_NbrOfChannel=1;
ADC_InitStruct.ADC_ScanConvMode=DISABLE;
ADC_Init(ADC1,&ADC_InitStruct);
ADC_Cmd(ADC1,ENABLE);
//ADC校准
ADC_ResetCalibration(ADC1);//复位校准
while(ADC_GetResetCalibrationStatus(ADC1)==SET);//等待复位校准完成
ADC_StartCalibration(ADC1);//开始校准
while(ADC_GetCalibrationStatus(ADC1)==SET);//等待校准完成
}
uint16_t AD_GetValue(void)
{
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==0);//转换完成
return ADC_GetConversionValue(ADC1);
}
主函数中用一个数来收取这个数据即可。
光敏传感器演示
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)