51单片机按键数码管(简单设计)

        51单片机按键数码管是一个简单的设计项目,使用四位数码管进行显示,矩阵按键加独立按键输入,将读取到据显示在数码管上。

一、参考PCB图

二、参考代码

#include <reg51.h>
// LED数码管引脚定义
sbit LED1 = P2 ^ 0;
sbit LED2 = P2 ^ 1;
sbit LED3 = P2 ^ 2;
sbit LED4 = P2 ^ 3;
// 矩阵按键引脚定义
sbit P1_0 = P1 ^ 0;
sbit P1_1 = P1 ^ 1;
sbit P1_2 = P1 ^ 2;
sbit P1_3 = P1 ^ 3;
sbit P1_4 = P1 ^ 4;
sbit P1_5 = P1 ^ 5;
// 独立按键引脚定义
sbit KEY1 = P1 ^ 6;
sbit KEY2 = P1 ^ 7;
// 按键扫描变量
unsigned char KeyNumber = 0;
unsigned char Matrix_KeyNumber = 0;
// 定义变量存放数码管的数据
unsigned char Dig_Buf[] = {0x00, 0x00, 0x00, 0x00};
// 共阴极数码管表
unsigned char code tab[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C};
//--------------------------------定时器1--------------------------------
void Timer1Init(void)
{
	TMOD &= 0x0F; // 设置定时器16位 2ms
	TMOD |= 0x10;

	TL1 = 0x30;
	TH1 = 0xF8;

	TF1 = 0;
	ET1 = 1;
	EA = 1;
	TR1 = 1;
}

//--------------------------------动态扫描数码管-------------------------------
void Dig_Loop()
{
	// 声明静态变量,每次进入函数值不变
	static unsigned char CNT0 = 0;
	CNT0++;
	if (CNT0 > 3)
	{
		CNT0 = 0;
	}

	P0 = 0x00; // 段码清0,消影
	P2 = 0XFF;

	switch (CNT0) // 位码输出
	{
	case 0:
		LED1 = 0;
		break;
	case 1:
		LED2 = 0;
		break;
	case 2:
		LED3 = 0;
		break;
	case 3:
		LED4 = 0;
		break;
	}
	P0 = Dig_Buf[CNT0]; // 段码输出
}

//--------------------------------矩阵按键部分--------------------------------
unsigned char MatrixKey()
{
	unsigned char KeyNumber = 0;

	P1 = 0xFF;
	P1_0 = 0; // 依次发送低电平扫描按键 先拉高P1,再拉低某一端口

	if (P1_3 == 0)
	{
		KeyNumber = 1;
	}
	if (P1_4 == 0)
	{
		KeyNumber = 2;
	}
	if (P1_5 == 0)
	{
		KeyNumber = 3;
	}

	P1 = 0xFF;
	P1_1 = 0;

	if (P1_3 == 0)
	{
		KeyNumber = 4;
	}
	if (P1_4 == 0)
	{
		KeyNumber = 5;
	}
	if (P1_5 == 0)
	{
		KeyNumber = 6;
	}

	P1 = 0xFF;
	P1_2 = 0;

	if (P1_3 == 0)
	{
		KeyNumber = 7;
	}
	if (P1_4 == 0)
	{
		KeyNumber = 8;
	}
	if (P1_5 == 0)
	{
		KeyNumber = 9;
	}

	return KeyNumber;
}

void Loop_MatrixKey()
{

	static unsigned char LastKey = 0;
	static unsigned char NowKey = 0;

	LastKey = NowKey;
	NowKey = MatrixKey();

	if (LastKey == 0 && NowKey != 0)
	{
		Matrix_KeyNumber = NowKey;
	};
}

//--------------------------------独立按键部分--------------------------------
// 获取当前按键状态
unsigned char KeyState()
{
	unsigned char KeyNum = 0; // 没有按键按下返回0
	if (KEY1 == 0)
	{
		KeyNum = 1;
	}
	if (KEY2 == 0)
	{
		KeyNum = 2;
	}
	return KeyNum;
}
// 循环扫描,相当于沿检测
void Loop_Key()
{
	static unsigned char LastKey = 0, NowKey = 0;
	LastKey = NowKey;	 // 更新按键值
	NowKey = KeyState(); // 获取当前按键状态
	if (LastKey)		 // 判断有无按键按下
	{
		if (NowKey == 0) // 如果按下,获取按键编号
		{
			KeyNumber = LastKey;
		}
	}
}
//--------------------------------数码管显存左移函数--------------------------------
void Dig_Shift(unsigned char NewKey)
{
	Dig_Buf[0] = Dig_Buf[1];
	Dig_Buf[1] = Dig_Buf[2];
	Dig_Buf[2] = Dig_Buf[3];
	Dig_Buf[3] = NewKey;
}
//----------------------------主函数-----------------------------//
void main(void)
{
	// 定时器初始化
	Timer1Init();

	while (1)
	{

		// 按键响应
		if (KeyNumber)
		{ // 独立按键
			if (KeyNumber == 1)
			{ // 按键0
				Dig_Shift(tab[0]);
			}
			if (KeyNumber == 2)
			{ // 清零按键
				Dig_Buf[0] = 0x00;
				Dig_Buf[1] = 0x00;
				Dig_Buf[2] = 0x00;
				Dig_Buf[3] = 0x00;
			}

			KeyNumber = 0;
		}

		if (Matrix_KeyNumber)
		{ // 矩阵按键
			Dig_Shift(tab[Matrix_KeyNumber]);
			Matrix_KeyNumber = 0;
		}
	}
}

//----------------------------定时计数器1的中断服务子程序-----------------------------//
void Time1_ISR(void) interrupt 3
{
	// 重新装载定时器
	static unsigned char T0Count, T1Count = 0;

	TL1 = 0x30;
	TH1 = 0xF8;

	Dig_Loop(); // 数码管扫描

	T0Count++;
	if (T0Count >= 10)
	{ // 20ms进行一次按键扫描
		T0Count = 0;
		Loop_MatrixKey();
	}

	T1Count++;
	if (T1Count >= 15)
	{ // 30ms进行一次按键扫描
		T1Count = 0;
		Loop_Key();
	}
}

三、参考网址

        由于本次项目过于简单,不做过多描述,详情参考我的bilibili:

51单片机按键数码管_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值