|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
#include<reg52.h>
typedef unsigned char u8;
typedef unsigned int u16;
sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
unsigned char code LedChar[]={ //数码管显示字符转换表
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71
};
unsigned char Ledbuff[6] = { //数码管显示缓冲区
0x00,0x00,0x00,0x00,0x00,0x00
};
unsigned char KeySta[4]={ //按键当前状态
1,1,1,1
};
u8 T0RH = 0;
u8 T0RL = 0;
bit StopwatchRefresh=1; //秒表计数刷新标志
bit StopwatchRunning=0; //秒表运行标志
u8 DecimalPart = 0; //小数部分定义
u16 IntegerPart = 0; //整数部分定义
void ConfigTimer0(u16 ms);
void KeyDriver();
void StopwatchDisplay();
void main(void)
{
EA=1;
ConfigTimer0(2); //定时器周期函数
while(1)
{
if(StopwatchRefresh)
{
StopwatchRefresh=0; //秒表状态位
StopwatchDisplay(); //秒表显示函数
}
KeyDriver(); //按键驱动函数
}
}
void ConfigTimer0(u16 ms)
{
unsigned long tmp;
tmp=12000000/12;
tmp=(tmp*ms)/1000;
tmp=65536-tmp;
T0RH=(u8)(tmp>>8);
T0RL=(u8)tmp;
TMOD&=0XF0;
TMOD|=0X01;
TH0=T0RH;
TL0=T0RL;
ET0=1;
TR0=1;
}
void StopwatchDisplay()
{
signed char i;
u8 buf[4]; //数据转换的缓冲区
//小数部分转换到低2位
Ledbuff[0] = LedChar[DecimalPart%10];
Ledbuff[1] = LedChar[DecimalPart/10];
//整数部分转换到高4位
buf[0] = IntegerPart%10;
buf[1] = (IntegerPart/10)%10;
buf[2] = (IntegerPart/100)%10;
buf[3] = (IntegerPart/1000)%10;
for(i=3;i>1;i--) //整数部分高位的0 转换为空字符
{
if(buf[i] == 0)
{
Ledbuff[i+2] = 0xfe;
}
else
break;
}
for(;i>0;i--) //有效数字位转换为显示字符
{
Ledbuff[i+2] = LedChar[buf[i]];
}
Ledbuff[2] &= 0x7f; //点亮小数点
}
/*秒表启停函数*/
void StopwatchAction()
{
if(StopwatchRunning) //已启动则停止
StopwatchRunning = 0;
else //未启动则启动
StopwatchRunning = 1;
}
/* 秒表复位函数 */
void StopwatchReset()
{
StopwatchRunning = 0; //停止秒表
DecimalPart = 0; //清零计数值
IntegerPart = 0;
StopwatchRefresh =1; //置刷新标志
}
/* 按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用 */
void KeyDriver()
{
u8 i;
static u8 backup[4] = {1,1,1,1}; //按键上一次的状态
for(i=0;i<4;i++) //循环检测4个按键
{
if(backup[i]!= KeySta[i]) //按键状态改变
{
if(backup[i] != 0) //按键按下
{
if(i == 1) //Key1键复位秒表
StopwatchReset();
if( i== 2) //Key2键启停秒表
StopwatchAction();
}
backup[i] = KeySta[i]; //刷新前一次的备份值
}
}
}
/* 秒表计数函数,每隔10ms 调用一次进行秒表计数累加 */
void StopwatchCount()
{
if(StopwatchRunning) //当处于运行状态时递增计数值
{
DecimalPart++; //小数部分+1
if(DecimalPart >= 100) //小数部分计到100 时进位到整数部分
{
DecimalPart = 0;
IntegerPart++; //整数部分+1
if(IntegerPart >= 10000)
{
IntegerPart = 0;
}
}
StopwatchRefresh = 1;
}
}
/* 数码管动态扫描刷新函数,需在定时中断中调用 */
void LedScan()
{
static u8 i;
P0=0X00;
switch(i)
{
case 0:LSA=0;LSB=0;LSC=0;i++;P0=Ledbuff[0];break;
case 1:LSA=1;LSB=0;LSC=0;i++;P0=Ledbuff[1];break;
case 2:LSA=0;LSB=1;LSC=0;i++;P0=Ledbuff[2];break;
case 3:LSA=1;LSB=1;LSC=0;i++;P0=Ledbuff[3];break;
case 4:LSA=0;LSB=0;LSC=1;i++;P0=Ledbuff[4];break;
case 5:LSA=1;LSB=0;LSC=1;i++;P0=Ledbuff[5];break;
default:break;
}
}
/* 按键扫描函数,需在定时中断中调用 */
void KeyScan()
{
u8 i;
static u8 keybuf[4] = { //按键扫描初始化
0xFF,0xFF,0xFF,0xFF
};
//按键值移入缓冲区
keybuf[0] = (keybuf[0] << 1) | KEY1;
keybuf[1] = (keybuf[1] << 1) | KEY2;
keybuf[2] = (keybuf[2] << 1) | KEY3;
keybuf[3] = (keybuf[3] << 1) | KEY4;
//消抖后更新按键状态
for(i=0;i<4;i++)
{
if(keybuf[i] == 0x00) //连续8次扫描为0,即16ms内都是弹起状态,可认为按键已按下
KeySta[i]=0;
else if(keybuf[i] == 0xFF) //连续8次扫描为1,即16ms内都是按下状态,可认为按键已按下
KeySta[i]=1;
}
}
/*中断服务函数,完成数码管,按键扫描与秒表计数*/
void Timer0() interrupt 1
{
static unsigned char tmr10ms;
TH0 = T0RH;
TL0 = T0RL;
LedScan(); //数码管显示
KeyScan(); //按键扫描
tmr10ms++;
if(tmr10ms >= 5)
{
tmr10ms = 0;
StopwatchCount(); //调用秒表计数函数
}
}
|
|