记一次实践
题目要求:
电路图:
代码:
头文件
#ifndef traffic_h
#define traffic_h
#include <reg52.h>
#define LedD P0 //段选
#define LedC P2 //位选
sbit red=P1^2;
sbit yellow=P1^1;
sbit green=P1^0;
unsigned char t=0; //当前秒数,数码管显示时间的初值
unsigned char j=0; //闪烁位的延时参数
unsigned char key1=0,key2=0; //两个中断按键
unsigned int i=0; //计数器计数参数
//显示采用的是共阴极数码管
unsigned char num[] = {0,0}; /* 时钟待显示字符对应key值*/
code unsigned char wx[] = {0xfe,0xfd}; //数码管地址(位选)
code unsigned char dx[] = {0x3f,0x06,0x5b,0x4f,0x66, /* 0-9数字的编码 (段选)*/
0x6d,0x7d,0x07,0x7f,0x6f};
void init(); //初始化
void delay(unsigned char); //延时函数
void display(); //数码管显示
void count(); //计数(计时)
void transform(); //将秒的个位十位分离并转换
void twinkle(); //数码管某一位闪烁
void clear(); //重置led状态
void int0(); //外部中断0
void int1(); //外部中断1
#endif
c文件
#include "traffic.h"
void main(void)
{
init();
while(1)
{
if(key1) //紧急通行
{
twinkle(); //数码管00闪烁
red=~red; //数值取反 red=-red
}
else if(key2) //夜间通行
{
twinkle();
yellow=~yellow;
}
else
display();
}
}
void init(void) /*初始化*/
{
red=0;
yellow=0;
green=0; //灭掉红绿黄灯
EA=1; //总中断
ET1=1; //开启定时器1中断
TR1=1; //开启定时器1
TMOD=0x20; //定时器1,工作方式2,八位自动重装载
TH1=156;
TL1=156; //一次中断需 0.1ms
EX0=1; //打开外部中断0、1
EX1=1;
IT0=1; //下降沿(按键按下时高电平到低电平的一瞬间)触发中断
IT1=1;
}
void clear() //重置函数
{
red=0;
yellow=0;
green=0; //灭掉红绿黄灯
t=0; //计时清零
}
void display() //字符显示
{
unsigned char i;
for(i=0; i<2; i++) //i<2 是因为数码管只有两位,即i取值0,1足够
{
LedC = wx[i]; /* 选通某一位数码管,例如i=0,即选通第0位 */
LedD = dx[num[i]]; /* 通过码表数组将第i位要显示的数字转换成数码管能识别的编码 */
delay(10); /* 微量延时,用于显示保持 */
LedD=0x00; //消隐
}
}
void transform() //数位转换
{
if(t>0&&t<11) //红灯时的倒计时
{
num[0]=(11-t)/10; //十位
num[1]=(11-t)%10; //个位
}
else if(t>10&&t<14) //黄灯时的倒计时
{
num[0]=(14-t)/10; //十位
num[1]=(14-t)%10; //个位
}
else if(t>13) //绿灯时的倒计时
{
num[0]=(24-t)/10; //十位
num[1]=(24-t)%10; //个位
}
}
void twinkle() //数码管00闪烁
{
j%=100; //j<50
if(j<50) //j<25时,数码管亮
{
delay(20);
LedC=0xfc; //两位数码管一起选中 1111 1100
LedD=dx[0]; //显示0
}
else //j>=25,数码管不亮
{
delay(20);
LedC=0xff; //数码管都不选通
}
j++;
}
void int0() interrupt 0 //紧急通行 红灯 00闪烁 外部中断0服务函数
{
key1++;
key1%=2; //key1取值0、1
clear(); //排除干扰
}
void int1() interrupt 2 //夜间 黄灯 00闪烁 外部中断1服务函数
{
key2++;
key2%=2; //key2取值0、1
clear();
}
void count() interrupt 3 //计时 定时器1中断服务函数
{
if(key1||key2)
return; //若正在紧急状态,则直接回到主函数,不执行下列语句
i++;
if(i==10000) //0.1ms*10000=1s
{
t++; //秒数+1
transform();
i%=10000; //i每次余10000,确保i的值处于0-100之间,避免溢出
if(t==1)
{
red=1;
yellow=0;
green=0;
}
else if(t==11)
{
red=0;
yellow=1;
green=0;
}
else if(t==14)
{
red=0;
yellow=0;
green=1;
} //t记录当前秒数
t%=23;
}
}
void delay(unsigned char t) //延时
{
unsigned char i,j;
for(i=0; i<20; i++)
for(j=0; j<t; j++);
}
运行结果: