资源描述
//-----------------Main.c--------------
//名称:用8051与1601LCD设计的整数计算器
//---------------------------------------
#include <reg51.h>
#include <ctype.h>
#include "calc.h"
static data long lvalue;
static data long rvalue;
static data char currtoken;
static data char lasttoken;
static data char lastpress;
static xdata char outputbuffer[MAX_DISPLAY_CHAR];//输出缓冲
//----------------------------------------------
//主程序
//-------------
void main()
{
//变量初始化
lvalue=0;
rvalue=0;
currtoken='=';
lasttoken='=';
//初始化LCD
initialise();
calc_putput(OK);
calc_evaluate();
}
//-----------------------------------------
//获取按键值并进行计算处理
//-----------------------------------------
void calc_evaluate()
{
char data key;
int data i;
char xdata number[MAX_DISPLAY_CHAR];
char xdata *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;
}
}
//-------------------------------------------
// 根据运算符按键进行运算处理
//--------------------------------------------
void calc_opfunctions (char token)
{
char data result;
switch(token)
{
case '+':if(currtoken=='='||isdigit(lastpress))
{
lvalue+=rvalue;
result=calc_chkerror(lvalue);
}
else result=SLEEP;
break;
case '-':if(currtoken=='='||isdigit(lastpress))
{
lvalue-=rvalue;
result=calc_chkerror(lvalue);
}
else result=SLEEP;
break;
case '*':if(currtoken=='='||isdigit(lastpress))
{
lvalue*=rvalue;
result=calc_chkerror(lvalue);
}
else result=SLEEP;
break;
case '/':if(currtoken=='='||isdigit(lastpress))
{
lvalue/=rvalue;
result=calc_chkerror(lvalue);
}
else result=SLEEP;
break;
//取消
case 'C':lvalue=0;
rvalue=0;
currtoken='0';
lasttoken='0';
result=OK;
break;
default:result=SLEEP;
}
calc_output(result);
}
//--------------------------------------------------------
// 检查待显示数据的上界和下界
// 例如,99999999 and -99999999
//--------------------------------------------------------
int calc_chkerror (long num)
{
if(num>=-99999999&&num<=99999999)
return OK;
else
return ERROR;
}
//-----------------------------------------------------------
// 根据操作状态输出
//-----------------------------------------------------------
{
switch(status)
{
case OK:calc_deaplay(calc_decascii(lvalue));
break;
case SLEEP: break;
case ERROR:calc_display("Exception");
break;
default:calc_display("Exception")
break;
}
}
//----------------------------------------------------
//将ASCII字符串转换为浮点数
//----------------------------------------------------
long calc_asciidec (char *buffer)
{
long data value;
long data digit;
value=0;
while(*buffer!=' ')
{
digit=*buffer-'0';
value=value*10+digit;
buffer++
}
return value;
}
//----------------------------------------------------
//将浮点数转换为ASCII字符串
//----------------------------------------------------
char *calc_decascii(long num)
{
long data temp=num;
char xdata *avvayptr=&outputbuffer[MAX_DISPLAY_CHAR];
long data divisor=10;
long data result;
char data remainder,asciival;
int data i;
//如果计算结果为0。,则在缓冲中插入0并结束
if(!temp)
{
*arrayptr='0';
goto done;
}
if(temp<0) //处理负数
{
outputbuffer[0]='-';
temp-=2*temp;
}
for(i=0;i<sizeof(outputbuffer);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:return outputbuffer;
}
//------------------------------------------------
//测试按键时数字还是操作符,如果是数字则返回1.是操作符时返回0
//------------------------------------------------
char calc_testkey (char key)
{
if(isdigit(key))
return 1;
else
teturn 0;
}
//------------------------------------------------
//调用input例程搜索按键,并返回按键的ASCII码值
//------------------------------------------------
char calc_getkey()
{
char data mykey;
do
{
mykey=input();
}
while(mykey==0);
return mykey;
}
//------------------------------------------------
//调用Output和Clearscreen例程向LCD输出ASCII
//------------------------------------------------
void calc_display (char buf[MAX_DISPLAY_CHAR])
{
int data i=0;
clearscreen();
for(i;i<=MAX_DISPLAY_CHAR;i++)
{
if(buf[i]!=' ')
output(buf[i]);
}
}
//----------------------calc.h---------------------
//本例头文件
//-------------------------------------------------
typedef unsigned short WORD;
typedef unsigned char BYTE;
//------------------------------------------------
//定义适合屏幕显示的ASCII字符的最大个数
//------------------------------------------------
#define MAX_DISPLAY_CHAR 9
//------------------------------------------------
//错误处理状态
//------------------------------------------------
enum ERROR {OK=0,SLEEP=1,ERROR=2};
//------------------------------------------------
//函数声明
//------------------------------------------------
void calc_evaluate();
void calc_opfunctions (char token);
char calc_testkey (char ch);
long calc_asciidec (char *buffer);
char *calc_decascii (long num);
int calc_chkerror (long num);
void calc_output (int status);
char calc_getkey();
void calc_display(char buf[MAX_DISPLAY_CHAR]);
void initialise();
char input();
char output(char ch);
void clearscreen;
//---------------------------lcd.c-------------------------
//单行液晶显示程序
//---------------------------------------------------------
#include<reg51.h>
#include<absacc.h>
#define uchar unsigned char
#define LCD_CMD_WR 0x00
#define LCD_DATA_WWR 0x01
#define LCD_BUSY_RD 0x02
#define LCD_DATA_RD 0x03
#define LCD_PAGE 0x80
#define LCD_CLS 1
#define LCD_HOME 2
#define LCD_SETMODE 4
#define LCD_SETVISIBLE 8
#define LCD_SHIFT 16
#define LCD_SETFUNCTION 32
#define LCD_SETCGADDR 64
#define LCD_SETDDADDR 128
sbit bflag=ACC^7;//忙标志位
void wrcmd(uchar);
void output(char);
void busywait();
//------------------------------------------------
//初始化LCD
//------------------------------------------------
void initialise()
{
wrcmd(0x30); //1行8位
wrcmd(LCD_SETVISIBLE+4); //显示开,关光标
wrcmd(LCD_SETDDADDR+15); //从右边开始显示
wrcmd(LCD_SETMODE+3); // 递增左移
}
//------------------------------------------------
//清屏并将显示位置起点设置在最右边
//------------------------------------------------
void clearscreen()
{
wrcmd(LCD_CLS);
wrcmd(LCD_SETDDADDR+15);
}
//------------------------------------------------
//向LCD写命令
//------------------------------------------------
void wrcmd(uchar cmd)
{
uchar volatile pdata *p=LCD_CMD_WR;
P2=LCD_PAGE;
*p=cmd;
//上面三行可用下面的代码替换
//XBYTE[0x8000]=cmd;
busywait();
}
//------------------------------------------------
//向LCD写一个字符
//------------------------------------------------
void output(char ch)
{
char volatile pdata *p=LCD_DATA_WR;
P2=LCD_PAGE;
*p=ch;
//上面三行可用下面的代码替换
//XBYTE[0x8001]=ch;
busywait();
}
//------------------------------------------------
//忙等待
//------------------------------------------------
void busywait()
{
uchar volatile pdata *p=LCD_BUSY_RD;
P2=LCD_PAGE;
//上面两行可改成:
//uchar volatile pdata *p=0x8002;
do
{
ACC=*p;
}
while(bflag==1);
//上述所有代码也可用以下代码替换
/*
do
{
ACC=XBYTE[0x8002];
}
while(bflag==1);
*/
}
//------------------keypad.c-------------------
//键盘扫描函数char input();返回按键的ASCII码
//---------------------------------------------
#include<reg51.h>
#include<intrins.h>
char code keycodes[]=
{
'7','8','9','/',
'4','5','6','*',
'1','2','3','-',
'C','0','=','+'
};
char data keyflags[16];
//------------------------------------------------
//获取键盘按键子程序
//------------------------------------------------
char input()
{
char *pKeyflag=keyflags; //标识按键指针
char RowAddr=0xef; //键盘行地址1110 1111
char ColData=0; //列数据
char i,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;
return keycodes[pKeyflag-keyflags];
}
}
else *pKeyflag=0;
pKeyflag++;
Tmp=ColData>>1;
}
RowAddr<<=1;
}
P2=0xff;
return 0;
}
展开阅读全文