目录

一、实验题目

二、实验要求

三、实验过程及结果分析

四、实验流程图

五、实验源代码


一、实验题目

3.7 LCD 1602显示实验

二、实验要求

1、画出实验的流程图

2、编写源程序并进行注释

3、记录实验过程

4、记录程序运行结果截图

三、实验过程及结果分析

要求利用LCD1602和16个按键实现简单的十进制数的加减乘除四则运算。其中按键KEY0-KEY9代表数字0-9,按键KEY10-KEY13分别代表运算符+、-、*、/,按键KEY15代表=,按键KEY14代表清除命令。不管什么时候按下清除按键,计算过程均将停止,两个输入变量清零,屏幕将清屏。

LCD1602第一行用于显示所输入的两个计算数以及计算符,第二行用于显示计算结果,结果允许为附属,但输入的两个输入数都必须是双字节正整数范围内的数,即0-32767.除数必须保证不为0,否则将报错。在有余数除法中,必须能同时显示商与余数。

1. 在Proteus 环境下建立图1所示原理图,并将其保存为LCD1602_self.DSN 文件:

图1:实验原理图

2. 编写源程序,将其保存为LCD1602_self.c。运行Keil开发环境,建立工程LCD1602_self.uV2,CPU 为AT89C51,包含启动文件STARTUP.A51。将C 语言源程序LCD1602_self.c 加入工程LCD1602_self.uV2,并设置工程LCD1602_self.uV2 属性,将其晶振频率设置为12MHz,选择输出可执行文件,仿真方式为选择硬仿真,并选择其中的“PROTEUS VSM

MONITOR 51 DRIVER”仿真器。

3. 构造(Build)工程LCD1602_self.uV2。如果输入有误进行修改,直至构造正确,生成可执行程序LCD1602_self.hex 为止,为AT89C51 设置可执行程序LCD1602_self.hex。

4. 运行程序,点击按键输入数据与运算符,计算,观察计算结果,并验证其是否正确,输入过程中,按“清除按键”观察结果,重新输入数据计算并验证。

1)加法:1+2=3,如图2:

图2:加法测试

2)减法:5-3=2,如图3:

图3:减法测试

3)特殊情况:6-9=-3,如图4:

图4:负数减法测试

4)乘法:4*5=20,如图5:

图5:乘法测试

5) 除法:20/5=4,如图6:

图6:除法测试

6) 带余数的除法,如图7:

图7:带余数的除法测试

7) 除法为0报错,如图8:

图8:除法为0报错

8) 清零,如图9:

图9:清零

四、实验流程图

图10:实验流程图

编程时要有一个状态变量,该变量用于记录当前是输入的哪个变量。输入第一个变量,遇到输入运算符时结束第一个变量的输入。输入第二个变量,遇到“=”号时结束第二个变量的输入,并且开始计算结果。

计算结果由于是16 进制的,要将其转换成十进制,并将该十进制的数转换成字符串后逐位显示出来。减法时要注意结果是否为负,除法时要注意除数是否为0,结果是否带有余数。另外,按键要注意去抖动处理。

采用的是逐行扫描,扫描的时候将要扫描的行置0,其余的行置1;扫描过程中,所有的列全部置1,当某一行的其中一个按键被按下,且正好扫描到这一样,那么所在的列将会被置0. 这时只需要;将行与1111相与即可判断那一列为0,即按下了哪一列。也是实验3.6中键盘扫描的基本思路。

五、实验源代码

