具体功能实现
当我们按下矩阵按键中不同的按键时,在LCD1602显示相应的内容,同时一个按键按下多次可以切换不同的字母或数字,并且LED灯会闪烁。最后当我们按下确认时,蜂鸣器会发出不同频率的声音。
器件
蜂鸣器,AT89C51,若干按键,LCD1602,两支LED灯,排阻
仿真展示图
仿真前
仿真后
知识介绍
矩阵按键控制原理
如果使用独立按键与单片机连接, 每一个按键都需要单片机的一个 I/O 口, 若某单片机系统需较多按键, 用独立按键便会占用过多的 I/O 口资源。 单片机系统中 I/O 口资源往往比较宝贵, 当用到多个按键时为了减少 I/O 口引脚, 引入了矩阵按键。
矩阵按键检测原理
按键检测一般通过扫描来实现,先使某一列变为低电平,其余几列为高电平,后检测每行是否出现低电平。若没有出现,则某行按键没有被按下,若出现则说明按键被按下,即可锁定位置。
矩阵按键控制方法
①行列式法:
上图将第一列全部置0,其余位置均为1
将第一行全部置0,其余位全部置1。
因此我们可以得出按键按下的正是第一行第一列的
②线翻转法:
首先使所有行置为0,然后检测列是否含有低电平,如果有,则记录列的位置;之后再翻转,使所有列置为0,检测行是否有低电平,如果有,则记录行的位置(本文采用的是线翻转法)
主函数代码(C语言)KEIL5实现
#include
#include void delay(unsigned char ms); void delay2(int i); void lcd_wcmd(unsigned char cmd); void lcd_pos(unsigned char pos); void lcd_wdat(unsigned char dat); void lcd_init(); void xianshi(); void KeyDown(); void la_ba(); sbit rs= P2^6; sbit rw = P2^5; sbit ep = P2^7; sbit d=P3^0; sbit d1=P3^1; sbit lb=P3^2; int b,c,s=0,q=0,w=0; #define GPIO_KEY P1 unsigned char dis1[32]; unsigned char dis2[9]={',','A','D','G','J','M','P','T','W'}; unsigned char dis3[9]={'1','2','3','4','5','6','7','8','9'}; unsigned int code laba[36][5]={ 1,2,3,3,3,//A 2,1,1,1,3,//B 2,1,2,1,3,//C 2,1,1,3,3,//D 1,3,3,3,3,//E 1,1,2,1,3,//F 2,2,1,3,3,//G 1,1,1,1,3,//H 1,1,3,3,3,//I 1,2,2,2,3,//J 2,1,2,3,3,//K 1,2,1,1,3,//L 2,2,3,3,3,//M 2,1,3,3,3,//N 2,2,2,3,3,//0 1,2,2,1,3,//P 2,2,1,2,3,//Q 1,2,1,3,3,//R 1,1,1,3,3,//S 2,3,3,3,3,//T 1,1,2,3,3,//U 1,1,1,2,3,//V 1,2,2,3,3,//W 2,1,1,2,3,//X 2,1,2,2,3,//Y 2,2,1,1,3,//Z 2,2,2,2,2,//0 1,2,2,2,2,//1 1,1,2,2,2,//2 1,1,1,2,2,//3 1,1,1,1,2,//4 1,1,1,1,1,//5 2,1,1,1,1,//6 2,2,1,1,1,//7 2,2,2,1,1,//8 2,2,2,2,1,//9 }; // LCD1602代码开始 bit lcd_bz() { bit result; rs = 0; rw = 1; ep = 1; _nop_(); _nop_(); _nop_(); _nop_(); result = (bit)(P0 & 0x80); ep = 0; return result; } void lcd_wcmd(unsigned char cmd) { while(lcd_bz());//判断LCD是否忙碌 rs = 0; rw = 0; ep = 0; _nop_(); _nop_(); P0 = cmd; _nop_(); _nop_(); _nop_(); _nop_(); ep = 1; _nop_(); _nop_(); _nop_(); _nop_(); ep = 0; } void lcd_pos(unsigned char pos) { lcd_wcmd(pos | 0x80); } void lcd_wdat(unsigned char dat) { while(lcd_bz());//判断LCD是否忙碌 rs = 1; rw = 0; ep = 0; P0 = dat; _nop_(); _nop_(); _nop_(); _nop_(); ep = 1; _nop_(); _nop_(); _nop_(); _nop_(); ep = 0; } void lcd_init() { lcd_wcmd(0x38); delay(1); lcd_wcmd(0x0c); delay(1); lcd_wcmd(0x06); delay(1); lcd_wcmd(0x01); delay(1); } void xianshi() { int i=0,j=1,n=0; while(dis1[i] != '