微架构 运算器 芯片 控制器 晶体管 处理器
主页 正文

51单片机简易计算器负数运算设计技巧

我在用51单片机设计简易计算器,目前只能进行最大五位正整数的加减乘除的运算。 怎样才能设计出负数运算

将所有数据都计算为正整数,并分别处理正负号的方法。
例如,如果两个数相减,首先判断被减数是否更大。
减数和减数相加。
数字翻转并相减后,结果前会加上负号。
在乘法和除法中,如果两个数的乘法和除法的符号不同,则结果为负。
直接使用C语言库函数根据浮点类型计算数据类型,结果为负数和小数,然后转换为字符串进行显示。

基于51单片机的简易计算器设计,急

//函数0123456789+-×÷=清除表3-1 3.2计算器软件设计

#include //头文件

#define intunsignedint//

#defineucharunsignedchar

sbitlcden=P2^3;//定义引脚

sbitrs=P2 ^4;

sbitrw=P2^0;

sbitbusy=P0^7;

chari,j,temp,num,num_1;

龙加,b,c; //第一个数字b; 第二个数字c, 获取数字

floata_c,b_c;

ucharflag, fuhao;//flag表示符号键是否被按下; 夫豪透露。
点击了哪个符号

ucharcodetable[]={7,8,9,0,4,5,6,0,1,2,3,0,0,0,0,0};< /p >

ucharcodetable1[] ={

7,8,9,0x2 f-0x30,

4,5,6,0x2a-0x30,

1,2,3,0x2d-0x30,

voiddelay(ucharz)//延迟函数

{

uchary;

0;z--)

for(y=0;y<110;y++);

} voidcheck()//忙或不工作 判断

{

do{

P0=0xFF;

rs=0; //命令

rw=1; //读取

lcden=0; // 禁止读写

delay(1);//等待液晶显示器处理数据

lcden= 1; //允许读取

}(bus sy==1);//判断是否空闲; 1 忙; 0空闲

}

voidwrite_com(ucharcom)//写命令函数

{

P0=com; //com命令设置P0口

rs=0;

rw=0;

lcden=0;

check( ) ;

lcden=1;

}

voidwrite_date(uchardate)//写入数据函数

{

P0=日期;

rs=1;

rw=0;

lcden =0;

check();

lcden=1;

}

voidinit()//初始化

