【51单片机】2-8【I/O口】数码管显示矩阵按键值

1.硬件

2.软件

  • 动态数码管
#include "reg52.h"			 //头文件

typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;

#define GPIO_DIG P0//数码管段选
#define GPIO_KEY P1//按键

u8 KeyValue;	//用来存放读取到的键值

u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
					0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//共阴极,显示0~F的值

void delay(u16 i)//延时
{
	while(i--);	
}

void KeyDown(void)//矩阵按键扫描函数
{
	char a=0;
	GPIO_KEY=0x0f;//矩阵按键接P1口,默认高四位为低电平,低四位为高电平
	if(GPIO_KEY!=0x0f)//读取按键是否按下
	{
		delay(1000);//延时10ms进行消抖
		if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
		{	
			//测试列
			GPIO_KEY=0X0F;//0000 1111
			switch(GPIO_KEY)
			{
				case(0X07):	KeyValue=0;break;//P1为0000 0111
				case(0X0b):	KeyValue=1;break;//0000 1011
				case(0X0d): KeyValue=2;break;//0000 1101
				case(0X0e):	KeyValue=3;break;//0000 1110
			}
			//测试行
			GPIO_KEY=0XF0;//1111 0000
			switch(GPIO_KEY)
			{
				case(0X70):	KeyValue=KeyValue;break;//0111 0000
				case(0Xb0):	KeyValue=KeyValue+4;break;//1011 0000
				case(0Xd0): KeyValue=KeyValue+8;break;//1101 0000
				case(0Xe0):	KeyValue=KeyValue+12;break;//1110 0000
			}
			
		}
	}
	while((a<50)&&(GPIO_KEY!=0xf0))	 //检测按键松手检测
	{
		delay(100);
		a++;
	}
}

void main()
{	

	while(1)
	{	
		KeyDown();		   //按键判断函数
		GPIO_DIG=smgduan[KeyValue];	  //检测按键松手检测
	}		
}

3.实物效果

在这里插入图片描述

  • 硬件接线
    在这里插入图片描述
    在这里插入图片描述
### 实现方案 以下是基于51单片机数码管显示矩阵键盘的具体实现方法。该代码实现了初始化I/O端、扫描4×4矩阵键盘以及在数码管显示对应按键的功能。 #### 初始化 I/O `initIO()` 函数负责配置单片机的GPIO引脚,将矩阵键盘的列设置为输出模式,行设置为输入模式;同时将数码管的段选引脚也设为输出模式[^1]。 ```c void initIO(void) { // 假设P1连接到键盘行列,P2连接到数码管段选 P1 = 0xFF; // 设置初始状态 P2 = 0x00; // 配置P1方向:低四位作为行输入,高四位作为列输出 P1DIR |= 0xF0; P1DIR &= ~0x0F; // 配置P2方向:全部作为输出 P2DIR = 0xFF; } ``` #### 扫描矩阵键盘 `scanKey()` 函数通过逐行列扫描的方式检测是否有按键被按下,并返回对应的键。如果没有按键按下,则返回默认 `0xFF` 表示无操作[^1]。 ```c unsigned char scanKey(void) { unsigned char row, col, keyVal; for (col = 0; col < 4; col++) { // 列循环 P1 = ~(0x1 << (col + 4)); // 将某一列为低电平 for (row = 0; row < 4; row++) { // 行循环 if (!(P1 & (0x1 << row))) { // 如果某行为低电平 delay(10); // 消抖处理 if (!(P1 & (0x1 << row))) { // 再次确认按键稳定 keyVal = (row * 4) + col + 1; // 计算按键编号 return keyVal; // 返回按键 } } } P1 = 0xFF; // 复位所有列为高电平 } return 0xFF; // 若未检测到按键则返回0xFF } // 简单延时函数用于消抖 void delay(unsigned int ms) { while(ms--) { _nop_(); } } ``` #### 数码管显示功能 `displayDigit()` 函数接收一个数参数,在数码管显示出对应的字符。这里假设使用的是共阴极数码管,因此需要定义一段映射表来存储不同数字对应的段码[^1]。 ```c const unsigned char segCode[] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E }; void displayDigit(unsigned char digit) { if(digit >= sizeof(segCode)) { P2 = 0xFF; // 超过范围时不显示任何内容 } else { P2 = segCode[digit]; // 输出相应段码至数码管 } } ``` #### 主程序逻辑 主函数部分调用了上述三个子模块完成整个流程控制——先执行硬件初始化工作,接着进入无限循环等待用户触发事件并更新显示屏上的数据展示结果。 ```c #include <reg51.h> void main(void){ unsigned char keyValue; initIO(); // 初始化 IO while(1){ // 循环运行 keyValue = scanKey(); if(keyValue != 0xFF){ // 当有有效按键时 displayDigit(keyValue - 1); // 显示按键(减去偏移量) while(scanKey() != 0xFF); // 等待按键释放 displayDigit(0xFF); // 清除屏幕 } } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值