单片机学习-使用矩阵按键来显示数码管0-F

1、硬件电路

2.软件编程思想

矩阵按键分两种

1、行列扫码

//数码管字摸
u8 gsmg_code[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
                        0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};      //共阴 显示0-F

#include "reg52.h"

// 类型重命名
typedef unsigned char u8;
typedef unsigned int u16;

// 使用宏定义端口
#define SMG_A_DP_PORT	P0	// 数码管段选端口
#define KEY_MAXRIX_SCAN P1	// 按键 端口

// 数码管字模
u8 smg_code[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
					0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};	//共阴 显示0-F

void delpaly(u16 times)
{
	while(times--);

}

// 定义一个char 类型的函数 void 是没有形参
u8 key_maxrix_ranks_scan(void)
{
	u8 key_value = 0;   // 定义一个变量	来接收按键的状态 键值
	//1111 0111  这个代表第一列 按键没有按下为高 按下为低电平
	KEY_MAXRIX_SCAN = 0xf7;
	if(KEY_MAXRIX_SCAN!= 0xf7)
	{
		delpaly(1000);	// 消抖
	   	switch(KEY_MAXRIX_SCAN)
		{
		// 第一个按下 0111 1111	转换十六进制 0x7f 
		case 0x77: key_value = 1; break; 
		case 0xb7: key_value = 5; break; 
		case 0xd7: key_value = 9; break; 
		case 0xe7: key_value = 13; break; 	
		}
		while(KEY_MAXRIX_SCAN != 0xf7);  // 循环 当按键不等于0xf7 就结束了	
	}


	// 第二列 第三列 第四列跟第一列是一样的
	// 第二列
	KEY_MAXRIX_SCAN = 0xfb; // 1111 1011  代表第二列
	if(KEY_MAXRIX_SCAN!=0xfb)
	{
	   	delpaly(1000);	// 消抖
	 	switch(KEY_MAXRIX_SCAN)
		{
		case 0x7b: key_value = 2; break; // 0111 1011 
		case 0xbb: key_value = 6; break;  // 1011 1011  / 1101 1011  / 1110 1011
		case 0xdb: key_value = 10; break; 
		case 0xeb: key_value = 14; break; 	
		}
		while(KEY_MAXRIX_SCAN != 0xfb);
	}
	  
	
	// 第三列
	KEY_MAXRIX_SCAN = 0xfd;	  // 1111 1101 代表第三列
	if(KEY_MAXRIX_SCAN!=0xfd)
	{
	 	delpaly(1000);	// 消抖
		switch(KEY_MAXRIX_SCAN)
		{
		case 0x7d: key_value = 3; break;   // 0111  1101/ 1011 1101 / 1101 1101 / 1110 1101
		case 0xbd: key_value = 7; break; 
		case 0xdd: key_value = 11; break; 
		case 0xed: key_value = 15; break; 	
		}
		while(KEY_MAXRIX_SCAN != 0xfd);
	} 
 

	// 第四列
	KEY_MAXRIX_SCAN = 0xfe;	   // 1111 1110 代表第四列
	if(KEY_MAXRIX_SCAN!=0xfe)
	{
		delpaly(1000);	// 消抖
		switch(KEY_MAXRIX_SCAN)
		{
		case 0x7e: key_value = 4; break;   // 0111 1110  / 1011 1110  / 1101 1110  / 1110 1110
		case 0xbe: key_value = 8; break; 
		case 0xde: key_value = 12; break; 
		case 0xee: key_value = 16; break; 	
		}
		while(KEY_MAXRIX_SCAN != 0xfe); 
	}
		
	return key_value; 	  // 返回 按键的键值
}



void main()
{

	u8 key =0;  // 定义变量 key初始为0 
	while(1)
	{
		key = key_maxrix_ranks_scan();   // 使用函数 需要接收键值
		if(key!=0)
			SMG_A_DP_PORT = smg_code[key-1];  			
	}
}

2、线翻转扫描

#include "reg52.h"

// 类型重命名
typedef unsigned char u8;
typedef unsigned int u16;

// 使用宏定义端口
#define SMG_A_DP_PORT	P0	// 数码管段选端口
#define KEY_MAXRIX_SCAN P1	// 按键 端口

// 数码管字模
u8 smg_code[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
					0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};	//共阴 显示0-F

void delpaly(u16 times)
{
	while(times--);

}

