- UID
- 274637
- 阅读权限
- 60
- 推广
-
- 幽默
-
- 注册时间
- 2012-3-21
- 最后登录
- 1970-1-1
|
注册家电维修技术论坛,与同行畅聊维修技术,享更多技术论坛功能。
您需要 登录 才可以下载或查看,没有帐号?快速注册
x
/*开机倒计时读秒到0后数码管加1,倒计时可设置并保存,倒计时设置限定5~100,
数码管实时保存,下一次开机读秒后从上一次的数码管数字继续加1,9999后清零*/
#include <STC89C5xRC.H>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit SDA=P2^7;
sbit SCL=P2^6; //24C02数据线和时钟线
sbit w1=P3^4;
sbit w2=P3^5;
sbit w3=P3^7;
sbit w4=P3^6; //数码管4个位选
sbit she=P1^0;
sbit jia=P1^1;
sbit jian=P1^2;
sbit ok=P1^3; //设置,加,减,确定(取消)
uchar cc,ge,shi,bai,qian,time,a22,a33,a44,dc;
bit fa,ya,key,s0;
uchar code table[ ]={0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90 }; //共阳0~9段码
void delay(uint z) //1ms延时
{
uint x,y;
for(x=z;x>0;x--)
for(y=114;y>0;y--);
}
void start( ) //启动IIC总线
{
SDA=1; //发送起始条件的数据信号
_nop_( );
SCL=1;
_nop_( ); //起始条件建立时间大于4.7us,延时
_nop_( );
_nop_( );
_nop_( );
_nop_( );
SDA=0; //发送起始信号
_nop_( ); //起始条件锁定时间大于4μ
_nop_( );
_nop_( );
_nop_( );
_nop_( );
SCL=0; //钳住I2C总线,准备发送或接收数据
_nop_( );
_nop_( ); //SCL置低,准备接收或发送数据
}
void stop( ) //停止IIC总线
{
SDA=0; //发送结束条件的数据信号
_nop_( ); //发送结束条件的时钟信号
SCL=1; //结束条件建立时间大于4μ
_nop_( );
_nop_( );
_nop_( );
_nop_( );
_nop_( );
SDA=1; //发送I2C总线结束信号
_nop_( );
_nop_( );
_nop_( );
_nop_( ); //延时保持4.7US以上
}
void write(uchar a) //传送一个字节8位数据
{
uchar b,shu;
for(b=0;b<8;b++) //要传送的数据长度为8位
{
shu=a<<b; //把即将发送的数据的为移到最高位
if((shu&0x80)!=0) //判断最高位是否为0
SDA=1; //不等于0说明最明当前要发送的数据为1
else SDA=0; //否则数据为0
SCL=1; //置时钟线为高,通知被控器开始接收数据位
_nop_( );
_nop_( ); //保证时钟高电平周期大于4μ
_nop_( );
_nop_( );
_nop_( );
SCL=0;
}
_nop_( );
SDA=1; //8位发送完后释放数据线,准备接收应答位
_nop_( );
SCL=1;
_nop_( );
}
bit ack( ) //等待应答函数
{
bit h;
SDA=1;
_nop_( );
SCL=1; //SDA和SCL全部置高
_nop_( );
_nop_( );
_nop_( );
_nop_( );
SCL=0; //等待4.7US以上,把SCL置低
_nop_( );
_nop_( );
_nop_( );
_nop_( );
h=SDA; //等待4.7SU以上读取SDA应答信号
return h; //应答成功则是0,没有应答则是1
}
uchar reade( ) //接收一个字节8位数据
{
uchar d,g;
SDA=1; //数据线置高电平
for(d=0;d<8;d++)
{
_nop_( );
_nop_( );
SCL=0;
_nop_( );
_nop_( );
_nop_( );
_nop_( ); //SCL低电平,数据变化
SCL=1;
_nop_( );
_nop_( ); //SCL高电平,数据稳定
if(SDA==1)
g=(g<<1)|0x01; //如果读到的数据是1就是最低位置1
else
g=g<<1; //否则读到是0,直接左移1位(左移后右补0)
}
return g; //经过8次读取移位,把g返回
}
void fasong(uchar add , uchar tab) //指定地址发送一个字节
{
start( ); //启动总线
write(0xa0); //器件地址(发送)
ack( ); //等待应答
write(add); //发送器件内部地址
ack( ); //等待应答
write(tab); //发送数据
ack( ); //等待应答
stop( );
}
uchar jieshou(uchar add) //指定地址接收一个字节
{
uchar shu;
start( ); //读取(开始-器件地址(发)- 器件内部地址 - 开始 - 器件地址(收)- 接收数据 -发应答或停止接收
write(0xa0);
ack( );
write(add);
ack( );
start( );
write(0xa1);
ack( );
shu=reade( );
stop( );
return shu;
}
void display(uchar a , uchar b , uchar c , uchar d) //数码管显示函数
{
if(a!=0) //最高位不为0则显示千位
{
w1=0;
P0=table[a];
delay(5);
P0=0XFF;
w1=1;
}
if(a!=0||b!=0) //千位或者百位不为0则显示百位(如1024这种百位是0)
{
w2=0;
P0=table[b];
delay(5);
P0=0XFF;
w2=1;
}
if(a!=0||b!=0||c!=0) //千位或者百位或者十位不为0则显示十位
{
w3=0;
P0=table[c];
delay(5);
P0=0XFF;
w3=1;
}
w4=0; //个位始终显示
P0=table[d];
delay(5);
P0=0XFF;
w4=1;
}
void main( )
{
w1=w2=w3=w4=1; //初始化位选
ge=jieshou(0x03); //接收个位
shi=jieshou(0x04); //接收十位
bai=jieshou(0x05); //接收百位
qian=jieshou(0x06); //接收千位
time=jieshou(0x07); //接收读秒时间
fasong(0x07,time); //把时间再存回去
a22=time%1000/100;
a33=time%100/10;
a44=time%10; //分离出读秒的个十百(读秒最大100,没有千位)
EA=1;
ET0=1;
ET1=1;
TMOD=0X11;
TH0=0X3C;
TL0=0XB0;
TH1=0X3C;
TL1=0XB0;
TR1=1; //配置定时器0和1,启动定时器1
while(1)
{
display(0,a22,a33,a44); //读秒显示
while(ya==1) //ya默认是0,读秒结束后定时器1把ya置1,进入数字++显示
{
display(qian,bai,shi,ge); //显示数字
if(fa==1) //定时器0标记数字有变化,需要进行保存
{
fa=0;
fasong(0x03,ge); //存个位
display(qian,bai,shi,ge);
fasong(0x04,shi);
display(qian,bai,shi,ge);
fasong(0x05,bai);
display(qian,bai,shi,ge); //由于存4次时间较长,数码管会闪烁,插入数码管显示函数
fasong(0x06,qian);
}
if(she==0&&key==0) //数字++时,按下设置键,暂停加,再按一次恢复加
{
delay(5);
if(she==0)
{
s0=~s0;
key=1;
TR0=~TR0;
}
}
if(ok==0&&key==0&&s0==1) //设置有效时,ok键把数字清零
{
delay(5);
if(ok==0)
{
key=1;
s0=0;
time=0;
qian=bai=shi=ge=0; //更新个十百千
fasong(0x03,0);
fasong(0x04,0);
fasong(0x05,0);
fasong(0x06,0); //更新EEPROM,直接给实参就行
display(0,0,0,0); // 显示出来,并启动定时器0
TR0=1;
}
}
if(key==1) //松手检测
{
if(she==1&&ok==1)
{
delay(5);
if(she==1&&ok==1)
key=0;
}
}
}
if(she==0&&key==0) //读秒设置,暂停读秒,再按一次恢复读秒
{
delay(5);
if(she==0)
{
TR1=~TR1;
s0=~s0;
key=1;
time=jieshou(0x07);
fasong(0x07,time);
a22=time%1000/100;
a33=time%100/10;
a44=time%10;
}
}
if(jia==0&&key==0&&s0==1) //读秒设置++
{
delay(5);
if(jia==0)
{
uchar sa;
key=1;
sa=time;
sa++;
if(sa>100) //限定读秒上限100
sa=5;
time=sa;
fasong(0x07,sa); //加一次保存一次
a22=time%1000/100;
a33=time%100/10;
a44=time%10;
}
}
if(jian==0&&key==0&&s0==1) //读秒设置--
{
delay(5);
if(jian==0)
{
uchar sb;
key=1;
sb=time;
sb--;
if(sb<5) //限定读秒下限5
sb=100;
time=sb;
fasong(0x07,sb); //减一次保存一次
a22=time%1000/100;
a33=time%100/10;
a44=time%10;
}
}
if(key==1) //松手检测
{
if(she==1&&jia==1&&jian==1)
{
delay(5);
if(she==1&&jia==1&&jian==1)
key=0;
}
}
}
}
void aa( ) interrupt 1 //定时器0负责数字++
{
TH0=0X3c;
TL0=0Xb0;
cc++;
if(cc==10)
{
fa=1;
cc=0;
ge++;
if(ge==10)
{
ge=0;
shi++;
if(shi==10)
{
shi=0;
bai++;
if(bai==10)
{
bai=0;
qian++;
if(qian==10)
{
qian=0;
}
}
}
}
}
}
void bb( ) interrupt 3 //定时器1负责读秒--
{
TH1=0X3c;
TL1=0Xb0;
dc++;
if(dc==20)
{
dc=0;
time--;
if(time<=0)
{
ya=1;
TR1=0;
TR0=1;
}
a22=time%1000/100;
a33=time%100/10;
a44=time%10;
}
} |
评分
-
查看全部评分
|