基于51单片机的多功能计算器proteus仿真 支持二八十进制小数负数计算 LCD1602显示

硬件设计

附:http://www.jh-tec.cn/archives/7513

工作原理
利用矩阵键盘进行按键的输入,通过对矩阵键盘的扫描,获取用户的输入,并实时的显示在1602液晶上,每次获取到输入时,根据软件设计的相应方法对输入进行处理、运算,输入结束后(以“=“为标志),将最终的运算结果输出的液晶上。

在这里插入图片描述

仿真图1: (LCD1602显示,支持负数和进制运算及有限的连续运算,连续运算时候无法识别优先级,不支持小数;)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

仿真图2: LCD1602显示,支持负数和小数及开根号,不支持连续运算;

在这里插入图片描述
在这里插入图片描述

程序设计1

#include <reg51.h>
#include <stdio.h>
#include <intrins.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>


#define u8  unsigned char
#define u16  unsigned char
sbit LCDEN=P3^4;
sbit RS=P3^5;
sbit RW=P3^6;
sbit BF=P0^7; 
sbit change_m=P3^7;

u8 code keyval[]="789/456*123-c0=+"; //按键对应的符号 
u8 data1[10];
u8 k=0;
char  m[8]={0};
double sum=0;
int flag;
void WrDatLCD(unsigned char DatVal);
void WrComLCD(unsigned char ComVal);
void delay(u16 x)	  //延时x毫秒
{
u16 i,j;
for(i=0;i<x;i++)
	for(j=0;j<115;j++)
		;
}
int convertBinaryToDecimal(long n)
{
	int decimalNumber = 0, i = 0, remainder;
	while (n != 0)
	{
		remainder = n % 10;
		n /= 10;
		decimalNumber += remainder * pow(2, i);
		++i;
	}
	return decimalNumber;
}

int convertBinaryToDecimal8(long n)
{
	int decimalNumber = 0, i = 0, remainder;
	while (n != 0)
	{
		remainder = n % 10;
		n /= 10;
		decimalNumber += remainder * pow(8, i);
		++i;
	}
	return decimalNumber;
}





u8 keypad4_4()//按键扫描函数:要去抖,若有按键按下,返回对应的按键值(0-15),没有按键按下返回16
{
u8 i,row,temp;
u8 key=16;//按键号,初值设置为16,目的是:没有按键按下时返回16;
          //若不设初值(默认值为0),没有按键按下时,将返回0,会误认为0被按下  
row=0xef; //从第一列开始      
for(i=0;i<4;i++)
{
	P1=0xff;  
	P1=row;	//第i列信号,对应列为低,其他全为高
	row=_crol_(row,1); 	  //生成下一列信号
	temp=P1; //读入扫描信号
	temp=temp&0x0f; //屏蔽高4位列信号,只保留低4位行信号 
	if(temp!=0x0f)//有按键被按下,因为第i列某行有按键按下,则低4位中有一位为低  
 	{  
		delay(20);  //延时去抖
		temp=P1;  
		temp=temp&0x0f;  
		if(temp!=0x0f)   //再次确认有按键被按下
  		{  
        	switch(temp)  //根据低4位行信号,判断哪个按键被按下
            {  
            	case 0x0e:key=0+i;break; //第i列第1行按键被按下 
                case 0x0d:key=4+i;break; //第i列第2行按键被按下  
                case 0x0b:key=8+i;break; //第i列第3行按键被按下
				case 0x07:key=12+i;      //第i列第4行按键被按下 
            }
			
			do
			{
				temp=P1;  	    //再次扫描按键
  				temp=temp&0x0f;  
  			}while(temp!=0x0f); //等待按键释放   
  		}  
     }
	
	
		 if(change_m == 0)
		 {
			 delay(50);
			 if(change_m == 0)
			 {
				 flag++;
				 if(flag == 3)
				 {
					 flag = 0;
				 }
			 } while(!change_m);
		 }



		 
}  
return(key);//扫面结束,返回按键值
}

unsigned char DectectBusyBit(void)//状态判断函数(忙/闲?)
{   
	bit result;
	P0 = 0xff;	//读状态前先置高电平,防止误判
	RS = 0;
	delay(5);
    RW = 1;
	LCDEN = 1;
	delay(5);
	result=BF; //若LCM忙,则反复测试,在此处原地踏步;当LCM闲时,才往下继续
	LCDEN = 0;
	return result;		      
}

void WrComLCD(unsigned char ComVal)//写命令函数
{
	while(DectectBusyBit()==1);         //先检测LCM是否空闲
	RS = 0;
	delay(1);
    RW = 0;
	LCDEN = 1;
	P0 = ComVal;
	delay(1);
	LCDEN = 0;	
}

void WrDatLCD(unsigned char DatVal)//写数据函数
{
while(DectectBusyBit()==1); 
	RS = 1;
	delay(1);
    RW = 0;
	LCDEN = 1;
	P0 = DatVal;
	delay(1);
	LCDEN = 0;	
}

void LCD_Init(void)//1602初始化函数
{ 
	WrComLCD(0x38);     // 功能设定:16*2行、5*7点阵、8位数据接口
	WrComLCD(0x38);
	WrComLCD(0x38);    
//多次重复设定功能指令,因为LCD启动后并不知道使用的是4位数据接口还是8位的,所以开始时总是默认为4位
	WrComLCD(0x01);    // 清屏 
	WrComLCD(0x06);    // 光标自增、屏幕不动  
	delay(1);	      // 延时,等待上面的指令生效,下面再显示,防止出现乱码
	WrComLCD(0x0c);    // 开显示
}
			 
void compute(){
	u8 i,j=0,k,n=0;
	char data3[3]={0};
	int sum1,data2[4]={0};
	int a,b,c,d,o;
	int getValue[6]={0};
	sum=0;

	for(i=0;data1[i]!='\0';i++){
		  if(data1[i]!='+' && data1[i]!='-' && data1[i]!='*' && data1[i]!='/'){
		  	data2[j] =data2[j]*10+(data1[i]-'0');

		  }
		  else{
		  	data3[n++] = data1[i];
		  	j++;
		  } 
	}
	a=data2[0];
	b=data2[1];
	c=data2[2];
	d=data2[3];
	if(flag == 1)  //如果二进制
	{
	a=convertBinaryToDecimal(a);
	b=convertBinaryToDecimal(b);
	c=convertBinaryToDecimal(c);
	d=convertBinaryToDecimal(d);
	}
	if(flag == 2)  //如果8进制
	{
	a=convertBinaryToDecimal8(a);
	b=convertBinaryToDecimal8(b);
	c=convertBinaryToDecimal8(c);
	d=convertBinaryToDecimal8(d);
	}

	
	for(i=0;i<n;i++){
		if(i==0){
			if(data3[0]=='+')  sum = a + b;
			if(data3[0]=='-')  sum = a - b;
			if(data3[0]=='*')  sum = a * b;
			if(data3[0]=='/')  sum = a / (double)b; 
		}
		if(i==1){
			if(data3[1]=='+')  sum = sum+c;
			if(data3[1]=='-')  sum = sum-c;
			if(data3[1]=='*')  sum = sum*c;
			if(data3[1]=='/')  sum = sum/((float)c); 
		}
		if(i==2){
			if(data3[2]=='+')  sum = sum+d;
			if(data3[2]=='-')  sum = sum-d;
			if(data3[2]=='*')  sum = sum*d;
			if(data3[2]=='/')  sum = sum/((float)d); 
		}

	
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值