代码如下,比较乱,请自行根据实际使用情况修改:
#include <STC8G.h>
#include <intrins.h>
#include<math.h>
#define ulong unsigned long
#define uint unsigned int
#define uchar unsigned char
typedef unsigned char U8;
typedef unsigned int U16;
typedef unsigned long U32;
sfr INT_CLKO = 0x8f;
sbit an1 =P3^0; //按键1
sbit an2 =P3^1; //按键2没有使用
sbit Y0 =P3^2; //雾化片驱动
sbit Y1 =P3^3;
sbit LED =P5^4; //指示灯
sbit ADC_VIN=P5^5; //输入电压检测
bit standby;
U16 num,num0,num1,*BGV,adcvref,adcvin;
void delay1ms() //@24.000MHz
{
unsigned char i, j;
_nop_();
i = 32;
j = 40;
do
{
while (--j);
} while (--i);
}
void delay10ms() //@24.000MHz
{
unsigned char i, j, k;
i = 2;
j = 56;
k = 172;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void init1() //初始化
{
P3M1=0x00;P3M0=0x0c; //高阻,23推挽,01准双向口,开漏。
P5M1=0x20;P5M0=0x10; //5高阻,4推挽,准双向口,开漏。
TMOD=0x11;
TH0=(65536-40000)/256; TL0=(65536-40000)%256;
TH1=(65536-50000)/256; TL1=(65536-50000)%256;
ET0=1;ET1=1;
TR0=1;TR1=0;
BGV = (U16 code *)0x1ff7; //内部基准电压 STC8G1K08/08A
num=0;num0=0;num1=0;
Y0=0;
Y1=0;
LED=1;
EA=1;
}
U16 ADCRead() //读取内部基准电压
{
U16 AD_Date=0; // 10位AD转换值
U8 Tmpe; // 临时变量用于将AD转换出来的2个字节合成一个字节
ADC_CONTR |= 0x40; //开始AD转换
_nop_();_nop_();_nop_();
while (!(ADC_CONTR & 0x20)); //查询 ADC 完成标志
ADC_CONTR &= ~0x20; //清完成标志
AD_Date = ADC_RES; // 默认高字节高8位。
AD_Date <<= 2;
Tmpe = ADC_RESL; // 默认低字节低2位。
Tmpe &= 0x03; // 屏蔽无关位
AD_Date |= Tmpe; // 高低字节拼接成一个10位数。
return AD_Date;
}
void getadcref() //内部基准电压
{
U8 i;
U16 vref;
ADC_CONTR =0x80; //打开AD电源
delay10ms();
ADCTIM = 0x3f;
ADCCFG = 0x0f; //设置 ADC 时钟为系统时钟/2/16
ADC_CONTR = 0x8f; //使能 ADC 模块,并选择第 15 通道
ADCRead(); ADCRead(); //前两个数据丢弃
for (i=0; i<16; i++)
{vref += ADCRead();} //读取 16 次数据
vref >>= 4; //取平均值
adcvref = (U16)(1024L* *BGV / vref); //计算 VCC 管脚电压,即电池电压 //注意,此电压的单位为毫伏(mV)
ADC_CONTR &= 0x7f; //关闭AD电源
}
U16 ADchange() //AD转换
{
U16 AD_Date=0; // 10位AD转换值
U8 Tmpe; // 临时变量用于将AD转换出来的2个字节合成一个字节
ADC_RES = 0; //清除结果寄存器
ADC_RESL = 0; //清除结果寄存器
ADC_CONTR = 0x85;
TR0=0;
TR1=0;
ADC_CONTR |= 0x40; //开始AD转换 //ADC_CONTR|=0x08; //开始AD转换
_nop_();_nop_();
while (!(ADC_CONTR & 0x20)); //查询 ADC 完成标志
ADC_CONTR &= ~0x20; //清完成标志
TR0=1;
TR1=1;
AD_Date = ADC_RES; // 默认高字节高8位。
AD_Date <<= 2;
Tmpe = ADC_RESL; // 默认低字节低2位。
Tmpe &= 0x03; // 屏蔽无关位
AD_Date |= Tmpe; // 高低字节拼接成一个10位数。
return AD_Date;
}
void adcscancal() //AD转换结果计算
{
U8 jj,yy;
U16 adcxx=0,max,min,test[18];
U32 tt=0;
ADC_CONTR =0x80; //打开AD电源
delay1ms();
ADCTIM = 0x3f;
ADCCFG = 0x0f; //设置 ADC 时钟为系统时钟/2/16
ADchange();ADchange(); //多次扫描,丢弃前两次取平均值
for(jj=0;jj<18;jj++)
{
test[jj] = ADchange();
tt += test[jj];
}
max=min=test[0];
for(yy=0;yy<18;yy++)
{
if(min>test[yy]) min=test[yy]; //最小值
if(max<test[yy]) max=test[yy]; //最大值
}
adcxx=(tt-max-min)/16; //取平均值
adcvin=adcvref/1024.0*adcxx*11;
ADC_CONTR &= 0x7f; //关闭AD电源
}
void main()
{
init1();
getadcref(); //内部1.19V基准电压
while(1)
{
if(an1==0){delay10ms();if(an1==0){standby=~standby;while(!an1);}} //AN1按键检测
if(adcvin>4500&&adcvin<5500&&standby==1) //输入电压在4.5~5.5V范围且standby为1时开始工作
{
U8 jj;
jj++;
_nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); //频率微调:频率低了减少_nop_();频率高了增加 _nop_();
if(jj>2){jj=0;Y1=~Y1;Y0=~Y1;}
if(num0>25){num0=0;LED=~LED;} //工作时指示灯以0.5秒间隔闪烁
}
else{Y0=0;Y1=0;LED=1;} //standby为0时停止工作,指示灯常亮
}
}
void T0_time() interrupt 1 //T0
{
TH0=(65536-40000)/256; TL0=(65536-40000)%256; //20mS-24M
num0++;
adcscancal();
}
void T1_time() interrupt 3 //T1
{
TH1=(65536-50000)/256; TL1=(65536-50000)%256; //25mS 24M
num1++;
} |