山东大学单片机原理与应用实验 3.7LCD 1602显示实验
目录
一、实验题目
二、实验要求
三、实验过程及结果分析
四、实验流程图
五、实验源代码
一、实验题目
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显示实验相关推荐
- 山东大学单片机原理与应用实验 3.4 矩阵键盘扫描实验
目录 一.实验题目 二.实验要求 三.实验过程及结果记录 1. 在Proteus 环境下建立图1所示原理图,并将其保存为keyscan_self.DSN 文件. 2. 编写控制源程序,将其保存为key ...
- 山东大学单片机原理与应用实验 C语言程序实验
一.实验题目 C语言程序实验 二.试验要求 片内RAM30H开始的32个单元中分布着随机的有符号8位二进制数,按从小到大的顺序进行排序,排序后的数据仍然保存到30H开始的32个单元中(低地址存放小数据 ...
- 山东大学单片机原理与应用实验 汇编程序实验2
一.实验题目 汇编程序实验2 二.实验要求 片内RAM30H开始的32个单元中分布着随机的有符号8位二进制数,按从小到大的顺序进行排序,排序后的数据仍然保存到30H开始的32个单元中(低地址存放小数据 ...
- 山东大学单片机原理与应用实验 3.2 拓展并行I/O口实验
目录 一.实验题目 二.实验要求 三.实验过程及结果记录 1. 在Proteus环境下建立原理图,如图1所示,并保存为expandIO.DSN文件. 2. 将实验代码写入文本文档,并保存为expand ...
- 实验六 键盘扫描显示实验(矩阵键盘)
实验六 键盘扫描显示实验(矩阵键盘) 一.实验要求 在上一个实验的基础上,利用实验仪提供的键盘扫描电路和显示电路,做一个扫描键盘和数码显示实验,把按键输入的键码在八位数码管上显示出来. 实验程序可分成 ...
- 山东大学单片机原理与应用实验 4.1 按键声光报警实验
目录 一.实验题目 二.实验要求 三.实验过程及结果 四.实验流程图 五.实验源代码 一.实验题目 4.4按键声光报警实验 二.实验要求 1.画出实验的流程图 2.编写源程序并进行注释 3.记录实验过 ...
- 山东大学单片机原理与应用实验 4.5 8255并行I/O扩展及交通信号灯控制实验
目录 一.实验题目 二.实验要求 三.实验过程及结果分析 四.实验流程图 五.实验源代码 一.实验题目 4.5 8255并行I/O扩展及交通信号灯控制实验 二.实验要求 1.画出实验的流程图 2.编写 ...
- STC51单片机20——DS1302可调电子时钟1602显示proteus仿真
#include<reg52.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned ...
- FPGA实验---数码管秒表显示实验
实验主要分为两大块: 第一部分就是秒表的实现功能: 第二部分就是数码管显示功能: 在这之前由于我们外部有启动,暂停的按钮,为了防止按键亚稳态需要打两拍寄存: 其中秒表显示部分主要实现是: 外部时钟采用 ...
最新文章
- 图像处理中的跨度(stride)
- 配置Xmanager连接linux
- Zookeeper配置文件中的配置项解释和Zookeeper的安装
- linux搜索过滤器,Unix和Linux管道(pipe)和过滤器(filter)使用介绍
- 子查询in和表连接效率
- 如何在Ubuntu系统下搭建Android开发环境
- linux etc 服务启动脚本,linux 服务脚本启动问题
- 单片机串行通信全解析
- python字符串对比两项_Python之字符串比较is、==、__cmp__
- Redmi K20 Pro尊享版官宣:升级为骁龙855 Plus旗舰平台
- Ajax实现搜索提示框~超级详细
- 2B码农想转做产品,这的规划是否靠谱?
- Linux搭建Git服务器教程
- 巨牛,访问github速度加快数倍
- PSCAD X4.6.2 免费下载
- 用access建立一个试题库_access2010怎样建立自己的试题库?
- windows上比较好用的截图软件+Gif录制软件+看图软件,建议收藏!
- 台湾大学林轩田机器学习技法课程学习笔记14 -- Radial Basis Function Network
- 工业B2B电商平台整合延伸工业供应链上下游,打造产业链闭环
- Recurrent Filter Learning for Visual Tracking(RFL)论文笔记
热门文章
- 2018护网杯第一场 web easy tornado LTshop超详细解答
- 计算机室在初中英语教学中的应用,浅谈现代教育技术在初中英语教学中的运用...
- STEMWIN窗口管理学习
- 百钱买百鸡——java
- 用Python筛选底部股票代码
- 利用html写一个日历,Vue写一个日历
- C# 使用串口分析SAM协议,读取身份证信息
- dotnetty android 交互,DotNetty发送请求的最佳实践
- 加盟库、物流园入出库顶层业务流程图
- 基于北洋OPOS SDK二次开发包,支持EPSON和北洋、佳博、商祺等支持标准ESC/POS指令的POS打印机