实现要求
前面两位数码管从20~0倒计时,LED全部点亮,记为红灯;随后中间两位数码管倒计时从20~0,LED全部熄灭,记为绿灯;再接着后面两位倒计时从10~0,LED闪烁,记为黄灯,再从红灯开始循环。
如果外加一个外部中断按键,程序立即进入到中间数码管(绿灯)倒计时工作状态(从20s开始倒数)。
模式名称 | 模式代号 | 模式功能描述 |
红灯 | 0 | 从20s倒计时,LED灯常亮 |
绿灯 | 1 | 从20s倒计时,LED灯全灭 |
黄灯 | 2 | 从10s倒计时,LED灯闪烁 |
所含原理
定时器/计数器
定时器/计数器由高8位和低8位两个寄存器组成,本质是加1计数器。加1计数器输入的计数脉冲有两个来源,一个是由系统的时钟振荡器输出脉冲经12分频后送来;另一个是T0或T1引脚输入的外部脉冲源,每来一个脉冲计数器加1,当加到计数器全为1时,再输入一个脉冲就使计数器回零,且计数器的溢出使TCON寄存器中的TF0或TF1置1,向CPU发出中断请求(定时器/计数器中断允许时)。如果定时器/计数器工作于定时器模式,则表示定时时间已到;如果工作于计数模式,则表示计数值已满。设置为定时器模式时,加1计数器是对内部机器周期计数(1个机器周期等于12个振荡周期,即计数频率为晶振频率的1/12)。计数值N乘以机器周期Tcy就是定时时间t 。
中断
中断是为使单片机具有对外部或内部随即发生的事件实时处理而设置的, 51单片机内部一共有5个中断源,也就是说,有五种情况发生时,会使单片机去处理中断程序。对于单片机来讲,中断是指CPU在处理某一事件A时,发生了另一事件B,请求CPU迅速去处理(中断发生);CPU暂时停止当前的工作(中断响应),转去处理事件B(中断服务);待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返回),这一过程称为中断。
引起CPU中断的根源,称为中断源,中断源向CPU提出中断请求,CPU暂时中断原来的事务A,转去处理事件B,对事件B处理完毕后,再回到原来被中断的地方(即断点),称为中断返回。实现上述中断功能的部件称为中断系统(中断机构)。
数码管动态扫描
在这里要实现数码管每一位显示的数字不同,我们可以使用视觉暂留的方法,在很快的时间内,不断的将数码管上面的显示进行切换,如现在第一位上显示数字1之后其它位上不显示,再在第二位上显示数字2其它位上不显示,这样不断的来回切换,便能实现数码管显示12,同理便可在数码管上显示此时的瞬间的时间数值,具体实现在代码中可以看到。在此基础上,在程序中,一个大循环中不断的在数码管上显示数字,利用中断实现数字的变动,便能实现数码管上的数字,随着时间的变化而显示不同的数字。
所用器材
硬件:GTX TX-1C开发板
软件:Windows操作系统,Keil软件,STC烧写软件。
展示效果
相关代码
#include<reg52.h>
#include<intrins.h>
sbit buzz = P2 ^ 3;
sbit b5 = P3 ^ 7;
sbit b4 = P3 ^ 6;
sbit u1 = P2 ^ 6;
sbit u2 = P2 ^ 7;
unsigned char code table[] = { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0xff };
unsigned char code opt[] = { 0xff,0xdf,0xef,0xf7,0xfb,0xfd,0xfe };
unsigned int flag = 0; flag1 = 1; flag2 = 0, flag3 = 0;
int _1, _2, _3, _4, _5, _6;//数码管的数字
int a, b, c, d, e, f;//判断数码管每位是否亮灭
unsigned int num = 20, num_ = 6;
//延迟快
void delay1() {
unsigned int j, i;
for (i = 20; i > 0; i--)
for (j = 10; j > 0; j--);
}
//延迟
void delay(int i) {
unsigned int j;
for (; i > 0; i--)
for (j = 110; j > 0; j--);
}
//判断按键
int key() {
if (b5 == 0) {
delay(5);
if (b5 == 0) {
while (!b5);
return 1;
}
}
return 0;
}
//判断按键
int key1() {
if (b4 == 0) {
delay(5);
if (b4 == 0) {
while (!b4);
return 1;
}
}
return 0;
}
//数码管初始化
void init() {
u2 = 1;
P0 = 0xff;
u2 = 0;
P0 = 0x0;
u1 = 1;
P0 = 0x0;
u1 = 0;
}
//显示
void display(int a, int b, int c, int d, int e, int f, int _1, int _2, int _3, int _4, int _5, int _6) {
if (a == 1) {
u1 = 1;
P0 = table[_1];
u1 = 0;
P0 = 0xff;
u2 = 1;
P0 = opt[1];
u2 = 0;
delay1();
}
if (b == 1) {
u1 = 1;
P0 = table[_2];
u1 = 0;
P0 = 0xff;
u2 = 1;
P0 = opt[2];
u2 = 0;
delay1();
}
if (c == 1) {
u1 = 1;
P0 = table[_3];
u1 = 0;
P0 = 0xff;
u2 = 1;
P0 = opt[3];
u2 = 0;
delay1();
}
if (d == 1) {
u1 = 1;
P0 = table[_4];
u1 = 0;
P0 = 0xff;
u2 = 1;
P0 = opt[4];
u2 = 0;
delay1();
}
if (e == 1) {
u1 = 1;
P0 = table[_5];
u1 = 0;
P0 = 0xff;
u2 = 1;
P0 = opt[5];
u2 = 0;
delay1();
}
if (f == 1) {
u1 = 1;
P0 = table[_6];
u1 = 0;
P0 = 0xff;
u2 = 1;
P0 = opt[6];
u2 = 0;
delay1();
}
}
//模式交换
void swap(unsigned int x) {
if (x == 1) {
flag1 = 1;
_1 = 10; _2 = 10; _3 = 10; _4 = 10; _5 = 0; _6 = 2;
a = 0; b = 0; c = 0; d = 0; e = 1; f = 1;
P1 = 0x00; ET1 = 0; TR1 = 0;
}
if (x == 2) {
flag1 = 2;
_1 = 10; _2 = 10; _3 = 0; _4 = 2; _5 = 10; _6 = 10;
a = 0; b = 0; c = 1; d = 1; e = 0; f = 0;
P1 = 0xff; ET1 = 0; TR1 = 0;
}
if (x == 3) {
flag1 = 3;
_1 = 0; _2 = 1; _3 = 10; _4 = 10; _5 = 10; _6 = 10;
a = 1; b = 1; c = 0; d = 0; e = 0; f = 0;
ET1 = 1; TR1 = 1;
}
}
//时间中断
void jishi() interrupt 1{
num--;
if (num == 0) {
num = 20;
flag2 = 1;
}
}
//时间中断
void shanshuo() interrupt 3{
num_--;
if (num_ == 3) {
P1 = 0xff;
}
if (num_ == 0) {
num_ = 6;
P1 = 0x00;
}
}
//外部中断
void exter0() interrupt 0{
swap(2);
}
//中断的初始化
void init_() {
flag = 0;
TMOD = 0x11;
TH0 = (65536 - 45872) / 256; TH0 = (65536 - 45872) % 256;
TH1 = (65536 - 45872) / 256; TH1 = (65536 - 45872) % 256;
EA = 1; ET0 = 1; TR0 = 1; EX0 = 1; IT0 = 1;
swap(1);
}
void main() {
while (1) {
//判读是否进入功能
flag = key();
if (flag) {
//中断初始化
init_();
while (1) {
display(a, b, c, d, e, f, _1, _2, _3, _4, _5, _6);
init();
//判断是否按键按下
flag = key();
if (flag == 1) {
flag = 0;
P1 = 0xff;
ET0 = 0; TR0 = 0;
ET1 = 0; TR1 = 0;
EX0 = 0; IT0 = 0;
break;
}
//判断是否直接进入绿灯
init();
flag3 = key1();
if (flag3 == 1) {
flag3 = 0;
swap(2);
}
//过了1s
if (flag2 == 1) {
if (flag1 == 1) { //红灯
_5--;
if (_5 < 0) {
_5 = 9;
_6--;
if (_6 < 0) {
swap(2);//切换成绿灯
}
}
}
if (flag1 == 2) { //绿灯
_3--;
if (_3 < 0) {
_3 = 9;
_4--;
if (_4 < 0) {
swap(3);// 切换成黄灯
}
}
}
if (flag1 == 3) { //黄灯
_1--;
if (_1 < 0) {
_1 = 9;
_2--;
if (_2 < 0) {
swap(1);//切换成红灯
}
}
}
flag2 = 0;
}
}
}
}
}