虚拟仪器基于单片机的简易计算器设计.docx
- 文档编号:24465400
- 上传时间:2023-05-27
- 格式:DOCX
- 页数:15
- 大小:118.65KB
虚拟仪器基于单片机的简易计算器设计.docx
《虚拟仪器基于单片机的简易计算器设计.docx》由会员分享,可在线阅读,更多相关《虚拟仪器基于单片机的简易计算器设计.docx(15页珍藏版)》请在冰豆网上搜索。
虚拟仪器基于单片机的简易计算器设计
虚拟仪器
课程设计报告
作品名称:
基于51单片机的简易计算器设计
学校:
南阳师范学院
1、成员简介:
2、设计任务:
本次实验是要以51系列单片机为核心实现一个简易计算器,它的结构简单,外部主要由4*4矩阵键盘和一个液晶显示屏构成,内部由一块STC90C51单片机构成,通过软件编程可实现简单加、减、乘、除、清除结果。
实现对计算器的设计,具体设计如下:
1、采用6位显示,最大显示值为“999999”,设计16个按键的矩阵键盘,按键包括‘0~9’、‘+’、‘-’、‘*’、‘/’、‘=’、‘C’。
2、加减法做四字节运算;乘法做双字节运算;除法被除数为四字节,除数为两字节。
3、当运算结果超出显示范围时,显示ERROR!
。
4、上述运算输入值均为整数,当结果带有小数时,可以采用四舍五入方式处理,也可以带小数显示。
3、方案论证:
经分析,计算器电路包括三个部分:
显示电路、、4*4键扫描电路、单片机微控制电路。
具体如下:
1)LCD显示电路
LCD1602作为一个成熟的产品,使用简单,模式固定,便于移植到各种类型的程序,但是初学者往往要注意结合LCD本身的时序图来完善初始化程序。
又以其微功耗、体积小、显示内容丰富、超薄轻巧的诸多优点,故采用LCD.
2)4*4键盘扫描电路(中断式,扫描式,反转式)
用户设计行列键盘接口,一般常采用3种方法读取键值。
一种是中断式,外两种是扫描法和反转法。
扫描法:
对键盘上的某一行送低电平,其他行及列全为高电平,然后读取列值,检查各列线点评的变化,如果某列线电平为低电平,就列交叉点处的按键被按下,采用延时去抖动。
⒊) 单片机微控制电路
微控制电路就是以AT89C51为核心的控制核心,主要注意晶振电路的接法和复位电路的接法。
4、程序流程图:
5、程序代码:
#include"reg51.h"//此文件中定义了单片机的一些特殊功能寄存器
typedefunsignedintu16;//对数据类型进行声明定义
typedefunsignedcharu8;
//矩阵键盘定义
#defineGPIO_KEYP1
u8KeyValue;//用来存放读取到的键值
//LED灯定义
sbitLED=P3^6;
//74LS138定义
sbitCS2=P2^6;
sbitCS1=P2^7;
intNumber1=0;//计算的第一个数字
intNumber2=0;//计算的第二个数字
intResult=0;//结果
u8calculationflag=0;//计算标志位0表示未按加减1表示加2表示减
u8resultflag=0;//结算标志位0表示未按确认1表示按了确认
unsignedcharcodetable[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//数码管段显示口数据
/*******************************************************************************
*函数名:
Timer0Init
*函数功能:
定时器0初始化
*输入:
无
*输出:
无
*******************************************************************************/
voidTimer0Init()
{
TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
TH0=(65535-1000)/256;//给定时器赋初值,定时1ms
TL0=(65535-1000)%256;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=0;//关闭定时器
}
/*******************************************************************************
*函数名:
delay
*函数功能:
延时函数,i=1时,大约延时10us
*******************************************************************************/
voiddelay(u16i)
{
while(i--);
}
/*******************************************************************************
*函数名:
KeyDown
*函数功能:
检测有按键按下并读取键值
*******************************************************************************/
voidKeyDown(void)
{
chara=0;
GPIO_KEY=0x0f;
if(GPIO_KEY!
=0x0f)//读取按键是否按下
{
delay(1000);//延时10ms进行消抖
if(GPIO_KEY!
=0x0f)//再次检测键盘是否按下
{
//测试列给四列按键接到单片机的引脚为高电平,如果哪一列检测出来是低电平,说明该列有按键按下
GPIO_KEY=0X0F;
switch(GPIO_KEY)
{
case(0X07):
KeyValue=1;break;
case(0X0b):
KeyValue=2;break;
case(0X0d):
KeyValue=3;break;
case(0X0e):
KeyValue=4;break;
}
//测试行给四行按键接到单片机的引脚为高电平,如果哪一行检测出来是低电平,说明该行有按键按下
GPIO_KEY=0XF0;
switch(GPIO_KEY)
{
case(0X70):
KeyValue=KeyValue;break;
case(0Xb0):
KeyValue=KeyValue+4;break;
case(0Xd0):
KeyValue=KeyValue+8;break;
case(0Xe0):
KeyValue=KeyValue+12;break;
}
while((a<50)&&(GPIO_KEY!
=0xf0))//检测按键松手检测
{
delay(1000);
a++;
}
}
}
}
/*******************************************************************************
*函数名:
SegDisplay()
*函数功能:
数码管显示
*输入:
无
*输出:
无
*******************************************************************************/
voidSegDisplay()
{
//显示计算的数
if(resultflag==0)
{
//显示第一个数
if(calculationflag==0)
{
CS2=0;CS1=0;
P0=table[Number1/1000];
delay(10);
P0=0x00;
CS2=0;CS1=1;
P0=table[Number1%1000/100];
delay(10);
P0=0x00;
CS2=1;CS1=0;
P0=table[Number1%100/10];
delay(10);
P0=0x00;
CS2=1;CS1=1;
P0=table[Number1%10];
delay(10);
P0=0x00;
}
//显示第二个数
elseif(calculationflag>=1)
{
CS2=0;CS1=0;
P0=table[Number2/1000];
delay(10);
P0=0x00;
CS2=0;CS1=1;
P0=table[Number2%1000/100];
delay(10);
P0=0x00;
CS2=1;CS1=0;
P0=table[Number2%100/10];
delay(10);
P0=0x00;
CS2=1;CS1=1;
P0=table[Number2%10];
delay(10);
P0=0x00;
}
}
//显示计算结果
elseif(resultflag==1)
{
if(Result>=0)
{
CS2=0;CS1=0;
P0=table[Result/1000];
delay(10);
P0=0x00;
CS2=0;CS1=1;
P0=table[Result%1000/100];
delay(10);
P0=0x00;
CS2=1;CS1=0;
P0=table[Result%100/10];
delay(10);
P0=0x00;
CS2=1;CS1=1;
P0=table[Result%10];
delay(10);
P0=0x00;
}
elseif(Result<0)
{
CS2=0;CS1=0;
P0=0x40;//显示'-'号
delay(10);
P0=0x00;
CS2=0;CS1=1;
P0=table[(-Result)%1000/100];
delay(10);
P0=0x00;
CS2=1;CS1=0;
P0=table[(-Result)%100/10];
delay(10);
P0=0x00;
CS2=1;CS1=1;
P0=table[(-Result)%10];
delay(10);
P0=0x00;
}
}
}
/*******************************************************************************
*函数名:
main
*函数功能:
主函数
*输入:
无
*输出:
无
*******************************************************************************/
voidmain()
{
Timer0Init();
LED=1;
P2=0Xff;
while
(1)
{
KeyDown();
//清空
if(KeyValue==15)
{
LED=1;
TR0=0;
Number1=0;
Number2=0;
calculationflag=0;
Result=0;
resultflag=0;
//按键值是1~16这里让按键值=17是为了防止明明没按按键却一直进入这个判断
KeyValue=17;
}
//输入数字
if(KeyValue>=1&&KeyValue<=10)
{
resultflag=0;
if(calculationflag==0)
{
Number1=Number1*10+(KeyValue-1);
}
elseif(calculationflag>=1)
{
Number2=Number2*10+(KeyValue-1);
}
//按键值是1~16这里让按键值=17是为了防止明明没按按键却一直进入这个判断
KeyValue=17;
}
//加号
if(KeyValue==13)
{
//计算一次结果后直接再按加号
if(resultflag==1)
Number1=Result;
resultflag=0;
calculationflag=1;
//按键值是1~16这里让按键值=17是为了防止明明没按按键却一直进入这个判断
KeyValue=17;
}
//减号
if(KeyValue==14)
{
//计算一次结果后直接再按减号
if(resultflag==1)
Number1=Result;
resultflag=0;
calculationflag=2;
//按键值是1~16这里让按键值=17是为了防止明明没按按键却一直进入这个判断
KeyValue=17;
}
//结算
if(KeyValue==16)
{
resultflag=1;
if(calculationflag==1)
Result=Number1+Number2;
elseif(calculationflag==2)
Result=Number1-Number2;
if(Result>=9999)
{
TR0=1;
Result=Result%10000;
}
elseif(Result<=-999)
{
TR0=1;
Result=(-Result)%1000;
Result=-Result;
}
else
{
LED=1;
TR0=0;
}
calculationflag=0;
Number1=0;
Number2=0;
//按键值是1~16这里让按键值=17是为了防止明明没按按键却一直进入这个判断
KeyValue=17;
}
//数码管显示
SegDisplay();
}
}
/*******************************************************************************
*函数名:
voidTimer0()interrupt1
*函数功能:
定时器0中断函数
*输入:
无
*输出:
无
*******************************************************************************/
voidTimer0()interrupt1
{
staticu16i;
TH0=(65535-1000)/256;//给定时器赋初值,定时1ms
TL0=(65535-1000)%256;
i++;
if(i==500)
{
i=0;
LED=~LED;
}//endofif(i==1000)
}
6、实验结果:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 虚拟仪器 基于 单片机 简易 计算器 设计