一、使用proteus绘制简单的电路图,用于后续仿真
二、编写程序
/********************************************************************************************************************
---- @Project: LED-74HC595
---- @File: main.c
---- @Edit: ZHQ
---- @Version: V1.0
---- @CreationTime: 20200628
---- @ModifiedTime: 20200629
---- @Description:
---- 刚上电开机时,红棋加时键对应S1键,红棋减时键对应S2键.。
---- 刚上电开机时,黑棋加时键对应S3键,黑棋减时键对应S4键.。
---- 比赛中途暂停双方计时的暂停按键对应S6键。刚上电时,复位双方默认20分时间的复位按键对应S7按键。
---- 红棋的抢时按键对应S13键,黑棋的抢时按键对应S16按键。
---- 棋类计时器有点像抢答器,本质上有两个计时器。比赛的时候对弈的两个棋友各用一个不同的按键抢时间,红棋走一步棋后,就按一下自己的抢时按键,这个时候红棋的计时器停止计时,而黑棋的计时器开始计时,黑棋走了一步棋后,按一下自己的计时器,黑棋停止计时,红棋继续计时,依次循环,谁的时间最先用完谁就输,蜂鸣器也会发出长鸣的声音提示时间到。
---- 上电开机默认双方各有20分钟的时间,左边显示的是红棋的时间,右边显示的是黑棋的时间。此时可以通过S1,S2.,S3,S4的加减按键来设置各自的最大倒计时时间。此时如果按下复位按键S7,会自动把双方的时间设置为默认的20分钟。
---- 设置好最大倒计时的时间后,此时任意一方按下各自的抢时按键(S13或者S16),则自己的计时器停止计时,而对方开始倒计时。此时数码管显示的是对方的时间,而自己的时间屏蔽不显示。
---- 在开始倒计时的时候,如果中途有棋友要接听电话或者忙别的事情,需要暂时暂停一下双方的时间,这个时候可以按S6暂停按键来暂停双方的计时,忙完后再次按下暂停按键会继续倒计时。任何一方的时间走完,都会蜂鸣器长鸣提示。
---- 单片机:AT89C52
********************************************************************************************************************/
#include "reg52.h"
/*——————宏定义——————*/
#define FOSC 11059200L
#define T1MS (65536-FOSC/12/500) /*0.5ms timer calculation method in 12Tmode*/
#define const_voice_short 40 /*蜂鸣器短叫的持续时间*/
#define const_voice_long 900 /*蜂鸣器长叫的持续时间*/
#define const_key_time 9 /*按键去抖动延时的时间*/
#define const_1s 96 /*大概产生一秒钟的时间基准*/
/*——————变量函数定义及声明——————*/
/*定义数码管的74HC595*/
sbit Dig_Hc595_Sh = P2^0;
sbit Dig_Hc595_St = P2^1;
sbit Dig_Hc595_Ds = P2^2;
/*定义蜂鸣器*/
sbit Beep = P2^7;
/*作为中途暂停指示灯 亮的时候表示中途暂停*/
sbit LED = P3^5;
/*定义按键*/
sbit Key_S1 = P0^0; /*第一行输入*/
sbit Key_S2 = P0^1; /*第二行输入*/
sbit Key_S3 = P0^2; /*第三行输入*/
sbit Key_S4 = P0^3; /*第四行输入*/
sbit Key_D1 = P0^4; /*第一列输入*/
sbit Key_D2 = P0^5; /*第二列输入*/
sbit Key_D3 = P0^6; /*第三列输入*/
sbit Key_D4 = P0^7; /*第四列输入*/
unsigned char ucKeyStep = 1; /*按键扫描步骤变量*/
unsigned int uiKeyTimeCnt = 0; /*按键去抖动延时计数器*/
unsigned char ucKeyLock = 0; /*按键触发后自锁的变量标志*/
unsigned char ucRowRecord = 1; /*记录当前扫描到第几列了*/
unsigned char ucKeySec = 0; /*被触发的按键编号*/
unsigned char ucDigShow8 = 0; /*第8位数码管要显示的内容*/
unsigned char ucDigShow7 = 0; /*第7位数码管要显示的内容*/
unsigned char ucDigShow6 = 0; /*第6位数码管要显示的内容*/
unsigned char ucDigShow5 = 0; /*第5位数码管要显示的内容*/
unsigned char ucDigShow4 = 0; /*第4位数码管要显示的内容*/
unsigned char ucDigShow3 = 0; /*第3位数码管要显示的内容*/
unsigned char ucDigShow2 = 0; /*第2位数码管要显示的内容*/
unsigned char ucDigShow1 = 0; /*第1位数码管要显示的内容*/
unsigned char ucDigDot8; /*数码管8的小数点是否显示的标志*/
unsigned char ucDigDot7 = 1; /*数码管7的小数点是否显示的标志*/
unsigned char ucDigDot6; /*数码管6的小数点是否显示的标志*/
unsigned char ucDigDot5; /*数码管5的小数点是否显示的标志*/
unsigned char ucDigDot4; /*数码管4的小数点是否显示的标志*/
unsigned char ucDigDot3 = 1; /*数码管3的小数点是否显示的标志*/
unsigned char ucDigDot2; /*数码管2的小数点是否显示的标志*/
unsigned char ucDigDot1; /*数码管1的小数点是否显示的标志*/
unsigned char ucDigShowTemp = 0; /*临时中间变量*/
unsigned char ucDisplayDriveStep = 1; /*动态扫描数码管的步骤变量*/
unsigned char ucWd = 1; /*本程序的核心变量,窗口显示变量。类似于一级菜单的变量。代表显示不同的窗口。*/
unsigned int uiRedTimeCnt = 0; /*红棋产生秒基准的时间计时器*/
unsigned int uiBlackTimeCnt = 0; /*黑棋产生秒基准的时间计时器*/
unsigned int uiRedTotal = 1200; /*红棋的总时间*/
unsigned int uiBlackTotal = 1200; /*黑棋的总时间*/
unsigned char ucRedFlag = 0; /*红棋是否开始计时的标志*/
unsigned char ucBlackFlag = 0; /*黑棋是否开始计时的标志*/
unsigned char ucDisplayUpdate = 1; /*更新显示标志*/
unsigned int uiVoiceCnt = 0; /*蜂鸣器鸣叫的持续时间计数器*/
void Dig_Hc595_Drive(unsigned char, unsigned char);
/*根据原理图得出的共阴数码管字模表*/
code unsigned char Dig_Table[] =
{
0x3f, /*0 序号0*/
0x06, /*1 序号1*/
0x5b, /*2 序号2*/
0x4f, /*3 序号3*/
0x66, /*4 序号4*/
0x6d, /*5 序号5*/
0x7d, /*6 序号6*/
0x07, /*7 序号7*/
0x7f, /*8 序号8*/
0x6f, /*9 序号9*/
0x00, /*不显示 序号10*/
0x40, /*- 序号11*/
0x73, /*P 序号12*/
};
/**
* @brief 定时器0初始化函数
* @param 无
* @retval 初始化T0
**/
void Init_T0(void)
{
TMOD = 0x01; /*set timer0 as mode1 (16-bit)*/
TL0 = T1MS; /*initial timer0 low byte*/
TH0 = T1MS >> 8; /*initial timer0 high byte*/
}
/**
* @brief 外围初始化函数
* @param 无
* @retval 初始化外围
* 让数码管显示的内容转移到以下几个变量接口上,方便以后编写更上一层的窗口程序。
* 只要更改以下对应变量的内容,就可以显示你想显示的数字。
**/
void Init_Peripheral(void)
{
ET0 = 1;/*允许定时中断*/
TR0 = 1;/*启动定时中断*/
EA = 1;/*开总中断*/
}
/**
* @brief 初始化函数
* @param 无
* @retval 初始化单片机
**/
void Init(void)
{
LED = 1;
Beep = 1;
Dig_Hc595_Drive(0x00, 0x00); /*关闭所有经过另外两个74HC595驱动的LED灯*/
Init_T0();
}
/**
* @brief 延时函数
* @