{

num=-1;

lcden=1;//使能信号为高

write_com(0x38);//8位; 2行

write_com(0x0c);//显示开启,光标关闭不闪烁*/

write_com(0x06);//扩展模式不改变显示? 关闭 没有眨眼。

num_1=0;

i=0;

j=0;

a=0; // 先做吧。
参与人数

b=0; //加入操作的第二个数字

c=0;

flag=0;//flag表示是否按下某个符号键,

fuhao=0;//fuhao表示按下哪个符号

voidkeyscan()//键盘扫描仪

{

P3=0xfe;

if(P3!=0xfe)

{

delay(20);//延迟20ms

if(P3!=0x fe)

{

temp=P3&0xf0;

按钮(临时)

{

case0xe0:num =0;

鸽子;

case0xd0:num=1;

break;

case0xb0:num=2;

break;

case0x70:num=3;

break;

}

}

while(P3! =0xfe);

if(num==0 ||num==1||num==2)//如果按下“7”; '8' 或 '9

{

if(j!=0)

{

if(j!=0)

{

write_com(0x01)

}

if(fla ag==0)//符号按钮尚未按下

{

a=a*10+table [num]

}

else//如果符号按钮被点击

{

标志=1;

fuhao=4;//4表示点击分区标志

}

i=table1[num];

write_date(0x30+i);

}

P3=0xfd;

if(P3!=0xfd)

i f(P3!=0xfd)

{

延迟(5);

if(P3!=0xfd)

{

temp=P3&0xf0;

按钮 (临时)

{

case0xe0:num=4;

break;

case0xd0:num=5;

break;

ca se0xb0:num=6;

break;

case0x70:num=7;

break;

}

}

同时(P3!=0x fd);

if(num==4||num==5||num==6&&num!=7)// '4'; 如果按下“5”或“6”

{

if(j!=0)

{

write_com(0x01 );

j=0;

}

if(flag==0)//不按符号键

{

a=a*10+table[num];

}

else//如果符号按钮被点击

{

b=b*10 + 表 [num];

}

}

else//如果使用“/”

{

flag=1 ;

fuhao=3;//表示点击数字3。

}

i=table1[num];

write_date(0x30+i);

}

P3=0xbb;if(P3!=0xfb)

{

延迟(5);

如果 (P3!=0xfb)

{

temp=P3&0xf0;

按钮(temp)

{

case0xe0:num=8; /p>

break;

case0xd0:num=9;

打破;

case0xb0:num=10;

中断。

case0x70:num=11;

中断;

}

}

if(num==8||n um==9||num==10)//你'1'; 如果按下“2”或“3”

{

if(j!=0 )

{

write_com(0x01 );

j=0;

}

if(flag==0)//符号按钮尚未按下

{

a=a*10+table[num];

}

else//如果符号按钮被点击

{

b=b*10+table[num];

}

}

elseif(num==11)//'-'

{

flag=1;

fuhao =2; //按2表示你按了减号

}

i=table1[num];

write_date(0x30+i);

}

P3=0xf7 ;

if(P3!=0xf7)

{

延迟(5);

<

if(P3!=0xf7)

{

temp=P3&0xf0;

更改(临时)

{

case0xe0:num=12 ;

中断;

case0xd0:num=13;

打破;

case0xb0:num=14;

中断;

case0x70:num=15;

中断;

}

}

while(P3!=0xf7) ;

更改(数字 )

{

case12:{write_com(0x01);a=0;b=0;flag=0;fuhao=0;}//点击的是“清除”

打破,

a=a*10;

write_date(0x30);

P1=0;

}

elseif(flag==1)//如果符号单击按钮

{

b=b*1 0;

write_date(0x30);

}

}

break;

case14:{j =1;

if(fuhao= =1){write_com(0x80+0x4f); // 按等号键,光标到达第二行最后一个显示位置。

write_com(0x04); 写完后, 数据 光标返回空白

c=a+b;

while(c!=0)

{

write_date ( 0x30+c %10);

c=c/10 ;

}

write_date(0x3d); //再写一次"="

a=0;b=0;flag=0;fuhao=0 ;

}

els eif(fuhao= =2){write_com(0x80+0x4f); // 光标到达第二行最后一个显示位置

write_com(0x04); // 设置从最后写入数据。
向前 写入一条数据后; 光标移回空格

//(逻辑上说顺序错误,可以显示与上一段相同的)

if(a-b>0)

c=a-b;

其他

c=b-a;

while(c!=0)

{

write_date(0x30+c%10);

c =c/10;

}

i f(a-b<0)

write_date(0x2d);

write_date(0x3d); //再写一次"=

a=0;b=0;flag=0;fu hao=0;

}

elseif(fuhao==3){write_com(0x80+0x4f);

write_com(0x04);

c=a*b;

while(c!=0)

{

write_date(0x30+c%10);

c=c/10;

}

write_date(0x3d);

a=0;b=0;flag= 0;fuhao=0;

}

elseif(fuhao==4){write_ com(0x80+0x4f);

write_com(0x04);

i=0;

c=(long)(((float)a/b )*1000);

while(c!=0)

{

write_date(0x30+c%10);

c=c/10;

i++;

if(i==3)

write_date(0x2e);

}

if(a/b<=0)

write_date(0x30);

write_date(0x3d);

a=0;b=0;flag=0;fuhao=0;

}

}

break;

case15:{ _date(0x30+table1[num]);flag=1;fuhao=1;}

break;

}

}

main()

{

init();

while(1)

{

keyscan();

}

}

基于51单片机简易计算器设计

本文将详细介绍基于51单片机设计一个简单计算机的整个过程,包括硬件电路设计、软件程序实现、仿真、PCB制造等步骤。
使用Proteus7.8进行仿真,结合AltiumDesigner完成原理图和PCB设计,使用Keil4/5作为编译器,用C语言编写程序,以下是和功能具体设计步骤。
硬件设计包括按钮模块、LCD1602显示模块和51单片机作为核心控制器三部分。
按键模块采用4*4矩阵键盘提供输入功能; LCD1602负责显示数据; 微控制器作为系统控制中心,执行控制逻辑和数据处理。
软件程序主要包括主程序、按键扫描程序和LCD1602显示程序。
主程序负责总体协调,按键扫描程序负责读取输入的按键,显示程序根据计算结果显示数据。
性能指标如下:采用51单片机设计一个简单的计算器,支持基本的加、减、乘、除运算,最大运算结果可以达到9999*9999。
通过 Proteus 仿真验证设计准确性。
仿真图给出了硬件电路的连接以及在LCD1602上显示数据所需的关键操作。
通过按键输入测试加、减、除等运算功能,结果正确显示在第二行。
原理图是使用AD软件绘制的,并详细描述了每个组件的连接方式。
PCB设计是通过Proteus完成的。
与实物作品相比,Proteus仿真在运行环境、调试方法、电路连接、运行速度、功能实现等方面都与实物有所不同。
源程序中,主程序代码实现了系统的整体控制逻辑。
设计报告提供详细的信息列表,包括常见问题的解决方案、流程、模拟、原理图和 PCB、提案报告、功能要求、设计报告、讲解视频等。
为了帮助读者更好地设计,文章还提供了相关资源链接,包括AltiumDesigner安装与越狱、KEIL+Proteus单片机仿真设计指南、KEIL安装与越狱、Proteus组件搜索、Proteus安装、简单Proteus使用指南以及单片机学习文档、资料手册、答辩技巧、设计报告概要等

求助:关于80C51单片机简易计算器设计的程序,要求是汇编语言。 谢谢哈

ORG0000HSTART:MOV78H,#0; 初始化:78H放段码0,其余放熄灭码MOV79H、#10MOV7AH、#10MOV7BH、#10MOV7CH、#10MOV7。
DH, #10MOVR5, #0;R5 — 击键次数。
初始设置为0MOV30H。
#0;30H——功能键存储单元。
初始设置为0MOV40H。
最初,#0;40H 的单位设置为 0MOV41H。
单元#0;41H 初始设置为0MOV41H。
初始设置为0LOOP:LCALLDIRLCALLKEYINCR5; 自由传输程序决定按哪个键 S1:CJNEA、#10、S2; 如果不是“+”键,则转到S2LJMPFUN。
如果是“+”键,则转到; FUNS2:CJNEA,#11,S3; 这不是“-”键,转到S3LJMPFUN 这是“-”键,转到S4LJMPFUN; 这是“*”键; 跳转键至 FUNS4:CJNEA,#13,S5; 这不是“/”键,转到S5LJMPFUN; “/”键,转到FUNS5:CJNEA,#14,S6;如果是“=”键,转到FUNS6:CJNEA,#15,N1; 如果不是“CL”键,则转到N1LJMPSTART; 如果是“CL”键,则转到STARTN1:CJNER5,#。
1、N2确定LJ键将被按下多少次; MPD11N2:CJNER5,#2,N3LJMPT2N3:CJNER5,#3,N4LJMPT3N4:CJNER5,#4,N5LJMPT4N5:CJNER5,#5,N6LJMPT 5N6:CJNER5,#6,STARTLJMPT6D11:MOVR4,AMOV78H,A;输入值发送到显示缓冲区 MOV79H,#10MOV7AH,#10MOV7BH,#10MOV 7CH,#10MOV7DH,#10LJMPLOOPT2:MOVR7,AMOVB,#10MOVA,R4MULABADDA,R7MOVR4,AMOV7AH,#10MOV7BH,#10MOV7CH,#10MOV7DH,#10MOV79H,78H; 从个位到十位的数字 MOV78H,R7; 新数字 – 个位 LJMPLOOPT3:MOVR7,AMOVB,#10MOVA,R4MU LABADDA,R7MOVR4,AMOV7BH,#10MOV7CH,#10MOV7DH,#10MOV7AH,79H 从十到百 MOV79H, 78H 从个到十 MOV78H, R7; ;新数字-个位数 LJMPLOOPT4:MOVR7,AMOVB,#10MOVA,R4MULABADDA,R7MOVR4,AMOV7CH,#10MOV7DH,#10MOV7BH,7AH MOV7AH,79HMOV79H,78HMOV78H,R7LJMPLOOPT5:MOVR7,AMOV7DH,#10MOVA,R4MULABADDA,R7MOVR4,AMOV7DH, #10MOV7CH,7BHMOV7BH,7AHMOV7AH,79HMOV79H,78HMOV78H,R7LJMPLOOPT6:MOVR7,AMOVB,#10MOVA,R4MUL 阿巴达,R7MOVR4,AMOV7DH,7CHMOV7CH,7BHMOV7BH,7AHMOV7AH,79HMOV79H,78HMOV78H,R7LJMPLOOPMOV7C H,7BHMOV7BH,7AHMOV7AH,79HMOV79H,78HMOV78H,R7LJMPLOOPFUN:MOV78H,#10MOV79H,#10MOV7AH,#10MO VR0,30H;交换最后功能键 MOV30H,AMOVA,R0CJNEA,#10,FUN1;速率功能键 LJMPADDY;"+"FUN1:CJNEA,#11,FUN2LJMPS UBT;"-"FUN2:CJNEA,#12,FUN3LJMPMULT;"*"FUN3:CJNEA,#13,FUN4LJMPDIVI;"/"FUN4:CJNEA,#14,FUN5 ;第一次按功能键,即 A=#0LJMPEQUA;"="FUN5:MOV40H,R4;保存第一个数字 MOVR5,#0;将按键计数清零 LJMPBCD;将其分割成 bcd 代码以便稍后显示:LJMPSTART; 溢出处理ADDY:MOVA,40H; 将第一个数字发送到累加器ADDA、R4; 将第一个数字与第二个数字相加 JBCY、OF; 溢出MOV40H,A; 保存此结果 MOVR5, #0; 清除键数 LJMPBCDSUBT:MOVA,40HSUBBA,R4JBCY,OFMOV40H,AMOVR5,#0LJMPBCDMULT:MOVA,40HMOVB,AMOVA,R 4MULABJBOV,OFMOV40H,AMOVR5,#0LJMPBCDDIVI:MOVA,R4MOVB,AMOVA,40HDIVABJBOV,OFMOV40H,AMOVR5,#0LJMPBCDEQUA:MOVR5,#0LJMPBCDBCD:MOVB,#10MOVA,40H; 结果被发送到DIVAB累加器; 结果除以10MOV41H,A; “private”暂存于MOVA,B; 取一位图MOV78H,A; 发送一位显示缓存MOVA,41HJZRETURN,结果为一位,返回LOOPMOVB,#10MOVA,41HDIVABMOV41H,AMOVA,BMO; V79H,A; 十位发送到MOVA显示缓冲区,41HJZRETURN; 结果是一个两位数,返回LOOPMOV7AH,A; 百位数字被发送到显示缓冲区。
RETURN:LJMPLOOP动态映射子程序DIR; :MOVDPTR,#TAB;数码管译码表首地址 MOVR0,#78H;映射缓冲区单地址 MOVA,#0FEH;单选信号 MOVR1,ALD1:MOVA,@R0MOVCA,@A+D PTR; 观察台MOVP2、R1; 共阳极位选择发送到MOVP0、A的P2端口; 字段码发送到端口P0 LCALLDELAY1ms; 1ms延时设置子程序R0指向下一个MOVA模块; ,P1; JNBACC.5,LD2; 确定是否发送了6个RLA号码; 指示下一位 MOVR1,A; 将位选择信号存储回R3SJMPLD1; 去显示下一个数字LD2:RET; 发送6个号码后返回TAB。
:DB0 C0H,0F9H,0A4H,0B0H,099H,092H,082H,0F8H,80H,90H,0FFH 共阳极解码表 DELAY1ms:MOVR6,#2LOOP1:MOVR7,# 248NOPLOOP2:DJNZR7,LOOP2DJNZR6,LOOP1RETKEY:LCALLKS; 调用按键检测子程序JNZK1; 按 LCALLDELAY2 键继续; 使用延迟去抖动ACALLDIR; 调用动态显示AJMPKEY; 返回继续检测按钮K1:LCALLDELAY2; 去抖延迟LCALLKS,当按键再次按下时调用检测按键函数JNZK2; 进入下一步的按键 ACALLDIR; 调用动态显示AJMPKEY; 无键返回继续检测 K2:MOVR2,#0EFH; 将扫描到的值发送到暂存器R2 MOVR3,#00H; 将第一列值发送到R3临时存储器; storage K3:MOVP1,R2;将R2的值发送到端口P1 L0:JBP1.0,L1;P1.0为1,转到L1MOVA,#00H;将该行的第一个值发送到ACCAJMPLK;转到key值处理程序 L1:JBP1。
1,L2;P1.1对应1进入L2MOVA,#04H;发送第二行值到ACCAJMPLK;进入键值处理程序L2:JBP1.2,L3;P1.2对应1转到 L3MOVA, #08 H;将第三行值发送到 ACCAJMPLK;转到键值处理程序 L3:JBP1.3,NEXT;P1.3 为 1 并转到 NEXT MOVA,#0CH;将第四行值发送到 ACCLK:ADDA ,R3; 将行值和列值相加后的键值发送到APUSHACC; 将值A发送到临时堆栈存储器K4:LCALLDELAY2; 调用去抖程序LCALLKS; 继续而不释放按钮; 键返回检测POPACC; 将堆栈值发送到 ACCMOVDPTR、#KEYTABMOVCA、@A+DPTRETNEXT:INCR3; 列值加一MOVA,R2将R2值发送到AJNBACC.7; ,钥匙; 扫描完成后,进入KEY进行下一次RLA扫描; 完成扫描之前,将值左移一位并扫描下一列MOVR2,A; 将ACC值发送到暂存器R2,前往; K3继续KS:MOVP1,#0FH;将端口P1,四位高,四位低,1 MOVA,P1,读端口P1,5,6,11,7,8,9,12,15,0 ,14 ,13;键值表DELAY2:MOVR6,#2H;延迟去抖子程序 LP1:MOVR7,#0FAHLP2:DJNZR7,LP2DJNZR6,LP1RETEND

热门资讯
realmeQ3sLTE变5G教程:设置与升级指南
麒麟系统盘点最佳版本及特点解析
笔记本nvme掉盘
组态王与485串口设备通讯
存储器和寄存器有什么异同
麒麟系统查看mac地址
半导体ETF投资指南:选择与建议
单片机时钟周期计算方法详解