文档库 最新最全的文档下载
当前位置:文档库 › AD转换部分

AD转换部分

第9章.STC12C5A60S2系列单片机的A/D转换器9.1 A/D转换器的结构

STC12C5A60AD/S2系列带A/D转换的单片机的A/D转换口在P1口( (P1.7-P1.0),有8路10位高速A/D转换器,速度可达到250KHz(25万次/秒)。8路电压输入型A/D,可做温度检测、电池电压检测、按键扫描、频谱检测等。上电复位后P1口为弱上拉型I/O口,用户可以通过软件设置将8路中的任何一路设置为A/D转换,不需作为A/D使用的口可继续作为I/O口使用。

STC12C5A60S2系列单片机ADC(A/D转换器)的结构如下图所示:

当AUXR.1/ADRJ = 0时,A/D转换结果寄存器格式如下:

当AUXR.1/ADRJ = 1时,A/D转换结果寄存器格式如下:

STC12C5A60S2系列单片机ADC由多路选择开关、比较器、逐次比较寄存器、10位DAC、转换结果寄存器(ADC_RES和ADC_RESL)以及ADC_CONTR构成。

STC12C5A60S2系列单片机的ADC是逐次比较型ADC。逐次比较型ADC由一个比较器和D/A转换器构成,通过逐次比较逻辑,从最高位(MSB)开始,顺序地对每一输入电压与内置D/A转换器输出进行比较,经过多比较,使转换所得的数字量逐次逼近输入模拟量对应值。逐次比较型A/D转换器具有速度高,功耗低等优点。

从上图可以看出,通过模拟多路开关,将通过ADC0~7的模拟量输入送给比较器。用

数/模转换器(DAC)转换的模拟量与本次输入的模拟量通过比较器进行比较,将比较结果保存到逐次比较器,并通过逐次比较寄存器输出转换结果。A/D转换结束后,最终的转换结果保存到ADC转换结果寄存器ADC_RES和ADC_RESL,同时,置位ADC控制寄存器ADC_CONTR中的A/D转换结束标志位ADC_FLAG,以供程序查询或发出中断申请。模拟通道的选择控制由ADC控制寄存器ADC_CONTR中的CHS2 ~ CHS0确定。ADC的转换速度由ADC控制寄存器中的SPEED1和SPEED0确定。在使用ADC之前,应先给ADC上电,也就是置位ADC控制寄存器中的ADC_POWER位。

当ADRJ=0时,如果取10位结果,则按下面公式计算:

当ADRJ=0时,如果取8位结果,按下面公式计算:

当ADRJ=1时,如果取10位结果,则按下面公式计算:

式中,Vin为模拟输入通道输入电压,Vcc为单片机实际工作电压,用单片机工作电压作为模拟参考电压。

9.2 与A/D转换相关的寄存器

与STC12C5A60S2系列单片机A/D转换相关的寄存器列于下表所示。

1.P1口模拟功能控制寄存器P1ASF

STC12C5A60S2系列单片机的A/D转换通道与P1口(P1.7-P1.0)复用,上电复位后P1口为弱上拉型I/O口,用户可以通过软件设置将8路中的任何一路设置为A/D转换,不需作为A/D使用的P1口可继续作为I/O口使用(建议只作为输入)。需作为A/D使用的口需先

将P1ASF特殊功能寄存器中的相应位置为‘1’,将相应的口设置为模拟功能。P1ASF寄存器的格式如下:

P1ASF : P1口模拟功能控制寄存器(该寄存器是只写寄存器,读无效)

当P1口中的相应位作为A/D使用时,要将P1ASF中的相应位置1。

2.ADC控制寄存器ADC_CONTR

ADC_CONTR寄存器的格式如下:

ADC_CONTR : ADC控制寄存器

对ADC_CONTR寄存器进行操作,建议直接用MOV赋值语句,不要用‘与’和‘或’语句。

ADC_POWER:ADC电源控制位。

0:关闭A/D转换器电源;

1:打开A/D转换器电源。

建议进入空闲模式前,将ADC电源关闭,即ADC_POWER =0。启动A/D转换前一定要确认A/D电源已打开,A/D转换结束后关闭A/D电源可降低功耗,也可不关闭。初次打开内部A/D转换模拟电源,需适当延时,等内部模拟电源稳定后,再启动A/D转换。建议启动A/D转换后,在A/D转换结束之前,不改变任何I/O口的状态,有利于高精度A/D转换,若能将定时器/串行口/中断系统关闭更好。

SPEED1,SPEED0:模数转换器转换速度控制位

STC12C5A60S2系列单片机的A/D转换模块说使用的时钟是内部R/C振荡器所产生的

系统时钟,不使用时钟分频寄存器CLK_DIV对系统时钟分频后所产生的供给CPU工作所使用的时钟。

好处:

这样可以让ADC用较高的频率工作,提高A/D的转换速度。

这样可以让CPU用较低的频率工作,降低系统的功耗。

ADC_FLAG:模数转换器转换结束标志位,当A/D转换完成后,ADC_FLAG=1,要由软件清0。不管是A/D转换完成后由该位申请产生中断,还是由软件查询该标志位A/D转换是否结束,当A/D转换完成后,ADC_FLAG = 1,一定要软件清0。

ADC_START:模数转换器(ADC)转换启动控制位,设置为“1”时,开始转换,转换结束后为0。

CHS2/CHS1/CHS0:模拟输入通道选择,CHS2/CHS1/CHS0

程序中需要注意的事项:

由于是2套时钟,所以,设置ADC_CONTR控制寄存器后,要个4个空操作延时才可以正确读到ADC_CONTR寄存器的值,原因是设置ADC_CONTR控制寄存器的语句执行后,要经过4个CPU时钟的延时,其值才能够保证被设置进ADC_CONTR控制寄存器。

MOV ADC_CONTR, #DA TA

NOP

NOP

NOP

NOP

MOV A, ADC_CONTR

;经过4个时钟延时后,才能够正确读到ADC_CONTR控制寄存器的值3.A/D转换结果寄存器ADC_RES、ADC_RESL

特殊功能寄存器ADC_RES和ADC_RESL寄存器用于保存A/D转换结果,其格式如下:

AUXR1寄存器的ADRJ位是A/D转换结果寄存器(ADC_RES,ADC_RESL)的数据格式调整控制位。

当ADRJ=0时,10位A/D转换结果的高8位存放在ADC_RES中,低2位存放在ADC_RESL的低2位中。

此时,如果用户需要完整10位结果,按下面公式计算:

如果用户只需要8位结果,按下面公式计算:

式中,Vin为模拟输入通道输入电压,Vcc为单片机实际工作电压,用单片机工作电压作为模拟参考电压。

当ADRJ=1时,10位A/D转换结果的高2位存放在ADC_RES的低2位中,低8位存放在ADC_RESL中。

此时,如果用户需取完整10位结果,按下面公式计算:

式中,Vin为模拟输入通道输入电压,Vcc为单片机实际工作电压,用单片机工作电压作为模拟参考电压。

4.与A/D中断有关的寄存器

IE : 中断允许寄存器(可位寻址)

EA : CPU的中断开放标志,EA=1,CPU开放中断,EA=0,CPU屏蔽所有的中断申

请。EA的作用是使中断允许形成多级控制。即各中断源首先受EA控制;其次还受各中断源自己的中断允许控制位控制。

EADC : A/D转换中断允许位。

EADC=1,允许A/D转换中断;

EADC=0,禁止A/D转换中断。

如果要允许A/D转换中断则需要将相应的控制位置1:

1、将EADC置1,允许ADC中断,这是ADC中断的中断控制位。

2、将EA置1,打开单片机总中断控制位,此位不打开,也是无法产生ADC中断的A/D中断服务程序中要用软件清A/D中断请求标志位ADC_FLAG(也是A/D转换结束标志位)。

IPH : 中断优先级控制寄存器高 (不可位寻址)

IP :中断优先级控制寄存器低(可位寻址)

PADCH, PADC: A/D转换中断优先级控制位。

当PADCH=0且PADC=0时,A/D转换中断为最低优先级中断(优先级0)

当PADCH=0且PADC=1时,A/D转换中断为较低优先级中断(优先级1)

当PADCH=1且PADC=0时,A/D转换中断为较高优先级中断(优先级2)

当PADCH=1且PADC=1时,A/D转换中断为最高优先级中断(优先级3)

9.5.A/D转换模块的参考电压源

STC12C5A60S2系列单片机的参考电压源是输入工作电压Vcc,所以一般不用外接参考电压源。如7805的输出电压是5V,但实际电压可能是4.88V到4.96V,用户需要精度比较高的话,可在出厂时将实际测出的工作电压值记录在单片机内部的EEPROM里面,以供计算。

如果有些用户的Vcc不固定,如电池供电,电池电压在5.3V-4.2V之间漂移,则Vcc 不固定,就需要在8路A/D转换的一个通道外接一个稳定的参考电压源,来计算出此时的工作电压Vcc,再计算出其他几路A/D转换通道的电压。如可在ADC转换通道的第七通道外接一个1.25V(或1V,或...)的基准参考电压源,由此求出此时的工作电压Vcc,再计算出其它几路A/D转换通道的电压(理论值据是短时间之内,Vcc不变)。

9.6.A/D转换测试程序

1. C程序(中断方式):

/*------------------------------------------------------------------------------------*/

/* --- STC MCU International Limited ---------------------------------------*/

/* --- 演示STC 1T 系列单片机A/D转换功能-----------------------------*/

/* --- Mobile: (86)139******** -----------------------------------------------*/

/* --- Fax: 86-755-82944243 ---------------------------------------------------*/

/* --- Tel: 86-755-82948412 ----------------------------------------------------*/

/* --- Web: https://www.wendangku.net/doc/ca18122491.html, -----------------------------------------------*/

/* 如果要在程序中使用或在文章中引用该程序,-------------------- ---*/

/* 请在程序中或文章中注明使用了宏晶科技的资料及程序-----------*/

/*-------------------------------------------------------------------------------------*/

#include "reg51.h"

#include "intrins.h"

#define FOSC 18432000L

#define BAUD 9600

typedef unsigned char BYTE;

typedef unsigned int WORD;

/*Declare SFR associated with the ADC */

sfr ADC_CONTR = 0xBC; //ADC control register

sfr ADC_RES = 0xBD; //ADC hight 8-bit result register

sfr ADC_LOW2 = 0xBE; //ADC low 2-bit result register

sfr P1ASF = 0x9D; //P1 secondary function control regis /*Define ADC operation const for ADC_CONTR*/

#define ADC_POWER 0x80 //ADC power control bit

#define ADC_FLAG 0x10 //ADC complete flag

#define ADC_START 0x08 //ADC start control bit

#define ADC_SPEEDLL 0x00 //540 clocks

#define ADC_SPEEDL 0x20 //360 clocks

#define ADC_SPEEDH 0x40 //180 clocks

#define ADC_SPEEDHH 0x60 //90 clocks

void InitUart();

void SendData(BYTE dat);

void Delay(WORD n);

void InitADC();

BYTE ch = 0; //ADC channel NO.

void main()

{

InitUart(); //Init UART, use to show ADC result

InitADC(); //Init ADC sfr

IE = 0xa0; //Enable ADC interrupt and Open master interrupt switch

//Start A/D conversion

while (1);

}

/*----------------------------

ADC interrupt service routine

----------------------------*/

void adc_isr() interrupt 5 using 1

{

ADC_CONTR &= !ADC_FLAG; //Clear ADC interrupt flag

SendData(ch); //Show Channel NO.

SendData(ADC_RES); //Get ADC high 8-bit result and Send to

UART

//if you want show 10-bit result, uncomment next line

// SendData(ADC_LOW2); //Show ADC low 2-bit result

if (++ch > 7) ch = 0; //switch to next channel

ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;

}

/*----------------------------

Initial ADC sfr

----------------------------*/

void InitADC( )

{

P1ASF = 0xff; //Set all P1 as analog input port

ADC_RES = 0; //Clear previous result

ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;

Delay(2); //ADC power-on delay and Start A/D conversion

}

/*----------------------------

Initial UART

----------------------------*/

void InitUart()

{

SCON = 0x5a; //8 bit data ,no parity bit

TMOD = 0x20; //T1 as 8-bit auto reload

TH1 = TL1 = -(FOSC/12/32/BAUD); //Set Uart baudrate

TR1 = 1; //T1 start running

/*----------------------------

Send one byte data to PC

Input: dat (UART data)

Output:-

----------------------------*/

void SendData(BYTE dat)

{

while (!TI); //Wait for the previous data is sent

TI = 0; //Clear TI flag

SBUF = dat; //Send current data

}

/*----------------------------

Software delay function

----------------------------*/

void Delay(WORD n)

{

WORD x;

while (n--)

{

x = 5000;

while (x--);

}

}

2、C程序(查询方式):

/*------------------------------------------------------------------------------------*/

/* --- STC MCU International Limited ---------------------------------------*/

/* --- 演示STC 1T 系列单片机A/D转换功能------------------------------*/

/* --- Mobile: (86)139******** -----------------------------------------------*/

/* --- Fax: 86-755-82944243 ---------------------------------------------------*/

/* --- Tel: 86-755-82948412 ----------------------------------------------------*/

/* --- Web: https://www.wendangku.net/doc/ca18122491.html, -----------------------------------------------*/

/* 如果要在程序中使用或在文章中引用该程序,-------------------- ---*/

/* 请在程序中或文章中注明使用了宏晶科技的资料及程序-----------*/

/*-------------------------------------------------------------------------------------*/

#include "reg51.h"

#include "intrins.h"

#define FOSC 18432000L

#define BAUD 9600

typedef unsigned char BYTE;

typedef unsigned int WORD;

/*Declare SFR associated with the ADC */

sfr ADC_CONTR = 0xBC; //ADC control register

sfr ADC_RES = 0xBD; //ADC high 8-bit result register

sfr ADC_LOW2 = 0xBE; //ADC low 2-bit result register

sfr P1ASF = 0x9D; //P1 secondary function control register /*Define ADC operation const for ADC_CONTR*/

#define ADC_POWER 0x80 //ADC power control bit

#define ADC_FLAG 0x10 //ADC complete flag

#define ADC_START 0x08 //ADC start control bit

#define ADC_SPEEDLL 0x00 //540 clocks

#define ADC_SPEEDL 0x20 //360 clocks

#define ADC_SPEEDH 0x40 //180 clocks

#define ADC_SPEEDHH 0x60 //90 clocks

void InitUart();

void InitADC();

void SendData(BYTE dat);

BYTE GetADCResult(BYTE ch);

void Delay(WORD n);

void ShowResult(BYTE ch);

void main()

{

InitUart(); //Init UART, use to show ADC result InitADC(); //Init ADC sfr

while (1)

{

ShowResult(0); //Show Channel0

ShowResult(1); //Show Channel1

ShowResult(2); //Show Channel2

ShowResult(3); //Show Channel3

ShowResult(4); //Show Channel4

ShowResult(5); //Show Channel5

ShowResult(6); //Show Channel6

ShowResult(7); //Show Channel7

}

}

/*----------------------------

Send ADC result to UART

----------------------------*/

void ShowResult(BYTE ch)

{

SendData(ch); //Show Channel NO.

SendData(GetADCResult(ch)); //Show ADC high 8-bit result

//if you want show 10-bit result, uncomment next line

// SendData(ADC_LOW2); //Show ADC low 2-bit result }

/*----------------------------

Get ADC result

----------------------------*/

BYTE GetADCResult(BYTE ch)

{

ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;

_nop_(); //Must wait before inquiry

_nop_();

_nop_();

_nop_();

while (!(ADC_CONTR & ADC_FLAG)); //Wait complete flag

ADC_CONTR &= ~ADC_FLAG; //Close ADC

return ADC_RES; //Return ADC result

/*----------------------------

Initial UART

----------------------------*/

void InitUart()

{

SCON = 0x5a; //8 bit data ,no parity bit

TMOD = 0x20; //T1 as 8-bit auto reload

TH1 = TL1 = -(FOSC/12/32/BAUD); //Set Uart baudrate

TR1 = 1; //T1 start running

}

/*----------------------------

Initial ADC sfr

----------------------------*/

void InitADC()

{

P1ASF = 0xff; //Open 8 channels ADC function ADC_RES = 0; //Clear previous result

ADC_CONTR = ADC_POWER | ADC_SPEEDLL;

Delay(2); //ADC power-on and delay

}

/*----------------------------

Send one byte data to PC

Input: dat (UART data)

Output:-

----------------------------*/

void SendData(BYTE dat)

{

while (!TI); //Wait for the previous data is sent TI = 0; //Clear TI flag

SBUF = dat; //Send current data

}

/*----------------------------

Software delay function

----------------------------*/

void Delay(WORD n)

{

WORD x;

while (n--)

{

x = 5000;

while (x--);

}

}

相关文档