//用开发板制作的一个计算器实验
//下面是源代码,
#include<reg52.h>
#include<stdlib.h>
#include<stdio.h>
#define LCD_DATA P0 //lcd数据显示
#define LCD_KEY P2 //键盘接口
#define uchar unsigned char
#define uint unsigned int
sbit LCD_RS=P1^0; // LCD 1602的RS 接口
sbit LCD_RW=P1^1; //LCD 1602的RW 接口
sbit LCD_E=P1^2; //LCD 1602的E使能端接口
//是否有按键按下
bit isKeyPress;
//按键所选择键值
uchar selectKey;
//记录连续输入数字的个数
uchar count;
//记录连续接收到的数字,最多输入14位
uchar receivedData[14];
//记录存储结果
long result;
//输入数据暂存
long rectmp1,rectmp2;
//记录输入符号
uchar sign;
//定时器0
void Timer0();
//LCD初始化
void lcdInit();
//LCD写数据
void lcdWriteData(uchar dat);
//LCD写命令
void lcdWriteCommand(uchar com);
//最小延时1ms时参数为1
void delay1ms();
//键盘扫描程序
uchar scanKeyboard();
//将字符写入第Y行第x个位置
void displayCharAt(uchar x,uchar y,uchar dat);
//显示字符串在指定的位置
void displayStringAt(uchar x,uchar y,uchar *str);
//在当前字符的下一个位置显示字符
void displayChar(uchar dat);
//在当前字符的下一个位置显示字符串
void displayString(uchar *str);
//处理从键盘得到的按键值
void keyProcess(uchar key);
//清除LCD中的所有显示,并将光标至于地址0
void clearDisplay();
//将字符串转换成整形
uint stringToInt(uchar *str);
//复位
void lcdReset();
//在指定位置显示字符
void displayCharAt(uchar x,uchar y,uchar dat)
{
uchar address;
if(y==1)
address=0x80+x;
else
address=0xc0+x;
lcdWriteCommand(address);
lcdWriteData(dat);
}
void displayChar(uchar dat)
{
lcdWriteData(dat);
}
//在指定位置显示字符串
void displayStringAt(uchar x,uchar y,uchar *str)
{
uchar address;
uchar i;
if(y==1)
address=0x80+x;
else
address=0xc0+x;
for(i=0;str[i]!='\0';i++)
{
// lcdWriteCommand(address++);
lcdWriteData(str[i]);
}
}
void displayString(uchar *str)
{
uchar i;
for(i=0;str[i]!='\0';i++)
lcdWriteData(str[i]);
}
void lcdInit() //lcd初始化函数
{
uchar i;
count=0;
selectKey=0;
isKeyPress=0;
result=0;
rectmp1=0;
rectmp2=0;
sign=' '; //空格表示没有输入符号
for(i=0;i<14;i++)
receivedData[i]='\0';
lcdWriteCommand(0x38);//设置8位格式,2行,5x7
lcdWriteCommand(0x0C);//整体显示,关光标,不闪烁
lcdWriteCommand(0x06);//设定输入方式,增量不移位
lcdWriteCommand(0x01);//清除屏幕显示
delay1ms();
}
void lcdWriteData(uchar dat) //lcd写数据
{
LCD_RS=1; //写数据
LCD_RW=0;
LCD_E=0;
LCD_DATA=dat;
LCD_E=1;
delay1ms();
LCD_E=0;
delay1ms();
}
void lcdWriteCommand(uchar com) //lcd写命令
{
LCD_RS=0; //写命令
LCD_RW=0;
LCD_E=0;
LCD_DATA=com;
LCD_E=1;
delay1ms();
LCD_E=0;
delay1ms();
}
uchar scanKeyboard() //键盘扫描程序
{
uchar tmp1,tmp2,key;
LCD_KEY=0XFe; //第一行
tmp1=LCD_KEY;
tmp2=tmp1&0xf0;
if(tmp2!=0xf0)
{
delay1ms(); //键抖动处理
tmp1=LCD_KEY;
if((tmp1&0xf0)==tmp2)
{
switch(tmp2)
{
case 0xe0:key='7';break;
case 0xd0:key='8';break;
case 0xb0:key='9';break;
case 0x70:key=0xfd;break; //0xfd除号在1602液晶中的代码
}
while(tmp2!=0xf0) //键释放处理
{
tmp2=LCD_KEY;
tmp2=tmp2&0xf0;
}
isKeyPress=1; //键按标志置1
return(key);
}
}
LCD_KEY=0XFd; //第二行
tmp1=LCD_KEY;
tmp2=tmp1&0xf0;
if(tmp2!=0xf0)
{
delay1ms(); //键抖动处理
tmp1=LCD_KEY;
if((tmp1&0xf0)==tmp2)
{
switch(tmp2)
{
case 0xe0:key='4';break;
case 0xd0:key='5';break;
case 0xb0:key='6';break;
case 0x70:key='*';break; //乘号
}
while(tmp2!=0xf0) //键释放处理
{
tmp2=LCD_KEY;
tmp2=tmp2&0xf0;
}
isKeyPress=1; //键按标志置1
return(key);
}
}
LCD_KEY=0XFb; //第三行
tmp1=LCD_KEY;
tmp2=tmp1&0xf0;
if(tmp2!=0xf0)
{
delay1ms(); //键抖动处理
tmp1=LCD_KEY;
if((tmp1&0xf0)==tmp2)
{
switch(tmp2)
{
case 0xe0:key='1';break;
case 0xd0:key='2';break;
case 0xb0:key='3';break;
case 0x70:key='-';break; //减号
}
while(tmp2!=0xf0) //键释放处理
{
tmp2=LCD_KEY;
tmp2=tmp2&0xf0;
}
isKeyPress=1; //键按标志置1
return(key);
}
}
LCD_KEY=0XF7; //第四行
tmp1=LCD_KEY;
tmp2=tmp1&0xf0;
if(tmp2!=0xf0)
{
delay1ms(); //键抖动处理
tmp1=LCD_KEY;
if((tmp1&0xf0)==tmp2)
{
switch(tmp2)
{
case 0xe0:key='c';break;
case 0xd0:key='0';break;
case 0xb0:key='=';break;
case 0x70:key='+';break; //
}
while(tmp2!=0xf0) //键释放处理
{
tmp2=LCD_KEY;
tmp2=tmp2&0xf0;
}
isKeyPress=1; //键按标志置1
return(key);
}
}
return(0);
}
void delay1ms()
{
uchar a,b;
for(b=199;b>0;b--)
for(a=1;a>0;a--);
}
void keyProcess(uchar key)
{
if('0'<=key&&key<='9')
{
if(count==0)
{
uchar i;
// clearDisplay();
for(i=0;i<14;i++)
receivedData[i]='\0';
}
// if(count==14) //溢出则显示错误
// displayString(" data is limited ");
displayChar(key); //显示输入字符
receivedData[count]=key;
count++;
}
else if(key=='+'||key=='-'||key=='*'||key==0xfd)
{
uchar i;
if(receivedData[0]!='\0')
rectmp1=atol(receivedData);
sign=key;
count=0;
// clearDisplay();
displayChar(key);
for(i=0;i<14;i++)
receivedData[i]='\0';
}
else if(key=='=')
{
char buf[10];
uint i;
clearDisplay();
rectmp2=atol(receivedData);
switch(sign)
{
case '+': //加
rectmp1+=rectmp2;
break;
case '-': //减
rectmp1-=rectmp2;
break;
case '*': //乘
rectmp1*=rectmp2;
break;
case 0xfd: //除
rectmp1/=rectmp2;
break;
}
//将计算结果转化成字符串
sprintf(buf,"%ld",rectmp1);
displayString(buf);
count=0;
for(i=0;i<14;i++)
receivedData[i]='\0';
}
else if(key=='c')
{
lcdReset(); //复位
}
}
//复位
void lcdReset()
{
lcdInit();
}
//清除LCD中的所有显示,并将光标至于地址0
void clearDisplay()
{
lcdWriteCommand(0x01);
lcdWriteCommand(0x80);
}
void Timer0() interrupt 1
{
TH0 = 0x3C;
TL0 = 0x0B0;
}
void main()
{
lcdInit();
TMOD = 0x01; //定时器0,方式1
TH0 = 0x3C; //50us,晶振频率为12M
TL0 = 0x0B0;
EA = 1; //允许溢出中断设置
ET0 = 1;
TR0 = 1; //开始计时
while(1)
{
selectKey=scanKeyboard();
if(selectKey!=0)
{
keyProcess(selectKey);
}
}
}