📄 计算器.c
字号:
/********************************************************************************/
/* Project: 计算器(Calculator) 版本号:V1。0 */
/* Designed By: ma gong 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 即可。 */
/********************************************************************************/
#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);//初始化LCDvoid Init_LCD_Logo(void);//初始化
LCDvoid 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;//位置为0
while(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(); //初始化 Logo
Show_logo();//开机画面显示
Init_LCD_Cal(); //初始化 LCM
Digit_input_calcul();//计算值输入函数
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -