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