控制/MCU
STC15系列单片机内部集成了8路10位高速A/D转换器。STC15系列单片机的A/D转换口在P1口(P1.7-P1.0),有8路10位高速A/D转换器,速度到300KHz(30万次/秒)。8路电压输入型A/D,可做温度检测、电池电压检测、按键扫描、频谱检测等。
STC15系列单片机ADC由多路选择开关、比较器、逐次比较寄存器、10位DAC、转换结果寄存器(ADC_RES和ADC_RESL)以及ADC_CONTR构成。
STC15系列单片机的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位。
当CLK_DIV.5(PCON2.5)/ADRJ = 0时,A/D转换结果寄存器格式如下:
当ADRJ=0时,如果取10位结果,则按下面公式计算:
当ADRJ=0时,如果取8位结果,按下面公式计算:
当CLK_DIV.5(PCON2.5)/ADRJ = 1时,A/D转换结果寄存器格式如下:
当ADRJ=1时,如果取10位结果,则按下面公式计算:
式中,Vin为模拟输入通道输入电压,Vcc为单片机实际工作电压,用单片机工作电压作为模拟参考电压。
与STC15系列单片机A/D转换相关的寄存器列于下表所示。
STC15系列单片机的A/D转换口在P1口(P1.7-P1.0),有8路10位高速A/D转换器速度可达到到300KHz(30万次/秒)。8路电压输入型A/D,可做温度检测、电池电压检测、按键扫描、频谱检测等。上电复位后P1口为弱上拉型I/O口,用户可以通过软件设置将8路中的任何一路设置为A/D转换,不需作为A/D使用的P1口可继续作为I/O口使用(建议只作为输入)。需作为A/D使用的口需先将P1ASF特殊功能寄存器中的相应位置为‘1’,将相应的口设置为模拟功能。P1ASF存器的格式如下:
P1ASF : P1口模拟功能控制寄存器(该寄存器是只写寄存器,读无效)
ADC_CONTR寄存器的格式如下:
ADC_CONTR : ADC控制寄存器
对ADC_CONTR寄存器进行操作,建议直接用MOV赋值语句,不要用‘与’和‘或’语句。
ADC_POWER: ADC 电源控制位。
0:关闭ADC 电源;
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:模数转换器转换速度控制位
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
ADC转换结果调整寄存器位——ADRJ位于寄存器CLK_DIV/PCON中,用于控制ADC转换结果存放的位置。
ADRJ:ADC转换结果调整
0:ADC_RES[7:0]存放高8位ADC结果,ADC_RESL[1:0]存放低2位ADC结果
1:ADC_RES[1:0]存放高2位ADC结果,ADC_RESL[7:0]存放低8位ADC结果
特殊功能寄存器ADC_RES和ADC_RESL寄存器用于保存A/D转换结果,其格式如下:
CKKO_DIV寄存器的ADRJ位是A/D转换结果寄存器(ADC_RES,ADC_RESL)的数据格式调整控制位。
当ADRJ=0时,10位是A/D转换结果的高8位存放在在ADC_RES中,低2位存放在ADC_RESL的低2位中。
IE : 中断允许寄存器 (可位寻址)
EA : CPU的中断开放标志
EA=1,CPU开放中断,
EA=0,CPU屏蔽所有的中断申请。
EA的作用是使中断允许形成多级控制。即各中断源首先受EA控制;其次还受各中断源自己的中断允许控制位控制。
EADC : A/D转换中断允许位
EADC=1,允许A/D转换中断,
EADC=0,禁止A/D转换中断。
#include "stc15.h"
#include "intrins.h"
#include "delay.h"
#define uchar unsigned char
#define uint unsigned int
#define FOSC 11059200L //系统频率
#define BAUD 9600 //串口波特率
void UatrInit();
void SendData(uchar dat);
void SendString(char *s);
void AdInit();
uchar num[10] = {'0','1','2','3','4','5','6','7','8','9'};
uint adc_result = 0;
void main()
{
P1M0 = 0x02;
P1M1 = 0x00;
UatrInit();
AdInit();
EA = 1; // CPU开放中断
while (1);
}
// 初始化串口
void UatrInit()
{
SCON = 0x50; //8位可变波特率 串口工作模式1
T2L = (65536 - (FOSC/4/BAUD)); //设置波特率重装值
T2H = (65536 - (FOSC/4/BAUD)) > >8;
AUXR = 0x14; //T2为1T模式, 并启动定时器2
AUXR |= 0x01; //选择定时器2为串口1的波特率发生器
ES = 1; //使能串口1中断
}
// 初始化ADC
void AdInit()
{
P1ASF = 0x01; // P1.0作为模拟功能A/D使用
ADC_RES = 0;
ADC_RESL = 0; // 结果寄存器清零
ADC_CONTR = 0x88; // 打开ADC的电源 540个周期转换一次 选择P1.0作为A/D输入来用
delayus(20);
EADC = 1; // 允许A/D转换中断
}
// ADC中断服务函数
void adc_isr() interrupt 5
{
ADC_CONTR &= !0x10; // 清除ADC中断标志
adc_result = ADC_RES*4 + ADC_RESL; // 获取ADC结果,高2位在前
SendData(num[adc_result/1000]); // 千
SendData(num[adc_result%1000/100]); // 百
SendData(num[adc_result%100/10]); // 十
SendData(num[adc_result%10]); // 个
// SendData(ADC_RES);
// SendData(ADC_RESL);
SendString("\\r\\n"); // 换行
ADC_CONTR = 0x88;