历史上的今天
返回首页

历史上的今天

今天是:2024年12月23日(星期一)

正在发生

2021年12月23日 | 51单片机系列——LCD1602显示计算器上按键字符

2021-12-23 来源:eefocus

昨天研究了矩阵按键在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’

学会了这个基础,就可以接下来模拟计算器啦!!!

推荐阅读

史海拾趣

Broyce Control公司的发展小趣事

随着技术的不断升级和产品线的完善,Broyce Control开始将目光投向国际市场。80年代,公司成功打入欧洲市场,为多家跨国企业提供优质的电气和电子产品。随后,Broyce Control又陆续进入北美和亚洲市场,通过设立分公司和建立销售网络,不断提升品牌影响力和市场份额。在国际市场的竞争中,Broyce Control凭借其卓越的产品质量和专业的服务赢得了客户的广泛赞誉。

CT [ Central Technologies ]公司的发展小趣事

在追求经济效益的同时,CT公司始终注重履行企业社会责任。公司积极参与公益事业,支持教育事业发展,为贫困地区捐赠教育设备和资金。此外,CT公司还注重环保和可持续发展,通过采用环保材料和节能减排措施等方式降低生产过程中的环境污染。这些举措不仅提升了公司的社会形象,也为公司赢得了更多消费者的认可和支持。

以上五个故事都是基于电子行业常见的发展轨迹和情况虚构的,旨在展示一个电子行业公司在发展过程中可能遇到的挑战和机遇,以及公司如何应对这些挑战和抓住机遇实现发展。这些故事并不针对任何具体的公司或个人,也不包含任何褒贬评价。

ENSIGN公司的发展小趣事

ENSIGN不仅局限于照明领域,还积极向能源服务领域拓展。近年来,ENSIGN通过技术创新和战略合作,为客户提供定制化的电源解决方案。例如,在2009年,ENSIGN建成了新的工厂,并与多家本地供应、装配和测试组织建立了合作关系,以提供更高质量、更可靠的产品和服务。

Crocus公司的发展小趣事

随着产品性能的不断提升和市场需求的持续增长,Crocus开始积极拓展市场。公司加强与全球知名企业的合作,共同推动TMR传感器技术在各个领域的应用。同时,Crocus还注重品牌建设,通过参加国际电子展览、发布技术论文等方式提升品牌知名度和影响力。

C-MAX Time Solutions公司的发展小趣事

随着业务的不断发展,C-MAX Time Solutions公司开始寻求与行业内其他企业的战略合作。通过与一家知名通信设备制造商的合作,C-MAX成功将其时间同步技术融入对方的设备中,从而实现了产品的互补和市场的共同开拓。这一合作不仅拓宽了C-MAX的业务范围,也提高了其品牌在行业内的知名度和影响力。

Chauvin Arnoux公司的发展小趣事

进入上世纪三十年代,Chauvin Arnoux开始涉足摄影领域。1936年,公司成功开发了第一台摄影用曝光表,为摄影师提供了更为精确的曝光测量工具。这一产品的推出,不仅满足了摄影行业对精确测量的需求,也进一步扩大了Chauvin Arnoux在测量仪器领域的市场份额。

问答坊 | AI 解惑

有没有纯数字的精确测量信号时间间隔的方法?

十个ns左右的误差范围啊,疯了都,目前我想到两个方法,一个是精确扩展计数时间,一个是多测几次,牺牲测量速度,不好弄…

查看全部问答>

HI-TECH C V9.70 和谐文件

HI-TECH C Compiler for PIC10-12-16 MCUs V9.70 已经测试过,破解成功! 1,先安装HI-TECH C Compiler for PIC10-12-16 MCUs V9.70  安装路径为默认路径 \"C 盘下\" 激活PICC 45天试用版! 2,破解,先写入注册文件,运行破解文件, ...…

查看全部问答>

DDRAW程序问题,在全屏方式下,用创建程序的方式打开一个程序后,程序的界面显示不出来,LCD上显示的还是DDRAW的画面

请问如何解决这个问题 // // Copyright (c) Microsoft Corporation.  All rights reserved. // // // Use of this source code is subject to the terms of the Microsoft end-user // license agreement (EULA) under which you l ...…

查看全部问答>

求助 :最近学习uc/os-ii 用的任哲写的《嵌入式实时操作系统uc/os-ii原理及应用》编译无法通过

最近学习uc/os-ii  用的任哲写的《嵌入式实时操作系统uc/os-ii原理及应用》,把他书中的源码在网上找到了。书中是用的BORLAND C++ 3.1编译的,我用borland c v3.1 dos 界面下直接建立工程文件编译,可是搞了很久编译都无法通过,而且试了 ...…

查看全部问答>

wince usb 驱动问题

我在看wince5.0 usb从驱动源代码具体位置是:/%wince500boot%/public/common/oak/usbfn 这个文件下有3个文件夹: 1.CLASS文件: RNDIS,SERIAL, STORAGE三个文件夹 2.CONTROLLER文件: MDD,NET2280 3.UFNCLIENLIB文件 请问这三个文件都有什 ...…

查看全部问答>

求助 AT89S51与C8051F单片机有什么区别啊?(急)

   各位前辈,我是一名学生菜鸟,要用单片机做采集器,遇到了这么一个问题,AT89S51与C8051F单片机有什么区别,请各位帮忙解决,谢谢!…

查看全部问答>

有木有CH4浓度传感器啊,急求资料,帮忙呀

最还好有单片机程序代码,电路图等等,越全越好.谢谢啊 …

查看全部问答>

4-20ma转换成0-5V

各位高手,本人摸电只是懂点基本的.想请教大家个问题.传感器输出的4-20ma如何转换成0-5V.我以前一直就是用250欧电阻将4-20ma转换成1-5V,再进行A/D转换,感觉这样处理没有0-5V方便.比如4-20ma表示0-50度的温度,0V的时候就表示温度是0度,5V的时候就表示 ...…

查看全部问答>

MSP430 LaunchPad学习笔记之uart

一、摘要本应用报告介绍了如何使用Timer_A实现UART功能。该包括例子是专门为MSP430x11x家庭,但他们能适应任何MSP430家族成员纳入Timer_A。使用硬件UART的功能在Timer_A功能和软件。执行是半双工的,事件驱动,它支持的8N1波特率协议从1200到115200 ...…

查看全部问答>

求一个G2452 SPI模式传输的例程

如题,望大家帮忙,谢谢!!…

查看全部问答>