昨天研究了矩阵按键在proteus7.8上的仿真问题,今天直接上个实例,用LCD1602显示在计算器上按下的按键字符。
仿真图:
LCD1602.h
#ifndef _LCD1602_H_
#define _LCD1602_H_
#include //重定义关键字 #ifndef uchar #define uchar unsigned char #endif #ifndef uint #define uint unsigned int #endif /********************************** PIN口定义 **********************************/ #define Lcd1602DataPin P0 sbit LCD1602_E=P2^7; sbit LCD1602_RW=P2^5; sbit LCD1602_RS=P2^6; /********************************** 函数声明 **********************************/ /*在51单片机12MHZ时钟下的延时函数*/ void Lcd1602_Delay1ms(uint c); //误差 0us /*LCD1602写入8位命令子函数*/ void LcdWriteCom(uchar com); /*LCD1602写入8位数据子函数*/ void LcdWriteData(uchar dat) ; /*LCD1602初始化子程序*/ void Lcd1602Init(); #endif LCD1602.c #include "lcd1602.h" /******************************************************************************* * 函 数 名 : Lcd1602_Delay1ms * 函数功能 : 延时函数 * 输 入 : c * 输 出 : 无 *******************************************************************************/ void Lcd1602_Delay1ms(uint c){//延时函数 uchar a,b; for (; c>0; c--){ for (b=199;b>0;b--){ for(a=1;a>0;a--); } } } /******************************************************************************* * 函 数 名 : LcdWriteCom * 函数功能 : 向LCD写入一个字节的命令 * 输 入 : com * 输 出 : 无 *******************************************************************************/ void LcdWriteCom(uchar com) //写入命令 { LCD1602_E = 0; //使能 LCD1602_RS = 0; /*选择发送命令*/ LCD1602_RW = 0; //选择写入 Lcd1602DataPin = com; //放入命令 Lcd1602_Delay1ms(1); //等待数据稳定 LCD1602_E = 1; //根据写数据时序图,拉高写入时序(数据) Lcd1602_Delay1ms(5); //保持时间 LCD1602_E = 0; //再拉低数据写完了,释放 } /******************************************************************************* * 函 数 名 : LcdWriteData * 函数功能 : 向LCD写入一个字节的数据 * 输 入 : dat * 输 出 : 无 *******************************************************************************/ void LcdWriteData(uchar dat) //写入数据 { LCD1602_E = 0; //使能清零 LCD1602_RS = 1; /*选择输入数据*/ LCD1602_RW = 0; //选择写入 Lcd1602DataPin = dat; //写入数据 Lcd1602_Delay1ms(1); LCD1602_E = 1; //写入时序 Lcd1602_Delay1ms(5); //保持时间 LCD1602_E = 0; } /******************************************************************************* * 函 数 名 : Lcd1602Init() * 函数功能 : 初始化LCD屏 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Lcd1602Init() //LCD初始化子程序 { LcdWriteCom(0x38); //开显示,设置为8总线,2行显示,5*7点阵,这是“功能设定指令” LcdWriteCom(0x0c); //开显示不显示光标,“显示开关控制指令” LcdWriteCom(0x06); //写一个指针加1,“进入模式设置指令” LcdWriteCom(0x01); //清屏,“清屏指令” LcdWriteCom(0x80); //设置数据指针起点,第一个字符是在0x00,位置,但写入的数据地址格式必须是0x**+0x80,因此在这提前加地址加一个0x80;这里不写也行但必须在main函数中调用前将数据要写入的地址+0x80 } main.c #include #include #include"lcd1602.h" #define uint unsigned int #define uchar unsigned char #define GPIO_KEY P1 //宏定义P1口,方便移植 uint dat; // 传入LCD1602写数据函数的数,用于存放最终获得的计算器上按键的行列信息 uchar i; //用于主函数的for循环 uchar KeyValue; //设一个最后的传递值(给P0的) void delay(uint x){ while(x--); } /******************************************************************************* * 函 数 名 : KeyDown() * 函数功能 : 矩阵按键的扫描,确定按下哪个键 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void KeyDown(void){ if((GPIO_KEY&0xf0)!=0xf0){//读取是否有按键按下,符合(1)的说明;补充:P1.0——P1.3是低四位,行表示 KeyValue=~(0xf0|GPIO_KEY); //这步很关键,得到KeyValue(P0)低四位数据,P0.0~P0.3亮的含义:分别表示是第一行到——第四行的某行亮 switch((GPIO_KEY&0xf0)){ //这个'|'要有 case(0X70): KeyValue|=0x80;break; //'4'行 case(0Xb0): KeyValue|=0x40;break; //'3'行 case(0Xd0): KeyValue|=0x20;break; //'2'行 case(0Xe0): KeyValue|=0x10;break; //'1'行 } } else{GPIO_KEY=_crol_(GPIO_KEY,1); } //如果高四位是为1,到下一行去判断 if(GPIO_KEY==0xef){GPIO_KEY=0xfe;} //这句很重要!!!,判断第四次移位是否完成:若低电平移到第五位P1.4,则返回P1.0重新轮询扫描!!! } void main(void){ GPIO_KEY=0xfe; //设一个行的轮询的初始值,从第一行开始 while(1){ //死循环,不断的查询中 for(i=0;i<4;i++){ //完成一整次轮询 KeyDown(); //调用按键判断函数 delay(1000); dat=KeyValue; //得到按键所在行列的信息 } GPIO_KEY=0xfe; //再赋值准备下次轮询 i=0;//清零,为下次轮询准备 switch(dat){ //根据获得的行列信息,匹配是哪个对应的字符 case 0x88: dat='+';break; case 0x48: dat='=';break; case 0x28: dat='0';break; case 0x18: dat='C';break; case 0x84: dat='-';break; case 0x44: dat='3';break; case 0x24: dat='2';break; case 0x14: dat='1';break; case 0x82: dat='*';break; case 0x42: dat='6';break; case 0x22: dat='5';break; case 0x12: dat='4';break; case 0x81: dat='/';break; case 0x41: dat='9';break; case 0x21: dat='8';break; case 0x11: dat='7';break; } Lcd1602Init(); //调用LCD1602的初始化函数 LcdWriteData(dat);//将获取的字符显示在显示屏上 } } 结果:按下‘7’键显示屏上显示‘7’ 学会了这个基础,就可以接下来模拟计算器啦!!!
上一篇:51单片机系列学习——逐行扫描的方式实现矩阵按键的仿真
下一篇:51单片机系列——学习LCD1602液晶显示-8总线-显示一串字符
推荐阅读最新更新时间:2024-11-10 21:35
推荐帖子
- 串口通讯,接收端数据错误问题
- 板子采用串口通讯,板端设置如下:ioctl(com1Fd,FIOBAUDRATE,9600);//设置波特率ioctl(com1Fd,FIOFLUSH,0);//清空缓冲区ioctl(com1Fd,FIOSETOPTIONS,OPT_RAW);//设置com口工作模式板子启动后会发送消息,板端显示消息内容正确,但是在接收端收到的消息中倒数第二个字节位置多出一个字节0x0d,并且这种情况只是偶而出现.我想问一下出现这种情况可能和哪些因素有关?多
- superjeson 嵌入式系统
- 电感线圈的品质因素Q
- 因数Q是表示线圈质量的一个重要参数。Q值的大小,表明电感线圈损耗的大小,其Q值越大,线圈的损耗越小;反之,其损耗越大。品质因数Q的定义为:当线圈在某一频率的交流电压下工作时,线圈所呈现的感抗和线圈直流电阻的比值。它可以用公式表达如下:式中:W--工作角频率 L--线圈电感量 R--线圈总耗损电阻根据使用场合的不同,对品质因数Q的要求也不同。对调谐回路中的电感线圈,Q值要求较高,因为Q值越高,回路的损耗就越小,回路的效率就越高;对鹅合线圈来说,Q值可以低一些;而
- qwqwqw2088 模拟与混合信号
- 什么是汽车音响系统?汽车音响技术五要点讲解
- 1、组成结构音响系统之所以可以称为音响,最基本的条件就是,有回放声音的功能。音响系统中,至少要包含笔者提出的下列几点,才有资格称为音响,这一点任何音响系统皆然,汽车音响亦不例外。汽车音响主要包括主机、扬声器、功放三部分。主机是汽车音响中最重要的组成部分,就好像人的大脑,要发出什么样的声音,得由大脑来控制。流行的主机有只有广播接收功能的RADIO主机、RADIO加MP3主机、CD主机、MP3加CD碟盒、CD加导航主机和CD/DVD/车载MP5主机,MP5主机已替代一般的车载CD音响系统,海量硬
- Jacktang 模拟与混合信号
- ESP8266模块通信问题
- 有没有哪位大神知道ESP8266连接上WIFI和TCP服务器之后我向模块发送AT指令和AT+CIPSEND指令模块没有返回OK而是直接发送到TCPServer端是什么原因ESP8266模块通信问题检查一下硬连接,先串口配置完成,再用串口调试工具操作ESP8266串口WIFI模块,让它与OneNet建立连接、传输数据,这几步必须正确固件的问题你先检查是你的AT配置是不是进入了透传模式,用AT+CIPMODE?命令查询下,不明白多看下官方文档模块已经是进入透传模式了吧,所有接收到的数据
- xuannian stm32/stm8
- MSP430
- 我使用IAR环境,编写MSP430F6433单片机,遇到以下两个问题。请各位大侠帮帮忙(1)从低功耗模式LPM3.5唤醒,按照手册写得应当有BOR事件,则系统复位,复位标志置位。但是我唤醒LPM3.5时,复位标志没有置位,所以也没有系统复位。(2)系统复位中断向量0xFFFE。但是只要程序中写入以下代码,编译就会出错。按照论坛高手提示。菜单Project的Options的Linker选项中的Config中,选择Overridedefaultprogram,并在其子项中选择Defined
- zilong 微控制器 MCU
- 高效单端正激DC/DC变换器
- 摘要:介绍一种特殊的单端正激DC/DC变换器,该变换器具有较高的功率传输效率和较大的功率输出。关键词:单端正激变换器高效DC/DC变换器广泛应用于通信、计算机及汽车等领域,近年来DC/DC变换器技术有了很大的发展,重点是研究高效、高功率输出、结构简单和价廉的变换器。本文介绍一种特殊的单端正激200W48V/24V变换器,由于电路的特殊结构,该变换器具有稳定性好、效率高、功率密度高等优点。高效单端正激DC/DC变换器
- zbz0529 模拟电子
设计资源 培训 开发板 精华推荐
- 用于手机的 1 节锂离子/锂聚合物电池充电器
- 使用 Analog Devices 的 LTC4162EUFD-SAD 的参考设计
- LTC3630AEDHC 4V 至 24V 输入至 3.3V 输出、具有外部软启动、小尺寸的 250mA 稳压器的典型应用电路
- Si4706-EVB,Si4706 高性能、76 至 108 MHz 数字无线电调谐器评估板
- EVAL-ADV7194EB,NTSC/PAL 视频编码器-解码器评估套件
- TLE 4263 5V 低压降稳压器的典型应用
- LT3973EDD 12V 降压转换器的典型应用
- ADP2139 紧凑型、800mA、3 MHz、降压型 DC 至 DC 转换器的典型应用
- 使用 ON Semiconductor 的 CS-8181 的参考设计
- NCP45521 Eco SWITCH 高级负载管理的典型应用热插拔电路