《蓝桥杯CT107D单片机竞赛板》:矩阵键盘模块

Posted 是七喜呀!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《蓝桥杯CT107D单片机竞赛板》:矩阵键盘模块相关的知识,希望对你有一定的参考价值。

矩阵键盘模块

实验简介

CT107D单片机开发板上的矩阵键盘控制, 指示灯亮灭,数码管显示按键值

实验原理图

实验原理

  • 器件介绍:见独立按键模块,一个独立按键需要一个I/O口,如我们实现多按键控制功能的项目,如果仅使用独立按键,单片机的I/O口一定是不够的,为了减少I/O引脚使用数量,就在单片机上引入矩阵键盘。根据上面的原理图,4 * 4的独立按键,每一行有4个独立按键的一端连接,每一列有对应的独立按键的另外一端连接,共使用了8个I/O口(如果使用独立按键则需要16个I/O口,的确大大减少了I/O口使用数量!),采用矩阵键盘的行列扫描法,在能够实现独立按键功能的基础上,还能扩展其特有的功能。

  • 基本原理:与独立按键一样,我们仍然采用软件消抖,具体操作为,先设置按键IO口输入为高电平,读取IO口是否有按键被按下(即有低电平出现),使用软件延时函数10ms,再次检测IO口是否仍为低电平,若是,则有按键被按下,进而继续下面的按键程序。

  • 行列扫描法:我们先使得列对应的管脚P34,P35,P42,P44送入低电平(0),而对应的管脚P30,P31,P32,P33送入高电平(1),每当我们按下矩阵按键上的一个键时,我们就能确定一行,例如下图中我们按下S12这个键,此时我们可以确定它所在的行为第4行(因为与其同行的其他三个按键按下也能检测到低电平),再使得列高电平时,低电平,则能够确定其列数为第3列,故我们可知该键为S12, 同理我们能够检测其他按键。

  • 实现须知:HC573芯片的锁存端LE得输入高电平,即Y4C输入高电平,来控制LED对应的管脚。下图知Y4C,受Y4控制,WR输入固定为低电平(0),了解数字电路中或非门知识,我们得使得Y4输出低电平,才能使的Y4C输出高电平,而Y4为74HC138芯片(38译码器)的一个管脚,查阅对应芯片手册可知,其真值表满足C = 1,B = 0,A = 0,(对应管脚P27,P26,P25),才能使得Y4输出低电平,同时代码实现时要保证管脚P2的其他的管脚(0~4)保持原来的状态 。同理控制数码管的Y6C和Y7C,以及控制蜂鸣器的Y5C也一样


  • 注意:按键功能选择KBD(J5上的跳线2与1相连,此时切换至4 * 4矩阵键盘模块)

实验程序

显示对应的按键值

//config.h--用于声明头文件,声明函数,声明一些经常使用的变量或难书写的语句
#ifndef _CONFIG_H
#define _CONFIG_H
#include <STC15F2K60S2.H>//对应芯片函数头文件,定义了一些特殊功能寄存器

//typedef unsigned char uchar;
#define uchar unsigned char
void Delay1ms();		//@12.000MHz
void Delay10ms();		//@12.000MHz

#endif

//main.c--4 * 4矩阵键盘实现显示对应的按键值,按键值范围0 ~ 15,从左至右,从上到下
#include "config.h"
uchar key_num = 20;

//共阴数码管段码表
uchar smgduan[] =                       //标准字库
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46;    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

uchar smgwei[] = 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80;      //位码

uchar tab[8];
	
void dig_display(uchar pos, letter)

   P2 = (P2 & 0x1f) | 0xc0;
   P0 = smgwei[pos - 1];
   P2 &= 0x1f;
   
   P2 = (P2 & 0x1f) | 0xe0;
   P0 = ~smgduan[letter];
   P2 &= 0x1f;
	
	Delay1ms();//给足显示


void display()

	uchar i;
	for (i = 0; i < 8; i++)
		dig_display(i + 1, tab[i]);



