仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include<reg52.h>
- sbit KEY1 = P3^0; //计次
- sbit KEY2 = P3^1; //从快到慢显示计次数
- sbit KEY3 = P3^2; //复位
- sbit KEY4 = P3^3; //启停秒表
- unsigned char code LedChar[] = { //数码管显示字符转换表
- 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
- 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
- };
- unsigned char LedBuff[6] = { //数码管显示缓冲区
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
- };
- unsigned char KeySta[4] = {1,1,1,1}; //当前按键状态
- unsigned char T0RH = 0;
- unsigned char T0RL = 0;
- // static unsigned char Dec[10] = 0;
- // static unsigned int Int[10] = 0;
- bit kd = 0;
- bit lk = 1;
- bit stopwatchRefresh = 1;
- bit stopwatchRunning = 0;
- unsigned char DecimalPart = 0;
- unsigned int IntegerPart = 0;
- void ConfigTimer0(unsigned int ms);
- void stopwatchDisplay();
- void KeyDriver();
- void main()
- {
- EA = 1;
- ConfigTimer0(2);
- while(1)
- {
- if(stopwatchRefresh)
- {
- stopwatchRefresh = 0;
- stopwatchDisplay();
- }
- KeyDriver();
- }
- }
- void ConfigTimer0(unsigned int ms)
- {
- unsigned long tmp;
-
- tmp = 11059200/12;
- tmp = (tmp*ms)/1000;
- tmp = 65536 - tmp;
- tmp +=18; //定时误差补偿
-
- T0RH = (unsigned char)(tmp>>8);
- T0RL = (unsigned char)tmp;
- TMOD &=0xf0;
- TMOD |=0X01;
- TH0 = T0RH;
- TL0 = T0RL;
- ET0 = 1;
- TR0 = 1;
- }
- void stopwatchDisplay()
- {
- signed char i;
- unsigned char buf[4];
- LedBuff[0] = LedChar[DecimalPart%10];
- LedBuff[1] = LedChar[DecimalPart/10];
- 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--)
- {
- if(buf[i]==0)
- {
- LedBuff[i+2]=0xFF;
- }else break;
- }
- for(;i>=0;i--)
- {
- LedBuff[i+2] = LedChar[buf[i]];
- }
- LedBuff[2] &=0x7f;
- }
- void Stopwatchjc()
- {
- signed char i;
- unsigned char buf[4];
- static unsigned char Dec[10] = 0;
- static unsigned int Int[10] = 0;
- static char cnt = 0;
- static char cnt1 = 0;
- Dec[cnt] = DecimalPart;
- Int[cnt] = IntegerPart;
- cnt++;
- if(kd == 1)
- {
- LedBuff[0] = LedChar[Dec[cnt1]%10];
- LedBuff[1] = LedChar[Dec[cnt1]/10];
- buf[0] = Int[cnt1]%10;
- buf[1] = Int[cnt1]/10%10;
- buf[2] = Int[cnt1]/100%10;
- buf[3] = Int[cnt1]/1000%10;
- for(i=3;i>=1;i--)
- {
- if(buf[i]==0)
- {
- LedBuff[i+2]=0xFF;
- }else break;
- }
- for(;i>=0;i--)
- {
- LedBuff[i+2] = LedChar[buf[i]];
- }
- LedBuff[2] &=0x7f;
-
- cnt1++;
-
-
- }
-
- }
- void Stopwatchsy()
- {
- stopwatchRunning = 0;
- kd = 1;
- stopwatchRefresh = 1;
- }
- void StopwatchAction()
- {
- stopwatchRunning = ~stopwatchRunning;
- }
- void StopwatchReset()
- {
- stopwatchRunning = 0;
- lk = 0;
-
- DecimalPart = 0;
- IntegerPart = 0;
- stopwatchRefresh = 1;
- }
- void KeyDriver() //按键驱动函数
- {
- static unsigned char backup[4] = {1,1,1,1}; //按键值备份,保存前一次的扫描值
- unsigned char i;
- for(i=0;i<4;i++)
- {
- if (KeySta[i] != backup[i]) //当前值与前次值不相等说明此时按键有动作
- {
- if (backup[i] == 0) //如果前次值为0,则说明当前是弹起动作
- {
- if(i==0)
- Stopwatchjc(); //计次
- else if(i==1)
- Stopwatchsy(); //从快到慢
- else if(i==2) //复位
- StopwatchReset();
- else if(i==3) //启停秒表
- StopwatchAction();
-
- }
- backup[i] = KeySta[i]; //更新备份为当前值,以备进行下次比较
- }
- }
- }
- void LedScan()
- {
- static unsigned char i=0;
- P0 = 0xFF;
- switch(i) //每过1ms从低到高位刷新一个数码管
- {
- case 0:P2=0x01;i++; P0= LedBuff[0]; break;
- case 1:P2=0x02;i++; P0= LedBuff[1]; break;
- case 2:P2=0x04;i++; P0= LedBuff[2]; break;
- case 3:P2=0x08;i++; P0= LedBuff[3]; break;
- case 4:P2=0x10;i++; P0= LedBuff[4]; break;
- case 5:P2=0x20;i=0; P0= LedBuff[5]; break;
- default :break;
- }
- }
- void KeyScan()
- {
- static unsigned char keybuf[4] ={ 0xFF,0xFF,0xFF,0xFF}; //扫描缓冲区,保存一段时间内的扫描值
- static unsigned char i=0;
- 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;
- }
- else
- {} //其它情况则说明按键状态尚未稳定,则不对KeySta变量值进行更新
- }
- }
- void StowatchCount()
- {
- if(stopwatchRunning)
- {
- DecimalPart++;
- if(DecimalPart>=100)
- {
- DecimalPart=0;
- IntegerPart++;
- if(IntegerPart>=100) // 10000
- {
- IntegerPart=0;
- }
- }
- stopwatchRefresh=1;
- }
- }
- void InterruptTimer0() interrupt 1
- {
- static unsigned char ter10ms = 0;
- TH0 = T0RH; //重新加载重载值
- TL0 = T0RL;
- LedScan(); //数码管扫描显示
- KeyScan(); //按键扫描
- ter10ms++;
- if (ter10ms>=5)
- {
- ter10ms = 0;
- StowatchCount();
- }
- }
复制代码
仿真程序:
秒表记次+数码管+51+按键.7z
(63.29 KB, 下载次数: 31)
|