#include <STCREG52.h>
sbit DISP_A = P1^7; //20
sbit DISP_B = P1^6; //01
sbit DISP_C = P1^2; //02
sbit DISP_D = P1^3; //08
sbit DISP_E = P1^4; //04
sbit DISP_F = P1^5; //40
sbit DISP_G = P1^1; //10
sbit BAIT = P1^0; //电池电压检测(备注:如果改脚要把AD的配置函数也调整)
sbit LED1 = P3^0; //LED屏控制脚
sbit LED2 = P3^1; //LED屏控制脚
sbit LEDON= P3^4; //LED灯控制脚
sbit BEEP = P3^7; //蜂鸣器控制脚
//--------------按键位--------------//
sbit Power= P3^2; //开关机启动LED
sbit Mode = P3^3; //模式调节
sbit Time = P3^5; //时间调节
//---------------------------------//
#define ADC_POWER 0x80
#define ADC_FLAG 0x10
#define ADC_START 0x08
#define ADC_SPEEDLL 0x00
unsigned char DISP_NUM[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xc7,0xa3};
//显示数字数组 0 1 2 3 4 5 6 7 8 9 L o
unsigned char disp,NUM,NUM2,pwmzkb,pwmvol=100,pwmadd=1,Modenum;
//
unsigned char Timenum=10; //点亮计时值
unsigned char PWMNUM; //模式值
unsigned char save_num[3]; //缓存数组
unsigned char save_num_pre[3]; //缓存数组
unsigned int timer_1S,Power_class_timer=0,Autoff_timer=300,DEC_timer,battimer,Time_timer,AD_channel_result;
// |1秒值 | | 自动关机值 | | AD读取暂存值 |
extern unsigned char IapReadByte(unsigned int addr);
extern void IapProgramByte(unsigned int addr, unsigned char dat);
extern void IapEraseSector(unsigned int addr);
extern unsigned char GetADCResult(unsigned char ch);
extern void InitADC();
//----------------标志位---------------//
bit POWER_FALG=0; //固化灯工作标志位
bit Star=0; //
bit LOW_BATT=0; //低电平标志位
bit LOW_BATT_pre=0; //
//---------------------------------//
void delay1s(void) //延时0.2 秒子程序
{
unsigned char i,j,k,m;
for(m=10;m>0;m--)
{
for(i=20;i>0;i--);
for(j=20;j>0;j--)
for(k=248;k>0;k--);
}
}
/*********************************************************/
// 延时子程序
/*********************************************************/
void delayms(unsigned char ms)
{
unsigned char i ;
while(ms--)for(i=10;i>0;i--) ;
}
void delay2s(unsigned char num) //延时0.2 秒子程序
{
unsigned char i,j,k,m;
for(m=num;m>0;m--)
{
for(i=20;i>0;i--);
for(j=20;j>0;j--)
for(k=248;k>0;k--);
}
}
/*********************************************************/
//蜂鸣器子程序
/*********************************************************/
void Beepl(unsigned char num)
{
unsigned char i;
for(i=2;i>0;i--)
{
delay1s();
delay1s();
delay1s();
delay1s();
BEEP=0; //Beep取反
}
delay2s(num);
delay2s(num);
delay2s(num);
delay2s(num);
BEEP=1 ; //关闭蜂鸣器
}
void Beep()
{
unsigned char i;
for(i=2;i>0;i--)
{
delayms(200);
delayms(200);
delayms(200);
delayms(200);
delayms(200);
delayms(200);
delayms(200);
delayms(200);
BEEP=~BEEP ; //Beep取反
}
BEEP=1 ; //关闭蜂鸣器
}
/*****************************************************/
/** ADC 转换 **/
/*****************************************************/
void Ad_Change(void)
{
unsigned char n;
if(Star==0)
{
AD_channel_result=0;
for(n=0;n<4;n++)AD_channel_result+=GetADCResult(0); //将选择ADC功能P1的IO单位,实行四次读取的值给于平均值
AD_channel_result=AD_channel_result/4; //四次相加的值除于4次,求平均值
if(AD_channel_result<149)LOW_BATT=1; //判断取得的值<149,
if((LOW_BATT_pre!=LOW_BATT)&&(battimer==0))
{
LOW_BATT_pre=LOW_BATT;
battimer=5;
for(n=0;n<5;n++)Beepl(5);
}
}
}
void system_init(void) //IO口配置,定时器配置
{
P0M0=0xFE;
P0M1=0x00;
P1M0=0x80;
P1M1=0x80;
P3M0=0xC3;
P3M1=0x00;
TMOD=0x01;
TH0=0xff;
TL0=0x6a;//150us
TR0=1;
ET0=1;
EA=1;
LEDON=1; //固化灯关闭
}
void init_IO(void) //IO口配置
{
P0M0=0x00;
P0M1=0xFF;
P1M0=0x00;
P1M1=0xFF;
P3M0=0x00;
P3M1=0xFB;
}
void dispnum(unsigned char num) //显示转换函数
{
DISP_A=(num)&0x01;
DISP_B=((num&0x02)>>1)&0x01;
DISP_C=((num&0x04)>>2)&0x01;
DISP_D=((num&0x08)>>3)&0x01;
DISP_E=((num&0x10)>>4)&0x01;
DISP_F=((num&0x20)>>5)&0x01;
DISP_G=((num&0x40)>>6)&0x01;
}
void display(unsigned char num1,unsigned char num2,unsigned char timer) //调用显示转换函数
{
if(timer<10)
{
dispnum(num1);
LED1=0;
LED2=1;}
else {
dispnum(num2);
LED1=1;
LED2=0;}
}
void Int0(void)interrupt 0 //外部中断唤醒程序
{
IT0=0; //低电平触发
EX0=0; //外部(中断0)允许位,1为打开,0为关闭。
ET0=0; //禁止定时器0中断
EA=0; //关闭总中断
POWER_FALG=0; //电源标志位
Autoff_timer=300; //重新装载自动关机值
while(Power==0); //检测外部中断按键是否放开
delay1s();
delay1s();
delay1s();
IAP_CONTR=0x20;
ET0=1; //打开定时器0中断
EA=1; //打开总中断
}
void timer0(void) interrupt 1 //12Mhz--150uS
{
static unsigned char dispnum;
static unsigned int pwmclick=0;
unsigned char dispcode1,dispcode2;
TH0=0xff;
TL0=0x6a;
//**********1秒钟计时区***********************************//
if(timer_1S)timer_1S--;
else
{
timer_1S=6000;
if(Power_class_timer)Power_class_timer--;
if(Autoff_timer)Autoff_timer--;
if(battimer)battimer--;
if(Time_timer)Time_timer--;
}
//********************************************************//
if(Star)
{
if(DEC_timer)DEC_timer--;
else DEC_timer=6000;
if(DEC_timer==6000){if(NUM)NUM--;}
if((DEC_timer%600)==0){if(pwmzkb<pwmvol)pwmzkb=pwmzkb+pwmadd;}
disp=NUM;
if(Modenum==0) //模式值等于0,显示是01菜单
{
++pwmclick;
if(pwmclick>=100)pwmclick=0;
if(pwmclick<pwmzkb)LEDON=0;
else LEDON=1;
}
if(Modenum==1) //模式值等于1,显示是02菜单
{
if(DEC_timer>3000)
{
++pwmclick;
if(pwmclick>=100)pwmclick=0;
if(pwmclick<100)LEDON=0;
else LEDON=1;
}
else LEDON=1;
}
if(Modenum==2) //模式值等于2,显示是03菜单
{
++pwmclick;
if(pwmclick>=100)pwmclick=0;
if(pwmclick<pwmvol)LEDON=0;
else LEDON=1;
}
}
else
{
if(Time_timer)disp=Timenum;
else disp=Modenum+1;
LEDON=1;
}
//----------------------------------------------------------------------------//
if(battimer)
{
dispcode1=((dispcode1&0x80)|DISP_NUM[10]);dispcode2=((dispcode2&0x80)|DISP_NUM[11]);
}
else
{
dispcode1=DISP_NUM[disp/10];dispcode2=DISP_NUM[disp%10];
}
//----------------------------------------------------------------------------//
if(dispnum)dispnum--;
else dispnum=20;
display(dispcode1,dispcode2,dispnum);
}
//主程序//
void main(void)
{
unsigned char n;
system_init(); //初始化所有IO口
InitADC(); //ADC电压检测初始化
Modenum=IapReadByte(0x0000); //从EPROM地址读取模式值
if(Modenum>2)Modenum=0; //设置模式值强制只有3种(0,1,2)
save_num_pre[0]=save_num[0]=Modenum; //设置模式值付值给缓存数组
Timenum=IapReadByte(0x0001); //从EEPROM地址读取点亮时间值
if(Modenum==2)
{
if(Timenum>30)Timenum=30;
}
if(Timenum>40)Timenum=10; //设置默认时间值10S,依次递增(10S,20S,30S,40S)
if(Timenum<10)Timenum=10; //设置强制时间值为10S
save_num_pre[1]=save_num[1]=Timenum; //付值点亮时间值给缓存数组
Beepl(10); //开启蜂鸣提醒
while(1)
{
Ad_Change(); //执行AD转换
//对比两组缓存数组的数据是否相等,不