#include<reg51.h>     //预处理伪指令
#define uint unsigned int
#define uchar unsigned char
sbit lcden=P1^5;       //定义引脚E使能端,高到低液晶模块执行任务
sbit rs=P1^7;
sbit rw=P1^6;         // 控制读写
sbit busy=P0^7;
char i,j,temp,num;
long a=0,b=0,c=0,d=0;  //初始化a参与运算的第一个数,b参与运算的第二个数,c得数,d余数
float a_c,b_c;
uchar flag,signal;  //flag表示运算符是否按下//signal表示按下运算符的名称uchar code table[]={
0,1,2,3,
4,5,6,7,
8,9,0x2b-0x30,0x2d-0x30,
0x2a-0x30,0x2f-0x30,0x01-0x30,0x3d-0x30};    //定义table数组
uchar code error[]="Error!"; //定义error数组,用于显示除数为0的情况void delay(uchar z)     // 设置延迟函数
{uchar y;for(z;z>0;z--)for(y=0;y<110;y++);
}
void check()      // 判断系统状态
{do{P2=0xFF;rs=0;        rw=1;        lcden=0;     delay(1);    lcden=1;     }while(busy==1);  //判断是否为空闲,1为忙,0为空闲
}
void lcd_wcmd(uchar com) // 写指令
{P2=com;          rs=0;             rw=0;              lcden=0;      check();lcden=1;
}
void lcd_wdat(uchar date)       // 写数据
{P2=date;      rs=1;          rw=0;          lcden=0;check();lcden=1;
}
void init() //初始化
{num=-1;lcden=1;             // 使能信号为高电平lcd_wcmd(0x38);       // 8位,2行,5X7点阵lcd_wcmd(0x0c);      //显示开,光标关,不闪烁lcd_wcmd(0x06);     //增量方式不移位,地址自动增加 lcd_wcmd(0x80);     //检测忙信号lcd_wcmd(0x01);       //清屏i=0;j=0;flag=0;   signal=0;
}
void keyscan()   // 键盘扫描
{P3=0xfe;    //扫描第一行,后四位是行                          if(P3!=0xfe){delay(20);    //延时去抖动if(P3!=0xfe)        //第一行有键按下  {temp=P3&0xf0;  // 将列与1111进行与操作取列号switch(temp)   // 根据与出来的列号进行选择{case 0xe0:num=0;break;case 0xd0:num=1;break; case 0xb0:num=2;break;case 0x70:num=3;break;}}while(P3!=0xfe);               if(flag==0)    // 没有按过符号键时输入继续赋给第一个数{a=a*10+table[num]; }else           // 如果按过符号键,则赋给第二个数{b=b*10+table[num]; }i=table[num];lcd_wdat(0x30+i);    //  显示屏写入数字}P3=0xfd; //扫描第二行if(P3!=0xfd){delay(5);if(P3!=0xfd)  // 不等于初值,即代表该行有按键按下{          // 第二行有数被按下temp=P3&0xf0;   // 列与1111相与,判断按下的列switch(temp){case 0xe0:num=4;break;case 0xd0:num=5;break;case 0xb0:num=6;break;case 0x70:num=7;break;}}while(P3!=0xfd);if(flag==0)   //没有按过符号键{a=a*10+table[num]; }else  //按过符号键{b=b*10+table[num]; }i=table[num];lcd_wdat(0x30+i); //写入显示屏}P3=0xfb; //扫描第三行 if(P3!=0xfb){delay(5);if(P3!=0xfb){temp=P3&0xf0;switch(temp){case 0xe0:num=8;break;case 0xd0:num=9;break;case 0xb0:num=10;break;case 0x70:num=11;break;}}while(P3!=0xfb);     // 第三行的话不全是数字 if(num==8||num==9)   //按下的是'8','9'{ if(flag==0) //没有按过符号键{a=a*10+table[num]; }else     //按过符号键{b=b*10+table[num]; }}//0-9用tableelse if(num==10)   // 如果按下的是'+'{flag=1;signal=1;   // signal为1表示按下的是加号}else if(num==11) //如果按下的是'-'{flag=1;signal=2;  //2表示按下的是减号}i=table[num];lcd_wdat(0x30+i);}P3=0xf7;    // 第四行都是符号if(P3!=0xf7){delay(5);if(P3!=0xf7){temp=P3&0xf0;     // 列和1111相与取列号switch(temp){case 0xe0:num=12;break;case 0xd0:num=13;break;case 0xb0:num=14;break;case 0x70:num=15;break;}}while(P3!=0xf7);switch(num){case 12:{lcd_wdat(0x30+table[num]); flag=1;signal=3;}break;case 13:{lcd_wdat(0x30+table[num]); flag=1;signal=4;}                //运算符号用table   break;case 14:{lcd_wcmd(0x01);i=0;j=0;a=0;b=0;c=0;d=0;flag=0;signal=0;}    //按下的是"清零" ,0x01指令break;case 15:{j=1;if(signal==1)    //+号{lcd_wcmd(0x80+0x40); //第二行              c=a+b;lcd_wdat(0x3d);while(c!=0){if(c/10000!=0){lcd_wdat(0x30+c/10000);c=c%10000;lcd_wdat(0x30+c/1000);c=c%1000;lcd_wdat(0x30+c/100);c=c%100;lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);}  else if(c/1000!=0){lcd_wdat(0x30+c/1000);c=c%1000;lcd_wdat(0x30+c/100);c=c%100;lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);}else if(c/100!=0){lcd_wdat(0x30+c/100);c=c%100;lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);}else if(c/10!=0){lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c); }else if(c/10==0){lcd_wdat(0x30+c);}a=0;b=0;c=0;flag=0;signal=0;}}else if(signal==2)  {lcd_wcmd(0x80+0x40); //第二行if(a-b>0)c=a-b;else c=b-a;              //c为绝对值lcd_wdat(0x3d);     //写"="                          if(a-b<0)lcd_wdat(0x2d);      //小于0时为负号while(c!=0)           //若c不为0{if(c/10000!=0)          //则先从最高位写起{lcd_wdat(0x30+c/10000);c=c%10000;lcd_wdat(0x30+c/1000);c=c%1000;lcd_wdat(0x30+c/100);c=c%100;lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);}  else if(c/1000!=0){lcd_wdat(0x30+c/1000);    c=c%1000; lcd_wdat(0x30+c/100);c=c%100;lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);}else if(c/100!=0){lcd_wdat(0x30+c/100);c=c%100;lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);}else if(c/10!=0){lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);   }else if(c/10==0){lcd_wdat(0x30+c);}a=0;b=0;c=0;flag=0;signal=0;                          }}else if(signal==3)  //乘号的情况{lcd_wcmd(0x80+0x40);c=a*b;lcd_wdat(0x3d); while(c!=0){    if(c/10000!=0){lcd_wdat(0x30+c/10000);c=c%10000;lcd_wdat(0x30+c/1000);c=c%1000;lcd_wdat(0x30+c/100);c=c%100;lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);}                  else if(c/1000!=0){lcd_wdat(0x30+c/1000);c=c%1000;lcd_wdat(0x30+c/100);c=c%100;lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);}else if(c/100!=0){lcd_wdat(0x30+c/100);c=c%100;lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);}else if(c/10!=0){lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c); }else if(c/10==0){lcd_wdat(0x30+c);}a=0;b=0;c=0;flag=0;signal=0;}}else if(signal==4)  //除号的情况{lcd_wcmd(0x80+0x40);lcd_wcmd(0x06);if(b==0){i=0;while(error[i]!='\0'){lcd_wdat(error[i]); i++;}a=0;b=0;c=0;flag=0;signal=0;}                          //被除数为0显示errorelse if((a%b==0)&&(b!=0))  // 整除时输出c{lcd_wdat(0x3d);                              c=a/b;if(a/b<=0){lcd_wdat(0x30); }while(c!=0){if(c/10000!=0){lcd_wdat(0x30+c/10000);c=c%10000;lcd_wdat(0x30+c/1000);c=c%1000;lcd_wdat(0x30+c/100);c=c%100;lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);}  else if(c/1000!=0){lcd_wdat(0x30+c/1000);c=c%1000;lcd_wdat(0x30+c/100);c=c%100;lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);}else if(c/100!=0){lcd_wdat(0x30+c/100);c=c%100;lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);}else if(c/10!=0){lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c); }else if(c/10==0){lcd_wdat(0x30+c);}a=0;b=0;c=0;flag=0;signal=0;}}else if((a%b!=0)&&(b!=0))   //若不整除输出c```d{c=a/b;d=a%b;lcd_wdat(0x3d);  if(a/b<=0){lcd_wdat(0x30); }while(c!=0){ if(c/10000!=0){lcd_wdat(0x30+c/10000);c=c%10000;lcd_wdat(0x30+c/1000);c=c%1000;lcd_wdat(0x30+c/100);c=c%100;lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);}  else if(c/1000!=0){lcd_wdat(0x30+c/1000);c=c%1000;lcd_wdat(0x30+c/100);c=c%100;lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);}                           else if(c/100!=0){lcd_wdat(0x30+c/100);c=c%100;lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);}else if(c/10!=0){lcd_wdat(0x30+c/10);c=c%10;lcd_wdat(0x30+c);   }else if(c/10==0){lcd_wdat(0x30+c);}a=0;b=0;c=0;flag=0;signal=0;}lcd_wdat(0x2e);lcd_wdat(0x2e);lcd_wdat(0x2e);if(d/10000!=0){lcd_wdat(0x30+d/10000);d=d%10000;lcd_wdat(0x30+d/1000);d=d%1000;lcd_wdat(0x30+d/100);d=d%100;lcd_wdat(0x30+d/10);d=d%10;lcd_wdat(0x30+d);}else if(d/1000!=0){lcd_wdat(0x30+d/1000);d=d%1000;lcd_wdat(0x30+d/100);d=d%100;lcd_wdat(0x30+d/10);d=d%10;lcd_wdat(0x30+d);}else if(d/100!=0){lcd_wdat(0x30+d/100);d=d%100;lcd_wdat(0x30+d/10);d=d%10;lcd_wdat(0x30+d);}else if(d/10!=0){lcd_wdat(0x30+d/10);d=d%10;lcd_wdat(0x30+d);    }else if(d/10==0){lcd_wdat(0x30+d);  }}}break;}}}}main() // 定义主程序
{init();    //初始化子程序while(1)      //一直循环{keyscan();  // 键盘扫描函数扫描输入}
}

受于文本原因,本文相关实验工程无法展示出来,现已将资源上传,可自行下载。

山东大学单片机原理与应用实验工程文件3.7LCD1602显示实验-单片机文档类资源-CSDN下载山东大学单片机原理与应用实验工程文件3.7LCD1602显示实验详解博客地址:https:/更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/m0_52316372/85924094

山东大学单片机原理与应用实验 3.7LCD 1602显示实验相关推荐

  1. 山东大学单片机原理与应用实验 3.4 矩阵键盘扫描实验

    目录 一.实验题目 二.实验要求 三.实验过程及结果记录 1. 在Proteus 环境下建立图1所示原理图,并将其保存为keyscan_self.DSN 文件. 2. 编写控制源程序,将其保存为key ...

  2. 山东大学单片机原理与应用实验 C语言程序实验

    一.实验题目 C语言程序实验 二.试验要求 片内RAM30H开始的32个单元中分布着随机的有符号8位二进制数,按从小到大的顺序进行排序,排序后的数据仍然保存到30H开始的32个单元中(低地址存放小数据 ...

  3. 山东大学单片机原理与应用实验 汇编程序实验2

    一.实验题目 汇编程序实验2 二.实验要求 片内RAM30H开始的32个单元中分布着随机的有符号8位二进制数,按从小到大的顺序进行排序,排序后的数据仍然保存到30H开始的32个单元中(低地址存放小数据 ...

  4. 山东大学单片机原理与应用实验 3.2 拓展并行I/O口实验

    目录 一.实验题目 二.实验要求 三.实验过程及结果记录 1. 在Proteus环境下建立原理图,如图1所示,并保存为expandIO.DSN文件. 2. 将实验代码写入文本文档,并保存为expand ...

  5. 实验六 键盘扫描显示实验(矩阵键盘)

    实验六 键盘扫描显示实验(矩阵键盘) 一.实验要求 在上一个实验的基础上,利用实验仪提供的键盘扫描电路和显示电路,做一个扫描键盘和数码显示实验,把按键输入的键码在八位数码管上显示出来. 实验程序可分成 ...

  6. 山东大学单片机原理与应用实验 4.1 按键声光报警实验

    目录 一.实验题目 二.实验要求 三.实验过程及结果 四.实验流程图 五.实验源代码 一.实验题目 4.4按键声光报警实验 二.实验要求 1.画出实验的流程图 2.编写源程序并进行注释 3.记录实验过 ...

  7. 山东大学单片机原理与应用实验 4.5 8255并行I/O扩展及交通信号灯控制实验

    目录 一.实验题目 二.实验要求 三.实验过程及结果分析 四.实验流程图 五.实验源代码 一.实验题目 4.5 8255并行I/O扩展及交通信号灯控制实验 二.实验要求 1.画出实验的流程图 2.编写 ...

  8. STC51单片机20——DS1302可调电子时钟1602显示proteus仿真

    #include<reg52.h> #include<intrins.h> #define uchar unsigned char #define uint  unsigned ...

  9. FPGA实验---数码管秒表显示实验

    实验主要分为两大块: 第一部分就是秒表的实现功能: 第二部分就是数码管显示功能: 在这之前由于我们外部有启动,暂停的按钮,为了防止按键亚稳态需要打两拍寄存: 其中秒表显示部分主要实现是: 外部时钟采用 ...

最新文章

  1. 图像处理中的跨度(stride)
  2. 配置Xmanager连接linux
  3. Zookeeper配置文件中的配置项解释和Zookeeper的安装
  4. linux搜索过滤器,Unix和Linux管道(pipe)和过滤器(filter)使用介绍
  5. 子查询in和表连接效率
  6. 如何在Ubuntu系统下搭建Android开发环境
  7. linux etc 服务启动脚本,linux 服务脚本启动问题
  8. 单片机串行通信全解析
  9. python字符串对比两项_Python之字符串比较is、==、__cmp__
  10. Redmi K20 Pro尊享版官宣:升级为骁龙855 Plus旗舰平台
  11. Ajax实现搜索提示框~超级详细
  12. 2B码农想转做产品,这的规划是否靠谱?
  13. Linux搭建Git服务器教程
  14. 巨牛,访问github速度加快数倍
  15. PSCAD X4.6.2 免费下载
  16. 用access建立一个试题库_access2010怎样建立自己的试题库?
  17. windows上比较好用的截图软件+Gif录制软件+看图软件,建议收藏!
  18. 台湾大学林轩田机器学习技法课程学习笔记14 -- Radial Basis Function Network
  19. 工业B2B电商平台整合延伸工业供应链上下游,打造产业链闭环
  20. Recurrent Filter Learning for Visual Tracking(RFL)论文笔记

热门文章

  1. 2018护网杯第一场 web easy tornado LTshop超详细解答
  2. 计算机室在初中英语教学中的应用,浅谈现代教育技术在初中英语教学中的运用...
  3. STEMWIN窗口管理学习
  4. 百钱买百鸡——java
  5. 用Python筛选底部股票代码
  6. 利用html写一个日历,Vue写一个日历
  7. C# 使用串口分析SAM协议,读取身份证信息
  8. dotnetty android 交互,DotNetty发送请求的最佳实践
  9. 加盟库、物流园入出库顶层业务流程图
  10. 基于北洋OPOS SDK二次开发包,支持EPSON和北洋、佳博、商祺等支持标准ESC/POS指令的POS打印机