时间显示,按键调整时间的“分”“时”

 一、原理图

采用2个4位共阳数码管,由 74HC537控制段码,74HC595控制位码

二、代码

#include <reg52.h>
#include <intrins.h>

typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
sbit SRCLK = P2 ^ 3;
sbit LATCH = P2 ^ 2; //位锁存
sbit SER = P2 ^ 1;

#define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换

sbit LATCH1 = P2 ^ 0; //   段锁存

//定义独立按键控制脚
sbit KEY1 = P3 ^ 1;
sbit KEY2 = P3 ^ 0;
sbit KEY3 = P3 ^ 2;
sbit KEY4 = P3 ^ 3;

//使用宏定义独立按键按下的键值
#define KEY1_PRESS 1
#define KEY2_PRESS 2
#define KEY3_PRESS 3
#define KEY4_PRESS 4
#define KEY_UNPRESS 0

u8 gmsec = 0; // ms级定义
u8 gsec = 0;  //秒定义
u8 gmin = 0;  //分定义
u8 ghour = 0; //时定义

unsigned char code MIN_DuanMa[] = {0xbf, 0x86, 0xdb, 0xcf, 0xE6, 0xED, 0xFd, 0x87, 0xFF, 0XEF};
unsigned char code dofly_DuanMa[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
// 显示段码值0---F
unsigned char code dofly_WeiMa[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
//分别对应相应的数码管点亮,即位码

void delay_10us(u16 ten_us)
{
	while (ten_us--);
}

void delay_ms(u16 ms)
{
	u16 i, j;
	for (i = ms; i > 0; i--)
		for (j = 110; j > 0; j--);
}

void Out595(void)
{
	LATCH = 0;
	_nop_();
	LATCH = 1;
}

void SendByte(unsigned char dat) //位码发送
{
	unsigned char i;

	for (i = 0; i < 8; i++)
	{
		SRCLK = 0;
		SER = dat & 0x80;
		dat <<= 1;
		SRCLK = 1;
	}
}

void smg_display(u8 dat[], u8 pos)
{
	u8 i = 0;
	u8 pos_temp = pos - 1;

	for (i = pos_temp; i < 8; i++)
	{
		switch (i) //位选
		{
		case 0:
			SendByte(dofly_WeiMa[i]);
			Out595();
			break;
		case 1:
			SendByte(dofly_WeiMa[i]);
			Out595();
			break;
		case 2:
			SendByte(dofly_WeiMa[i]);
			Out595();
			break;
		case 3:
			SendByte(dofly_WeiMa[i]);
			Out595();
			break;
		case 4:
			SendByte(dofly_WeiMa[i]);
			Out595();
			break;
		case 5:
			SendByte(dofly_WeiMa[i]);
			Out595();
			break;
		case 6:
			SendByte(dofly_WeiMa[i]);
			Out595();
			break;
		case 7:
			SendByte(dofly_WeiMa[i]);
			Out595();
			break;
		}
		DataPort = dofly_DuanMa[dat[i]]; //取显示数据,段码
		delay_10us(100);				 //延时一段时间,等待显示稳定
		DataPort = 0XFF;				 //消音
	}
}

u8 key_scan(u8 mode)
{
	static u8 key = 1;
	if (mode)
		key = 1;														//连续扫描按键
	if (key == 1 && (KEY1 == 0 || KEY2 == 0 || KEY3 == 0 || KEY4 == 0)) //任意按键按下
	{
		delay_10us(1000); //消抖
		key = 0;
		if (KEY1 == 0)
			return KEY1_PRESS;
		else if (KEY2 == 0)
			return KEY2_PRESS;
		else if (KEY3 == 0)
			return KEY3_PRESS;
		else if (KEY4 == 0)
			return KEY4_PRESS;
	}
	else if (KEY1 == 1 && KEY2 == 1 && KEY3 == 1 && KEY4 == 1) //无按键按下
	{
		key = 1;
	}
	return KEY_UNPRESS;
}

void time0_init(void)
{
	TMOD |= 0X01; //选择为定时器0模式,工作方式1
	TH0 = 0XDC;	  //给定时器赋初值,定时10ms
	TL0 = 0X00;
	ET0 = 1; //打开定时器0中断允许
	EA = 1;	 //打开总中断
	TR0 = 0; //关闭定时器
}

void time0_start(void)
{
	TR0 = 1; //打开定时器
}

void time0_stop(void)
{
	TR0 = 0; //关闭定时器
	TH0 = 0X00;
	TL0 = 0X00;
}

u8 key = 0;
u8 time_buf[8];
u8 time_flag = 0;
void task()
{

	key = key_scan(0);
	if (key == KEY1_PRESS) //开始和停止计时
	{
		time_flag = !time_flag;
	}
	else if (key == KEY2_PRESS) //清除计时
	{
		time0_stop();
		time_flag = 0;
		gmin = 0;
		gsec = 0;
		gmsec = 0;
		ghour = 0;
	}
	else if (key == KEY3_PRESS)
		gmin++;
	else if (key == KEY4_PRESS)
		ghour++;
	if (time_flag)
		time0_start(); //开始计时
	else
		time0_stop(); //停止计时
	time_buf[1] = ghour / 10;
	time_buf[0] = ghour % 10; //时

	time_buf[3] = gmin / 10;
	time_buf[2] = gmin % 10; //分

	time_buf[5] = gsec / 10;
	time_buf[4] = gsec % 10; //秒

	time_buf[7] = gmsec / 10;
	time_buf[6] = gmsec % 10; //毫秒
	smg_display(time_buf, 1); //显示
}

void main()
{
	time0_init();
	while (1)
	{
		task();
	}
}

void time0() interrupt 1 //定时器0中断函数
{
	TH0 = 0XDC; //给定时器赋初值,定时10ms
	TL0 = 0X00;
	gmsec++;		  // 10ms加1次
	if (gmsec == 100) //定时1秒
	{
		gmsec = 0;
		gsec++;			//对秒计数
		if (gsec == 60) //到达60秒,即1分钟
		{
			gsec = 0;
			gmin++; //对分计数
			if (gmin == 60)
			{
				gmin = 0;
				ghour++; //对时计数
				if (ghour == 60)
					ghour = 0;
			}
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Xiaoen_Lee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值