呵呵,没想到这个兄弟,在我之前把代码给贴出来了
我也来一份了!
/********************************************************************************/
/* Project: 计算器(Calculator) 版本号:V1。0 */
/* */
/* */
/* Designed By: whoami CPU:AT89S51 or C51 */
/* */
/* */
/* 键盘布局如下: */
/* K2(0) K4(1) K6(2) K8(3) K10(8) K12(9) K14(.) K16(+) */
/* K3(4) K5(5) K7(6) K9(7) K11(-) K13(*) K15(/) K17(=) */
/* */
/* 功能描述: */
/* 可以运算+,-,*,/等计算,运算的长度可以自行设定 */
/* 修改 Max_disp_buff 即可。 */
/* */
/* http://www.mculover.net */
/* http://www.mculover.net/bbs 湘灵电子版权所有 */
/* */
/* 转载请保留以上信息,谢谢合作 ! */
/* */
/********************************************************************************/#include <reg51.h>
#include <math.h>
#include <stdlib.h>#define Lcd_Data P0 //定义数据端口
#define TH0_TL0 (65536-5000)//设定中断的间隔时长#define Max_disp_buff 10 //定义最大的显示位数
#define Key_con P1 //定义44键盘的连接口线sbit RS = P2 ^ 0; //定义和LCM的连接端口
sbit RW = P2 ^ 1;
sbit E = P2 ^ 2;
sbit Busy = P0 ^ 7;unsigned char Key_value, Time_delay;
static float left_value = 0;
static float right_value = 0;//开机画面预定义
unsigned char code welcome[] = {"Welcome to : "};
unsigned char code website[] = {"www.mculover.net"};
unsigned char code designed[]= {"Designed By: "};
unsigned char code whoami[] = {" whoami"};//定义数组变量
unsigned char code keycodes[16]={'0','1','2','3','4','5','6','7','8','9','.','+','-','*','/','=',};
unsigned char number[Max_disp_buff + 1];//定义按键数字的缓冲大小//函数声明
void Delay(unsigned char x);//延时处理
void Delay_1ms(unsigned char t);//延时子程序,延时 1MS*t S
unsigned char Read_key(void);//按键处理,返回按键的值
unsigned char Test_key(void);//按键检测函数
void Read_Busy(void);//读忙信号判断
void Write_Comm(unsigned char lcdcomm); //写指令函数
void Write_Data(unsigned char lcddata);//写数据函数
void Init_LCD_Cal(void);//初始化LCD
void Init_LCD_Logo(void);//初始化LCD
void Init_Timer0(void);//定时器0初始化
void Display (char *buf); //显示函数
void Display_Logo(unsigned char code *DData);//显示LOGO
void Digit_input_calcul(void);//字符输入
void Fun_calculator(unsigned int fuhao);//运算函数
void Calculator_output(float value);//输出计算结果函数
void Show_logo(void);//显示开机画面/******************************************************************************/
void Delay(unsigned char x)//延时处理
{
Time_delay = x;while(Time_delay != 0);
}/******************************************************************************/
void Delay_1ms(unsigned char t)//延时子程序,延时 1MS*t S
{
unsigned char a;
while(--t != 0)
{
for(a = 0; a < 125; a++);
}
}/******************************************************************************/
unsigned char Read_key(void)//按键处理,返回按键的值
{
unsigned char j, k, s, key;Key_con = 0xf0;//
if(Key_con != 0xf0)
{
Delay_1ms(30);//延时消抖
if(Key_con != 0xf0)
{
Key_con=0xfe;
k=0xfe;
for(j=0;j<4;j++)
{
s=Key_con & 0xf0;
switch(s)
{
case 0xe0: key=4*j+0; break;
case 0xd0: key=4*j+1; break;
case 0xb0: key=4*j+2; break;
case 0x70: key=4*j+3; break;
default: break;
}
k = (k << 1) | 0x01;
Key_con = k;}//for
Key_value = keycodes[key];
}
}//if
else
Key_value = 0x00;//如果为O, 则表示无键按下return Key_value;
}/******************************************************************************/
void Timer0_int(void) interrupt 1 using 1//定时0中断处理
{
// 调整出入栈的时间,在精度不高的场合可不要!
TR0 = 0;
TL0 += (TH0_TL0 + 9) % 256;
TH0 += (TH0_TL0 + 9) / 256 + (char)CY;
TR0 = 1;if(Time_delay != 0)//延时函数用
{
Time_delay--;
}Read_key();//读取键盘的值
}/******************************************************************************/
unsigned char Test_key(void)//按键检测函数
{
unsigned char mykey;while((mykey = Key_value) == 0x00);//等待
return mykey;
}/******************************************************************************/
void Read_Busy(void)//读忙信号判断
{
do{
Lcd_Data = 0xff;
RS = 0;
RW = 1;
E = 0;
Delay(2);//调用中断延时
E = 1;
}while(Busy);
}/******************************************************************************/
void Write_Comm(unsigned char lcdcomm) //写指令函数
{
Lcd_Data = lcdcomm;
RS = 0;
RW = 0;
E = 0;
Read_Busy();
E = 1;
}/******************************************************************************/
void Write_Data(unsigned char lcddata)//写数据函数
{
Lcd_Data = lcddata;
RS = 1;
RW = 0;
E = 0;
Read_Busy();
E = 1;
}/******************************************************************************/
void Init_LCD_Cal(void)//初始化LCD
{
Delay_1ms(400); //稍微延时,等待LCM进入工作状态
Write_Comm(0x01);//清显示Write_Comm(0x38); // 8位 2行.
Write_Comm(0x0c); //
Write_Comm(0x07); // 显示模式,从左至右增加
Write_Comm(0x80+0x10); // 定义首地址.
}/******************************************************************************/
void Init_LCD_Logo(void)//初始化LCD
{
Delay_1ms(400); //稍微延时,等待LCM进入工作状态
Write_Comm(0x01);//清显示Write_Comm(0x38);//8位2行5*8
Write_Comm(0x06);//文字不动,光标右移
Write_Comm(0x0c);//显示开/关,光标开闪烁开
}/******************************************************************************/
void Init_Timer0(void)//定时器0初始化
{
TMOD=0x01;
TH0=TH0_TL0 / 256;
TL0=TH0_TL0 % 256;
TR0=1;
ET0=1;
EA=1;
}/******************************************************************************/
void Display(char *buf)//显示函数
{
unsigned char i;
Write_Comm(0x01);//clearscreen,清屏命令
Write_Comm(0x80+0x10);for (i=0 ; buf[i] != 0; i++)
Write_Data(buf[i]);
}/******************************************************************************/
void Display_Logo(unsigned char code *DData)//显示LOGO
{
unsigned char j;
for(j=0;j<16;j++)
{
Write_Data(DData[j]); //显示单个字符
Delay(20);
}
}/*******************************************************************************/
void Digit_input_calcul(void)//字符输入
{
static unsigned char pos;
float tmp;unsigned int last_op = 0;
Write_Data('0'); //上电显示" 0 "
pos = 0;//位置为0while(1)
{
Key_value = Test_key();//判断是数字还是运算符号,具有等待功能if((Key_value == '.') || ((Key_value >= '0') && (Key_value <= '9')))//如果是数字或小数点
{
if (pos != Max_disp_buff ) //最大计算位
{
number[pos++] = Key_value;
number[pos] = 0;
Display(number);
}
}
else //如果输入的是运算符号(+,-,*,/,=)
{tmp = atof(number);//atof函数就是把字符转换成双精度的值
if((Key_value == '+') || (Key_value == '-') || (Key_value == '*') || (Key_value == '/'))
{
left_value = tmp;
last_op = Key_value;
}
else if (Key_value == '=')
{
right_value = tmp;Fun_calculator(last_op);//计算
}
pos = 0;//从新归位,输入右值
}//else
}//for
}/**********************************************************************************/
void Fun_calculator(unsigned int fuhao)//运算函数
{
bit result = 1;switch(fuhao)
{
case '+': left_value += right_value;result = 1;break;
case '-': left_value -= right_value;result = 1;break;
case '*': left_value *= right_value;result = 1;break;
case '/':
if(right_value != 0)
{
left_value /= right_value;
result = 1;
}
else
result = 0;//出错
break;
default : break;
}if(result == 1)
Calculator_output(left_value);
else
Display("*ERROR*");
}/******************************************************************************/
void Calculator_output(float value)//输出计算结果函数
{
unsigned char buff[Max_disp_buff + 1];//定义显示缓冲
unsigned char p1=0, p=0;
float divisor = 100000000;//除数
float digit = 0;if(value >= 0)
buff[p++] = ' ';
else
{
buff[p++] = '-';
value = -value;
}if(value >= divisor )
buff[p++]='E';
else
while((p < Max_disp_buff ) && (divisor > 1 || value >= 0.00000001))
{
divisor /= 10;
digit = floor(value/divisor);//小于指定数的最小整数
if (divisor < 1 && divisor > 0.01)
buff[p++] = '.';
if (digit != 0 || divisor < 10)
{
buff[p++] = digit + '0';
p1 = 1;
}
else if (p1)
buff[p++] = '0';
value -= digit*divisor;
}
buff[p] = 0;
Display(buff);
}/******************************************************************************/
void Show_logo(void)//显示开机画面
{
Write_Comm(0x80);//写入"welcome to"首地址(第一行)
Display_Logo(welcome);Write_Comm(0xc0);//写入"website"首地址(第2行)
Display_Logo(website);
Delay(200);Write_Comm(0x01);//清屏
Write_Comm(0x80);//写入"designed "首地址(第一行)
Display_Logo(designed);
Write_Comm(0xc0);//写入"whoami"首地址(第2行)
Display_Logo(whoami);
Delay(200);Write_Data(0x01);//清屏
}/******************************************************************************/
void main(void)//主函数
{
Init_Timer0();//初始化T0
Init_LCD_Logo(); //初始化 LogoShow_logo();//开机画面显示
Init_LCD_Cal(); //初始化 LCM
Digit_input_calcul();//计算值输入函数
}