MC9S12XS128 AD转换详解

MC9S12XS128 AD转换详解
MC9S12XS128 AD转换详解

A/D转换模块详解

1、A/D转换原理

A/D转换的过程是模拟信号依次通过取样、保持和量化、编码几个过程后转换为数字格式。

a)取样与保持

一般取样与保持过程是同时完成的,取样-保持电路的原理图如图16所示,由输

入放大器A

1、输出放大器A

2

、保持电容C

H

和电子开关S组成,要求 A

V1

* A

V2

= 1。原

理是:当开关S闭合时,电路处于取样阶段,电容器充电,由于 A

V1 * A

V2

= 1,所以

输出等于输入;当开关S断开时,由于A

2输入阻抗较大而且开关理想,可认为C

H

没有

放电回路,输出电压保持不变。

图16 取样-保持电路

取样-保持以均匀间隔对模拟信号进行抽样,并且在每个抽样运算后在足够的时间内保持抽样值恒定,以保证输出值可以被A/D 转换器精确转换。

b)量化与编码

量化的方法,一般有舍尾取整法和四舍五入法,过程是先取顶量化单位Δ,量化单位取值越小,量化误差的绝对值就越小,具体过程在这里就不做介绍了。将量化后的结果用二进制码表示叫做编码。

2、A/D转换器的技术指标

a)分辨率

分辨率说明A/D转换器对输入信号的分辨能力,理论上,n位A/D转换器能区分的输入电压的最小值为满量程的1/2n 。也就是说,在参考电压一定时,输出位数越多,量化单位就越小,分辨率就越高。S12的ATD模块中,若输出设置为8位的话,那么转换器能区分的输入信号最小电压为19.53mV。

b)转换时间

A/D转换器按其工作原理可以分为并联比较型(转换速度快ns级)、逐次逼近型(转换速度适中us级)、双积分型(速度慢抗干扰能力强)。

不同类型的转化的A/D转换器转换时间不尽相同,S12的ATD模块中,8位数字

量转换时间仅有6us,10位数字量转换时间仅有7us。

S12内置了2组10位/8位的A/D模块:ATD0和ATD1,共有16个模拟量输入通道,属于逐次逼近型A/D转换器(这个转换过程与用天平称物的原理相似)。

1、功能结构图

图17 A/D 模块功能结构图

图17所示的是A/D 模块的功能结构,这个功能模块被虚线划分成为图示所示的虚线所隔离的三个部分:IP总线接口、转换模式控制/寄存器列表,自定义模拟量。

IP 总线接口负责该模块与总线的连接,实现A/D 模块和通用I/O 的目的,还起

到分频的作用;

转换模式控制寄存器列表中有控制该模块的所有的寄存器,执行左右对齐运行和连

续扫描。

自定义模拟量负责实现模拟量到数字量的转换。包括了执行一次简单转换所需的模

拟量和数字量。

2、HCS12中A/D转化模块特点

8/10 位精度;7 us, 10-位单次转换时间.;采样缓冲放大器;可编程采样时间;左/

右对齐, 有符号/无符号结果数据;外部触发控制;转换完成中断;模拟输入8 通道复用;模拟/数字输入引脚复用;1到8转换序列长度;连续转换模式;多通道扫描方式。

ATD 模块有模拟量前端、模拟量转换、控制部分及结果存储等四部分组成。其中模拟前端包括多路转换开关、采样缓冲器、放大器等,结果存储部分主要有8个16 位的存储器和反映工作状态的若干标志位。

A/D转换应用实例

要让ATD 开始转换工作,必须经过以下三个步骤:

1.将ADPU 置1,使ATD 启动;

2.按照要求对转换位数、扫描方式、采样时间、时钟频率及标志检查等方式进行设置;

3.发出启动命令;

如果上电默认状态即能满足工作要求,那么只要将ADPU 置1,然后通过控制寄存器发出转换命令,即可实现转换。

程序描述:由通道ATD0进行单通道A/D转换,转换值在B口显示。

程序如下:

程序一:

#include /* common defines and macros */

#include "derivative.h" /* derivative-specific definitions */

byte ad_value; //AD转换结果

void Delay(int i) { //延时程序

int j;

for(;i>0;i--)

for(j=500;j>0;j--)

;

}

/***---------------初始化程序---------------***/

void InitBusClk(void) {

CLKSEL=0X80; //PLLSEL 1 : Bus Clock=PLLCLK/2

// 0 : Bus Clock=OSCCLK/2

PLLCTL_PLLON=1; //开启PLL

SYNR=0;

REFDV=0X03; //OSCCLK=16MHz

//PLLCLK=2*OSCCLK*[(1+SYNR)/(1+REFDV]=32/4=8MHz

while(!(CRGFLG_LOCK==1)); //直到LOCK=1,when PLL is ready,退出循环

CLKSEL_PLLSEL=1;

//PLLSEL 1 : Bus Clock=PLLCLK/2=8MHz/2=4MHz

// 0 : Bus Clock=OSCCLK/2=16M/2=8MHz

}

