标题:
51单片机设计秒表计时器,proteus仿真程序
[打印本页]
作者:
songkdksljf
时间:
2021-1-5 16:00
标题:
51单片机设计秒表计时器,proteus仿真程序
27,28两个按键用于控制时间的暂停和重新计数
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei截图20210105155944.jpg
(119.48 KB, 下载次数: 76)
下载附件
2021-1-5 16:00 上传
单片机源程序如下:
#include <reg51.h>
#include <absacc.h>
#include <intrins.h>
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80
#define KeyInPort XBYTE[0xE800]
#define KeyOutPort XBYTE[0xEC00]
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
u16 Timer0_flag = 0;
u16 time100ms_cnt = 0;//100ms计数变量
u8 xdata smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,//0x00全灭
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71, 0x00};//显示0~F的值,18不显示
u8 xdata smgduan_num[] = { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0xff};//0xff选中所有数码管
u8 code KeyOutTAB[] = {
0xFF, // 凑数的
~BIT0,
~BIT1,
~BIT2,
~BIT3,
~BIT4,
~BIT5,
~BIT6,
~BIT7,
};
u8 code conKeyFunCode[] = {
3, // 凑数
0x81,// 0
0x22,// 1
0x42,// 2
0x82,// 3
0x83,// 4
0x43,// 5
0x23,// 6
0x84,// 7
0x44,// 8
0x24,// 9
0x14,// A
0x13,// B
0x12,// C
0x11,// D
0x21,// E
0x41,// F
0x00,// 空键 16
0x85,// 17
0x45,// 18
0x25,// 19
0x15,// 20
0x86,// 21
0x46,// 22
0x26,// 23
0x16,// 24
0x0C,// 25
0x0B,// 26
0x0A,// 27
0x09,// 28
};
u16 smgduan_addr = 0XE3FF; //E3FF是PS0的地址,段码的8位数据
u16 smgduan_num_addr = 0XE7FF; //E7FF是PS1的地址,选择那一个数码管亮
u16 key_out_addr = 0XEFFF; //EFFF是PS3的地址,矩阵按键输出地址
u16 key_in_addr = 0XEBFF; //EBFF是PS2的地址,矩阵按键读地址
u8 Key_Flag = 0;
u8 Sys_Key = 0; // 键值存放在这里
u8 duanma_mode = 0;
u8 preKey = 0;
u8 curKey = 0;
u8 SameKeyNum = 0;
bit Flag_1ms = 0;
unsigned char Cnt_1ms = 0;
bit Flag_10ms = 0;
unsigned char Cnt_10ms = 0;
bit Flag_100ms = 0;
unsigned char Cnt_100ms = 0;
bit Flag_1s = 0;
unsigned char Cnt_1s = 0;
void Fun_KeyScan( void ){
unsigned char Temp = 0;
unsigned char LineNum = 0;
// 1、获取键值
for( LineNum = 6; LineNum > 0; LineNum-- ){
KeyOutPort = KeyOutTAB[LineNum]; // 输出
Temp = KeyInPort; // 读取
Temp = ~Temp; // 取反,有按下的是低电平
Temp &= 0x1F; // 屏蔽,0001 1111
if( Temp ){ // 如果有键按下
break; // 则跳出循环
} // 否则继续扫描
}
// 2、拼合键值
Temp <<= 3;//左移3位
Temp |= LineNum;//6 = 110B
// 3、获取功能码
for( LineNum = 29; LineNum > 0; LineNum-- ){//一共30个数,但是第一个数是无效数,从29扫描到1
if( Temp == conKeyFunCode[ LineNum ] ){
break;
}
}
if( LineNum > 0 ){ LineNum--; }
// 4、数字滤波
curKey = LineNum;
if( curKey != preKey ){//判断下一次扫描的是不是还是上一个按键
preKey = curKey;
SameKeyNum = 0;
}
else{
SameKeyNum++;
if( SameKeyNum == 30 ){ Key_Flag = 1; Sys_Key = curKey; }
if( SameKeyNum == 80 ){ Key_Flag = 1; Sys_Key = curKey; }
if( SameKeyNum >= 100 ){ Key_Flag = 1; Sys_Key = curKey; SameKeyNum = 80; }
}
}
bit key28_down = 0;
bit key28_up = 0;
bit key27_down = 0;
bit key27_up = 0;
bit time_start = 1;
void InitTimer0(void)
{
TMOD = 0x01;
TH0 = 0x0FC;
TL0 = 0x18;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void delay1ms(void) //误差 0us
{
unsigned char a,b,c;
for(c=1;c>0;c--)
for(b=142;b>0;b--)
for(a=2;a>0;a--);
}
void main(void)
{
InitTimer0();
while(1)
{
Fun_KeyScan();
if (Sys_Key == 28)//当28号键按下去然后在松开,key28_up == 1
{
key28_down = 1;
}
if(key28_down == 1 && Sys_Key == 16)
{
key28_down = 0;
key28_up = 1;
}
if(key28_up == 1)
{
key28_up = 0;
time_start = ~time_start;
}
if (Sys_Key == 27)//当27号键按下去然后在松开,key27_up == 1
{
key27_down = 1;
}
if(key27_down == 1 && Sys_Key == 16)
{
key27_down = 0;
key27_up = 1;
}
if((key27_up == 1) && (time_start == 0))
{
key27_up = 0;
duanma_mode++;
// if(duanma_mode >= 3)
// {
// duanma_mode = 0;
// }
}
if(duanma_mode == 1)
{
time100ms_cnt = 0;
}
if(duanma_mode == 2)
{
duanma_mode = 0;
time_start = 1;
}
XBYTE[smgduan_num_addr] = smgduan_num[1];
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
51.zip
(69.18 KB, 下载次数: 19)
2021-1-5 16:00 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1