单片机:矩阵键盘和LCD1602

一、矩阵键盘

                            

1、检测按键的方法:

(1)先使1-4全部赋低电平,5-8赋高电平。当有按键按下时,5-8中会有某个点平被拉低。

(2)然后依次将1-4中的某一位置0,其他位置1,观察对应返回值,即可确定哪个按键被按下。

2、对应程序

unsigned char bsp_mkeyscan()
{
    unsigned char keyvalue = 0x99;
	KEYPORT = 0xF0;
	if (KEYPORT != 0xF0)
	{
		KEYPORT = 0xFE;
		if (KEYPORT != 0xFE)
		{
			keyvalue = KEYPORT;
			while(keyvalue == KEYPORT)bsp_segb();;
		}
		KEYPORT = 0xFD;
		if (KEYPORT != 0xFD)
		{
			keyvalue = KEYPORT;
			while(keyvalue == KEYPORT)bsp_segb();;
		}
		KEYPORT = 0xFB;
		if (KEYPORT != 0xFB)
		{
			keyvalue = KEYPORT;
			while(keyvalue == KEYPORT)bsp_segb();;
		}
		KEYPORT = 0xF7;
		if (KEYPORT != 0xF7)
		{
			keyvalue = KEYPORT;
			while(keyvalue == KEYPORT)bsp_segb();;
		}
	}
	return keyvalue; //根据keyvalue的值即可以确定按下的键
}

二、LCD1602

1、LCD原理

LCD(Liquid Crystal Display):液晶显示器的缩写,一种被动式的显示器,即液晶本身并不发光,而是经液晶经过处理后能改变光线通过方向的特性,而达到白底黑字或黑底白字显示的目的。
  液晶显示器具有功耗低、抗干扰能力强等优点,广泛用在仪器仪表和控制系统中。

2、LCD分类

按排列形状分:字段型、点阵字符型和点阵图形。
 字段型
      广泛用于电子表、数字仪表、计算器中。
 点阵字符型
      显示字母、数字、符号。它是由5×7或5×4点阵组成
,广泛应用在单片机应用系统中。
 点阵图形型
      笔记本电脑和彩色电视等设备中。

 1602液晶也叫1602字符型液晶 它是一种专门用来显示字母、数字、符号等的点阵型液晶模块 它有若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符。每位之间有一个点距的间隔 每行之间也有也有间隔 起到了字符间距和行间距的作用。

 1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块。

3、LCD1602的引脚

                

第1脚接地

第2脚接5V正电源

第3脚VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高, 对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。

第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。

第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址RS为低电平R/W为高电平时可以读忙信号RS为高电平R/W为低电平时可以写入数据。

第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。

第7~14脚:D0~D7为8位双向数据线。

第15脚:背光源正极。
第16脚:背光源负极。

4、显示地址映射

第一行第一个的地址是:80H

第二行第一个的地址是:C0H

5、字符发生存储器

 在对液晶模块的初始化中要先设置其显示模式,在液晶模块显示字符时光标是自动右移的,无需人工干预。每次输入指令前都要判断液晶模块是否处于忙的状态。

 1602液晶模块内部的字符发生存储器(CGROM)已经存储了128个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号等,每一个字符都有一个固定的代码(ASCII字符集字库),比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”

6、LCD指令说明
 指令1:清显示,指令码01H,光标复位到地址00H位置。
 指令2:光标复位,光标返回到地址00H。
 指令3:光标和显示模式设置 I/D:光标移动方向,高电平右移,低电平左移S:屏幕上所有文字是否左移或者右移。高电平表示有效,低电平则无效
 指令4:显示开关控制。 D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示; C:控制光标的开与关,高电平表示有光标,低电平表示无光标;B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。
 指令5:光标或显示移位 S/C:高电平时移动显示的文字,低电平时移动光标。
 指令6:功能设置命令 DL:高电平时为4位总线,低电平时为8位总线   N:低电平时为单行显示,高电平时双行显示 F: 低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符。
 指令7:字符发生器RAM地址设置。
 指令8:DDRAM地址设置。
 指令9:读忙信号和光标地址 BF:为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。
 指令10:写数据。
 指令11:读数据。
