深入浅出玩转51单片机——学习笔记:数码管时间显示+调时功能
0赞
发表于 5/23/2014 9:11:16 AM
阅读(4508)
/**********************************************
实现功能:数码管时间显示+调时功能(按键只具备单击功能)
时间初始值:12:34:56
Key1未按下,Key2、Key3按下无效
当Key1第一次按下,可以调整秒时间(Key2按下,秒加1;Key3按下,秒减1)
当Key1第二次按下,可以调整分时间(Key2按下,分加1;Key3按下,分减1)
当Key1第三次按下,可以调整时时间(Key2按下,时加1;Key3按下,时减1)
当Key1第四次按下,时间正常运行
硬件平台:基于MGMC-V1.0实验板
晶振频率:11.0592Mhz
时间:2014年5月16日
***********************************************/
#include<reg52.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
sbit We_En = P1^6; //定义数码管位选
sbit Du_En = P1^7; //定义数码管段选
uint8 Key_Return = 0; //返回的按键键值
uint8 j = 0;
sbit Key1 = P3^4;
sbit Key2 = P3^5;
sbit Key3 = P3^6;
#define Initial_State 0 //按键初始状态
#define Affirm_State 1 //按键消抖状态
#define Signel_State 2 //按键松手确认状态
uint8 Bit_Tab[8] = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //数码管位选
uint8 SEG_Tab[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f}; //数码管段选
char time[3];
uint8 Dis_Buff[6];
uint8 We_Cnt = 0;
uint8 time_2ms_ok = 0; //2ms时间到标志位
uint8 time_1s_ok = 0; //1s时间到标志位
uint8 time_10ms_ok = 0; //10ms时间到标志位
uint16 i = 0;
void initial_myself(); //上电初始化
void initial_peripheral(); //外围设备初始化
void Dleay_Ms(uint16 z);
void Dis_Buffer(); //时间分离函数
void SEG_Display(); //数码管刷新函数
void Time_Service(); //时间计时函数
char Key_Scan(); //按键扫描函数
void Key_Service(); //按键调整时间函数
void main()
{
initial_myself(); //上电初始化
Dleay_Ms(10);
initial_peripheral(); //外围设备初始化
time[0] = 56;
time[1] = 34;
time[2] = 12; //设置时间为:12:34:56
while(1)
{
if(1 == time_10ms_ok) //10ms时间到
{
time_10ms_ok = 0;
Key_Scan(); //按键扫描
}
Dis_Buffer(); //时间分离函数
SEG_Display(); //数码管刷新函数
Time_Service(); //时间计时函数
Key_Service(); //按键调整时间函数
}
}
void Time_Service() //时间计时函数
{
if(1 == time_1s_ok) //1s时间到
{
time_1s_ok = 0;
if(++time[0] >= 60)
{
time[0] = 0;
if(++time[1] >= 60)
{
time[1] = 0;
if(++time[2] >= 24)
{
time[2] = 0;
}
}
}
}
}
void SEG_Display() //数码管刷新函数
{
if(1 == time_2ms_ok) //2ms时间到
{
time_2ms_ok = 0;
switch(We_Cnt)
{
case 0: //刷新第一个数码管
{
Du_En = 1; P0 = 0x00; Du_En = 0;
We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
P0 = 0x00;
Du_En = 1; P0 = SEG_Tab[Dis_Buff[0]]; Du_En = 0;
We_Cnt++;
}
break;
case 1: //刷新第二个数码管
{
Du_En = 1; P0 = 0x00; Du_En = 0;
We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
P0 = 0x00;
Du_En = 1; P0 = SEG_Tab[Dis_Buff[1]]; Du_En = 0;
We_Cnt++;
}
break;
case 2: //刷新第三个数码管
{
Du_En = 1; P0 = 0x00; Du_En = 0;
We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
P0 = 0x00;
Du_En = 1; P0 = 0x40; Du_En = 0;
We_Cnt++;
}
break;
case 3: //刷新第四个数码管
{
Du_En = 1; P0 = 0x00; Du_En = 0;
We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
P0 = 0x00;
Du_En = 1; P0 = SEG_Tab[Dis_Buff[2]]; Du_En = 0;
We_Cnt++;
}
break;
case 4: //刷新第五个数码管
{
Du_En = 1; P0 = 0x00; Du_En = 0;
We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
P0 = 0x00;
Du_En = 1; P0 = SEG_Tab[Dis_Buff[3]]; Du_En = 0;
We_Cnt++;
}
break;
case 5: //刷新第六个数码管
{
Du_En = 1; P0 = 0x00; Du_En = 0;
We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
P0 = 0x00;
Du_En = 1; P0 = 0x40; Du_En = 0;
We_Cnt++;
}
break;
case 6: //刷新第七个数码管
{
Du_En = 1; P0 = 0x00; Du_En = 0;
We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
P0 = 0x00;
Du_En = 1; P0 = SEG_Tab[Dis_Buff[4]]; Du_En = 0;
We_Cnt++;
}
break;
case 7: //刷新第八个数码管
{
Du_En = 1; P0 = 0x00; Du_En = 0;
We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
P0 = 0x00;
Du_En = 1; P0 = SEG_Tab[Dis_Buff[5]]; Du_En = 0;
We_Cnt = 0;
}
break;
}
}
}
void Dis_Buffer() //时间分离函数
{
Dis_Buff[0] = time[0]%10; //秒个位
Dis_Buff[1] = time[0]/10; //秒十位
Dis_Buff[2] = time[1]%10; //分个位
Dis_Buff[3] = time[1]/10; //分十位
Dis_Buff[4] = time[2]%10; //时个位
Dis_Buff[5] = time[2]/10; //时十位
}
void initial_myself() //上电初始化
{
P0 = 0xff;
P3 = 0xff;
We_En = 0; //关位选
Du_En = 0; //关段选
TMOD &= 0x00;
TMOD |= 0x01; // 定时器0,模式1
TMOD |= 0x10; // 定时器1,模式1
TH0 = 0xf8; //设置初值,没2ms进入一次中断
TL0 = 0xcd;
TH1 = 0xdc; //设置初值,没10ms进入一次中断
TL1 = 0x00;
}
void initial_peripheral() //外围设备初始化
{
EA = 1; //开总中断
ET0 = 1; //使能T0中断
TR0 = 1; //使能T0
ET1 = 1; //使能T1中断
TR1 = 1; //使能T1
}
void T0_interrupt() interrupt 1 //定时器0中断函数
{
TF0 = 0;
TH0 = 0xf8;
TL0 = 0xcd;
time_2ms_ok = 1; //2ms时间到
if(++j >= 5)
{
j = 0;
time_10ms_ok = 1; //10ms时间到
}
}
void T1_interrupt() interrupt 3 //定时器1中断函数
{
TF1 = 0;
TH1 = 0xdc;
TL1 = 0x00;
if(++i >= 100)
{
i = 0;
time_1s_ok = 1; //1s时间到
}
}
void Dleay_Ms(uint16 z)
{
uint16 x,y;
for(x = 0; x < z; x++)
for(y = 0; y < 100; y++);
}
char Key_Scan()
{
static uint8 Key_State = 0;
uint16 Key_Valve;
Key_Valve = (Key1&Key2&Key3);
switch(Key_State)
{
case Initial_State : //按键初始状态
{
if(Key_Valve != 1)
{
Key_State = Affirm_State;
}
}
break;
case Affirm_State : //按键消抖状态
{
if(Key_Valve != 1)
{
if(0 == Key1)
{
Key_Return = 1;
}
if(0 == Key2)
{
Key_Return = 2;
}
if(0 == Key3)
{
Key_Return = 3;
}
Key_State = Signel_State; //转到松手检测
}
else
{
Key_State = Initial_State; //转到初始状态
}
}
break;
case Signel_State : //按键松手检测
{
if(1 == Key_Valve)
{
Key_State = Initial_State;
}
}
break;
}
return 0;
}
void Key_Service()
{
static uint8 Key_Num = 0;
if(1 == Key_Return) // Key1按下
{
Key_Return = 0;
TR1 = 0; //关定时器1,时间停止计数
Key_Num++; //Key1按下次数
}
switch(Key_Num)
{
case 1: //Key1按下1次,秒调整状态
{
if(2 == Key_Return) //Key2按下,秒时间加1;
{
Key_Return = 0;
time[0]++;
if(time[0] > 59)
{
time[0] = 0;
}
}
if(3 == Key_Return) //Key3按下,秒时间减1
{
Key_Return = 0;
time[0]--;
if(time[0]<0)
{
time[0] = 59;
}
}
}
break;
case 2: //Key1按下2次,分钟调整状态
{
if(2 == Key_Return) //Key2按下,分时间加1;
{
Key_Return = 0;
time[1]++;
if(time[1] > 59)
{
time[1] = 0;
}
}
if(3 == Key_Return) //Key3按下,分时间减1
{
Key_Return = 0;
time[1]--;
if(time[1]<0)
{
time[1] = 59;
}
}
}
break;
case 3: //Key1按下3次,小时调整状态
{
if(2 == Key_Return) //Key2按下,小时时间加1;
{
Key_Return = 0;
time[2]++;
if(time[2] > 24)
{
time[2] = 0;
}
}
if(3 == Key_Return) //Key3按下,小时时间减1
{
Key_Return = 0;
time[2]--;
if(time[2]<0)
{
time[2] = 24;
}
}
}
break;
case 4: //Key1按下4次,时间运行确认
{
Key_Num = 0;
TR1 = 1;
}
break;
}
}
