打印
[其他ST产品]

ARM裸机-ADC

[复制链接]
181|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
l63t89|  楼主 | 2023-5-29 23:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
AD, ADC, ARM, dc
一、ADC基础知识
1.ADC是什么?

(1) ADC 即 analog digital converter,AD转换,模数转换(也就是模拟转数字)

(2) CPU本身是数字的,而外部世界变量(如电压、温度、高度、压力·…)都是模拟的,所以需要用CPU来处理这些外部的模拟变量的时候就需要做AD转换。
2.为什么需要ADC?

为了用数字技术来处理外部的模拟物理量。
3.模拟量和数字量

(1)模拟的就是连续的,现实生活当中的时间、电压、高度等都是模拟的(连续分布的,划分的话可以无限的更小划分)。模拟量反映在数学里面就是无限小数位(从0到1之间有无数个数)

(2)数字的就是离散的,离线的就是不连续的。这种离散处理实际上是从数学上对现实中的模拟 量的一种有限精度的描述。数字化就是离散化,就是把连续分布的模拟量按照一定精度进行取点 (采样)变成有限多个不连续分布的数字值,就叫数字量。

(4)计算机处理参量的时候都是数字化的,计算机需要数字化的值来参与运算。如果系统输入参 数中有模拟量,就需要外加AD转换器将模拟量转成数字量再给计算机。

(3)数字化的意义就在于可以用(离散)数学来简化描述模拟量,这东西是计算机技术的基础。
4.AD和DA

(1)AD是analog to digital, DA自然就是digital to analog,数字转模拟

(2)纯粹用cpu是不可能实现数字转模拟,因为cpu本身就是数字的。使用一些(具有一些积分或微分效果的)物理器件就可实现数字转模拟。

(3)数字转模拟的作用。譬如可以用来做波形发生器,波形跟踪器等

使用特权

评论回复
沙发
l63t89|  楼主 | 2023-5-29 23:38 | 只看该作者
二、ADC的主要相关概念
量程(模拟量输入范围)

1.AD转换器的本质是一个电子器件,所以他只能输入电压信号,其他种类的模拟信号要先经过传感器(Sensor)的转换变成模拟的电压信号然后才能给AD。

    AD输入端的模拟电压要求有一个范围,一般是0-0.3V或0-5V或者0-12V等。模拟电压的范围本身是AD芯片的一个参数。实际工作时给AD的电压信号不能超过这个电压范围。

使用特权

评论回复
板凳
l63t89|  楼主 | 2023-5-29 23:38 | 只看该作者
精度

1.AD转换输出的数字值是有一定的位数的(比如说10位,意思就是输出的数字值是用10个二进制位来表示的,这种就叫10位AD),这个位数就表示了转换精度。

2.10位AD就相当于把整个范围分成了1024个格子,每个格子之间的间隔就是电压的表示精度,假如AD芯片的量程是0-3.3V,则每个格子代笔的电压值是 3.3V/1024=0.0032265V

3.AD的位数越多,则每个格子表示的电压值越小,将来算出来的模拟电压值就越精确。

4.AD的模拟量程一样的情况下,AD精度位数越多精度越高,测出来的值越准。但是如果AD的量 程不一样。如2个AD,A的量程是050V,B的量程是00.5V,A是12位的,B是10位的,可能B 的精度比A的还要高。(A的精度:50/1024=0.04883, B的精度:0.5/4096=0.000122)

使用特权

评论回复
地板
l63t89|  楼主 | 2023-5-29 23:39 | 只看该作者
转化速率(MSPS与conventor clock的不同)

1.首先要明白:AD芯片进行AD转换是要耗费时间的。这个时间需要多久,不同的芯片是不一样 的,同一颗芯片在配置不一样时转换时间也不一样(警如说精度配置为10位时时间比精度配置为12位时要小,10位要比12位的更快一些,有些AD可以配转换时钟,时钟频率高则转换时间短)。

    详细的需要时间可以参考数据手册。一般数据手册中描述转换速率用的单位是MSPS(第一个M 是兆,S是sample,就是采样;PS就是per,second,总的意思就是兆样本每秒,每秒种转出来多少M个数字值)

3.AD工作都需要一个时钟,这个时钟有一个范围,我们实际给他配置时不要超出这个范围就可以了。AD转换是在这个时钟下进行的,时钟的频率控制着AD转换的速率。
注意:时钟频率和MSPS 不是一回事,只是成正比不是完全相等。譬如S5PV210中的AD转换器,MSPS=时钟频率/5(也就是5个时钟频率才能转出一个样本)

使用特权

评论回复
5
l63t89|  楼主 | 2023-5-29 23:39 | 只看该作者
通道数

AD芯片有多少路analog input通道,代表了将来可以同时进行多少路模拟信号的输入。

使用特权

