代碼如下,比較亂,請自行根據實際使用情況修改:
#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++;
} |