基于51单片机的多功能计算器,支持二八十进制小数负数计算

发布者:HeavenlyLove最新更新时间:2022-01-10 来源: eefocus关键字:51单片机 手机看文章 扫描二维码
随时随地手机看文章

硬件设计


工作原理

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

在这里插入图片描述

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

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

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

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

程序设计1

#include

#include

#include

#include

#include

#include


#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 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]!='';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 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); 

}


}


文件仅供参考:


链接:https://pan.baidu.com/s/1ZAxAbTe_oD_cuTvvKWxU5A

提取码:x102

关键字:51单片机 引用地址:基于51单片机的多功能计算器,支持二八十进制小数负数计算

上一篇:基于51单片机的计算器 汇编语言
下一篇:基于51单片机的简易计算器proteus仿真 数码管显示

推荐阅读最新更新时间:2024-11-08 12:13

51单片机按键直接控制舵机旋转
#include reg52.h #include math.h typedef unsigned char uchar; typedef unsigned int uint; sbit KEY1=P3^4; sbit KEY2=P3^5; sbit KEY3=P3^6; sbit KEY4=P3^7; void Delay(unsigned int s); uchar flag_0; uchar flag_1; void Delay(unsigned int s) { unsigned int i; for(i=0; i s; i++); for(i=0; i s; i++); } sbit PWM_OUT0=P2^1; sbi
[单片机]
基于51单片机的简易电子琴课程设计
1.本设计采用51单片机作为主控制器 2.外部加上放音设备如喇叭等,来实现音乐演奏控制器的硬件电路 3.用8个手工的按键发出八个音阶 制作出来的电子琴实物图如下: 仿真原理图如下(proteus仿真工程文件可到本帖附件中下载) 视频讲解: 电子琴原件清单 1.8欧0.25w小喇叭 2.8050三极管*2 3.10k电阻*2 4.30欧姆电阻 5.40脚座 6.STC89c51 7.10uf电容 8.30pf电容*2 9.小按键*8 10.自锁开关 11.DC电源座 12.12m晶振 13.7*9万用板 14.导线若干 15.焊锡若干 16.usb电源线或电池盒+DC电源插头 单片机源程序如下: #include reg
[单片机]
基于<font color='red'>51单片机</font>的简易电子琴课程设计
基于AT89C51单片机的交通灯控制系统设计与仿真
0 引言 随着微控技术的日益完善和发展,单片机的应用不断走向深入。它的应用必定导致传统的控制技术从根本上发生变革。它在工业控制、数据采集、智能仪表、机电一体化、家用电器等领域得到广泛的应用,极大地提高了这些领域的技术水平和自动化控制。同时,伴随着我国经济的高速发展,私家车、公交车的增加,无疑会给我国的道路交通系统带来沉重的压力,很多大城市都不同程度地受到交通堵塞问题的困扰。为解决交通堵塞问题,采用AT89C51单片机为核心,与74LS86与74LS04组成特殊情况控制电路、七段数码管及LED组成显示电路,设计出以人性化、智能化为目的的交通灯控制系统,如遇特殊情况可人为控制交通从而解决交通堵塞的实际问题,整个电路简单,易于实现。
[单片机]
基于AT89C<font color='red'>51单片机</font>的交通灯控制系统设计与仿真
51单片机4×4矩阵按键程序
ORG 0000H LJMP MAIN ;跳转至主程序 ORG 0100H MAIN: LCALL KEY_IN MOV P0,A LCALL DEL AJMP MAIN ;====================== ;判断有无按键,无按键直接返回 ;KEY_IN: MOV P1,#0F0H ;置行线为低电平,读列线状态(在高4位,无按键则全为1) ; MOV A,P1 ; ANL A,#0F0H ;屏蔽低四位 ; MOV B,A ; MOV P1,#0FH ;置列线为低电平,读行线状态(在低4位,无按键则全为1) ; MOV A,P1 ; ANL A,#0FH ; ORL A,B ;高四位与低四位重新组合 ; CJNE A,#
[单片机]
基于AT89C51单片机的智能计步器设计
1 引言 当今社会,随着经济的发展,人们生活水平的提高,肥胖的人越来越多,也就导致了越来越多的疾病产生,因此,人们越来越关注健康问题,而锻炼身体是让自己健康的最有效的方法。因此计步器应运而生,就成了时下流行的趋势。步行时,通过伸缩肌肉,血液在流动时的抵抗值下降,血压下降且稳定。经常步行的人很少患高血压或低血压病。坚持步行能减少血管内附着的脂肪性物质,使体重减轻,也逐渐减少心脏的负荷。而基于单片机为核心控制的计步器有着精确,可靠,稳定,方便等优点,已被大多数人所接受。通过计步器人们可以知道自己跑了多少步,实时掌握自己的锻炼情况。 2 总体设计方案 计步器由振荡电路、复位电路、显示电路以及按键电路几个部分组成,由电池进行供电。系统
[单片机]
基于AT89C<font color='red'>51单片机</font>的智能计步器设计
51单片机针脚排列和定义
针脚排列: 针脚定义: 40个引脚按引脚功能大致可分为4个种类:电源、时钟、控制和I/O引脚。 ⒈ 电源: ⑴ VCC - 芯片电源,接+5V; ⑵ VSS - 接地端; 注:用万用表测试单片机引脚电流一般为0v或者5v,这是标准的TTL电平,但有时候在单片机程序正在工作时候测试结果并不是这个值而是介于0v-5v之间,其实这之是万用表反映没这么快而已,在某一个瞬间单片机引脚电流还是保持在0v或者5v的。 ⒉ 时钟:XTAL1、XTAL2 - 晶体振荡电路反相输入端和输出端。 ⒊ 控制线:控制线共有4根, ⑴ ALE/PROG:地址锁存允许/片内EPROM编程脉冲
[单片机]
基于AT89C51单片机和放大器实现音频信号均幅控制放大电路的设计
引言 现在的学校,有许多已经采用计算机加网络多媒体系统来进行现场教学。此外,工程施工人员在施工现场进行对讲通话,驾驶人员在开动的坦克等自行火炮车辆上进行通话等,都避免不了讲话时嘈杂的背景噪声或无线干扰(包括网络射频干扰),因而声音有大有小。怎样才能使听到的广播声或耳机中说话的声音平稳清晰,本文给出了一种用SG270、LM4884电路配合AT89C51单片机来解决干扰问题的实现方案。 1 电路主要器件 1.1 SG270放大器 SG270电路为国产工业级(-40℃~+85℃)可控增益音频放大器,该芯片的1、2脚为正、反相信号输人端,A、B、C为压控输入端,增益控制电压范围为2.1~2.5 V,可通过输出反馈信号来即时进行自动增益
[单片机]
基于AT89C<font color='red'>51单片机</font>和放大器实现音频信号均幅控制放大电路的设计
PC机与多MCS-51单片机间的串行通信设计
1 引 言   在测控系统和工程应用中,常遇到多项任务需同时执行的情况,因而主从式多机分布式系统成为现代工业广泛应用的模式。它们大多由IBM-PC微机和MCS-51单片机组成。单片机功能强、体积小、价格低廉、开发应用方便,尤其具有全双工串行通讯的特点,在工业控制、数据采集、智能仪器仪表、家用电器方面都有广泛的应用。同时,IBM-PC机正好补充单片机人机对话和外围设备薄弱的缺陷。各单片机独立完成数据采集处理和控制任务,同时通过通信接口将数据传给PC机,PC机将这些数据进行处理、显示或打印,把各种控制命令传给单片机,以实现集中管理和最优控制。   故IBM-PC机(上位机)与各MCS-51单片机(下位机)之间的通信显得尤其重要。本文主要
[单片机]
PC机与多MCS-<font color='red'>51单片机</font>间的串行通信设计