7、LCD1602的初始化过程。
延时15mS
 写指令38H(不检测忙信号)
 延时5mS
 写指令38H(不检测忙信号)
 延时5mS
 写指令38H(不检测忙信号)
 以后每次写指令、读/写数据操作均需要检测忙信号
 写指令38H:显示模式设置
 写指令08H:显示开
 写指令01H:清屏
 写指令06H:显示光标移动设置
 写指令0CH:显示开及光标设置
8、自定义字符显示
(1)1602LCD共有8个自定义字符。

  • 18
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
44矩阵键盘控制液晶1602程序 #include<reg52.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int #define shuju P0 //数据 #define bus P3 //键盘 sbit rs=P1^0; sbit rw=P1^1; sbit e=P1^2; sbit sda=P0; //IO口定义 sbit scl=P2^1; // uchar r; void delayms(int i) { int j; for(j=0;j<i;j++) {} } void enable() { rs=0; rw=0; e=0; delayms(65000); e=1; } void write() { rs=1; rw=0; e=0; delayms(65000); e=1; } void chushi() { sda=0; scl=0; shuju=0x01; enable(); shuju=0x38; enable(); shuju=0x0f; enable(); shuju=0x06; enable(); shuju=0x80; enable(); } void display(uchar i) { //uchar a; shuju=i; write(); } void jianpan() { uchar a; uchar k; bus=0xff; bus=0xef; //扫描第一行 delayms(600); a=bus; a=a&0x0f; if(a!=0x0f) { delayms(200); if(a!=0x0f) { switch(a) { case 0x0e: k=0x30; break; case 0x0d: k=0x34; break; case 0x0b: k=0x38; break; case 0x07: k=0x43; break; } display(k); r=r-1; while(a!=0x0f) { bus=0x0f; delayms(200); a=bus; //a=a&0x0f; } } } bus=0xdf; //扫描第二行 // lcdbus=0xff; delayms(600); a=bus; a=a&0x0f; if(a!=0x0f) { delayms(200); if(a!=0x0f) { switch(a) { case 0x0e: k=0x31; // shuju=0x05; break; case 0x0d: k=0x35; // shuju=0x06; break; case 0x0b: k=0x39; shuju=0x07; break; case 0x07: k=0x44; // shuju=0x08; break; } display(k); r=r-1; while(a!=0x0f) { bus=0x0f; delayms(200); a=bus; } } } bus=0xbf; //扫描第3行 delayms(600); a=bus; a=a&0x0f; if(a!=0x0f) { delayms(200); if(a!=0x0f) { switch(a) { case 0x0e: k=0x32; break; case 0x0d: k=0x36; break; case 0x0b: k=0x41; //k=58; // jia(); break; case 0x07: k=0x45; // jian(); break; } display(k); r=r-1; while(a!=0x0f) { bus=0x0f; delayms(200); a=bus; } } } bus=0x7f; //扫描第4行 delayms(600); a=bus; a=a&0x0f; if(a!=0x0f) { delayms(200); if(a!=0x0f) { switch(a) { case 0x0e: k=0x33; // jia(); // shuju=0x13; break; case 0x0d: k=0x37; //jian(); // shuju=0x14; break; case 0x0b: k=0x42; //cheng(); // shuju=0x50; break; case 0x07: k=0x46; //chu(); //shuju=0x16; break; } display(k); r=r-1; //a=lcdbus; // a=a&0x0f; while(a!=0x0f) { bus=0x0f; delayms(200); a=bus; } } } } void main() { while(1) { chushi(); r=0x10; while(r>0) { jianpan(); } shuju=0xc0; enable(); r=0x10; while(r>0) { jianpan(); } } }
以下是使用C51单片机矩阵键盘LCD1602显示器编写的计算器程序示例: ```c #include <reg52.h> #define uchar unsigned char #define uint unsigned int sbit RS=P2^0; //LCD1602的RS引脚接在单片机的P2.0口 sbit RW=P2^1; //LCD1602的RW引脚接在单片机的P2.1口 sbit EN=P2^2; //LCD1602的EN引脚接在单片机的P2.2口 uchar code table[]="0123456789*#"; //定义矩阵键盘输入字符对应的数组 uchar flag; //定义标志位,用于判断是否按下了键 void delay(uint x) //延时函数 { uint i,j; for(i=x;i>0;i--) for(j=110;j>0;j--); } void write_com(uchar com) //向LCD1602写入指令 { RS=0; //RS置0表示写入指令 RW=0; //RW置0表示写入模式 P0=com; //将指令写入P0口 EN=1; //使能 delay(1); //延时 EN=0; //取消使能 } void write_data(uchar dat) //向LCD1602写入数据 { RS=1; //RS置1表示写入数据 RW=0; //RW置0表示写入模式 P0=dat; //将数据写入P0口 EN=1; //使能 delay(1); //延时 EN=0; //取消使能 } void init_lcd1602() //LCD1602初始化函数 { write_com(0x38); //8位数据接口,显示2行,5*7点阵字符 write_com(0x0c); //开显示(无光标,不闪烁) write_com(0x06); //文字不动,光标自动右移 write_com(0x01); //清屏 } void keyscan() //矩阵键盘扫描函数 { uchar i; flag=0; //将标志位清零 P1=0xf0; //将P1口的低四位设置为0xf0,用于读取行的状态 if(P1!=0xf0) //如果有一行的状态不为0xf0,表示有按键按下 { delay(5); //延时去抖 if(P1!=0xf0) //再次检测按键是否按下 { for(i=0;i<4;i++) //循环读取列的状态 { P1=0x0f; //将P1口的高四位设置为0x0f,用于读取列的状态 if(P1!=(0x0f&(0x01<<i))) //如果列的状态与当前循环的列不同,表示该列的按键按下 { while(P1!=(0x0f&(0x01<<i))); //等待按键释放 write_data(table[i*4+(P1>>4)]); //将输入字符写入LCD1602 flag=1; //将标志位设置为1,表示有按键按下 break; //跳出循环 } } } } } void main() { uchar a[16]; //定义一个存储输入字符的数组 uchar b; //定义一个字符变量,用于存储每次输入的字符 uchar i,j,k=0; //定义三个计数器 uint x,y,z; //定义三个整型变量,用于存储输入的数字 init_lcd1602(); //初始化LCD1602 while(1) { keyscan(); //扫描矩阵键盘 if(flag==1) //如果有按键按下 { b=P0; //将输入字符存储到变量b中 if(b=='#') //如果输入字符为# { a[k]='\0'; //将数组a末尾加上'\0'表示字符串结束 for(i=0;i<k;i++) //循环检测输入字符串中是否含有非数字字符 { if(a[i]<'0'||a[i]>'9') //如果有非数字字符 { write_com(0xc0); //将光标移动到第二行第一个字符位置 write_data('E'); //在LCD1602上显示'E'表示错误 write_data('r'); write_data('r'); write_data('o'); write_data('r'); delay(1000); //延时1秒钟 write_com(0x01); //清屏 k=0; //将计数器k置0 break; //跳出循环 } } if(i==k) //如果输入字符串中没有非数字字符 { for(j=k-1,y=1,z=0;j>=0;j--,y*=10) //将输入字符串转换为整数 z+=y*(a[j]-'0'); write_com(0xc0); //将光标移动到第二行第一个字符位置 write_data('='); //在LCD1602上显示'=' for(i=0;x=z;i++) //将整数转换为字符数组 { a[i]=x%10+'0'; x/=10; } for(i--;i>=0;i--) //从后往前输出字符数组,即为计算结果 write_data(a[i]); delay(1000); //延时1秒钟 write_com(0x01); //清屏 k=0; //将计数器k置0 } } else if(b=='*') //如果输入字符为* { write_com(0xc0); //将光标移动到第二行第一个字符位置 write_data('*'); //在LCD1602上显示'*' a[k++]='*'; //将输入字符存储到数组a中 } else if(b>='0'&&b<='9') //如果输入字符为数字 { write_data(b); //在LCD1602上显示输入字符 a[k++]=b; //将输入字符存储到数组a中 } } } } ``` 该程序使用P1口读取矩阵键盘的状态,通过判断行和列的状态来确定用户输入的字符。输入的字符会存储到一个字符数组中,最终通过将字符数组转换为整数进行计算,并将计算结果转换为字符数组输出到LCD1602上显示。 需要注意的是,在使用矩阵键盘时,需要设置P1口的高四位为输入模式,低四位为输出模式,并将低四位全部置0,以便读取行的状态。同时,需要将高四位全部置1,以便读取列的状态。在LCD1602初始化时,需要先发送8位数据接口的指令,否则无法正常显示。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值