基于单片机的简易设计原理
专业:通信专业 班级:通信1班 姓名:刘民 学号:1304041127
摘要:按下键盘,通过键盘扫描程序,在LCD 液晶显示屏上显示按键的操作过程,最终显示计算结果,实现计算器的基本功能。本文详细介绍LCD 显示屏、矩阵键盘与C51单片机接口的应用,并介绍如何通过C51单片机实现计算器的算法。 关键字:C51单片机,键盘,LCD 液晶,计算器
一、设计任务:
本次实验是要以51系列单片机为核心实现一个简易计算器,它的结构简单,外部主要由4*4矩阵键盘和一个液晶显示屏构成,内部由一块STC90C51单片机构成,通过软件编程可实现简单加、减、乘、除、清除结果。实现对计算器的设计,具体设计如下:
1、采用6位显示,最大显示值为“999999”,设计16个按键的矩阵键盘,按键包括‘0~9’、‘+’、‘-’、‘*’、‘/’、‘=’、‘C ’。
2、加减法做四字节运算;乘法做双字节运算;除法被除数为四字节,除数为两字节。
3、当运算结果超出显示范围时,显示ERROR !。
4、上述运算输入值均为整数,当结果带有小数时,可以采用四舍五入方式处理,也可以带小数显示。
二 、方案论证
经分析,计算器电路包括三个部分:显示电路、、4*4键扫描电路、单片机微控制电路。具体如下:
⒈)LCD 显示电路
LCD1602作为一个成熟的产品,使用简单,模式固定,便于移植到各
种类型的程序,但是初学者往往要注意结合LCD 本身的时序图来完善初始化程序。又以其微功耗、体积小、显示内容丰富、超薄轻巧的诸多优点,故采用LCD.
⒉)4*4键盘扫描电路(中断式,扫描式,反转式)
用户设计行列键盘接口,一般常采用3 种方法读取键值。一种是中
断式,外两种是扫描法和反转法。
扫描法:
对键盘上的某一行送低电平,其他行及列全为高电平,然后读取列值,检查各列线点评的变化,如果某列线电平为低电平,就可以确定此行此列交叉点处的按键被按下,采用延时去抖动。 ⒊) 单片机微控制电路
微控制电路就是以AT89C51为核心的控制核心,主要注意晶振电路的接法和复位电路的接法。
三 硬件电路的设计
3.1 硬件设计电路框图
线路原理框图
3.2、系统模块图:
四、键盘接口电路:
计算器输入数字和其他功能按键要用到很多按键,矩阵键盘采用四条I/O 线作为行线,四条I/O 线作为列线组成键盘,在行线和列线的每个交叉点上设置一个按键。这样键盘上按键的个数就为4×4个。这种行列式键盘结构能有效地提高
单片机系统中I/O 口的利用率。
矩阵键盘的工作原理:
计算器的键盘布局如图1所示:一般有16个键组成,在单片机中正好可以用一个P 口实现16个按键功能,这种形式在单片机系统中也最常用。
图2 键盘接口电路图
五、LCD 显示 LCD 显示器介绍
有字符型液晶显示模块(SMC1602A )和点阵式液晶显示模块(TCM12232A 、TCM12864N )下面以SMC1602A 为例介绍字符型液晶显示模块的功能及应用。
(一)、字符型液晶显示模块的引脚及功能
在1602液晶内部有字模发生存储器CGROM 及显示数据存储器DDRAM 。其中,字模发生存储器CGROM 主要用来存储192个常用字符的字模编码,包含标准的ASCII 码。DDRAM 是显示数据存储器共80个字节,分别对应1602液晶显示器的两行。第一行地址为0X00H~0X27H,共40个字节;第二行地址为0X40H~67H,共40个字节。 RAM 地址映像如下图:
(二):字符型液晶显示模块的控制操作
在1602读回的状态字中,D7位为状态BF ,当BF=1时表示忙碌, 此时不能进行写操作。当BF=0时表示状态为空闲,可以进行写操作。 (2)写操作:
(3)初始化命令字:
a. 工作方式设置指令
DL 设置与MCU 的接口方式。DL=1表示数据宽度为8位,DB0~DB7有效。 DL=0表示数据宽度为4位,DB4~DB7有效。N 设置显示字符行数。 N=0表示显示一行字符,N=1表示显示两行字符。F 设置显示字符字体, 一般为0。F=0表示显示5X8点阵字体,F=1表示显示5X11点整字体。
b. 显示状态设置
D 为画面显示状态位。D=1表示显示功能开,D=0表示显示功能关。 C 为光标显示状态位。C=1表示有光标,C=0表示无光标。
B 闪烁显示状态位。B=1表示光标闪烁,B=0表示光标不闪烁。
c. 输入方式设置指令
该指令的操作主要是设置显示字符的输入方式。即在操作数据写入/读出 后,AC 数据地址指针的修改方式。I/D=1时,AC 为自动加一计数器, I/D=0时,AC 为自动减一计数器。S 设置写入字符时是否允许画面滚动。 S=1时允许画面/光标滚动,S=0时禁止画面/光标滚动。
d. 光标或画面滚动设置指令
S/C滚动对象选择位。S/C=1时画面滚动,S/C=0时光标滚动。 R/L滚动方向选择位。R/L=1时向右滚动,R/L=0时向左滚动。
e.
清屏指令
执行清屏指令后,DDRAM 内容为空白的ASCII 码20H ,光标归位在 左上方,地址计数器AC=0.
f.
光标复位指令
执行光标复位指令后,AC=0,DDRAM 中的值不变。
g.DDRAM 地址设置指令
当需要向某一地址中写入数据时,先写入地址,再写入数据。
程序图
五、运算模块(单片机控制):
MCS-51 单片机是在一块芯片中集成了CPU 、RAM 、ROM 、定时器/计数器和多功能I/O等一台计算机所需要的基本功能部件。如果按功能划分,它由如下功能部件组成,即微处理器(CPU )、数据存储器(RAM )、程序存储器(ROM/EPROM)、并行I/O 口、串行口、定时器/计数器、中断系统及特殊功能寄存器(SFR )。
单片机是靠程序运行的,并且可以修改。通过不同的程序实现不同的功能,尤其是特殊的独特的一些功能,通过使用单片机编写的程序可以实现高智能,高效率,以及高可靠性!因此我们采用单片机作为计算器的主要功能部件,可以很快地实现运算功能。
六:设计心得、体会、总结
我的题目简易计算器的设计,对于我们这些实践中的新手来说,这是一次考验,怎样才能找到课堂所学与实际应用的最佳结合点?怎样让自己的计划更具有程序性,而不会忙无一用?这都需要我们所要考虑和努力的。这次设计我学到了很多,在设计过程中怎样去克服心理上的不良情绪。不仅巩固了所学知识,而且学到了很多书上学不到的知识,掌握了一种系统的学习方法,可以进行一些简单的编程。这次设计使我懂得了理论与实际结合很重要,只有理论知识是远远不够的,从而提高自己的实际动手能力和独立思考的能力,同时在设计过程中发现自己的不足,加强巩固,有利于后续的单片机考试。
调试过程中也遇到了很多问题,例如,液晶显示明明定义了两行显示,但实际中却只有一行,最后竟查资料发现,液晶内部自检时间比单片机慢,需要延时多定义,避免未完成自检就执行指。
主要参考文献
《单片机原理与接口技术》,李升主编,北京大学出版社,2011年7月
《单片机原理及应用实验指导书》,屈波等编,2012年2月25日 《微处理器综合实训系统模块化设计》戴建 编 2012年2月 《单片机原理及应用》,赵德安等编,机械工业出版社,2009年
附原理图
附:硬件设计电路的元件清单
void write_com(uchar com) //写指令 //***P1.0~P1.3接行*******P1.4~P1.7接列.
{ ******* P0接LCD******************//
附源代码
#include #define uchar unsigned char uchar code dis1[]="!rorre";//后面使用倒序显示 uchar code dis2[]="!rorre htam"; sbit busy=P0^7; sbit RS=P2^2; sbit RW=P2^1; sbit EN=P2^0; char i,j,temp,num; long a,b,c; uchar flag,fuhao; uchar code table[]={ 7,8,9,0, 4,5,6,0, 1,2,3,0, 0,0,0,0 }; uchar code table1[]={ 7,8,9,0x2f-0x30, 4,5,6,0x2a-0x30, 0x01-0x30,0,0x3d-0x30,0x2b-0x30 }; void delay(uchar z) //延时
{ uchar x,y; for(x=z;x>0;x--) for(y=0;y
} void ready() //忙检测 { do { P0=0xff; RS=0; RW=1; EN=0; delay(5); EN=1; } while(busy==1); } P0=com; RS=0; RW=0; EN=0; ready(); EN=1; delay(10); } void write_data(uchar m) //写数据 {P0=m; RS=1; RW=0; EN=0; ready(); EN=1; }
void inital() //初始化 { EN=1; write_com(0x38); //【设置LCD 为16X2
显示,5X7点阵, 八位数据接口】 delay(10); write_com(0x38); //【LCD 内检较单片机慢,
为防止未完成内检就执行指令,延迟,再写指令以完成内检】 write_com(0x0c); //无光标 write_com(0x06); //光标后移 write_com(0x80); write_com(0x01); //清屏 i=0; j=0; a=0; //第一个参与运算的数 b=0; //第二个参与运算的数 c=0; flag=0; //flag表示是否有符号键按下 fuhao=0; //fuhao表征按下的是哪个符号 } void keyscan() //键盘扫描程序
{
P1=0xfe; //将某一行置低,列全为高 if(P1!=0xfe) //判断是否有键按下 {
delay(20); //延时去抖动 if(P1!=0xfe) //重新确认 {
temp=P1&0xf0; //【行全置低,判断列是
否变化】
switch(temp) {
case 0xe0:
num=0; break; case 0xd0:
num=1; break; case 0xb0:
num=2; break; case 0x70:
num=3; break; } } while(P1!=0xfe);
if(num==0||num==1||num==2)
//如果按
下的是'7','8' 或'9
{
if(j==1) //确认一次计算完毕,清屏 { write_com(0x01); j=0; }
if(flag==0) //没有按过符号键 {
a=a*10+table[num]; }
else //如果按过符号键 {
b=b*10+table[num]; } }
else //如果按下的是'/' { flag=1;
fuhao=4; }
i=table1[num]; write_data(0x30+i); }
P1=0xfd; if(P1!=0xfd) {
delay(20); if(P1!=0xfd)
{ temp=P1&0xf0; switch(temp) { case 0xe0:
num=4 ; break; case 0xd0:
num=5; break; case 0xb0:
num=6; break;
case 0x70:
num=7; break; } }
while(P1!=0xfd);
if(num==4||num==5||num==6) //如
果按下是'4','5' 或'6
{
if(j==1) {
write_com(0x01); j=0; }
if(flag==0) {
a=a*10+table[num]; } else {
b=b*10+table[num];
} } else { flag=1; fuhao=3; }
i=table1[num]; write_data(0x30+i); } P1=0xfb; if(P1!=0xfb) {delay(20); if(P1!=0xfb) {
temp=P1&0xf0; switch(temp) {
case 0xe0:
num=8; break; case 0xd0:
num=9; break; case 0xb0:
num=10; break; case 0x70:
num=11; break; } }
while(P1!=0xfb);
if(num==8||num==9||num==10) //如果
按下的是'1','2' 或'3
{
if(j==1)
{ write_com(0x01); j=0; }
if(flag==0)
{ a=a*10+table[num]; } else
{
b=b*10+table[num]; } } else {
flag=1; fuhao=2; }
i=table1[num]; write_data(0x30+i); }
P1=0xf7; if(P1!=0xf7) { delay(20); if(P1!=0xf7) {
temp=P1&0xf0; switch(temp) { case 0xe0:
num=12; break; case 0xd0:
num=13; break; case 0xb0:
num=14; break; case 0x70:
num=15; break; } }
while(P1!=0xf7); switch(num)
{ case 12: //按下的是" 清零" { write_com(0x01); a=0; b=0; flag=0; fuhao=0; }
break;
case 13: //写'0'
{ if(j==1) //确认一次计算完毕,清屏 { write_com(0x01); j=0; }
if(flag==0) {
a=a*10;
write_data(0x30); }
if(flag==1) { b=b*10;
write_data(0x30); } }
break; case 14:
{ write_data(0x3d); // 写'=' j=1;
if(fuhao==1) //'写+'
{ write_com(0x80+0x4f); //【也可写成成write_com(0xc0+0x0f); 定义第二行】
write_com(0x04); // 光标前移 c=a+b;
if(c==0)
{write_data(0x30);} while(c!=0)
{ write_data(0x30+c%10); c=c/10; } a=0; b=0; flag=0; fuhao=0; } else
if(fuhao==2) //写负号'-' { write_com(0x80+0x4f); write_com(0x04); if(a-b>=0) c=a-b; else c=b-a; if(c==0)
{write_data(0x30);} while(c!=0) {
write_data(0x30+c%10); c=c/10; } if(a-b
write_data(0x2d); //写负号"-" a=0; b=0; flag=0; fuhao=0; } else
if(fuhao==3) //按下乘号按键 { write_com(0x80+0x4f); write_com(0x04); c=a*b; if(c==0)
{write_data(0x30);}
if(c>999999) //六位显示,最大显示'999999' 超
出显示 ‘error! ’
{
i=0;
while(dis1[i]!='\0') {write_data(dis1[i]); i++;
} }
if(c
write_data(0x30+c%10); c=c/10; }
a=0;b=0;flag=0;fuhao=0; } else
if(fuhao==4) //按下除号按键
{ write_com(0x80+0x4f); //重新定位 write_com(0x04); //光标前移
if(b==0) //错误 math error! {
i=0;
while(dis1[i]!='\0') {write_data(dis1[i]); i++;
} } else
{ i=0;
c=(long)(((float)a/b)*1000); while(c!=0) {
write_data(0x30+c%10); c=c/10; i++;
if(i==3) //精确到小数点后三位 write_data(0x2e); //写小数点 }
if(a/b
write_data(0x30); } a=0; b=0; flag=0; fuhao=0; } }
break; case 15: {
write_data(0x30+table1[num]); // '+' flag=1; fuhao=1; }
break; } } }
void main() {
inital();
while(1) {
keyscan(); } }
基于单片机的简易设计原理
专业:通信专业 班级:通信1班 姓名:刘民 学号:1304041127
摘要:按下键盘,通过键盘扫描程序,在LCD 液晶显示屏上显示按键的操作过程,最终显示计算结果,实现计算器的基本功能。本文详细介绍LCD 显示屏、矩阵键盘与C51单片机接口的应用,并介绍如何通过C51单片机实现计算器的算法。 关键字:C51单片机,键盘,LCD 液晶,计算器
一、设计任务:
本次实验是要以51系列单片机为核心实现一个简易计算器,它的结构简单,外部主要由4*4矩阵键盘和一个液晶显示屏构成,内部由一块STC90C51单片机构成,通过软件编程可实现简单加、减、乘、除、清除结果。实现对计算器的设计,具体设计如下:
1、采用6位显示,最大显示值为“999999”,设计16个按键的矩阵键盘,按键包括‘0~9’、‘+’、‘-’、‘*’、‘/’、‘=’、‘C ’。
2、加减法做四字节运算;乘法做双字节运算;除法被除数为四字节,除数为两字节。
3、当运算结果超出显示范围时,显示ERROR !。
4、上述运算输入值均为整数,当结果带有小数时,可以采用四舍五入方式处理,也可以带小数显示。
二 、方案论证
经分析,计算器电路包括三个部分:显示电路、、4*4键扫描电路、单片机微控制电路。具体如下:
⒈)LCD 显示电路
LCD1602作为一个成熟的产品,使用简单,模式固定,便于移植到各
种类型的程序,但是初学者往往要注意结合LCD 本身的时序图来完善初始化程序。又以其微功耗、体积小、显示内容丰富、超薄轻巧的诸多优点,故采用LCD.
⒉)4*4键盘扫描电路(中断式,扫描式,反转式)
用户设计行列键盘接口,一般常采用3 种方法读取键值。一种是中
断式,外两种是扫描法和反转法。
扫描法:
对键盘上的某一行送低电平,其他行及列全为高电平,然后读取列值,检查各列线点评的变化,如果某列线电平为低电平,就可以确定此行此列交叉点处的按键被按下,采用延时去抖动。 ⒊) 单片机微控制电路
微控制电路就是以AT89C51为核心的控制核心,主要注意晶振电路的接法和复位电路的接法。
三 硬件电路的设计
3.1 硬件设计电路框图
线路原理框图
3.2、系统模块图:
四、键盘接口电路:
计算器输入数字和其他功能按键要用到很多按键,矩阵键盘采用四条I/O 线作为行线,四条I/O 线作为列线组成键盘,在行线和列线的每个交叉点上设置一个按键。这样键盘上按键的个数就为4×4个。这种行列式键盘结构能有效地提高
单片机系统中I/O 口的利用率。
矩阵键盘的工作原理:
计算器的键盘布局如图1所示:一般有16个键组成,在单片机中正好可以用一个P 口实现16个按键功能,这种形式在单片机系统中也最常用。
图2 键盘接口电路图
五、LCD 显示 LCD 显示器介绍
有字符型液晶显示模块(SMC1602A )和点阵式液晶显示模块(TCM12232A 、TCM12864N )下面以SMC1602A 为例介绍字符型液晶显示模块的功能及应用。
(一)、字符型液晶显示模块的引脚及功能
在1602液晶内部有字模发生存储器CGROM 及显示数据存储器DDRAM 。其中,字模发生存储器CGROM 主要用来存储192个常用字符的字模编码,包含标准的ASCII 码。DDRAM 是显示数据存储器共80个字节,分别对应1602液晶显示器的两行。第一行地址为0X00H~0X27H,共40个字节;第二行地址为0X40H~67H,共40个字节。 RAM 地址映像如下图:
(二):字符型液晶显示模块的控制操作
在1602读回的状态字中,D7位为状态BF ,当BF=1时表示忙碌, 此时不能进行写操作。当BF=0时表示状态为空闲,可以进行写操作。 (2)写操作:
(3)初始化命令字:
a. 工作方式设置指令
DL 设置与MCU 的接口方式。DL=1表示数据宽度为8位,DB0~DB7有效。 DL=0表示数据宽度为4位,DB4~DB7有效。N 设置显示字符行数。 N=0表示显示一行字符,N=1表示显示两行字符。F 设置显示字符字体, 一般为0。F=0表示显示5X8点阵字体,F=1表示显示5X11点整字体。
b. 显示状态设置
D 为画面显示状态位。D=1表示显示功能开,D=0表示显示功能关。 C 为光标显示状态位。C=1表示有光标,C=0表示无光标。
B 闪烁显示状态位。B=1表示光标闪烁,B=0表示光标不闪烁。
c. 输入方式设置指令
该指令的操作主要是设置显示字符的输入方式。即在操作数据写入/读出 后,AC 数据地址指针的修改方式。I/D=1时,AC 为自动加一计数器, I/D=0时,AC 为自动减一计数器。S 设置写入字符时是否允许画面滚动。 S=1时允许画面/光标滚动,S=0时禁止画面/光标滚动。
d. 光标或画面滚动设置指令
S/C滚动对象选择位。S/C=1时画面滚动,S/C=0时光标滚动。 R/L滚动方向选择位。R/L=1时向右滚动,R/L=0时向左滚动。
e.
清屏指令
执行清屏指令后,DDRAM 内容为空白的ASCII 码20H ,光标归位在 左上方,地址计数器AC=0.
f.
光标复位指令
执行光标复位指令后,AC=0,DDRAM 中的值不变。
g.DDRAM 地址设置指令
当需要向某一地址中写入数据时,先写入地址,再写入数据。
程序图
五、运算模块(单片机控制):
MCS-51 单片机是在一块芯片中集成了CPU 、RAM 、ROM 、定时器/计数器和多功能I/O等一台计算机所需要的基本功能部件。如果按功能划分,它由如下功能部件组成,即微处理器(CPU )、数据存储器(RAM )、程序存储器(ROM/EPROM)、并行I/O 口、串行口、定时器/计数器、中断系统及特殊功能寄存器(SFR )。
单片机是靠程序运行的,并且可以修改。通过不同的程序实现不同的功能,尤其是特殊的独特的一些功能,通过使用单片机编写的程序可以实现高智能,高效率,以及高可靠性!因此我们采用单片机作为计算器的主要功能部件,可以很快地实现运算功能。
六:设计心得、体会、总结
我的题目简易计算器的设计,对于我们这些实践中的新手来说,这是一次考验,怎样才能找到课堂所学与实际应用的最佳结合点?怎样让自己的计划更具有程序性,而不会忙无一用?这都需要我们所要考虑和努力的。这次设计我学到了很多,在设计过程中怎样去克服心理上的不良情绪。不仅巩固了所学知识,而且学到了很多书上学不到的知识,掌握了一种系统的学习方法,可以进行一些简单的编程。这次设计使我懂得了理论与实际结合很重要,只有理论知识是远远不够的,从而提高自己的实际动手能力和独立思考的能力,同时在设计过程中发现自己的不足,加强巩固,有利于后续的单片机考试。
调试过程中也遇到了很多问题,例如,液晶显示明明定义了两行显示,但实际中却只有一行,最后竟查资料发现,液晶内部自检时间比单片机慢,需要延时多定义,避免未完成自检就执行指。
主要参考文献
《单片机原理与接口技术》,李升主编,北京大学出版社,2011年7月
《单片机原理及应用实验指导书》,屈波等编,2012年2月25日 《微处理器综合实训系统模块化设计》戴建 编 2012年2月 《单片机原理及应用》,赵德安等编,机械工业出版社,2009年
附原理图
附:硬件设计电路的元件清单
void write_com(uchar com) //写指令 //***P1.0~P1.3接行*******P1.4~P1.7接列.
{ ******* P0接LCD******************//
附源代码
#include #define uchar unsigned char uchar code dis1[]="!rorre";//后面使用倒序显示 uchar code dis2[]="!rorre htam"; sbit busy=P0^7; sbit RS=P2^2; sbit RW=P2^1; sbit EN=P2^0; char i,j,temp,num; long a,b,c; uchar flag,fuhao; uchar code table[]={ 7,8,9,0, 4,5,6,0, 1,2,3,0, 0,0,0,0 }; uchar code table1[]={ 7,8,9,0x2f-0x30, 4,5,6,0x2a-0x30, 0x01-0x30,0,0x3d-0x30,0x2b-0x30 }; void delay(uchar z) //延时
{ uchar x,y; for(x=z;x>0;x--) for(y=0;y
} void ready() //忙检测 { do { P0=0xff; RS=0; RW=1; EN=0; delay(5); EN=1; } while(busy==1); } P0=com; RS=0; RW=0; EN=0; ready(); EN=1; delay(10); } void write_data(uchar m) //写数据 {P0=m; RS=1; RW=0; EN=0; ready(); EN=1; }
void inital() //初始化 { EN=1; write_com(0x38); //【设置LCD 为16X2
显示,5X7点阵, 八位数据接口】 delay(10); write_com(0x38); //【LCD 内检较单片机慢,
为防止未完成内检就执行指令,延迟,再写指令以完成内检】 write_com(0x0c); //无光标 write_com(0x06); //光标后移 write_com(0x80); write_com(0x01); //清屏 i=0; j=0; a=0; //第一个参与运算的数 b=0; //第二个参与运算的数 c=0; flag=0; //flag表示是否有符号键按下 fuhao=0; //fuhao表征按下的是哪个符号 } void keyscan() //键盘扫描程序
{
P1=0xfe; //将某一行置低,列全为高 if(P1!=0xfe) //判断是否有键按下 {
delay(20); //延时去抖动 if(P1!=0xfe) //重新确认 {
temp=P1&0xf0; //【行全置低,判断列是
否变化】
switch(temp) {
case 0xe0:
num=0; break; case 0xd0:
num=1; break; case 0xb0:
num=2; break; case 0x70:
num=3; break; } } while(P1!=0xfe);
if(num==0||num==1||num==2)
//如果按
下的是'7','8' 或'9
{
if(j==1) //确认一次计算完毕,清屏 { write_com(0x01); j=0; }
if(flag==0) //没有按过符号键 {
a=a*10+table[num]; }
else //如果按过符号键 {
b=b*10+table[num]; } }
else //如果按下的是'/' { flag=1;
fuhao=4; }
i=table1[num]; write_data(0x30+i); }
P1=0xfd; if(P1!=0xfd) {
delay(20); if(P1!=0xfd)
{ temp=P1&0xf0; switch(temp) { case 0xe0:
num=4 ; break; case 0xd0:
num=5; break; case 0xb0:
num=6; break;
case 0x70:
num=7; break; } }
while(P1!=0xfd);
if(num==4||num==5||num==6) //如
果按下是'4','5' 或'6
{
if(j==1) {
write_com(0x01); j=0; }
if(flag==0) {
a=a*10+table[num]; } else {
b=b*10+table[num];
} } else { flag=1; fuhao=3; }
i=table1[num]; write_data(0x30+i); } P1=0xfb; if(P1!=0xfb) {delay(20); if(P1!=0xfb) {
temp=P1&0xf0; switch(temp) {
case 0xe0:
num=8; break; case 0xd0:
num=9; break; case 0xb0:
num=10; break; case 0x70:
num=11; break; } }
while(P1!=0xfb);
if(num==8||num==9||num==10) //如果
按下的是'1','2' 或'3
{
if(j==1)
{ write_com(0x01); j=0; }
if(flag==0)
{ a=a*10+table[num]; } else
{
b=b*10+table[num]; } } else {
flag=1; fuhao=2; }
i=table1[num]; write_data(0x30+i); }
P1=0xf7; if(P1!=0xf7) { delay(20); if(P1!=0xf7) {
temp=P1&0xf0; switch(temp) { case 0xe0:
num=12; break; case 0xd0:
num=13; break; case 0xb0:
num=14; break; case 0x70:
num=15; break; } }
while(P1!=0xf7); switch(num)
{ case 12: //按下的是" 清零" { write_com(0x01); a=0; b=0; flag=0; fuhao=0; }
break;
case 13: //写'0'
{ if(j==1) //确认一次计算完毕,清屏 { write_com(0x01); j=0; }
if(flag==0) {
a=a*10;
write_data(0x30); }
if(flag==1) { b=b*10;
write_data(0x30); } }
break; case 14:
{ write_data(0x3d); // 写'=' j=1;
if(fuhao==1) //'写+'
{ write_com(0x80+0x4f); //【也可写成成write_com(0xc0+0x0f); 定义第二行】
write_com(0x04); // 光标前移 c=a+b;
if(c==0)
{write_data(0x30);} while(c!=0)
{ write_data(0x30+c%10); c=c/10; } a=0; b=0; flag=0; fuhao=0; } else
if(fuhao==2) //写负号'-' { write_com(0x80+0x4f); write_com(0x04); if(a-b>=0) c=a-b; else c=b-a; if(c==0)
{write_data(0x30);} while(c!=0) {
write_data(0x30+c%10); c=c/10; } if(a-b
write_data(0x2d); //写负号"-" a=0; b=0; flag=0; fuhao=0; } else
if(fuhao==3) //按下乘号按键 { write_com(0x80+0x4f); write_com(0x04); c=a*b; if(c==0)
{write_data(0x30);}
if(c>999999) //六位显示,最大显示'999999' 超
出显示 ‘error! ’
{
i=0;
while(dis1[i]!='\0') {write_data(dis1[i]); i++;
} }
if(c
write_data(0x30+c%10); c=c/10; }
a=0;b=0;flag=0;fuhao=0; } else
if(fuhao==4) //按下除号按键
{ write_com(0x80+0x4f); //重新定位 write_com(0x04); //光标前移
if(b==0) //错误 math error! {
i=0;
while(dis1[i]!='\0') {write_data(dis1[i]); i++;
} } else
{ i=0;
c=(long)(((float)a/b)*1000); while(c!=0) {
write_data(0x30+c%10); c=c/10; i++;
if(i==3) //精确到小数点后三位 write_data(0x2e); //写小数点 }
if(a/b
write_data(0x30); } a=0; b=0; flag=0; fuhao=0; } }
break; case 15: {
write_data(0x30+table1[num]); // '+' flag=1; fuhao=1; }
break; } } }
void main() {
inital();
while(1) {
keyscan(); } }