电子计算器.docx

上传人:b****3 文档编号:5408884 上传时间:2022-12-16 格式:DOCX 页数:29 大小:25.10KB
下载 相关 举报
电子计算器.docx_第1页
第1页 / 共29页
电子计算器.docx_第2页
第2页 / 共29页
电子计算器.docx_第3页
第3页 / 共29页
电子计算器.docx_第4页
第4页 / 共29页
电子计算器.docx_第5页
第5页 / 共29页
点击查看更多>>
下载资源
资源描述

电子计算器.docx

《电子计算器.docx》由会员分享,可在线阅读,更多相关《电子计算器.docx(29页珍藏版)》请在冰豆网上搜索。

电子计算器.docx

电子计算器

单片机计算器代码

#include//用XBYTE时需要导入的头文件

#include

#defineuintunsignedint

#defineucharunsignedchar

//*******************电压表部分********************************************

//关于电压表ADC0808芯片的工作时序见书本206页

//绝对寻址,地址每一位都为0,P2.7=0(液晶显示使能端控制)控制P2,P0

#defineIN0XBYTE[0X0000]

ucharxdata*adr1;//总线中读取信息的指针

sbitstart=P3^6;//连接控制电压表部分ADC0808芯片的Start端

sbitOE=P3^7;//连接控制电压表部分ADC0808芯片的OE端

sbitEOC=P3^5;//连接受电压表部分ADC0808芯片的OE端控制

floatjieguo;//电压表中用于存储电压值的一个变量

uintzhong;//中间变量

ucharbai,shi,ge;//存放转换结果,百,十,个位

uintidd=0;//adr1赋值的参数

/*这种用法用74LS373的一个口控制一个外设,总共可控7个*/

//定义DAC0832端口地址P0.0=0;其余为1用于使用控制74LS373的输出Q0口

#defineDAC0832XBYTE[0xfffe]

//LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80)

//D7=1禁止读写操作(万年历显示用)

#definefirstL0x80

//LCD第二行初始位置(因为第二行第一个字符位置地址是0x40)

#definesecondL0x80+0x40

#definebusy0x80//判断液晶是否忙

ucharxdataLCMWriteCOM_at_0x80ff;//写指令寄存器

ucharxdataLCMReadCOM_at_0xa0ff;//读指令寄存器

ucharxdataLCMWriteData_at_0xc0ff;//写数据寄存器

ucharxdataLCMReadData_at_0xe0ff;//读数据寄存器

uchartemp;//键盘扫描中的参数

bitscanFlag=0;//中断扫描判断参数

uchari,j,num;//计算器相关参数i判断小数点位数

//j判断是否按过等号,num程序中Switch语句中表示case值的参数

longa,b,c;//a,第一个数b,第二个数c,得数

ucharflag,fuhao;//flag表示是否有符号键按下,fuhao表征按下的是哪个符号

//计算器对应位置的字符的码表

ucharcodetable[]={

7,8,9,0x2f-0x30,

4,5,6,0x2a-0x30,

1,2,3,0x2d-0x30,

0x01-0x30,0,0x3d-0x30,0x2b-0x30};

//****************延时函数**********************

voidDelayms(ucharms)

{

uchari,j;

for(i=0;i

for(j=0;j<57;j++)

;

}

//********液晶写入指令函数与写入数据函数************************

//每次读写指令,数据时必须判断D7是否等于0

//***************写指令寄存器***************************

voidLCMWriteC(ucharCOMData)

{ucharLCMStatus;

do

{

LCMStatus=(LCMReadCOM&busy);//判断D7是否等于1

}

while(LCMStatus!

=0);//D7等于1时继续等直到D7=0

LCMWriteCOM=COMData;//给读指令寄存器赋值(所需读写的指令)

}

//****************写数据寄存器无地址*********************

voidLCMWriteD(ucharLCMData)

{ucharLCMStatus;

do

{

LCMStatus=(LCMReadCOM&busy);//判断D7是否等于1

}

while(LCMStatus!

=0);//D7等于1时继续等直到D7=0

LCMWriteData=LCMData;//给写指令寄存器赋值(所需读写的数据)

}

//*********************LCD初始化******************************

voidLCDInit(void)

{

Delayms(15);

LCMWriteCOM=0x38;//不检测忙信号

Delayms(5);

LCMWriteCOM=0x38;//不检测忙信号

Delayms(5);

LCMWriteCOM=0x38;//不检测忙信号

Delayms(5);

LCMWriteC(0x38);//显示模式设置

LCMWriteC(0x08);//显示关闭

LCMWriteC(0x01);//显示清屏

LCMWriteC(0x06);//显示光标移动设置

LCMWriteC(0x0c);//显示开及光标设置

}

//*******************计算器**********************************

//fuhao=1按下加号fuhao=2按下减号fuhao=3按下乘号fuhao=4按下除号

//*********************键盘扫描程序第一行7,8,9,/*************************

voidkeyLine1()

{

//P1.0=0;0行有按钮按下

P1=0xfe;//P1八位的值为11111110,只有P1.0为低电平

if(P1!

=0xfe)//判断第一行是否有按钮按下

{

Delayms(20);//延时20ms消抖

if(P1!

=0xfe)//判断第一行是否有按钮按下

{

temp=P1&0xf0;

switch(temp)

{

case0xe0:

num=0;break;

case0xd0:

num=1;break;

case0xb0:

num=2;break;

case0x70:

num=3;break;

}

}

while(P1!

=0xfe);//死循环,直到我们松开按键为止

if(num==0||num==1||num==2)//如果按下的是'7','8'或'9判断按下的是哪个数

{

if(j!

=0)

{

LCMWriteC(0x01);//清屏

j=0;//只做一次清屏

}

if(flag==0)//没有按过符号键,前后按的是同一个数

{

a=a*10+table[num];//若开始按的是3,后来按的是2,则a=3*10+2=32

}

else//如果按过符号键,前后按的就是两个数

{

b=b*10+table[num];

}

}

else//如果按下的是'/'

{

flag=1;

fuhao=4;//4表示除号已按

}

i=table[num];

//显示所读到的数或符号0+i0x30为LCD中0字符对应的码

LCMWriteD(0x30+i);//若i=9则,在液晶显示屏上显示9

}

}

//**************键盘扫描程序第二行4,5,6,[*乘]**********************************

voidkeyLine2()

{

//P3.1=0;1行有按钮按下

P1=0xfd;

if(P1!

=0xfd)

{

Delayms(5);

if(P1!

=0xfd)

{

temp=P1&0xf0;

switch(temp)

{

case0xe0:

num=4;break;

case0xd0:

num=5;break;

case0xb0:

num=6;break;

case0x70:

num=7;break;

}

}

while(P1!

=0xfd);

if(num==4||num==5||num==6&&num!

=7)//如果按下的是'4','5'或'6'

{

if(j!

=0)

{

LCMWriteC(0x01);

j=0;

}

if(flag==0)//没有按过符号键

{

a=a*10+table[num];

}

else//如果按过符号键

{

b=b*10+table[num];

}

}

else//如果按下的是'/'

{

flag=1;

fuhao=3;//3表示乘号已按

}

i=table[num];

LCMWriteD(0x30+i);

}

}

//**************键盘扫描程序第三行1,2,3,-*************************************

voidkeyLine3()

{

//P3.1=0;1行有按钮按下

P1=0xfb;

if(P1!

=0xfb)

{

Delayms(5);//消抖

if(P1!

=0xfb)

{

temp=P1&0xf0;

switch(temp)

{

case0xe0:

num=8;break;

case0xd0:

num=9;break;

case0xb0:

num=10;break;

case0x70:

num=11;break;

}

}

while(P1!

=0xfb);

if(num==8||num==9||num==10)//如果按下的是'1','2'或'3'

{

if(j!

=0)

{

LCMWriteC(0x01);

j=0;

}

if(flag==0)//没有按过符号键

{

a=a*10+table[num];

}

else//如果按过符号键

{

b=b*10+table[num];

}

}

elseif(num==11)//如果按下的是'-'

{

flag=1;

fuhao=2;//2表示减号已按

}

i=table[num];

LCMWriteD(0x30+i);

}

}

//*************键盘扫描程序第四行-清零,0,=,+************************************

voidkeyLine4()

{

P1=0xf7;

if(P1!

=0xf7)

{

Delayms(5);

if(P1!

=0xf7)

{

temp=P1&0xf0;

switch(temp)

{

case0xe0:

num=12;break;//清零

case0xd0:

num=13;break;//0

case0xb0:

num=14;break;//等于

case0x70:

num=15;break;//加号

}

}

while(P1!

=0xf7);

switch(num)

{

//按下的是"清零",讲计算器程序用到的参数初始化,并且将LCD也初始化

case12:

{LCMWriteC(0x01);a=0;b=0;flag=0;fuhao=0;}break;

case13:

//按下的是"0"

{

if(flag==0)//没有按过符号键

{

a=a*10+0;

LCMWriteD(0x30);//在液晶屏上显示0

P1=0;//D7=0,允许LCD读写数据

}

elseif(flag==1)//如果按过符号键

{

b=b*10+0;

LCMWriteD(0x30);//在液晶屏上显示0

}

}

break;

//fuhao=1代表按下加号fuhao=2代表按下减号fuhao=3代表按下乘号fuhao=4代表按下除号

//结果输出是从最后一位到最前面一位

case14:

{j=1;//之前按过等于号

if(fuhao==1)//按下加号键

{

LCMWriteC(0x80+0x4f);//按下等于键,光标前进至第二行最后一个显示处

LCMWriteC(0x04);//设置从后住前写数据,每写完一个数据,光标后退一格

c=a+b;//c是两个数相加的值结果显示是从最后一位开始写到屏幕上的从后往前写

while(c!

=0)//将C的每一位的值显示出来

{

LCMWriteD(0x30+c%10);

c=c/10;//读取c的每一位的数值

}

LCMWriteD(0x3d);//再写"="

//做完一次运算各个系数要清零

a=0;

b=0;

flag=0;

fuhao=0;

}

elseif(fuhao==2)//按下减号键

{

LCMWriteC(0x80+0x4f);//光标前进至第二行最后一个显示处

//设置从后住前写数据,每写完一个数据,光标后退一格(这个照理说顺序不对,可显示和上段一样)

LCMWriteC(0x04);

if(a-b>0)//c是两个数相减的值结果显示是从最后一位开始写到屏幕上的从后往前写

c=a-b;

else

c=b-a;

while(c!

=0)

{

LCMWriteD(0x30+c%10);

c=c/10;

}

if(a-b<0)

LCMWriteD(0x2d);//写"-"号

LCMWriteD(0x3d);//再写"="

//做完一次运算各个系数要清零

a=0;

b=0;

flag=0;

fuhao=0;

}

elseif(fuhao==3)//按下乘号键

{

LCMWriteC(0x80+0x4f);//光标前进至第二行最后一个显示处

//设置从后住前写数据,每写完一个数据,光标后退一格(这个照理说顺序不对,可显示和上段一样)

LCMWriteC(0x04);

//c是两个数的积结果显示是从最后一位开始写到屏幕上的从后往前写

c=a*b;

while(c!

=0)

{

LCMWriteD(0x30+c%10);

c=c/10;

}

LCMWriteD(0x3d);

//做完一次运算各个系数要清零

a=0;

b=0;

flag=0;

fuhao=0;

}

elseif(fuhao==4)

{

LCMWriteC(0x80+0x4f);//光标前进至第二行最后一个显示处

LCMWriteC(0x04);

//除法我们只保留三位小数,i为计数值,这个也可以根据自己的喜好更改

i=0;

/*除法我们只保留三位小数,所以先将(float)a/b的值乘以10003/2=1;(float)3/2=1.5*/

c=(long)(((float)a/b)*1000);

while(c!

=0)

{

LCMWriteD(0x30+c%10);

c=c/10;

i++;

if(i==3)

LCMWriteD(0x2e);//显示小数点

}

if(a/b<=0)

LCMWriteD(0x30);//显示0

LCMWriteD(0x3d);//显示等号

//做完一次运算各个系数要清零

a=0;

b=0;

flag=0;

fuhao=0;

}

}

break;

case15:

//按下加号

{

flag=1;

fuhao=1;

i=table[num];

LCMWriteD(0x30+i);

}

break;

}

}

}

//*********************键盘扫描程序*****************************************

voidkeyscan()

{

keyLine1();//扫描第一行

keyLine2();//扫描第二行

keyLine3();//扫描第三行

keyLine4();//扫描第四行

}

//**************键盘扫描参数初始化程序********************************

voidKeyInti()

{

i=0;//判断小数位数

j=0;//判断等号是否按下

a=0;//第一个参与运算的数

b=0;//第二个参与运算的数

c=0;

flag=0;//flag表示是否有符号键按下,

fuhao=0;//fuhao表征按下的是哪个符号

}

//**********************波形输出*********************************************

ucharFunctionChange=0;//这个是功能切换的参数

ucharxdata*adr;//总线中读取信息的指针

sbitchoose=P2^0;//用choose表示P2.0口

//用ifInti表示P2.0口ifInti用来控制输出波形时的LCD的初始化,ifInti=1不初始化ifInti=0初始化

sbitifInti=P2^1;

//************************锯齿波发生函数**************************************

voidsaw(void)

{

uchary;

for(y=0;y<255;y++)

{

*adr=y;//讲y的值赋给adr这个指针所指向的地址

}

}

//************************方波发生函数**************************************

voidsquare(void)

{

*adr=0X00;//输入低电平

Delayms(500);//延时

*adr=0xff;//输入高电平

Delayms(500);

}

//************************切换波形**************************************

voidChooseBo()

{

adr=&DAC0832;//将DAC0832代表的地址赋给adr这个地址DAC0832的地址内存储的是P0,P2口的数据值

if(choose==0)//判断P2.0

{

saw();//输出的为锯齿波

}

elseif(choose==1)//判断P2.0=1

{

square();//输出的为方波

}

}

//************************液晶显示波名**************************************

voidBoShow()

{

if(ifInti==0)

{

//液晶显示初始化为了防止前面写的数据没清除影响后面写到屏幕上的数据

LCDInit();

}

if(choose==0)//判断P2.0

{

//在液晶屏上显示"Saw"

LCMWriteD('S');

LCMWriteD('a');

LCMWriteD('w');

}

elseif(choose==1)//判断P2.0=1

{

//在液晶屏上显示"Square"

LCMWriteD('S');

LCMWriteD('q');

LCMWriteD('u');

LCMWriteD('a');

LCMWriteD('r');

LCMWriteD('e');

}

}

//****************电压表液晶显示**********************************************

voiddisplay(void)

{

//显示子函数

//液晶屏不能自动显示小数,我们要将其放大,读出每一位的数值,自己显示小数点

//将光标跳到液晶屏的第二行的第五位,电压表的电压值从液晶屏的第二行的第五位开始写

LCMWriteC(secondL+5);

LCMWriteD('=');//显示等于号

LCMWriteD(0x30+bai);//显示百位数(实际电压的个位)

LCMWriteD('.');//显示小数点

LCMWriteD(0x30+shi);//显示十位数(实际电压的小数点后第一位)

LCMWriteD(0x30+ge);//显示个位数(实际电压的小数点后第二位)

}

//***************************万年历********************************************

//万年历部分比较复杂,大致的过程就是从芯片里读取时间日期的信息值(BCD码的)

//装换成十进制数,然后按照位置显示出来

ucharaa,miao,shi,fen,ri,yue,nian,week,key1n,temp;

//DS1302时钟芯片与C51之间的引脚连接定义

sbitIO=P2^2;

sbitSCLK=P2^3;

sbitRST=P2^4;

sbitACC0=ACC^0;

sbitACC7=ACC^7;

/************************************************************

ACC累加器=A

ACC.0=E0H

ACC.0就是ACC的第0位。

Acc可以位寻址。

累加器ACC是一个8位的存储单元,是用来放数据的。

但是,这个存储单元有其特殊的地位,

是单片机中一个非常关键的

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1