void InitAD(void){

ATD0CTL2 = 0XC0; // 1100 0000 启动A/D,快速清除标志位

// 无等待模式,外部触发禁止(bit2=0),

中断禁止(bit1=0)

ATD0CTL3 = 0X0C;

// 0 0001 1 00 转换序列为1 、FIFO模式启动,冻结模式下继续转换

ATD0CTL4 = 0XE1; // 1 11 00001 8位精度,16AD采样时间

// 总线(1+1)*2 = 4 分频,AD时钟= 1MHz ATD0CTL5 = 0X27;

// 0 0 1 0 0 111 右对齐,无符号,连续转换,单通道, 起始通道ATD7

// DJM DSGN SCAN MULT 0 CC CB CA

// DJM :1-Right justified 0-Left justified

// DSGN:1-Signed data 0-Unsigned data

// SCAN:1-Continuous 0-Single conversion

// CC CB CA : Analog Input Channel Select Code

ATD0DIEN = 0X00; // 数字输入disabled

}

/***---------------主程序---------------***/

void main(void) {

/* put your own code here */

_DISABLE_COP(); // 关看门狗

InitBusClk();

InitAD();

DDRB=0XFF; // 设PORTB为输出口

PORTB=0x00;

EnableInterrupts; // 开放总中断

for(;;) {

while(!ATD0STAT2L_CCF7); //等待转换结束,退出循环

ad_value=(byte)ATD0DR7H;

//左对齐,右对齐时转换结果都先存储在ATD0DRxH,后存储在ATD0DRxL.

Delay(200); //延时

PORTB=ad_value;

//PORTB输出AD转换结果,并用8个LED发光二极管显示

//_FEED_COP(); /* feeds the dog */

} /* loop forever */

/* please make sure that you never leave main */

}

程序二:(用指针实现AD转换)

#include /* common defines and macros */

#include "derivative.h" /* derivative-specific definitions */

byte AD_Value; //AD转换结果

void Delay(int i) { //延时程序

int j;

for(;i>0;i--)

for(j=500;j>0;j--)

;

}

/***---------------初始化程序---------------***/

(初始化程序与上述相同)

/***---------------读取AD转换结果---------------***/

void AD_GetValue(word *AD_Value){

*AD_Value=ATD0DR0;

}

void main(void) {

/* put your own code here */

_DISABLE_COP(); //关看门狗

InitBusClk();

InitAD();

DDRB=0XFF; //设PORTB为输出口

PORTB=0x00;

EnableInterrupts;

for(;;) {

while(!ATD0STAT2L_CCF7); //等待转换结束,退出循环

AD_GetValue(&AD_Value); //读取转换结果

Delay(400);

PORTB=AD_Value; //转换结果在B口显示

_FEED_COP(); /* feeds the dog */

} /* loop forever */

/* please make sure that you never leave main */

}

程序三:(用中断实现AD转换)

#include /* common defines and macros */

#include "derivative.h" /* derivative-specific definitions */

#include

byte AD_Data=0;

//*

void Delay(int i) {

int j;

for(;i>0;i--)

for(j=500;j>0;j--)

;

}

//*/

/***---------------初始化程序---------------***/

void InitBusClk(void) {

CLKSEL=0X80; //PLLSEL 1 : Bus Clock=PLLCLK/2

// 0 : Bus Clock=OSCCLK/2

PLLCTL_PLLON=1; //开启PLL

SYNR=0;

REFDV=0X03; //OSCCLK=16MHz

//PLLCLK=2*OSCCLK*[(1+SYNR)/(1+REFDV]=32/4=8MHz while(!(CRGFLG_LOCK==1)); //直到LOCK=1,when PLL is ready,退出循环

CLKSEL_PLLSEL=1; //PLLSEL 1 : Bus Clock=PLLCLK/2=8MHz/2=4MHz

// 0 : Bus Clock=OSCCLK/2=16M/2=8MHz }

void InitAD(void){

A TD0CTL2 = 0XC3;

// 110 000 11 启动A/D,快速清除标志位,无等待模式,外部触发禁止(bit2=0) // 中断开放(bit1=1,bit0=1)

// bit1 :A TD Sequence Complete Interrupt Enable

// bit0 :A TD Sequence Complete Interrupt Flag

A TD0CTL3 = 0X0C;

// 0 0001 1 00 转换序列为1 、FIFO模式启动,冻结模式下继续转换

A TD0CTL4 = 0XE1; // 1 11 00001 8位精度,16AD采样时间

// 总线(1+1)*2 = 4 分频,AD时钟= 1M

A TD0CTL5 = 0XA7;

// 1010 0111 右对齐,无符号,连续转换,单通道, 起始通道A TD7

A TD0DIEN = 0X00; // 数字输入disabled

}

/***---------------主程序---------------***/

void main(void) {

/* put your own code here */

DisableInterrupts; //关中断

InitBusClk();

InitAD();

DDRB=0XFF; //设B口为输出口

PORTB=0X00;

EnableInterrupts; //开中断

for(;;){

//while(!A TD0STA T2L_CCF7);

PORTB=(byte)AD_Data; //B口显示转换结构

}

}

/***---------------中断服务程序---------------***/

#pragma CODE_SEG NON_BANKED

void interrupt 22 IntAD(void){ // AD转换的中断向量号为33

DisableInterrupts; //关中断

//while(!A TD0STA T2L_CCF7);

AD_Data=A TD0DR0H; //读取AD转换结果

EnableInterrupts; //开中断

}

#pragma CODE_SEG DEFAULT

相关主题
相关文档
最新文档