一、ADC简介
1.1 ADC
ADC(Analog to Digital Converter)即模数转换器,指一个能将模拟信号转化为数字信号的电子元件
1.2 ADC主要参数
分辨率
ADC的分辨率一般以输出二进制数的位数来表示,当最大输入电压一定时,位数越高,分辨率越高; n位的ADC能区分输入电压的最小值为满量程输入的1/2^n; 比如一个12位的ADC,最大输入电压为1.8v,那么该ADC能区分的最小电压为1.8v/2^12≈0.00044v,当转换的结果为m时,则 实际的电压值为m*(1.8v/2^12);
二、 Exynos4412下的ADC控制器
这4个引脚是ADC专用引脚。(本次实验实验XadcAIN3)
可选10位精度或者12位精度,有四个通道,最大转换速度1M s是采样 ps是秒,采样频率是1M/s。
他有一个前提ADC时钟是5MHz。每五个时钟采样一次。支持采样保持功能和低功耗模式
模拟输入范围是0-1.8V
PCLK是时钟源,是100M的,这里拿66M举例,当分频是65时,分频后的时钟频率就是1MHz
因为他五个周期采样一次,1MHz在除以5是ADC的转换频率,所以转换速度就是200kHz,频率的倒数就是转换周期,也就是5us。
但是注意,时钟频率不能超过5M,因为他的极限转换速度是1M。
三、ADC寄存器
控制寄存器、延迟寄存器、数据寄存器、中断功能寄存器、选择通道寄存器
RES: 设置精度是10位或12位
ECFLG:这个写的有问题,它是只读的位,如果转换完成则会自动置1,否则是0.
PRSCEN: 写1打开分频器,写0关闭分频器
PRSCVL:设置寄存器的分频倍数。如果你往这个区域写了个N,实际的分频倍数则是N+1。ADC的最大转换速度是1MHz,所以时钟频率不能超过5MHz,所以N一定要设置在19-255之间。
STANDBY: 1待机模式(低功耗模式),0正常模式
READ_START: ADC转化的数据会放入一个寄存器,读走数据就会自动进行下次转化,不读就停止转化。写1开启此模式,写0关闭
ENABLE_START:写1开始转换,然后自动变成0。如果开启READ_START模式,则此模式自动失效。
ADCADT寄存器:用于存储转化结果,只用[11:0]位,读的时候要将高20位清零,不然随机结果可能会影响结果。
ADCMUX寄存器:用于选择转换的通道。由于ADC只有一个,而我们有四个引脚支持ADC功能,所以采取分时复用模式,同一时间只有一个通道可以转化。(本次实验实验AIN3)
步骤:对ADCCON寄存器进行设置,然后选择转换的通道,然后设置ADCCON的[0]位开始转换,ADCCON的[15]位变成1,然后区ADCDAT寄存器读取转换结果。
四、ADC编程
#include "exynos_4412.h"
int main()
{
unsigned int AdcValue;
/*将ADC的精度设置为12bit*/
ADCCON = ADCCON | (1 << 16);
/*使能ADC的分频器*/
ADCCON = ADCCON | (1 << 14);
/*设置ADC的分频 ADC时钟频率=PLCK/(19+1)=5MHz,ADC的转换频率=5MHz/5=1MHz*/
ADCCON = ADCCON & (~(0xFF << 6)) | (19 << 6);
/*关闭待机模式,使能正常模式*/
ADCCON = ADCCON & (~(1 << 2));
/*关闭通过读使能AD转换*/
ADCCON = ADCCON & (~(1 << 1));
/*选择转换通道 3通道*/
ADCMUX = 3;
while(1)
{
/*开始转换*/
ADCCON = ADCCON | 1;
/*等待转换完成*/
while(!(ADCCON & (1 << 15)));
/*读取转换结果*/
AdcValue = ADCDAT & 0xFFF;
/*将结果转换成实际的电压值 =AdcValue*(1800/4096) mv*/
AdcValue =AdcValue * 0.44;
/*打印转换结果*/
printf("AdcValue = %dmv\n", AdcValue);
}
return 0;
}
五、作业
1.编程实现通过LED状态显示当前电压范围
注:
电压在1501mv~1800mv时,LED2、LED3、LED4、LED5点亮
电压在1001mv~1500mv时,LED2、LED3、LED4点亮
电压在501mv~1000mv时,LED2、LED3点亮
电压在0mv~500mv时,LED2闪烁
#include "exynos_4412.h"
void Delay(unsigned int Time)
{
while(Time--);
}
int main()
{
unsigned int AdcValue;
/*将ADC的精度设置为12bit*/
ADCCON = ADCCON | (1 << 16);
/*使能ADC的分频器*/
ADCCON = ADCCON | (1 << 14);
/*设置ADC的分频 ADC时钟频率=PLCK/(19+1)=5MHz,ADC的转换频率=5MHz/5=1MHz*/
ADCCON = ADCCON & (~(0xFF << 6)) | (19 << 6);
/*关闭待机模式,使能正常模式*/
ADCCON = ADCCON & (~(1 << 2));
/*关闭通过读使能AD转换*/
ADCCON = ADCCON & (~(1 << 1));
/*选择转换通道 3通道*/
ADCMUX = 3;
/*LED2*/
GPX2.CON = GPX2.CON | (0x1 << 28);
/*LED3*/
GPX1.CON = GPX1.CON | 0x1;
/*LED4*/
GPF3.CON = GPF3.CON | (0x1 << 16);
/*LED5*/
GPF3.CON = GPF3.CON | (0x1 << 20);
while(1)
{
/*开始转换*/
ADCCON = ADCCON | 1;
/*等待转换完成*/
while(!(ADCCON & (1 << 15)));
/*读取转换结果*/
AdcValue = ADCDAT & 0xFFF;
/*将结果转换成实际的电压值 =AdcValue*(1800/4096) mv*/
AdcValue =AdcValue * 0.44;
/*打印转换结果*/
printf("AdcValue = %dmv\n", AdcValue);
if(AdcValue > 1501)
{
GPX2.DAT = GPX2.DAT | (1 << 7);
GPX1.DAT = GPX1.DAT | 1;
GPF3.DAT = GPF3.DAT | (1 << 4);
GPF3.DAT = GPF3.DAT | (1 << 5);
}
else if(AdcValue > 1001)
{
GPX2.DAT = GPX2.DAT | (1 << 7);
GPX1.DAT = GPX1.DAT | 1;
GPF3.DAT = GPF3.DAT | (1 << 4);
}
else if(AdcValue > 501)
{
GPX2.DAT = GPX2.DAT | (1 << 7);
GPX1.DAT = GPX1.DAT | 1;
}
else
{
GPX2.DAT = GPX2.DAT | (1 << 7);
Delay(1000000);
GPX2.DAT = GPX2.DAT & (~(1 << 7));
}
}
return 0;
}