运用知识:
按键消抖,动态数码管显示,模块化编程,矩阵键盘(原来用不到,看任务里是s1,s2以为是矩阵键盘),定时器
任务分析:
概述:通过按键 S1,S2,S3,S4 能够控制 89c52 单片机的工作模式,每次按下 S1 按键时,单片机进入模式一;按下 S2 按键时,单片机进入模式二;按下 S3 按键时,单片机进入模式三;按下 S4 按键时,单片机进入模式四。四个不同的模式下,89c52 单片机的数码管和 LED 灯有不同的工作状态。
模式1:
仅运用到动态数码管显示的内容即可
模式2:
在这个模式中,需要计时每次的间隔,但是变化的时候数码管不可熄灭(最好不要),因此需要用到定时器的功能。每隔1秒显示加1,到10之后重置为0
模式3:
与模式二一样,不干扰原数码管显示,仅需给那两个短横线加个定时器即可
模式4:
先判断是否是第一次按下s4,是的话切换模式,不是的话就在原基础上加1,如果切换到其他模式,再把判断的变量置零
细节点:
切换模式时会使整体熄灭,是按键消抖中的while循环导致的,解决方案是将显示部分的代码放进while循环里面
代码:
主函数代码:
#include <REGX52.H>
#include <INTRINS.H>
#include "tool.h"
unsigned int jud1=1,jud2=1,jud3=1;//用于u2、u3、u4初始化
unsigned int a=0,b=0;//用于u2计数
unsigned int f=0;//用于判断模式
unsigned int c=11;//用于u3短横线
unsigned int d=0;//用于u4计数
void main(){
while(1){
f=flag_judge();
if(f==1){
Nixie(1,10);
Nixie(2,1);
Nixie(7,0);
Nixie(8,1);
if(P3_0==0||P3_2==0||P3_3==0){
Delay(20);
while(P3_0==0||P3_2==0||P3_3==0){
Nixie(1,10);
Nixie(2,1);
Nixie(7,0);
Nixie(8,1);
f=flag_judge();
}
Delay(20);
}
}
if(f==2){
//只初始化一次
if(jud1==1){
Timer0_Init();
a=0;
b=0;
jud1=0;
}
Nixie(1,10);
Nixie(2,2);
Nixie(7,b);
Nixie(8,a);
if(P3_1==0||P3_2==0||P3_3==0){
Delay(20);
while(P3_1==0||P3_2==0||P3_3==0){
Nixie(1,10);
Nixie(2,2);
Nixie(7,b);
Nixie(8,a);
f=flag_judge();
jud1=1;
}
Delay(20);
}
}
if(f==3){
if(jud2==1){
Timer1_Init();
jud2=0;
}
Nixie(1,10);
Nixie(2,3);
Nixie(5,c);
Nixie(6,c);
Nixie(7,0);
Nixie(8,3);
if(P3_1==0||P3_0==0||P3_3==0){
Delay(20);
while(P3_1==0||P3_0==0||P3_3==0){
Nixie(1,10);
Nixie(2,3);
Nixie(5,c);
Nixie(6,c);
Nixie(7,0);
Nixie(8,3);
f=flag_judge();
jud2=1;
}
Delay(20);
}
}
if(f==4){
if(jud3==1){
jud3=0;
d=0;
}
Nixie(1,10);
Nixie(2,4);
Nixie(7,d);
Nixie(8,d);
if(P3_3==0){
Delay(20);
while(P3_3==0){
Nixie(1,10);
Nixie(2,4);
Nixie(7,d);
Nixie(8,d);
}
Delay(20);
d++;
if(d==10) d=0;
}
if(P3_1==0||P3_0==0||P3_2==0){
Delay(20);
while(P3_1==0||P3_0==0||P3_2==0){
Nixie(1,10);
Nixie(2,4);
Nixie(7,d);
Nixie(8,d);
f=flag_judge();
jud3=1;
}
Delay(20);
}
}
}
}
//定时器0
void Timer0_Routine() interrupt 1
{
static unsigned int T0count; //计数
TL0 = 0x66;
TH0 = 0xFC;
T0count++;
if(T0count>=1000){ //定时为1s
T0count=0;
if (a <= 9 && b == 0) { a++; }
else if (a == 0 && b == 1) { a = 0; b = 0; }
if(a == 10 && b == 0) { a = 0; b = 1; }
}
}
//定时器1
void Timer1_Routine() interrupt 3
{
static unsigned int T1count;
TL1 = 0x66; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
T1count++;
if(T1count>=500){
T1count=0;
if(c==11){
c=12;
}else{
c=11;
}
}
}
tool.c代码:
#include <REGX52.H>
#include <INTRINS.H>
//延时函数
void Delay(unsigned int ms) //@11.0592MHz
{
unsigned char data i, j;
while(ms--){
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
//10是U,11是-,12是不显示
unsigned char Nixie_arr[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x3E,0x40,0x00};
//数码管显示
void Nixie(unsigned char location, num){
switch(location){
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=Nixie_arr[num];
//消影
Delay(1);
P0=0x00;
}
//定时器0配置
void Timer0_Init(void) //1毫秒@11.0592MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x66; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
PT0=0;
}
//定时器1配置
void Timer1_Init(void) //1毫秒@11.0592MHz
{
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x10; //设置定时器模式
TL1 = 0x66; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1=1;
EA=1;
PT0=0;
}
//按键检测
unsigned int fg=0;
unsigned int flag_judge(){
if(P3_1==0) fg=1;
if(P3_0==0) fg=2;
if(P3_2==0) fg=3;
if(P3_3==0) fg=4;
return fg;
}
tool.h代码:
#ifndef __TOOL__H__
#define __TOOL__H__
void Delay(unsigned int ms);
void Nixie(unsigned char location, num);
void Timer0_Init(void);
unsigned int flag_judge();
void Timer1_Init(void);
#endif