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位 2msTMOD |= 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; // 没有按键按下返回0if (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){ // 按键0Dig_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