蓝桥杯之单片机设计与开发(9)——独立按键实现计时器

功能:
    1.按下S6,清零并停止计时
    2.按下S5,暂停计时
    3.按下S4,开始计时

计时时,LED为流水灯状态,计时显示格式为 分-秒-毫秒

main.c

/*******************************************************************************
* 文件名:main.c
* 描  述:1.按下S6,停止计时并清零
					2.按下S5,暂停计时
					3.按下S4,开始/继续计时
* 作  者:小默haa
* 版本号:v1.0.0
* 日  期: 2019年1月30日
* 备  注:独立按键控制LED流水灯
*         
*******************************************************************************/
#include 
#include "sys.h"

u8 sec = 0, min = 0;	//分 秒
u16 point = 0;		//毫秒
u8 Led_dat;				//led显示状态
u8 KeySta[4] = {1,1,1,1};		//当前按键状态
u8 Key_backup[4] = {1,1,1,1};	//按键状态备份,保存前一次的按键值
u8 flag = 0;

void main(void)
{
	u8 i;
	All_Init();
	Time0_Init();
	Time1_Init();
	Led_dat = 0x7f;
	EA = 1;
	while(1)
	{
		for(i = 0;i < 4;i++)
		{
			if(Key_backup[i] != KeySta[i])
			{
				if(Key_backup[i] == 0)	//说明按键时弹起状态
					Key_Drive(i);
				Key_backup[i] = KeySta[i];
			}
		}
		Show_Num();
	}
}

sys.c

#include "sys.h"

/*******************************************************************************
* 函数名	:All_Init
* 输入值	:无
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月15日
* 功能描述:外设初始化
* 备注		:关闭所有外设
*******************************************************************************/
void All_Init(void)
{
	P2 = (P2 & 0x1f) | 0x80;	//打开Y4C(LED)
	P0 = 0xff;					//关闭LED
	P2 = (P2 & 0x1f) | 0xe0;	//打开Y7C(数码管)
	P0 = 0xff;					//关闭数码管
	P2 = (P2 & 0x1f) | 0xa0;	//打开Y5C
	P0 = 0x00;					//关闭蜂鸣器、继电器
	P2 = P2 & 0x1f;		//关闭Y4C,Y5C,Y6C,Y7C
}

//定时器0初始化
void Time0_Init(void)
{
	AUXR |= 0x80;	//定时器时钟1T模式
	TMOD &= 0xF0;	//设置定时器模式
	TL0 = 0x9a;		//设置定时初值2ms
	TH0 = 0xa9;		//设置定时初值2ms
	TF0 = 0;		//清除TF0标志
	ET0 = 1;		//允许定时器0中断
	TR0 = 1;		//定时器0开始计时
}

/*******************************************************************************
* 函数名	:Timer0
* 输入值	:无
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月30日
* 功能描述:定时器0中断服务程序
* 备注		:2ms执行一次按键扫描和数码管显示
*******************************************************************************/
void Timer0(void) interrupt 1
{
	Key_Scan();
	if (flag == 1)
		TR1 = 1;
	else if (flag == 2)
		TR1 = 0;
	else if (flag == 3)
	{
		TR1 = 0;
		min = 0;
		sec = 0;
		point = 0;
	}
	
	Nixie_Scan();
}

//定时器1初始化
void Time1_Init(void)
{
	AUXR |= 0x40;	//定时器时钟1T模式
	TMOD &= 0x0F;	//设置定时器模式
	TL1 = 0x9a;		//设置定时初值2ms
	TH1 = 0xa9;		//设置定时初值2ms
	TF1 = 0;		//清除TF0标志
	ET1 = 1;		//允许定时器0中断
}

/*******************************************************************************
* 函数名	:Timer1
* 输入值	:无
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月30日
* 功能描述:定时器1中断服务程序
* 备注		:实现计时功能
*******************************************************************************/
void Timer1(void) interrupt 3
{
	static u16 t0 = 0;

	t0 ++;
	if(t0 % 5 == 0)			//10ms
	{
		point ++;
		if(point == 100)
		{
			sec ++;
			if(sec == 60)
			{
				min ++;
				if(min == 60)
					min = 0;
				sec = 0;
			}
			point = 0;
		}
		if(t0 == 50)		//100ms
		{
			Led_dat = _crol_(Led_dat, 1);
			Led_illume(Led_dat);		//点亮LED
			t0 = 0;
		}
		
		Show_Num();
	}
}

sys.h

#ifndef _SYS_H_
#define _SYS_H_

typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;

#include 
#include 

//全局变量定义
#define FOSC 11059200L		//系统时钟

//外部变量
extern u8 sec, min;
extern u8 Led_dat, flag;
extern u8 KeySta[4],Key_backup[4];
extern u16 point;


//sys.c
void All_Init(void);
void Time0_Init(void);
void Time1_Init(void);

//led.c
void Led_illume(u8 dat);


//key.c
sbit s4 = P3^3;
sbit s5 = P3^2;
sbit s6 = P3^1;
sbit s7 = P3^0;
void Key_Scan(void);
void Key_Drive(u8 key);


