实现加减乘除,进制转换及三角函数运算开方平方等
1.程序如下
main.c
------------------------------------------
#include <REGX52.H>
#include "LCD1602.h" //包含LCD1602头文件
#include "KEYCON.h" //键控
#include "Delay.h" //延时
#include "Calculate.h" //计算
/*
初始化
基本程序计算逻辑实现/1+1;
键扫
增加功能
检测
*/
typedef unsigned char uint8;
typedef unsigned int uint16;
uint8 flag=0; //判断是否为操作位 1有一符号 2等号按下 3单操作数运算符号按下
//extern uint8 KeyNum=0;
uint8 dat1[]={0,1,4,7,0,2,5,8,0,3,6,9};//保存显示的数据 用于操作数
uint8 KeyNum; //键值
uint8 KeyCc; // 防连按,标志位 前状态 1未按下 0按中
uint8 LineX=1; //行
uint8 ColumnY=1; //列
idata uint8 flagC=0 ; // 算法区分
uint16 flagOut=0; //溢出标志位 1 溢出
uint16 flagFl=0; //浮点型输出标志位 1 浮点输出
uint8 flagFF=0; //小鼠负号控制位 0+ 1—
uint16 cnt=0; //结果位数
uint8 SB=0; //p.
unsigned int i1=0;
unsigned long a,b; //操作数a,b 总长13
unsigned long c; //结果 总长13=6X6+1 +1
typedef struct nub {
uint8 x, y;//显示行列
uint8 bitter;//显示字符
}nub_t;
// 用于分值输出
unsigned int i=2;
unsigned int num[10]; //0~4294967295 int num[BitMax];
void init1(){
P1=0xff;
ColumnY=1;
KeyCc=1;
a=0;
b=0;
c=0;
flagC=0;
cnt=0;
flagOut=0;
flagFl=0;
flag=0;
i=2;
SB=0;
flagFF=0;
KeyNum=0;
if(SB==0){
LCD_ShowChar(1,1,'p');
LCD_ShowChar(1,2,'.');
SB=1;
}
}
void main()
{
LCD_Init();
init1();
while(1){
KeyNum=KeyCon();
if (KeyNum==0){
KeyCc=1;}
if(KeyCc){
if(KeyNum){
if(SB==1){
LCD_Init();
SB=0;
}
switch(KeyNum){
case 1: {if(flag!=2){LCD_ShowChar(LineX,ColumnY,'1'); ColumnY++;}break;} //1
case 2: {if(flag!=2){LCD_ShowChar(LineX,ColumnY,'4'); ColumnY++;}break;} //4
case 3: {if(flag!=2){LCD_ShowChar(LineX,ColumnY,'7'); ColumnY++;}break;} //7
case 4: {if(flag!=2){LCD_ShowChar(LineX,ColumnY,'0'); ColumnY++;}break;} //0
case 5: {if(flag!=2){LCD_ShowChar(LineX,ColumnY,'2'); ColumnY++;}break;} //2
case 6: {if(flag!=2){LCD_ShowChar(LineX,ColumnY,'5'); ColumnY++;}break;} //5
case 7: {if(flag!=2){LCD_ShowChar(LineX,ColumnY,'8'); ColumnY++;}break;} //8
case 8: {if(flag==0){LCD_ShowChar(LineX,ColumnY,'%');ColumnY++;flagC=8;} if(flag!=2){flag=1;}break;} // 求余%
case 9: {if(flag!=2){LCD_ShowChar(LineX,ColumnY,'3'); ColumnY++;}break;} //3
case 10: {if(flag!=2){LCD_ShowChar(LineX,ColumnY,'6'); ColumnY++;}break;} //6
case 11: {if(flag!=2){LCD_ShowChar(LineX,ColumnY,'9'); ColumnY++;}break;} //9
case 13: {if(flag==0){LCD_ShowChar(LineX,ColumnY,'+');ColumnY++;flagC=13;} if(flag!=2){flag=1;}break;} //+
case 14: {if(flag==0){LCD_ShowChar(LineX,ColumnY,'-');ColumnY++;flagC=14;} if(flag!=2){flag=1;}break;} //-
case 15: {if(flag==0){LCD_ShowChar(LineX,ColumnY,'X');ColumnY++;flagC=15;} if(flag!=2){flag=1;}break;} //X
case 16: {if(flag==0){LCD_ShowChar(LineX,ColumnY,'/');ColumnY++;flagC=16;} if(flag!=2){flag=1;}break;} // 除
case 17: {if(flag==0||flag==3){flagC=17;LCD_ShowChar(1,12,'1'); LCD_ShowChar(1,13,'6');} if(flag!=2){flag=3;}break;} //16进制
case 18: {if(flag==0||flag==3){flagC=18;LCD_ShowChar(1,13,'2');} if(flag!=2){flag=3;}break;} //2进制
case 19: {if(flag==0||flag==3){flagC=19;LCD_ShowString(1,12,"sin");} if(flag!=2){flag=3;}break;} //sin
case 20: {if(flag==0||flag==3){flagC=20;LCD_ShowString(1,12,"cos");} if(flag!=2){flag=3;}break;} //cos
case 21: { LCD_Init();init1();break;} // 清屏
case 22: {if(flag==0||flag==3){LCD_ShowString(1,12,"2->16");flagC=22;} if(flag!=2){flag=3;}break;} // 2->16
case 23: {if(flag==0||flag==3){flagC=23;LCD_ShowString(1,12,"^2");} if(flag!=2){flag=3;}break;} //平方
case 24: {if(flag==0||flag==3){flagC=24;LCD_ShowString(1,12,"sqrt");} if(flag!=2){flag=3;}break;} //开方
case 25: {if(flag==0||flag==3){LCD_ShowString(1,12,"tan");flagC=25;} if(flag!=2){flag=3;}break;} //tan
case 12: { //等于=
if(flag==2){break;}
flag=2;
LCD_ShowChar(2,1,'=');
c=Calc(a,b,flagC);
b=c;
if(flagOut==0){
while (c!=0) {
num[cnt++] =(unsigned int)(c%10);//取余数
c/=10;
}
if((flagC==16)||(flagC==19)||(flagC==20)||(flagC==24)||(flagC==25)){ //浮点型
//根据输出是否大于1
if(b>=(unsigned long)(1000)){
if(flagFF==2){ // sin270
LCD_ShowChar(2,2,'-');
LCD_ShowChar(2,3,'1');
LCD_ShowChar(2,4,'.');
LCD_ShowChar(2,5,'0');
LCD_ShowChar(2,6,'0');
LCD_ShowChar(2,7,'0');
}else{
if(flagFF==1){LCD_ShowChar(2,2,'-');i++;} //tan 特殊
for(;cnt>0;cnt--){
if((cnt==3)&&(flagFl==1)){LCD_ShowChar(2,i,'.');i++;}; //cnt-1=2
LCD_ShowNum(2,i,num[cnt-1],1);
i++;
}}
}else{
//判断sin是否输出负数 不覆盖负号后撤一
if(flagFF==1){
LCD_ShowChar(2,2,'-');
LCD_ShowChar(2,3,'0');
LCD_ShowChar(2,4,'.');
LCD_ShowChar(2,5,'0');
LCD_ShowChar(2,6,'0');
LCD_ShowChar(2,7,'0');
i=7;//5
}else{
LCD_ShowChar(2,2,'0');
LCD_ShowChar(2,3,'.');
LCD_ShowChar(2,4,'0');
LCD_ShowChar(2,5,'0');
LCD_ShowChar(2,6,'0');
i=6;//4
}
for(i1=0;i1<cnt;i1++){ //有问题
LCD_ShowNum(2,i,num[i1],1);
i--;
if(flagFF==1){if(i==4){break;}}else{if(i==3){break;} }
}
}
}else{
for(;cnt>0;cnt--){// 整形
LCD_ShowNum(2,i,num[cnt-1],1);
i++;
}
}
}else{ LCD_ShowString(2,2,"more max");
}
}
}
KeyCc=0;
if(KeyNum<=11&&KeyNum>=1&&KeyNum!=8){
if(flag==0||flag==3) //没有按下符号键或单操作数
{
//led=1;
a=a*10+dat1[KeyNum];
}
else{if(flag==1) //防止连按=号
{
//led=1;
b=b*10+dat1[KeyNum];
} //记录操作数
}
}
// LCD_ShowChar(2,2,'a');
//Delay(1000);
if(flagOut==1){LCD_ShowString(2,2,"more max");
}
}
}
}}
Delay.c
-------------------------------------------------------------------
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
Delay.h
--------------------------------------------------------------------
#ifndef __DELAY_H__
#define __DELAY_H__
void Delay(unsigned int xms);
#endif
LCD1602.c
----------------------------------------------------------------------
该LCD1602液晶显示屏配置文件引用
51单片机——LCD1602液晶显示屏_51单片机1602插上电源不亮-CSDN博客
----------------------------------------------------------------------
#include <REGX52.H>
#include "Delay.h"
//引脚配置:
sbit LCD_RS=P2^5;
sbit LCD_RW=P2^6;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0
/**
* @brief LCD1602写命令
* @param Command 要写入的命令
* @retval 无
*/
void LCD_WriteCommand(unsigned char Command)
{
LCD_RS=0;
LCD_RW=0;
LCD_DataPort=Command;
LCD_EN=1;
Delay(1);
LCD_EN=0;
Delay(1);
}
/**
* @brief LCD1602写数据
* @param Data 要写入的数据
* @retval 无
*/
void LCD_WriteData(unsigned char Data)
{
LCD_RS=1;
LCD_RW=0;
LCD_DataPort=Data;
LCD_EN=1;
Delay(1);
LCD_EN=0;
Delay(1);
}
/**
* @brief LCD1602设置光标位置
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @retval 无
*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD_WriteCommand(0x80|(Column-1));
}
else if(Line==2)
{
LCD_WriteCommand(0x80|(Column-1+0x40));
}
}
/**
* @brief LCD1602初始化函数
* @param 无
* @retval 无
*/
void LCD_Init()
{
LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
LCD_WriteCommand(0x01);//光标复位,清屏
}
/**
* @brief 在LCD1602指定位置上显示一个字符
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @param Char 要显示的字符
* @retval 无
*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
LCD_SetCursor(Line,Column);
LCD_WriteData(Char);
}
/**
* @brief 在LCD1602指定位置开始显示所给字符串
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param String 要显示的字符串
* @retval 无
*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=0;String[i]!='\0';i++)
{
LCD_WriteData(String[i]);
}
}
/**
* @brief 返回值=X的Y次方
*/
int LCD_Pow(int X,int Y)
{
unsigned char i;
int Result=1;
for(i=0;i<Y;i++)
{
Result*=X;
}
return Result;
}
/**
* @brief 在LCD1602指定位置开始显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~65535
* @param Length 要显示数字的长度,范围:1~5
* @retval 无
*/
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
}
}
/**
* @brief 在LCD1602指定位置开始以有符号十进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:-32768~32767
* @param Length 要显示数字的长度,范围:1~5
* @retval 无
*/
/*void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
unsigned char i;
unsigned int Number1;
LCD_SetCursor(Line,Column);
if(Number>=0)
{
LCD_WriteData('+');
Number1=Number;
}
else
{
LCD_WriteData('-');
Number1=-Number;
}
for(i=Length;i>0;i--)
{
LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
}
}*/
/**
* @brief 在LCD1602指定位置开始以十六进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~0xFFFF
* @param Length 要显示数字的长度,范围:1~4
* @retval 无
*/
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned int i,SingleNumber;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
SingleNumber=Number/LCD_Pow(16,i-1)%16;
if(SingleNumber<10)
{
LCD_WriteData(SingleNumber+'0');
}
else
{
LCD_WriteData(SingleNumber-10+'A');
}
}
}
/**
* @brief 在LCD1602指定位置开始以二进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~1111 1111 1111 1111
* @param Length 要显示数字的长度,范围:1~16
* @retval 无
*/
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
}
}
LCD1602.h
---------------------------------------------------------------------
#ifndef __LCD1602_H__
#define __LCD1602_H__
//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
#endif
KEYCON.c
---------------------------------------------------------------------------
#include <REGX52.H>
#include "Delay.h"
unsigned char KeyCon()
{
unsigned char KeyNum33=0;
P1=0xff;P2_0=1;P2_1=1;
P1_0=0;
if(P1_4==0){Delay(20); KeyNum33=1;} //while(P1_5==1){Delay(20);
if(P1_5==0){Delay(20); KeyNum33=2;}
if(P1_6==0){Delay(20); KeyNum33=3;}
if(P1_7==0){Delay(20); KeyNum33=4;}
if(P2_1==0){Delay(20); KeyNum33=17;}
P1=0xff;P2_0=1;P2_1=1;
P1_1=0;
if(P1_4==0){Delay(20); KeyNum33=5;}
if(P1_5==0){Delay(20); KeyNum33=6;}
if(P1_6==0){Delay(20); KeyNum33=7;}
if(P1_7==0){Delay(20); KeyNum33=8;}
if(P2_1==0){Delay(20); KeyNum33=18;}
P1=0xff;P2_0=1;P2_1=1;
P1_2=0;
if(P1_4==0){Delay(20); KeyNum33=9;}
if(P1_5==0){Delay(20); KeyNum33=10;}
if(P1_6==0){Delay(20); KeyNum33=11;}
if(P1_7==0){Delay(20); KeyNum33=12;}
if(P2_1==0){Delay(20); KeyNum33=19;}
P1=0xff;P2_0=1;P2_1=1;
P1_3=0;
if(P1_4==0){Delay(20); KeyNum33=13;}
if(P1_5==0){Delay(20); KeyNum33=14;}
if(P1_6==0){Delay(20); KeyNum33=15;}
if(P1_7==0){Delay(20); KeyNum33=16;}
if(P2_1==0){Delay(20); KeyNum33=20;}
P1=0xff;P2_0=1;P2_1=1;
P2_0=0;
if(P1_4==0){Delay(20); KeyNum33=21;}
if(P1_5==0){Delay(20); KeyNum33=22;}
if(P1_6==0){Delay(20); KeyNum33=23;}
if(P1_7==0){Delay(20); KeyNum33=24;}
if(P2_1==0){Delay(20); KeyNum33=25;}
return KeyNum33;
}
KEYCON.h
----------------------------------------------------
#ifndef __KEYCON_H__
#define __KEYCON_H__
unsigned char KeyCon();
#endif
Calculate11.c
-----------------------------------------------------
#include <REGX52.H>
#include <math.h>
#include "LCD1602.h"
extern ColumnY;
extern i;
extern flagOut;
extern flagFl;
extern unsigned char flagFF; //无符号型的一定要加类型名
extern a;
extern b;
unsigned long sum;
code unsigned long UlMax=4294967295; //传出值的最大值
code unsigned long FlMax=4294967; //浮点型传出最大值
code float _fast_sin[91] = { 0,
0.0174524,0.0348995,0.052336,0.0697565,0.0871558,0.104528,0.121869,0.139173,0.156434,0.173648,
0.190809,0.207912,0.224951,0.241922,0.258819,0.275637,0.292372,0.309017,0.325568,0.34202,
0.358368,0.374607,0.390731,0.406737,0.422618,0.438371,0.453991,0.469472,0.48481,0.5,
0.515038,0.529919,0.544639,0.559193,0.573576,0.587785,0.601815,0.615662,0.62932,0.642788,
0.656059,0.669131,0.681998,0.694658,0.707107,0.71934,0.731354,0.743145,0.75471,0.766045,
0.777146,0.788011,0.798636,0.809017,0.819152,0.829038,0.838671,0.848048,0.857167,0.866025,
0.87462,0.882948,0.891007,0.898794,0.906308,0.913546,0.920505,0.927184,0.93358,0.939693,
0.945519,0.951057,0.956305,0.961262,0.965926,0.970296,0.97437,0.978148,0.981627,0.984808,
0.987688,0.990268,0.992546,0.994522,0.996195,0.997564,0.99863,0.999391,0.999848,1};
float sinXX(unsigned int d){
if(d>((unsigned int)180)){
flagFF=1; //LCD_ShowChar(2,11,'0');
// i=i+1;
if((d-180)>90){return _fast_sin[360-d];}else{if(d==270){flagFF=2;} return _fast_sin[d-180];} //d%360; d>180 - 270特
}else{if(d>=90){return _fast_sin[180-d];}else{return _fast_sin[d];}}
}
unsigned long Calc(unsigned long a1,unsigned long b1,unsigned char num){
sum=0;
switch(num){
case 8 :{if(a1%b1==0){LCD_ShowChar(2,2,'0');}return a1%b1;}
case 13 :{if((a1==520)&&(b1==1314)){LCD_ShowString(2,7,"#love you#");} return a1+b1;} //+
case 14 :{if(a1>b1){return a1-b1;}//-
else{if(a1!=b1){LCD_ShowChar(2,2,'-');i=i+1;}else{LCD_ShowChar(2,2,'0');}
return b1-a1;}}
case 15 :{//X
//if((b==0)||(a==0)){sum=0;break;}
if(UlMax/a1 < b1){flagOut=1;break;}//发生溢出
else {sum=a1*b1;a=0;b=0;break;}}
case 16:{// 除
flagFl=1;
if(b1==0){flagOut=1;break;}
if(FlMax<(unsigned long)(a1/b1)){flagOut=1;break;}
else{sum=(unsigned long)((((float)a1/(float)b1))*1000);//强制转换为long。保留三位小数
break;} }
//16jin
case 17 :{ if(a1>65535){flagOut=1;}else{LCD_ShowHexNum(2,2,(unsigned int)a1,4);}
break;}
case 18 :{if(a1>16383){flagOut=1;}else{ LCD_ShowBinNum(2,2,(unsigned int)a1,14);}break;} //2jin
case 19 :{flagFl=1;sum=(unsigned long)((sinXX((unsigned int)(a1%360)))*1000);break;}//sin
case 20 :{flagFl=1;
b1=a1%360;if(b1<=90){sum=(unsigned long)((sinXX((unsigned int)(90-b1)))*1000);break;}
else{sum=((unsigned long)((sinXX((unsigned int)((b1+90)%360)))*1000));break;}
// sum=(unsigned long)((sinXX(((unsigned int)(450-(a%360)))))*1000)
}//cos
case 22 :{i=0;b1=0;sum=0;
while(a1!=0){
b1=a1%10;
a1=a1/10;
if(b1>1){flagOut=1;break;}
sum=sum+b1*pow(2,i);
i++;
}
LCD_ShowHexNum(2,2,(unsigned int)sum,4);
sum=0;
break;}
case 23 :{if (a1>64031){flagOut=1;}else{return a1*a1;}break;}//平方
case 24 :{flagFl=1; return (unsigned long)(sqrt(a1)*1000);break;}//开方
case 25 :{flagFl=1; if(a%180>90){flagFF=1;}// 符号控制
//sum=((unsigned long)tan(a1)*1000);}
b1=a1%360;if(b1<=90){b1=(unsigned long)((sinXX((unsigned int)(90-b1)))*1000);}
else{b1=((unsigned long)((sinXX((unsigned int)((b1+90)%360)))*1000));}
a1=(unsigned long)((sinXX((unsigned int)(a1%360)))*1000);
if(FlMax<(unsigned long)(a1/b1)){flagOut=1;sum=0;}
else{sum=(unsigned long)((((float)a1/(float)b1))*1000);}//强制转换为long。保留三位小数
if(b1==0){flagOut=1;} break;}
}
return sum;
}
Calculate11.h
-----------------------------------------
#ifndef __CALCULATE_H__
#define __CALCULATE_H__
unsigned long Calc(unsigned long a,unsigned long b,unsigned char num);
#endif
2.仿真如下 单片机使用AT89C52系列 (拥有8k字节)