呵呵,沒想到這個兄弟,在我之前把代碼給貼出來了
我也來一份了!
/********************************************************************************/
/* 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();//計算值輸入函數
}