推荐帖子

TI M4 DAY资料
分享一下!没有电子版的PPT,无法上传,有点遗憾。TIM4DAY资料顶,谢谢分享!回复沙发songhaifei的帖子很给力的资料啊,谢谢楼主分享,学习中……回复楼主songhaifei的帖子
songhaifei 微控制器 MCU
有什么办法可以得到当前OS所在的分区名称?
请问有什么办法可以知道当前正在运行的winceos所在的分区的名称?不写驱动,不去读bootargs一类的设定。有什么办法可以得到当前OS所在的分区名称?GetPartitionInfo.不符合要求。继续顶搞定怎么做到的?楼主!tellme就是怎么做的!在wince下不是有分区操作的接口吗!可以用吗!easy,塞个IOCTL去某个现成的驱动当proxy读取bootargs就得了。
flygh 嵌入式系统
基于AVR单片机的精密温控系统设计
摘要:本文设计了一种基于Atmegal6单片机的精密温控系统。该系统采用单片机为核心控制器。改进型智能温度传感器DS18B20完成对温度信号的采集。并把采集的信号送入单片机进行处理。实时显示温度值,根据系统设定完成相应的智能控制。基于AVR单片机的精密温控系统设计这个论文不好,一点内容都没有。。。
xtss Microchip MCU
为什么bootloader会调用_KernelRelocate函数?
为什么bootloader会调用_KernelRelocate函数?查了些资料,大致原因如下:“内核的初始化数据都保存在镜像文件中(data段的数据)。对数据的读写,必须要把镜像的真实数据内容,复制到RAM中,才允许使用。Kernelrelocate()函数就是完成该功能的。”但是既然数据已经在.data数据段了为什么还要复制到内存中呢?我想.data数据段也是在内存中的,那为什么不直接访问.data数据段呢?为什么bootloader会调用_KernelRelocate函数?跟我
ogmwyv 嵌入式系统
测评汇总:嘉楠科技CanMV 勘智(Kendryte)K230嵌入式AI开发板
活动详情:【嘉楠科技CanMV勘智(Kendryte)K230嵌入式AI开发板】更新至2024-10-28测评报告汇总:@dfjs嘉楠科技CanMV勘智(Kendryte)K230嵌入式AI开发板--测评3__基础实验2嘉楠科技CanMV勘智(Kendryte)K230嵌入式AI开发板--测评2_基础实验1嘉楠科技CanMV勘智(Kendryte)K230嵌入式AI开发板--测评1@jinglixixi【K230嵌入式AI开发板测评】+字符识
EEWORLD社区 测评中心专版
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved