用8051与1601LCD设计的整数计算器.docx
《用8051与1601LCD设计的整数计算器.docx》由会员分享,可在线阅读,更多相关《用8051与1601LCD设计的整数计算器.docx(14页珍藏版)》请在冰豆网上搜索。
![用8051与1601LCD设计的整数计算器.docx](https://file1.bdocx.com/fileroot1/2022-11/22/2afa3719-6fa2-45fb-b827-6f40318c89da/2afa3719-6fa2-45fb-b827-6f40318c89da1.gif)
用8051与1601LCD设计的整数计算器
//-----------------Main.c--------------
//名称:
用8051与1601LCD设计的整数计算器
//---------------------------------------
#include
#include
#include"calc.h"
staticdatalonglvalue;
staticdatalongrvalue;
staticdatacharcurrtoken;
staticdatacharlasttoken;
staticdatacharlastpress;
staticxdatacharoutputbuffer[MAX_DISPLAY_CHAR];//输出缓冲
//----------------------------------------------
//主程序
//-------------
voidmain()
{
//变量初始化
lvalue=0;
rvalue=0;
currtoken='=';
lasttoken='=';
//初始化LCD
initialise();
calc_putput(OK);
calc_evaluate();
}
//-----------------------------------------
//获取按键值并进行计算处理
//-----------------------------------------
voidcalc_evaluate()
{
chardatakey;
intdatai;
charxdatanumber[MAX_DISPLAY_CHAR];
charxdata*bufferptr;
//清除缓冲
for(i=0;i<=MAX_DISPLAY_CHAR;i++)
number[i]='';
bufferptr=number;
while
(1)
{
key=calc_getkey();
if(calc_testkey(key))
{
if(bufferptr!
=&number[MAX_DISPLAY_CHAR-2])
{
*bufferptr=key;
calc_display(number);
bufferptr++;
}
}
else
{
if(lasttoken=='0')
lvalue=calc_asciidec(number);
else
rvalue=calc_asciidec(number);
//清除数字蝗虫
bufferptr=number;
for(i=0;i<=MAX_DISPLAY_CHAR;i++)
number[i]='';
//处理操作符
currtoken=key;
if(currtoken=='C')
calc_opfunctions(currtoken);
else
calc_opfunctions(lasetoken);
//清除输出缓冲
for(i=0;i<=MAX_DISPLAY_CHAR;i++)
outpufbuffer[i]='';
bufferptr=number;
if(currtoken!
0x3d)
lasttoken=currtoken;
}
lastpress=key;
}
}
//-------------------------------------------
//根据运算符按键进行运算处理
//--------------------------------------------
voidcalc_opfunctions(chartoken)
{
chardataresult;
switch(token)
{
case'+':
if(currtoken=='='||isdigit(lastpress))
{
lvalue+=rvalue;
result=calc_chkerror(lvalue);
}
elseresult=SLEEP;
break;
case'-':
if(currtoken=='='||isdigit(lastpress))
{
lvalue-=rvalue;
result=calc_chkerror(lvalue);
}
elseresult=SLEEP;
break;
case'*':
if(currtoken=='='||isdigit(lastpress))
{
lvalue*=rvalue;
result=calc_chkerror(lvalue);
}
elseresult=SLEEP;
break;
case'/':
if(currtoken=='='||isdigit(lastpress))
{
lvalue/=rvalue;
result=calc_chkerror(lvalue);
}
elseresult=SLEEP;
break;
//取消
case'C':
lvalue=0;
rvalue=0;
currtoken='0';
lasttoken='0';
result=OK;
break;
default:
result=SLEEP;
}
calc_output(result);
}
//--------------------------------------------------------
//检查待显示数据的上界和下界
//例如,99999999and-99999999
//--------------------------------------------------------
intcalc_chkerror(longnum)
{
if(num>=-99999999&&num<=99999999)
returnOK;
else
returnERROR;
}
//-----------------------------------------------------------
//根据操作状态输出
//-----------------------------------------------------------
{
switch(status)
{
caseOK:
calc_deaplay(calc_decascii(lvalue));
break;
caseSLEEP:
break;
caseERROR:
calc_display("Exception");
break;
default:
calc_display("Exception")
break;
}
}
//----------------------------------------------------
//将ASCII字符串转换为浮点数
//----------------------------------------------------
longcalc_asciidec(char*buffer)
{
longdatavalue;
longdatadigit;
value=0;
while(*buffer!
='')
{
digit=*buffer-'0';
value=value*10+digit;
buffer++
}
returnvalue;
}
//----------------------------------------------------
//将浮点数转换为ASCII字符串
//----------------------------------------------------
char*calc_decascii(longnum)
{
longdatatemp=num;
charxdata*avvayptr=&outputbuffer[MAX_DISPLAY_CHAR];
longdatadivisor=10;
longdataresult;
chardataremainder,asciival;
intdatai;
//如果计算结果为0。
,则在缓冲中插入0并结束
if(!
temp)
{
*arrayptr='0';
gotodone;
}
if(temp<0)//处理负数
{
outputbuffer[0]='-';
temp-=2*temp;
}
for(i=0;i{
remainber=temp%divisor;
result=temp/divisor;
if((!
remainder)&&(!
result))
*arrayptr='';
else
{
asciival=remainder+'0';
*arrayptr=asciival;
}
temp/=10;
//为“—”号保留位置
if(arrayptr!
=&outputbuffer[1])
arrayptr--;
}
done:
returnoutputbuffer;
}
//------------------------------------------------
//测试按键时数字还是操作符,如果是数字则返回1.是操作符时返回0
//------------------------------------------------
charcalc_testkey(charkey)
{
if(isdigit(key))
return1;
else
teturn0;
}
//------------------------------------------------
//调用input例程搜索按键,并返回按键的ASCII码值
//------------------------------------------------
charcalc_getkey()
{
chardatamykey;
do
{
mykey=input();
}
while(mykey==0);
returnmykey;
}
//------------------------------------------------
//调用Output和Clearscreen例程向LCD输出ASCII
//------------------------------------------------
voidcalc_display(charbuf[MAX_DISPLAY_CHAR])
{
intdatai=0;
clearscreen();
for(i;i<=MAX_DISPLAY_CHAR;i++)
{
if(buf[i]!
='')
output(buf[i]);
}
}
//----------------------calc.h---------------------
//本例头文件
//-------------------------------------------------
typedefunsignedshortWORD;
typedefunsignedcharBYTE;
//------------------------------------------------
//定义适合屏幕显示的ASCII字符的最大个数
//------------------------------------------------
#defineMAX_DISPLAY_CHAR9
//------------------------------------------------
//错误处理状态
//------------------------------------------------
enumERROR{OK=0,SLEEP=1,ERROR=2};
//------------------------------------------------
//函数声明
//------------------------------------------------
voidcalc_evaluate();
voidcalc_opfunctions(chartoken);
charcalc_testkey(charch);
longcalc_asciidec(char*buffer);
char*calc_decascii(longnum);
intcalc_chkerror(longnum);
voidcalc_output(intstatus);
charcalc_getkey();
voidcalc_display(charbuf[MAX_DISPLAY_CHAR]);
voidinitialise();
charinput();
charoutput(charch);
voidclearscreen;
//---------------------------lcd.c-------------------------
//单行液晶显示程序
//---------------------------------------------------------
#include
#include
#defineucharunsignedchar
#defineLCD_CMD_WR0x00
#defineLCD_DATA_WWR0x01
#defineLCD_BUSY_RD0x02
#defineLCD_DATA_RD0x03
#defineLCD_PAGE0x80
#defineLCD_CLS1
#defineLCD_HOME2
#defineLCD_SETMODE4
#defineLCD_SETVISIBLE8
#defineLCD_SHIFT16
#defineLCD_SETFUNCTION32
#defineLCD_SETCGADDR64
#defineLCD_SETDDADDR128
sbitbflag=ACC^7;//忙标志位
voidwrcmd(uchar);
voidoutput(char);
voidbusywait();
//------------------------------------------------
//初始化LCD
//------------------------------------------------
voidinitialise()
{
wrcmd(0x30);//1行8位
wrcmd(LCD_SETVISIBLE+4);//显示开,关光标
wrcmd(LCD_SETDDADDR+15);//从右边开始显示
wrcmd(LCD_SETMODE+3);//递增左移
}
//------------------------------------------------
//清屏并将显示位置起点设置在最右边
//------------------------------------------------
voidclearscreen()
{
wrcmd(LCD_CLS);
wrcmd(LCD_SETDDADDR+15);
}
//------------------------------------------------
//向LCD写命令
//------------------------------------------------
voidwrcmd(ucharcmd)
{
ucharvolatilepdata*p=LCD_CMD_WR;
P2=LCD_PAGE;
*p=cmd;
//上面三行可用下面的代码替换
//XBYTE[0x8000]=cmd;
busywait();
}
//------------------------------------------------
//向LCD写一个字符
//------------------------------------------------
voidoutput(charch)
{
charvolatilepdata*p=LCD_DATA_WR;
P2=LCD_PAGE;
*p=ch;
//上面三行可用下面的代码替换
//XBYTE[0x8001]=ch;
busywait();
}
//------------------------------------------------
//忙等待
//------------------------------------------------
voidbusywait()
{
ucharvolatilepdata*p=LCD_BUSY_RD;
P2=LCD_PAGE;
//上面两行可改成:
//ucharvolatilepdata*p=0x8002;
do
{
ACC=*p;
}
while(bflag==1);
//上述所有代码也可用以下代码替换
/*
do
{
ACC=XBYTE[0x8002];
}
while(bflag==1);
*/
}
//------------------keypad.c-------------------
//键盘扫描函数charinput();返回按键的ASCII码
//---------------------------------------------
#include
#include
charcodekeycodes[]=
{
'7','8','9','/',
'4','5','6','*',
'1','2','3','-',
'C','0','=','+'
};
chardatakeyflags[16];
//------------------------------------------------
//获取键盘按键子程序
//------------------------------------------------
charinput()
{
char*pKeyflag=keyflags;//标识按键指针
charRowAddr=0xef;//键盘行地址11101111
charColData=0;//列数据
chari,j,Tmp=0;
for(i=0;i<4;i++)
{
P2=RowAddr;//在P2端口设置行地址
_nop_();
Tmp=P1&0x0f;//从P1端口读取列数据
for(j=0;j<4;j++)
{
ColData=Tmp;//保存当前列数据
if((Tmp&0x01)==0x00)//如果有键按下
{
Tmp=*pKeyflag;
*pKeyflag=1;//标识按键
if(Tmp==0)//有新按键按下
{
P2=0xff;
returnkeycodes[pKeyflag-keyflags];
}
}
else*pKeyflag=0;
pKeyflag++;
Tmp=ColData>>1;
}
RowAddr<<=1;
}
P2=0xff;
return0;
}