#include"at89x51.h"
unsigned char num[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //数字0~9
unsigned char ctr[]={0xfa,0xf5}; //0xfa(P3_0和P3_2为0,即高位有效)0xf5(P3_1和P3_3为0,即低位有效)
unsigned char disEW[2]; //记录东西向高低位数值
unsigned char disSN[2]; //记录南北向高低位数值
unsigned char v;
unsigned char cnt_ctr;
unsigned int scdEW,scdSN;
unsigned int cntSN,cntEW;
unsigned char cntP3_4,cntP3_5,cntP3_6;
unsigned int cnt_num,cnt_key,cnt_flash,keyMemory;
int greenEW = 20,yellowEW = 3,greenSN = 25,yellowSN = 5;
//延时函数,a为1延时1毫秒
void delay_ms(unsigned int a)
{
int i;
while(a--)
{
i = 70;
while(i--);
}
}
//设置红绿黄灯秒数
void setSecond(void)
{
while(P3_4 == 0);
cntP3_4++; //标志设置键被按下的次数
switch(cntP3_4)
{
case 1:
cntEW = 5;
P1 = 0xf7;
break;
case 2:
cntEW = 1;
P1 = 0xef;
break;
case 3:
cntSN = 1;
P1 = 0xfe;
break;
case 4:
cntSN = 3;
P1 = 0xfd;
break;
case 5:
cntEW = 5;
cntSN = 5;
cnt_num = 0;
cntP3_4 = 0;
break;
}
}
//秒数加1
void addSecond(void)
{
while(P3_5 == 0);
cnt_key = 0; //记录长按键的参数清零
switch(cntP3_4)
{
case 1:
if(keyMemory != greenEW + 10) //判断按键是否已经加10,如果没有加10则秒数加1,如果已经加10则不加1
{
greenEW++;
}
if(greenEW == 90)
{
greenEW = 0;
}
scdEW = greenEW;
scdSN = greenEW + yellowEW + 1;
break;
case 2:
if(yellowEW++ == 9)
{
yellowEW = 0;
}
scdEW = yellowEW;
break;
case 3:
if(keyMemory != greenSN + 10)
{
greenSN++;
}
if( greenSN == 90)
{
greenSN = 0;
}
scdEW = greenSN + yellowSN + 1;
scdSN = greenSN;
break;
case 4:
if(yellowSN++ == 9)
{
yellowSN = 0;
}
scdSN = yellowSN;
break;
}
}
//秒数减1
void subSecond(void)
{
while(P3_6 == 0);
cnt_key = 0; //记录长按键的参数清零
switch(cntP3_4)
{
case 1:
if(keyMemory != greenEW - 10) //判断按键是否已经减10,如果没有减10则秒数减1,如果已经减10则不减1
{
greenEW--;
}
if(greenEW == -1)
{
greenEW = 89;
}
scdEW = greenEW;
scdSN = greenEW + yellowEW + 1;
break;
case 2:
if(yellowEW-- == 0)
{
yellowEW = 9;
}
scdEW = yellowEW;
break;
case 3:
if(keyMemory != greenSN - 10)
{
greenSN--;
}
if(greenSN == -1)
{
greenSN = 89;
}
scdEW = greenSN + yellowSN + 1;
scdSN = greenSN;
break;
case 4:
if(yellowSN-- == 0)
{
yellowSN = 9;
}
scdSN = yellowSN;
break;
}
}
//正常显示秒数
void display(void)
{
cnt_num++;
if(cnt_ctr == 10)
{
cnt_ctr = 0;
P3 = 0xff;
P3 = ctr[v];
P2 = num[disEW[v]]; //显示东西方向秒数
P0 = num[disSN[v]]; //显示南北方向秒数
if(v++ == 1)
{
v = 0;
}
}
}
//闪烁显示秒数
void dspFlash(void)
{
cnt_flash++;
if(cnt_flash < 660)
{
P3 = 0xff;
//数码管灭
}
else
{
if(cnt_flash == 1333)
//数码管亮 1333=4000/3 即1秒闪3次
{
cnt_flash = 0;
}
if(cnt_ctr == 25)
{
cnt_ctr = 0;
P3 = 0xff;
P3 = ctr[v];
switch(cntP3_4)
{
case 1:
P3_0 = 1;
P3_1 = 1;
P2 = num[disEW[v]];
break;
case 2:
P3_0 = 1;
P3_1 = 1;
P2 = num[disEW[v]];
break;
case 3:
P3_2 = 1;
P3_3 = 1;
P0 = num[disSN[v]];;
break;
case 4:
P3_2 = 1;
P3_3 = 1;
P0 = num[disSN[v]];
break;
}
if(v++ == 1)
{
v = 0;
}
}
}
}
//长按加10秒
void add_10s(void)
{
cnt_key = 0;
switch(cntP3_4)
{
case 1:
greenEW = greenEW + 10; //长按秒数加10
if(greenEW >= 90)
{
greenEW = 0;
}
keyMemory = greenEW + 10; //keyMemory用来标记秒数已经加10
scdEW = greenEW;
scdSN = greenEW + yellowEW + 1;
break;
case 3:
greenSN = greenSN + 10;
if(greenSN >=90)
{
greenSN = 0;
}
keyMemory = greenSN + 10;
scdEW = greenSN + yellowSN + 1;
scdSN = greenSN;
break;
}
}
//长按减10秒
void sub_10s(void)
{
cnt_key = 0;
switch(cntP3_4)
{
case 1:
greenEW = greenEW - 10; //长按秒数减10
if(greenEW < 0)
{
greenEW = 89;
}
keyMemory = greenEW - 10; //keyMemory用来标记秒数已经减10
scdEW = greenEW;
scdSN = greenEW + yellowEW + 1;
break;
case 3:
greenSN = greenSN - 10;
if(greenSN < 0)
{
greenSN = 89;
}
keyMemory = greenSN - 10;
scdEW = greenSN + yellowSN + 1;
scdSN = greenSN;
break;
}
}
//T0中断
void t0(void) interrupt 1
{
cnt_ctr++;
if(cntP3_4 == 0)
{
display(); //正常显示秒数
}
if(cntP3_4 != 0)
{
dspFlash(); //闪烁显示秒数
}
if(cnt_num == 4000)
{
cnt_num = 0;
if(scdEW-- == 0)
{
cntEW++; //东西向秒数减至0,标志位加1
}
if(scdSN-- == 0)
{
cntSN++; //南北向秒数减至0,标志位加1
}
}
switch(cntEW)
{
case 1:
scdEW = yellowEW; //东西向黄灯亮,显示黄灯秒数
P1_3 = 1;
P1_4 = 0;
P1_5 = 1;
cntEW++; //避免程序到此阻塞,故将其至为2
break;
case 3: //避免cntEW为2
scdEW = greenSN + yellowSN + 1; //东西向红灯亮,显示红灯秒数
P1_3 = 1;
P1_4 = 1;
P1_5 = 0;
cntEW++; //避免程序到此阻塞,故将其至为4
break;
case 5: //避免cntEW为4
scdEW = greenEW; //东西向绿灯亮,显示绿灯秒数
P1_3 = 0;
P1_4 = 1;
P1_5 = 1;
cntEW = 0;
break;
}
switch(cntSN)
{
case 1:
scdSN = greenSN; //南北向绿灯亮,显示绿灯秒数
P1_0 = 0;
P1_1 = 1;
P1_2 = 1;
cntSN++; //避免程序到此阻塞,故将其至为2
break;
case 3: //避免cntSN为2
scdSN = yellowSN; //南北向黄灯亮,显示黄灯秒数
P1_0 = 1;
P1_1 = 0;
P1_2 = 1;
cntSN++; //避免程序到此阻塞,故将其至为4
break;
case 5: //避免cntSN为4
scdSN = greenEW + yellowEW + 1; //南北向红灯亮,显示红灯秒数
P1_0 = 1;
P1_1 = 1;
P1_2 = 0;
cntSN = 0;
break;
}
if(P3_5 == 0)
{
if(cnt_key++ == 4000)
{
add_10s(); //长按数码管加10秒
}
}
if(P3_6 == 0)
{
if(cnt_key++ == 4000)
{
sub_10s(); //长按数码管减10秒
}
}
disEW[0] = scdEW/10;
disEW[1] = scdEW%10;
disSN[0] = scdSN/10;
disSN[1] = scdSN%10;
}
//主函数
void main(void)
{
TMOD = 0x02; //设置定时器0为工作方式2
TH0 = 0x06;
TL0 = 0x06; //初始化8位定时器 (256 - 6)*40000 = 1s
EA = 1; //总中断允许
ET0 = 1; //T0中断允许
TR0 = 1; //打开T0中断
P1 = 0xf3; //东西向绿灯,南北向红灯
P3_4 = 1;
scdEW = greenEW; //设置东西向显示秒数
scdSN = greenEW + yellowEW + 1; //设置南北向显示秒数
while(1)
{
if(P3_4 == 0)
{
delay_ms(15);
if(P3_4 == 0)
{
setSecond(); //设置红绿黄灯秒数
}
}
else if(P3_5 == 0)
{
delay_ms(15);
if(P3_5 == 0)
{
addSecond();
}
}
else if(P3_6 == 0)
{
delay_ms(15);
if(P3_6 == 0)
{
subSecond();
}
}
keyMemory = 200; //给keyMemory任意赋值,防止长按加10或减10后不能正常加减
}
}
评论16