void display_ds(uchar p1, p2, p3, p4, p5, p6, p7, p8)

	tab[0] = p1;
	tab[1] = p2;
	tab[2] = p3;
	tab[3] = p4;
	tab[4] = p5;
	tab[5] = p6;
	tab[6] = p7;
	tab[7] = p8;




void closeBeep()

	P2 = (P2 & 0x1f) | 0xa0;
	P06 = 0, P04 = 0;//关闭蜂鸣器和继电器
	P2 &= 0x1f;//P27 ~ P25清零


void led_initAlllight()

 P2 = (P2 & 0x1f) | 0x80;
 P0 = 0x00;
 P2 &= 0x1f;


void key_scanf()

	static uchar key_state = 0, row = 0;
	
	
	switch(key_state)
	
		case 0:
		
			P3 = 0x0f, P42 = 0, P44 = 0;
			if (P3 != 0x0f)//判断有无按键按下
			
				Delay10ms();//消抖
				if (P3 != 0x0f)
					key_state = 1;
			
			break;
		
		case 1:
		
			P3 = 0x0f, P42 = 0, P44 = 0;//先送行为高电平,列为低电平,找出哪一行
			if (P3 != 0x0f)
			
				if (P30 == 0) row = 1, key_state = 2;
				if (P31 == 0) row = 2, key_state = 2;
				if (P32 == 0) row = 3, key_state = 2;
				if (P33 == 0) row = 4, key_state = 2;
			
			
			switch(row)
			
				case 1:
				
					P3 = 0xf0, P42 = 1, P44 = 1;
					if (P44 == 0) key_num = 0;
					if (P42 == 0) key_num = 1;
					if (P35 == 0) key_num = 2;
					if (P34 == 0) key_num = 3;
					
					break;
				
				
				case 2:
				
					P3 = 0xf0, P42 = 1, P44 = 1;
					if (P44 == 0) key_num = 4;
					if (P42 == 0) key_num = 5;
					if (P35 == 0) key_num = 6;
					if (P34 == 0) key_num = 7;
					
					break;
				
				
				case 3:
				
					P3 = 0xf0, P42 = 1, P44 = 1;
					if (P44 == 0) key_num = 8;
					if (P42 == 0) key_num = 9;
					if (P35 == 0) key_num = 10;
					if (P34 == 0) key_num = 11;
					
					break;
				
			
				case 4:
				
					P3 = 0xf0, P42 = 1, P44 = 1;
					if (P44 == 0) key_num = 12;
					if (P42 == 0) key_num = 13;
					if (P35 == 0) key_num = 14;
					if (P34 == 0) key_num = 15;
					
					break;
				
			
		
		
		
		case 2://按完键之后,就没有按键下去
		
			P3 = 0x0f, P42 = 0, P44 = 0;
			if (P3 == 0x0f)
				key_state = 0;

			break;
		
	



void main()

	closeBeep();
	led_initAlllight();
	while(1)
	
	 display();//显示初始化
	 key_scanf();
	 display_ds(16, 16, 16, 16, 16, 16, key_num / 10, key_num % 10);//数码管黑的段码显示为16
	



void Delay1ms()		//@12.000MHz

	unsigned char i, j;

	i = 12;
	j = 169;
	do
	
		while (--j);
	 while (--i);



void Delay10ms()		//@12.000MHz

	unsigned char i, j;

	i = 117;
	j = 184;
	do
	
		while (--j);
	 while (--i);


2 * 2变式矩阵按键实现独立按键

  • 我们使用4 * 4左下角的 2 * 2小矩阵按键来实现四个独立按键并显示对应的键值实验
  • 注意:便是独立按键我们跳线帽接KBD(即1 和 2连)

主要代码改变部分

