以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。
参考博客
s5pv210 AD转换 - biaohc - 博客园
一、ADC的相关概念
1、量程(模拟量的输入范围)
ADC只能输入电压信号,其他种类的模拟信号要经过传感器的转换,变成模拟的电压信号。
ADC输入的模拟电压有一个范围,这个范围是ADC芯片本身的一个参数,一般是0~3.3V或0~5V或者是0~12V等等,实际工作时给AD的电压信号不能超过这个电压范围。
2、转换精度(分辨率resolution)
ADC输出的数字值是有一定的位数的。比如说10位,意思就是输出的数字值是用10个二进制位来表示的,这种就叫10位ADC。这个位数就表示转换精度。10位ADC,相当于把整个范围分成1024个格子,每个格子之间的间隔就是电压的表示精度。假如ADC芯片的量程是0~3.3V,则每个格子代表的电压值是3.3V/1024=0.0032265V。如果此时ADC转换后得到的数字量是447,则这个数字量代表的模拟值是:447×0.0032265V=1.44V。
ADC的位数越多,则每个格子表示的电压值越小,将来算出来的模拟电压值就越精确。
ADC的模拟量程一样的情况下,ADC精度位数越多则精度越高,测出来的值则越准。但是如果ADC的量程不一样,比如2个ADC,A的量程是0~50V,B的量程是0~0.5V,A是12位的,B是10位的,可能B的精度比A的还要高。
比如A的精度:50/1024=0.04883,B的精度:0.5/4096=0.000122
3、转换速率
ADC芯片进行AD转换需要耗费时间。不同的芯片所需的时间是不一样的;同一颗芯片当配置不一样时,所需的转换时间也不一样,比如说精度配置为10位,其转换耗费的时间就比精度配置为12位时要小。
AD工作需要一个时钟(这个时钟有一个范围,配置时不要超出这个范围),这个时钟频率控制着AD的转换速率。注意,时钟频率和AD的转换速率不是一回事,它们只是成正比而不是完全相等。比如S5PV210中的ADC转换器,AD的转换速率 = 时钟频率 / 5。
一般数据手册中描述转换速率所用的单位是MSPS。第一个M是兆,S是采样,PS就是每秒,MSPS的意思就是兆样本每秒,即每秒种转出来多少兆数字值。
4、通道数
ADC芯片有多少路模拟信号输入通道,代表着将来可以同时进行多少路模拟信号的输入。
二、S5PV210的ADC控制器
1、ADC控制器的框图
ADC的内容在数据手册的Section10.7。
因为电阻式触摸屏工作时依赖于AD转换,所以在S5PV210中,电阻触摸屏的接口和ADC接口合二为一,或者说电阻触摸屏接口复用了ADC的接口。
2、ADC的工作时钟框图
ADCCLK是ADC控制器工作的时钟,由PCLK_PSYS经过一次分频后得到的。
PCLK_PSYS时钟总线频率为66MHz,一般设置分频器为65,所以ADC的时钟是1MHz,根据公式,此时的转换速率为1/200KHz。
ADC时钟频率最大可设置为5MHz,对应的最大转换速率为1MSPS。
3、S5PV210的10个ADC通道
SoC的引脚至少分2种,数字引脚和模拟引脚。以前接触的GPIO属于数字引脚,而ADC通道引脚属于模拟引脚。数字引脚和模拟引脚一般不能混用。
S5PV210一共支持10个ADC通道,分别叫AIN[0]~AIN[9],分别对应XadcAIN[0]~XadcAIN[9]引脚。理论上可以同时做10路AD转换。
4、S5PV210的ADC特性
可选的转换精度为10bit,或者12bit。
最大的转换速率1MSPS;
输入的模拟电压范围0-3.3V;
可设置普通AD模式,即TOUCH SCREEN触摸屏模式切换为普通AD模式。
5、ADC控制器的主要寄存器
(1)获取ADC数据的两种方法
轮询检查标志位
启动转换后循环检查标志位,直到标志位为1,表明转换完毕可以去读取数据。这种方式是同步的。
中断
设置好中断,写好中断isr来读取AD转换数据。AD转换完毕后,生成中断信号给CPU,CPU进入中断处理流程。这种方式是异步的。
(2)自动开启下一次AD转换(start by read机制)
转换完毕后要立即开启下一次转换,因此需要设计一种机制,能够自动开启下一次转换。这个机制叫start by read,当我们读取本次AD转换的AD值后,硬件自动开启下一次AD转换。
(3)主要寄存器(这里探讨n=0,即通道0的寄存器)
TSADCCONn寄存器:ADC控制寄存器
- bit16设置AD转换精度,10bit、12bit可选;
- bit15只读,状态寄存器,查看是否转换结束;
- bit14预分频器开关,设置为1;
- bit13:6分频倍率,如要设置3.3MHz,可设置为19,66/(19+1)=3.3,最大设置频率为5MHz,所以此位最小值为13;
- bit2设置为普通模式即可;
- bit1是否开启read star模式,read star模式意思是只要读取AD转换后的寄存器数据,就重新开始AD转换,使用这种模式第一次读数据要丢掉;
- bit0开启AD转换,开始后自动设置为0。另外如果设置了read star模式,此位无效。
TSCONn寄存器:touch screen控制寄存器
TSDATXn寄存器,TSDATYn寄存器:数据寄存器
- bit14查看输出数据位ADC 还是TOUCH SCREEN;
- bit11:0为转换后的数据;
CLRINTADCn寄存器:清中断,写入任意的数值就可以
ADCMUX寄存器:选择当前正在操作的AD通道
三、代码实战
1、编写代码步骤
(1)AD控制器初始化,即 adc_init函数。
(2)循环进行AD采样,即wihle(1)。注意这次实验是关闭start by read模式的。
2、关键的代码如下,完整案例代码见链接。
#include "main.h"#define TSADCCON0 0xE1700000 #define TSDATX0 0xE170000C #define TSDATY0 0xE1700010 //#define CLRINTADC0 0xE1700000 #define ADCMUX 0xE170001C#define rTSADCCON0 (*(volatile unsigned int *)TSADCCON0) #define rTSDATX0 (*(volatile unsigned int *)TSDATX0) #define rTSDATY0 (*(volatile unsigned int *)TSDATY0) //#define rCLRINTADC0 (*(volatile unsigned int *)CLRINTADC0) #define rADCMUX (*(volatile unsigned int *)ADCMUX)// 初始化ADC控制器的函数 static void adc_init(void) {rTSADCCON0 |= (1<<16); // resolution set to 12bitrTSADCCON0 |= (1<<14); // enable clock prescalerrTSADCCON0 &= ~(0xFF<<6);rTSADCCON0 |= (65<<6); // convertor clock = 66/66M=1MHz, MSPS=200KHzrTSADCCON0 &= ~(1<<2); // normal operation moderTSADCCON0 &= ~(1<<1); // disable start by read moderADCMUX &= ~(0x0F<<0); // MUX选择ADCIN0 }// 注意:第一,延时要确实能延时;第二,延时时间必须合适。 static void delay(void) {volatile unsigned int i, j;for (i=0; i<4000; i++)for (j=0; j<1000; j++); }// 测试ADC,完成的功能就是循环检测ADC并得到ADC转换数字值打印出来 void adc_test(void) {unsigned int val = 0;adc_init();while (1){// 第一步:手工开启ADC转换rTSADCCON0 |= (1<<0);// 第二步:等待ADC转换完毕while (!(rTSADCCON0 & (1<<15)));// 第三步:读取ADC的数字值// 第四步:处理/显示数字值val = rTSDATX0;printf("x: bit14 = %d.\n", (val & (1<<14)));printf("x: adc value = %d.\n", (val & (0xFFF<<0)));val = rTSDATY0;printf("y: bit14 = %d.\n", (val & (1<<14)));printf("y: adc value = %d.\n", (val & (0xFFF<<0)));// 第五步:延时一段delay();}}
3、测试结果
-------------adc test-------------- x: bit14 = 0.//第一组 x: adc value = 1598. y: bit14 = 0. y: adc value = 0.x: bit14 = 0.//第二组 x: adc value = 1583. y: bit14 = 0. y: adc value = 0.x: bit14 = 0.//第三组 x: adc value = 1599. y: bit14 = 0. y: adc value = 0. ……