// 线翻转法
u8 key_matrix_flip_scan(void)
{
	static u8 key_value =0;  // 要这个变量不坐变化的
	KEY_MAXRIX_SCAN = 0x0f; //0000 1111
	// 测试列
	if(KEY_MAXRIX_SCAN!= 0x0f)
	{
		delpaly(1000);
		switch(KEY_MAXRIX_SCAN)
		{
			KEY_MAXRIX_SCAN = 0x0f;
			case 0x07: key_value =1 ;break;	// 0000 0111 / 0000 1011 / 0000 1101 / 0000 1110 
			case 0x0b: key_value =2 ;break;	
			case 0x0d: key_value =3 ;break;
			case 0x0e: key_value =4 ;break; 
		}
		// 测试行
		KEY_MAXRIX_SCAN = 0xf0; // 1111 0000
		switch(KEY_MAXRIX_SCAN)
		{
			case 0x70: key_value = key_value  ;break;	// 0111 0000    、1011 0000 、 1101 0000 、 1110 0000
			case 0xb0: key_value=key_value+4 ;break;
			case 0xd0: key_value=key_value+8 ;break;
			case 0xe0: key_value=key_value+12 ;break; 
		}
		while(KEY_MAXRIX_SCAN !=0xf0);				
	}
	
	return key_value; 
		
}
void main()
{

	u8 key =0;  // 定义变量 key初始为0 
	while(1)
	{
		key = key_matrix_flip_scan();   // 使用函数 需要接收键值
		if(key!=0)
			SMG_A_DP_PORT = smg_code[key-1];  			
	}
}

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的C51程序,可以实现矩阵键盘的输入和数码管显示功能。注意,这里使用的是普通的共阳数码管,如果使用共阴数码管需要修改代码: ```c #include <reg52.h> // 51单片机头文件 sbit LSA = P2^2; // 数码管LSA引脚连接的IO口 sbit LSB = P2^3; // 数码管LSB引脚连接的IO口 sbit LSC = P2^4; // 数码管LSC引脚连接的IO口 sbit D1 = P0^0; // 数码管第1位的IO口 sbit D2 = P0^1; // 数码管第2位的IO口 sbit D3 = P0^2; // 数码管第3位的IO口 sbit D4 = P0^3; // 数码管第4位的IO口 unsigned char code Nums[] = { // 数码管显示0~F的值 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71 }; unsigned char KeySta[4][4] = { // 矩阵键盘按键状态 {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1} }; void InitLcd() // 初始化数码管 { P0 = 0xff; // 数码管全部关闭 LSA = 0; LSB = 0; LSC = 0; // 数码管显示第一位 TMOD &= 0xf0; // 设置定时器为模式0 TH0 = 0x3c; TL0 = 0xb0; // 定时器初值,定时1ms ET0 = 1; // 开启定时器中断 TR0 = 1; // 开启定时器 } void Display(unsigned char num, unsigned char pos) // 在数码管的指定位置显示一个数字 { unsigned char tmp = Nums[num]; switch(pos) { case 1: D1 = 0; P0 = tmp; D1 = 1; break; case 2: D2 = 0; P0 = tmp; D2 = 1; break; case 3: D3 = 0; P0 = tmp; D3 = 1; break; case 4: D4 = 0; P0 = tmp; D4 = 1; break; default: break; } } void KeyDriver() // 矩阵键盘驱动程序 { unsigned char i, j; static unsigned char backup[4][4] = { // 矩阵键盘状态备份 {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1} }; for(i = 0; i < 4; i++) { for(j = 0; j < 4; j++) { if(KeySta[i][j] != backup[i][j]) { // 检测到按键状态改变 if(KeySta[i][j] == 0) { // 按键按下 Display(i * 4 + j, 1); // 在数码管第一位显示按键编号 } } backup[i][j] = KeySta[i][j]; // 备份按键状态 } } } void main() { InitLcd(); // 初始化数码管 while(1) { KeyDriver(); // 矩阵键盘驱动程序 } } void Timer0() interrupt 1 // 定时器0中断服务程序 { static unsigned char cnt = 0; static unsigned char pos = 1; TH0 = 0x3c; TL0 = 0xb0; // 定时器重新赋初值,定时1ms cnt++; if(cnt >= 100) { // 每100ms更新数码管显示位置 cnt = 0; pos++; if(pos > 4) pos = 1; } switch(pos) { // 控制数码管显示位置的选择 case 1: LSA = 0; LSB = 0; LSC = 0; break; case 2: LSA = 1; LSB = 0; LSC = 0; break; case 3: LSA = 0; LSB = 1; LSC = 0; break; case 4: LSA = 1; LSB = 1; LSC = 0; break; default: break; } } ``` 这段程序中,使用P2口的LSA、LSB、LSC三个引脚控制数码管显示位置,使用P0口的D1~D4四个引脚控制数码管的亮灭。矩阵键盘的状态通过二维数组KeySta存储,在定时器中断服务程序Timer0中调用KeyDriver函数进行检测和处理。在按键按下时,将按键编号显示数码管的第一位。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值