void key_scanf()

	static uchar key_state = 0, row = 0;
	
	switch(key_state)
	
		case 0:
		
			P32 = 1, P33 = 1, P42 = 0, P44 = 0;
			if ((P32 != 1) || (P33 != 1))//判断有无按键按下
			
				Delay10ms();//消抖
				if ((P32 != 1) || (P33 != 1))
					key_state = 1;
			
			break;
		
		case 1:
		
			P32 = 1, P33 = 1, P42 = 0, P44 = 0;//先送行为高电平,列为低电平,找出哪一行
			if ((P32 != 1) || (P33 != 1))
			
				if (P32 == 0) row = 3, key_state = 2;
				if (P33 == 0) row = 4, key_state = 2;
			
			
			switch(row)
			
				
				case 3:
				
					P32 = 0, P33 = 0, P42 = 1, P44 = 1;
					if (P44 == 0) key_num = 8;
					if (P42 == 0) key_num = 9;
			
					break;
				
			
				case 4:
				
					P32 = 0, P33 = 0, P42 = 1, P44 = 1;
					if (P44 == 0) key_num = 12;
					if (P42 == 0) key_num = 13;
					
					break;
				
			
		
		
		
		case 2://按完键之后,就没有按键下去
		
			P32 = 1, P33 = 1, P42 = 0, P44 = 0;
			if ((P32 == 1) && (P33 == 1))
				key_state = 0;

			break;
		
	


2 * 2变式矩阵键盘控制蜂鸣器

//main.c--使用小2 * 2的小矩阵按键实现独立按键功能,按下S5键,蜂鸣器发声,按下S8键蜂鸣器关闭,按下另外两个键维持蜂鸣器当前的状态
#include "config.h"
#include "config.h"
uchar key_num = 20;
uchar start = 0;

void key_scanf()

	static uchar key_state = 0, row = 0;
	
	switch(key_state)
	
		case 0:
		
			P32 = 1, P33 = 1, P42 = 0, P44 = 0;
			if ((P32 != 1) || (P33 != 1))//判断有无按键按下
			
				Delay10ms();//消抖
				if ((P32 != 1) || (P33 != 1))
					key_state = 1;
			
			break;
		
		case 1:
		
			P32 = 1, P33 = 1, P42 = 0, P44 = 0;//先送行为高电平,列为低电平,找出哪一行
			if ((P32 != 1) || (P33 != 1))
			
				if (P32 == 0) row = 3, key_state = 2;
				if (P33 == 0) row = 4, key_state = 2;
			
			
			switch(row)
			
				
				case 3:
				
					P32 = 0, P33 = 0, P42 = 1, P44 = 1;
					if (P44 == 0) key_num = 8;
					if (P42 == 0) key_num = 9;
			
					break;
				
			
				case 4:
				
					P32 = 0, P33 = 0, P42 = 1, P44 = 1;
					if (P44 == 0) key_num = 12;
					if (P42 == 0) key_num = 13;
					
					break;
				
			
		
		
		
		case 2://按完键之后,就没有按键下去
		
			P32 = 1, P33 = 1, P42 = 0, P44 = 0;
			if ((P32 == 1) && (P33 == 1))
				key_state = 0;

			break;
		
	
	
	
	if (8 == key_num)
	
		start = 1;
	
	else if (13 == key_num)
	
		start = 0;
	
	else 
		start = 3;


void closeBeep()

	P2 = (P2 & 0x1f) | 0xa0;
	P06 = 0, P04 = 0;
	P2 &= 0x1f;

	Delay10ms();
		


void openBeep()

	P2 = (P2 & 0x1f) | 0xa0;
	P06 = 1, P04 = 1;
	P2 &= 0x1f;

	Delay10ms()以上是关于《蓝桥杯CT107D单片机竞赛板》:矩阵键盘模块的主要内容,如果未能解决你的问题,请参考以下文章

《蓝桥杯CT107D单片机竞赛板》:中断模块

《蓝桥杯CT107D单片机竞赛板》:蜂鸣器模块

《蓝桥杯CT107D单片机竞赛板》:LED模块

《蓝桥杯CT107D单片机竞赛板》:赛前准备工作

《蓝桥杯CT107D单片机竞赛板》:数码管模块

《蓝桥杯CT107D单片机竞赛板》:定时器模块