评论回复
6
l63t89|  楼主 | 2023-5-29 23:39 | 只看该作者
三、S5PV210的ADC控制器
ADC和(电阻式)触摸屏的关系

(1)ADC在210的数据手册的Section10.7
(2)电阻式触摸屏本身工作时依赖于AD转换,所以在210的SoC中电阻触摸屏接口本身和ADC接口是合二为一的。或者说电阻触摸屏接口使用了(复用了)ADC的接口。

使用特权

评论回复
7
l63t89|  楼主 | 2023-5-29 23:40 | 只看该作者
ADC的工作时钟框图

ADCCLK是ADC控制器工作的时钟,也就是前面提到的conventor clock。从时钟框图可以看出,它是PCLK(当然是PCLK_PSYS)经过了一次分频后得到的。所以将来初始化ADC控制器时一定有一个步骤是初始化这里的分频器。

使用特权

评论回复
8
l63t89|  楼主 | 2023-5-29 23:40 | 只看该作者
210的10个ADC通道(注意ADC引脚和GPIO的区别)


(1)210一共支持10个ADC通道,分别叫AIN[0]~AIN[9]。理论上可以同时做10路AD转换。
(2)SoC的引脚至少分2种:digit数字引脚和analog模拟引脚。我们以前接触的GPIO都属于数字引脚,ADC channel通道引脚属于模拟引脚。注意:数字引脚和模拟引脚一般是不能混用的,如果混用则就会丧失它原本的功能。

使用特权

评论回复
9
l63t89|  楼主 | 2023-5-29 23:41 | 只看该作者


(3)TS开头的引脚都是用在触摸屏上的,XadcAIN_0和XadcAIN_1只能用作ADC不能用作触摸屏

使用特权

评论回复
10
l63t89|  楼主 | 2023-5-29 23:41 | 只看该作者
ADC控制器的主要寄存器

TSADCCON0 用来做控制的

TSDATX0 TSDATY0 转出来的AD值主要存在TSDATX0 这里,我们读也是读这里,

CLRINTADC0 清中断

ADCMUX 选择当前正在操作的AD通道



(1)等待触摸屏转换完毕的方法有2种:一种是检查标志位,第二种是中断。第一种方式下我们先开启一次转换然后循环不停检查标志位直到标志位为1表明已经转换完可以去读了;第二种方式下就是设置好中断,写好中断isr来读取AD转换数据。然后开启中断后CPU就不用管了,等AD转换完成后会生成一个中断信号给CPU,就会进入中断处理流程。第一种方法是同步的,第二种方式是异步的。
(2)AD转换都是需要反复进行的,那么转完一次一般要立即开启下一次转换,所以需要有一种机制能够在一次转完时自动开启下一次。这个机制就叫start by read,这个机制的工作方法是:当我们读取本次AD转换的AD值后,硬件自动开启下一次AD转换。

使用特权

评论回复
11
l63t89|  楼主 | 2023-5-29 23:42 | 只看该作者
四、AD转换的编程实践
AD控制器初始化
static void adc_init(void)                  //初始化ADC控制器的函数
{
        rTSADCCON0 |=(1<<16);                         //bit16写1
        rTSADCCON0 |=(1<<14);                         //bit14写1,使能
        rTSADCCON0 &=~(0xff<<6);                 //全部清0
        rTSADCCON0 |=(65<<6);                         //66分频,convertor clock(转换器时钟) =66/66m=1MHZ,MSPS(毫秒)=200KHZ
        rTSADCCON0 &=~(1<<2);                        // normal operation mode
        rTSADCCON0 &=~(1<<1);                        //bit1写1
        rADCMUX    &=~(0x0f<<0);                         //MUX选择ADCIN0

}

使用特权

评论回复
12
l63t89|  楼主 | 2023-5-29 23:42 | 只看该作者
循环进行AD采样
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("bit14 =%d.\n",(val & (1<<14)));
        printf("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();
       
        }
       
       
}

使用特权

评论回复
13
l63t89|  楼主 | 2023-5-29 23:42 | 只看该作者
编译运行调试

使用特权

评论回复
14
l63t89|  楼主 | 2023-5-29 23:43 | 只看该作者
完整代码
#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)



static void adc_init(void)                  //初始化ADC控制器的函数
{
        rTSADCCON0 |=(1<<16);                         //bit16写1
        rTSADCCON0 |=(1<<14);                         //bit14写1,使能
        rTSADCCON0 &=~(0xff<<6);                 //全部清0
        rTSADCCON0 |=(65<<6);                         //66分频,convertor clock(转换器时钟) =66/66m=1MHZ,MSPS(毫秒)=200KHZ
        rTSADCCON0 &=~(1<<2);                        // normal operation mode
        rTSADCCON0 &=~(1<<1);                        //bit1写1
        rADCMUX    &=~(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("bit14 =%d.\n",(val & (1<<14)));
        printf("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();
       
        }
       
       
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

78

主题

684

帖子

0

粉丝