//drive.c
sbit Relay = P0^4;
sbit Beep = P0^6;
void Drive_ON(void);
void Drive_OFF(void);

//Nixie_tube.c
void Nixie_Scan(void);
void Nixie_Show(void);
void Show_Num(void);


#endif

key.c

#include "sys.h"

/*******************************************************************************
* 函数名	:Key_Scan
* 输入值	:无
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月20日
* 功能描述:独立按键扫描
* 备注		:检测按键状态(按下/松开)
*******************************************************************************/
void Key_Scan(void)
{
	u16 i;
	static u8 keybuff[] = {0xff,0xff,0xff,0xff};
	keybuff[0] = (keybuff[0] << 1) | s4;
	keybuff[1] = (keybuff[1] << 1) | s5;
	keybuff[2] = (keybuff[2] << 1) | s6;
	keybuff[3] = (keybuff[3] << 1) | s7;
	for(i = 0;i < 4;i ++)
	{
		if(keybuff[i] == 0xff)		//连续扫描8次都是1,16ms内都是弹起状态,按键已松开
		{
			KeySta[i] = 1;
		}
		else if(keybuff[i] == 0x00)	//连续扫描8次都是0,16ms内都是按下状态,按键已按下
		{
			KeySta[i] = 0;
		}
		else	//其他状态键值不稳定,不作处理
		{}
	}
}

/*******************************************************************************
* 函数名	:Key_Drive
* 输入值	:有活动的按键 key
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月30日
* 功能描述:独立按键驱动
* 备注		:根据独立按键转态,执行相应操作
*******************************************************************************/
void Key_Drive(u8 key)
{
	switch(key)
	{
		case 0: flag = 1; break;
		case 1: flag = 2; break;
		case 2: flag = 3; break;
//		case 3: flag = 3; break;
	}
}


led.c

#include "sys.h"

/*******************************************************************************
* 函数名	:Led_illume
* 输入值	:led数据
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月20日
* 功能描述:LED点亮程序
* 备注		:根据传输进来的数据值,点亮相应LED
*******************************************************************************/
void Led_illume(u8 dat)
{
	P2 = (P2 & 0x1f) | 0x80;	//打开Y4C(LED)
	P0 = dat;					//关闭LED
	P2 = P2 & 0x1f;
}


Nixie_tube.c

/*******************************************************************************
* 文件名:Nixie_tube.c
* 描  述:数码管相关程序
* 作  者:小默haa
* 版本号:v1.0
* 日  期: 2019年1月28日
* 备  注:与数码管相关的所有函数
*         
*******************************************************************************/
#include "sys.h"

u8 code Nixie[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};	//共阳数码管码字
u8 NixieBuff[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};	//数码管显示缓冲区,初值0xff确保启动时都不亮
u8 code Symbol[] = {0xff,0xbf};	//全灭,-

u8 smg1 = 0, smg2 = 0, smg3 = 0, smg4 = 0, smg5 = 0, smg6 = 0, smg7 = 0, smg8 = 0;

/*******************************************************************************
* 函数名	:Nixie_Scan
* 输入值	:无
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月29日
* 功能描述:数码管扫描函数
* 备注		:根据数码管显示数组,点亮数码管   
*******************************************************************************/
void Nixie_Scan(void)
{
	static u8 index = 0;
	P2 = (P2 & 0x1f) | 0xe0;	//数码管消隐
	P0 =0xff;
	
	P2 = (P2 & 0x1f) | 0xc0;	//数码管片选
	P0 = 0x01 << index;
	
	P2 = (P2 & 0x1f) | 0xe0;	//数码管段选
	P0 = NixieBuff[index];
	P2 &= 0x1f;
	
	index ++;
	index &= 0x07;
}

/*******************************************************************************
* 函数名	:Nixie_Show
* 输入值	:无
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月29日
* 功能描述:数码管显示函数
* 备注		:根据每一位的数码管需要显示内容,选择相应码子存放进数码管显示数组   
*******************************************************************************/
void Nixie_Show(void)
{
	NixieBuff[3] = Nixie[smg1];
	NixieBuff[2] = Nixie[smg2];
	NixieBuff[1] = Symbol[smg3];
	NixieBuff[0] = Nixie[smg4];
	NixieBuff[7] = Nixie[smg5];
	NixieBuff[6] = Symbol[smg6];
	NixieBuff[5] = Nixie[smg7];
	NixieBuff[4] = Nixie[smg8];
}

/*******************************************************************************
* 函数名	:Show_Num
* 输入值	:无
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月29日
* 功能描述:数值显示处理
* 备注		:将数值每一位分离,存放进每一位数码管显示指示变量smg中   
*******************************************************************************/
void Show_Num(void)
{
	smg8 = point % 10;
	smg7 = point / 10;
	smg6 = 1;
	smg5 = sec % 10;
	smg4 = sec / 10;
	smg3 = 1;
	smg2 = min % 10;
	smg1 = min / 10;

	Nixie_Show();
}


 

你可能感兴趣的:(蓝桥杯,第十届蓝桥杯)