用单片机怎么做计算器

作者&投稿:郝例 (若有异议请与网页底部的电邮联系)
怎样用51单片机做计算器啊?~

1、硬件仿真图

硬件部分比较简单,当键盘按键按下时它的那一行、那一列的端口为低电平。因此,只要扫描行、列端口是否都为低电平就可以确定是哪个键被按下。
2、主程序流程图

程序的主要思想是:将按键抽象为字符,然后就是对字符的处理。将操作数分别转化为字符串存储,操作符存储为字符形式。然后调用compute()函数进行计算并返回结果。具体程序及看注释还有流程图。
3、Altium Designer画的PCB图

4、程序源代码
#include #include
#include
#include
#define uchar unsigned char
#define uint unsigned int
uchar operand1[9], operand2[9];
uchar operator;
void delay(uint);
uchar keyscan();
void disp(void);
void buf(uint value);
uint compute(uint va1,uint va2,uchar optor);
uchar code table[] = {0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90,0xff};
uchar dbuf[8] = {10,10,10,10,10,10,10,10};
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
uchar keyscan()
{
uchar skey;
P1 = 0xfe;
while((P1 & 0xf0) != 0xf0)
{
delay(3);
while((P1 & 0xf0) != 0xf0)
{
switch(P1)
{
case 0xee: skey = '7'; break;
case 0xde: skey = '8'; break;
case 0xbe: skey = '9'; break;
case 0x7e: skey = '/'; break;
default: skey = '#';
}
while((P1 & 0xf0) != 0xf0)
;
}
}
P1 = 0xfd;
while((P1 & 0xf0) != 0xf0)
{
delay(3);
while((P1 & 0xf0) != 0xf0)
{
switch(P1)
{
case 0xed: skey = '4'; break;
case 0xdd: skey = '5'; break;
case 0xbd: skey = '6'; break;
case 0x7d: skey = '*'; break;
default: skey = '#';
}
while((P1 & 0xf0) != 0xf0)
;
}
}
P1 = 0xfb;
while((P1 & 0xf0) != 0xf0)
{
delay(3);
while((P1 & 0xf0) != 0xf0)
{
switch(P1)
{
case 0xeb: skey = '1'; break;
case 0xdb: skey = '2'; break;
case 0xbb: skey = '3'; break;
case 0x7b: skey = '-'; break;
default: skey = '#';
}
while((P1 & 0xf0) != 0xf0)
;
}
}
P1 = 0xf7;
while((P1 & 0xf0) != 0xf0)
{
delay(3);
while((P1 & 0xf0) != 0xf0)
{
switch(P1)
{
case 0xe7: skey = '$'; break;
case 0xd7: skey = '0'; break;
case 0xb7: skey = '='; break;
case 0x77: skey = '+'; break;
default: skey = '#';
}
while((P1 & 0xf0) != 0xf0)
;
}
}
return skey;
}
void main()
{
uint value1, value2, value;
uchar ckey, cut1 = 0, cut2 = 0;
uchar operator;
uchar i, bool = 0;
init:
buf(0);
disp();
value = 0;
cut1 = cut2 = 0;
bool = 0;
for(i = 0;i < 9;i++)
{
operand1[i] = '\0';
operand2[i] = '\0';
}
while(1)
{
ckey = keyscan();
if(ckey != '#')
{
if(isdigit(ckey))
{
switch(bool)
{
case 0:
operand1[cut1] = ckey;
operand1[cut1+1] = '\0';
value1 = atoi(operand1);
cut1++;
buf(value1);
disp();
break;
case 1:
operand2[cut2] = ckey;
operand2[cut2+1] = '\0';
value2 = atoi(operand2);
cut2++;
buf(value2);
disp();
break;
default: break;
}
}
else if(ckey=='+'||ckey=='-'||ckey=='*'||ckey=='/')
{
bool = 1;
operator = ckey;
buf(0);
dbuf[7] = 10;
disp();
}
else if(ckey == '=')
{
value = compute(value1,value2,operator);
buf(value);
disp();
while(1)
{
ckey = keyscan();
if(ckey == '$')
goto init;
else
{
buf(value);
disp();
}
}
}
else if(ckey == '$')
{ goto init;}
}
disp();
}
}
uint compute(uint va1,uint va2,uchar optor)
{
uint value;
switch(optor)
{
case '+' : value = va1+va2; break;
case '-' : value = va1-va2; break;
case '*' : value = va1*va2; break;
case '/' : value = va1/va2; break;
default : break;
}
return value;
}
void buf(uint val)
{
uchar i;
if(val == 0)
{
dbuf[7] = 0;
i = 6;
}
else
for(i = 7; val > 0; i--)
{
dbuf[i] = val % 10;
val /= 10;
}
for( ; i > 0; i--)
dbuf[i] = 10;
}
void disp(void)
{
uchar bsel, n;
bsel=0x01;
for(n=0;n<8;n++)
{
P2=bsel;
P0=table[dbuf[n]];
bsel=_crol_(bsel,1);
delay(3);
P0=0xff;
}
}
扩展资料:
PROTEUS 是单片机课堂教学的先进助手
PROTEUS不仅可将许多单片机实例功能形象化,也可将许多单片机实例运行过程形象化。前者可在相当程度上得到实物演示实验的效果,后者则是实物演示实验难以达到的效果。
它的元器件、连接线路等却和传统的单片机实验硬件高度对应。这在相当程度上替代了传统的单片机实验教学的功能,例:元器件选择、电路连接、电路检测、电路修改、软件调试、运行结果等。
课程设计、毕业设计是学生走向就业的重要实践环节。由于PROTEUS提供了实验室无法相比的大量的元器件库,提供了修改电路设计的灵活性、提供了实验室在数量、质量上难以相比的虚拟仪器、仪表,因而也提供了培养学生实践精神、创造精神的平台
随着科技的发展,“计算机仿真技术”已成为许多设计部门重要的前期设计手段。它具有设计灵活,结果、过程的统一的特点。可使设计时间大为缩短、耗资大为减少,也可降低工程制造的风险。相信在单片机开发应用中PROTEUS也能茯得愈来愈广泛的应用。
使用Proteus 软件进行单片机系统仿真设计,是虚拟仿真技术和计算机多媒体技术相结合的综合运用,有利于培养学生的电路设计能力及仿真软件的操作能力;
在单片机课程设计和全国大学生电子设计竞赛中,我们使用 Proteus 开发环境对学生进行培训,在不需要硬件投入的条件下,学生普遍反映,对单片机的学习比单纯学习书本知识更容易接受,更容易提高。
实践证明,在使用 Proteus 进行系统仿真开发成功之后再进行实际制作,能极大提高单片机系统设计效率。因此,Proteus 有较高的推广利用价值。
参考资料来源:百度百科-protues

前段时间我自己写的一个,你看看,先是电路图,后面是代码图是用protues画的,有什么不懂加我QQ478769652 //程序测试通过
//能使用的功能:输入K1(+,-,*,/)K2,按=得到结果,然后按on/c或0重新开始
//不能输入K1+K2+K3或者类似的输入,这种输入导致程序出错
//计算除法的时候不能显示小数,如5/3得到的结果是1
#include
unsigned char code tab[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
sbit P2_0=P2^0;
sbit P2_1=P2^1;
sbit P2_2=P2^2;
sbit P2_3=P2^3;
sbit P2_4=P2^4;
sbit P2_5=P2^5;
sbit P3_4=P3^4;
sbit P3_5=P3^5;
sbit P3_6=P3^6;
sbit P3_7=P3^7;long int n=0;
unsigned int flag;
void display();
void delay();
void keyboard();
main()
{
//m1,m2分别保存第一次和第二次输入的两个数据
//当m1,m2的输入值超过999999时,此时将其情0

long int m1,m2;
P2=0xff;
while(1)
{
//检测输入的第一个数据
while(1)
{
display();
keyboard();
if(n>999999) n=0;
P3=0xf7;
if(P3_7==0) {flag=1; while(!P3_7); m1=n; n=0; break; }
P3=0xfb;
if(P3_7==0) {flag=2; while(!P3_7); m1=n; n=0; break; }
P3=0xfd;
if(P3_7==0) {flag=3; while(!P3_7); m1=n; n=0; break; }
P3=0xfe;
if(P3_7==0) {flag=4; while(!P3_7); m1=n; n=0; break; }
}
//检测输入的第二个数据
while(1)
{
display();
keyboard();
if(n>999999) n=0;
P3=0xf7;
if(P3_6==0) {m2=n; break;}
}
//计算结果,将其保存在n中然后进行显示,注意当n的值太大超过4字节时,此时显示乱码
while(1)
{
if(flag==1) n=m1+m2;
if(flag==2) n=m1-m2;
if(flag==3) n=m1*m2;
//由于类型原因,计算结果没有小数
if(flag==4) n=m1/m2;
if(n>999999) n=0;
display();
P3=0xf7;
//计算完成之后,可以用on/c或者是0进行清0,然后进行下一轮计算
if(P3_4==0||P3_5==0) {n=0;break;}
}
}

}void keyboard()
{
//检测第一行的按键
P3=0xfe;
if(P3_4==0)
{
n=n*10+7;
while(!P3_4);
}
if(P3_5==0)
{
n=n*10+8;
while(!P3_5);
}
if(P3_6==0)
{
n=n*10+9;
while(!P3_6);
}
//检测第二行的按键
P3=0xfd;
if(P3_4==0)
{
n=n*10+4;
while(!P3_4);
}
if(P3_5==0)
{
n=n*10+5;
while(!P3_5);
}
if(P3_6==0)
{
n=n*10+6;
while(!P3_6);
}
//检测第三行的按键
P3=0xfb;
if(P3_4==0)
{
n=n*10+1;
while(!P3_4);
}
if(P3_5==0)
{
n=n*10+2;
while(!P3_5);
}
if(P3_6==0)
{
n=n*10+3;
while(!P3_6);
} P3=0xf7;
if(P3_5==0)
{
n=n*10+0;
while(!P3_5);
}
}//显示子程序
void display()
{
P0=tab[n%10];
P2_5=0;
delay();
P2_5=1; P0=tab[n/10%10];
P2_4=0;
delay();
P2_4=1; P0=tab[n/100%10];
P2_3=0;
delay();
P2_3=1; P0=tab[n/1000%10];
P2_2=0;
delay();
P2_2=1; P0=tab[n/10000%10];
P2_1=0;
delay();
P2_1=1; P0=tab[n/100000];
P2_0=0;
delay();
P2_0=1;
}
void delay()
{
int i;
for(i=0;i<500;i++);
}

1. 4X4键盘输入,点阵字符型液晶显示。
2. 由于所采用的浮点程序库的限制(MCU平台只找到这个……),浮点运算采用3字节二进制补码表示,有效数字6位。对于输入输出,采用3字节BCD码浮点数格式,有效数字只有4位,因此最终有效数字只有4位。
3. 可进行连续输入,例如:1.23+4.56*8.23/234.8 ,但是运算结果为从左到右,这也是8位简易计算器的方式。
4. 可进行错误判断,溢出、除零等错误将显示一个字符 E 。
5. 由于键盘只有16个按键,安排如下:  
+---------------+ 
  | 7 | 8 | 9 | + |  
| 4 | 5 | 6 | - |  
| 1 | 2 | 3 | * |  
| 0 | . | = | / | 
+---------------+

6. 按键的缺少导致取消了一些特殊函数,即开根号,三角函数(sin, cos, tan, ctg)的实现,由于这些函数在浮点程序库中均已提供,如果硬件允许,在原来的框架上添加这些附加功能是很容易的(可以看作和+, -, *, /等价的按键操作,调用不同的子程序进行运算即可)
7. 按两次 = 等于清灵。因为按键实在太少,才采用了这个做法。

8. 相应举例: 按键   结果  说明- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  123+=    123  按下等号而没有第二个操作数,保留第一个操作数      并认为此次运算结束(等号的功能)
  123+321/111   4.0  等价于(123+321) / 111
  2.3+5.4=/0.1+   77  等号后直接按 / ,则将前面的运算结果作为第一个     
 操作数 
1/0=    E  错误显示

9. 不足   使用3字节的浮点数表示,不可避免的带来了数表示的不精确,加上有效数字比较少,因此计算结果很容易产生误差,尤其是进行连续多次运算后,结果和精度较高的科学计算器的误差会很快达到0.01以上,当然这个差距和所测试的用例也有关系,4位有效数字导致了数字123456只能表示为123400,最后两位有效数字被摒弃了。   同时,虽然纯整数可以进行较为高精度的运算,实现也较为容易,但是考虑到要和浮点数混合在一起处理,如果在算法上分别考虑整数和浮点数,整个程序框架代码将会膨胀不少,因此将其简化为统一作为浮点数对待。

我这里有一个类似的程序;简单的计算器演示程序 硬件连接:矩阵键盘接p1口1602液晶控制p2.0-2.2 液晶数据p0 *;0-99之间的加、减、乘、除运算 *; 0a键+ 0b键- 0c键* 0#键/ 0#键清除 00键 等于 *;矩阵键盘定义: *;P1.0-P1.3为列线,P1.4-P1.7为行线 *;出口:A、R3存键值 * RELAY EQU P1.3 BEEP EQU P3.7;------------------------------- RS EQU P2.0 RW EQU P2.1 EN EQU P2.2 X EQU 3fH ;LCD 地址变量;------------------------------- TEMP1 EQU 30H ;临时暂存器 TEMP2 EQU 31H TEMP3 EQU 32H TEMP4 EQU 33H RES_H EQU 24H ;输入被加(减、乘、除)数 RES_L EQU 25H ;输入加(减、乘、除)数 OUT_H EQU 26H ;运算结果高位 OUT_L EQU 27H ;运算结果低位;------------------------------- ORG 0000H JMP MAIN;-------------------------------MAIN: MOV SP,#60H CLR EN CALL SET_LCD MOV 20H,#00H CALL BEEP_BL ;起延时作用 MOV R1,#00H MOV TEMP1,#00H MOV TEMP2,#00H MOV TEMP3,#00H MOV RES_L,#00H MOV RES_H,#00H MOV OUT_H,#00H MOV OUT_L,#00HLOOP: CALL KEY_IN ;送被(加、减、乘、除)数 JNB 20H.0,LOOP ;键标记 CALL BEEP_BL INC R1 CJNE R1,#01H,LOOP_1 MOV TEMP2,A ;高位 MOV X,#2 CALL CONV0LOOP_1: CJNE R1,#02H,LOOP SUBB A,#0AH ;判是否是功能键? JNC LOOP_2 ;是,转LOOP_2 MOV TEMP1,TEMP2 MOV A,TEMP1 MOV X,#1 CALL CONV0 MOV A,R3 ;恢复有效键值 MOV TEMP2,A ;低位 MOV X,#2 CALL CONV0 MOV A,TEMP1 ANL A,#0FH SWAP A ORL A,TEMP2 MOV RES_H,A JMP LOOP0LOOP_2: MOV RES_H,TEMP2 AJMP LOOP0ALOOP0: CALL KEY_IN JNB 20H.0,LOOP0 CALL BEEP_BLLOOP0A: MOV A,R3 ;重装键值 CJNE A,#0AH,LOOP1 ;加运算 CALL CONV1 SETB 20H.1 ;加运算标记 AJMP LOOP5LOOP1: CJNE A,#0BH,LOOP2 ;减运算 CALL CONV2 SETB 20H.2 ;减运算标记 AJMP LOOP5LOOP2: CJNE A,#0CH,LOOP3 ;乘运算 CALL CONV3 SETB 20H.3 ;乘运算标记 AJMP LOOP5LOOP3: CJNE A,#0DH,LOOP4 ;除运算 CALL CONV4 SETB 20H.4 ;除运算标记 AJMP LOOP5LOOP4: CJNE A,#0FH,LOOP4A AJMP MAIN LOOP4A: AJMP LOOP0LOOP5: MOV R1,#00H MOV TEMP1,#00H MOV TEMP2,#00H CLR 20H.0 ;送(加、减、乘、除)数LOOP5A: CALL KEY_IN JNB 20H.0,LOOP5A CALL BEEP_BL CJNE A,#0FH,LOOP5B AJMP MAINLOOP5B: INC R1 CJNE R1,#01H,LOOP5C MOV TEMP2,A MOV X,#6 CALL CONV0LOOP5C: CJNE R1,#02H,LOOP5A SUBB A,#0AH ;判是否是功能键? JNC LOOP5D ;是,转LOOP5C MOV TEMP1,TEMP2 MOV A,TEMP1 MOV X,#6 CALL CONV0 MOV A,R3 MOV TEMP2,A MOV X,#7 CALL CONV0 MOV A,TEMP1 ANL A,#0FH SWAP A ORL A,TEMP2 MOV RES_L,A JMP LOOP6LOOP5D: MOV RES_L,TEMP2 JMP LOOP6ALOOP6: CALL KEY_INLOOP6A: MOV A,R3 ;重装键值 CJNE A,#0FH,LOOP6B AJMP MAINLOOP6B: CJNE A,#0EH,LOOP6 ;显示(=) CALL CONV5 CALL BEEP_BL ;显示运算结果 JNB 20H.1,LOOP6C CALL SUADDLOOP6C: JNB 20H.2,LOOP6D CALL SUSUBLOOP6D: JNB 20H.3,LOOP6E CALL SUMULLOOP6E: JNB 20H.4,LOOP7 CALL SUDIVLOOP7: CALL KEY_IN CJNE A,#0FH,LOOP7 ;复位(清零) AJMP MAIN;------------------------;加法运算子程序;入口:R0-被加数,R1-加数;出口:R4(高)、R2(低)为和值;------------------------SUADD: MOV R1,RES_L MOV R0,RES_H MOV A,R0 ADD A,R1 DA A MOV R2,A CLR A ADDC A,#00H MOV R4,A MOV OUT_H,R4 MOV OUT_L,R2 CALL T_CONV RET;------------------------;减法运算子程序;入口:R0-被减数,R1-减数;出口:R2-差值;------------------------SUSUB: MOV R1,RES_L MOV R0,RES_H CLR C MOV A,#9AH SUBB A,R1 ;减数十进制求补 ADD A,R0 DA A MOV R2,A ;差值送R2 JC POSI ;C=1,表示差值为正 NEGA: MOV A,#9AH ;差值为负,求补后得差值的绝对值 SUBB A,R2 MOV R2,A SETB 20H.5 ;显示负号标记 POSI: MOV OUT_H,#00H MOV OUT_L,R2 CALL T_CONV RET;-------------------------;乘法运算子程序; 单字节BCD码乘法子程序;入口: R0(被乘数)、R1(乘数);出口: R3(高)、R2(低),积为双字节,BCD码形式的积;从乘数高位开始进行BCD码移位乘法;-------------------------SUMUL: MOV R1,RES_L MOV R0,RES_HBCDMUL: CLR A ;积单元清零 MOV R2,A MOV R3,A MOV A,R1 JZ RETURN ANL A,#0F0H ;取乘数高位 JZ LBCD ;乘数高位是否为0? SWAP A MOV R4,A ACALL DDBCDM SWAP A ;BCD码左移一位 MOV R3,A MOV A,R2 SWAP A MOV R2,A ANL A,#0FH ORL A,R3 MOV R3,A MOV A,R2 ANL A,#0F0H MOV R2,A LBCD: MOV A,R1 ;取乘数低位 ANL A,#0FH JZ RETURN ;乘数低位是否为0? MOV R4,A ACALL DDBCDMRETURN: MOV OUT_H,R3 MOV OUT_L,R2 CALL T_CONV RETDDBCDM: ;一位BCD码乘法 MOV A,R2 ADD A,R0 DA A MOV R2,A MOV A,R3 ADDC A,#00H DA A MOV R3,A DJNZ R4,DDBCDM RET;------------------------------------------------;除法运算子程序;单字节BCD码除法;入口:R0(被除数)、R1(非零除数);出口:R2(商)、R3(余数);《MCS-51系列单片机实用子程序集锦》Page 73;-----------------------------------------------SUDIV: MOV R1,RES_L MOV R0,RES_HBCDDIV: MOV R2,#00H ;商单元清零 MOV A,R1 ;除数求补 CPL A ADD A,#9BH MOV R1,A MOV A,R0 ;被除数高位移入 ANL A,#0F0H ;部分余单元 SWAP A LP0: MOV R3,A ;做除法 ADD A,R1 DA A JNC LP1 ;部分余数>=除数? INC R2 ;商加1 SJMP LP0 LP1: MOV A,R3 ; SWAP A MOV R3,A MOV A,R2 ;商左移一位 SWAP A MOV R2,A MOV A,R0 ;移位 ANL A,#0FH ORL A,R3 LP2: MOV R3,A ;做除法 ADD A,R1 DA A JNC LP3 INC R2 ;商加1 SJMP LP2 LP3: MOV A,R3 ;四舍五人 ADD A,R3 DA A JC LP4 ADD A,R1 DA A JNC RETURN1 LP4: MOV A,R2 ADDC A,#00H DA A MOV R2,A RETURN1: MOV OUT_H,#00H MOV OUT_L,R2 CALL T_CONV RET;-----------------------------------------------------; LCD 初始化设置;-----------------------------------------------------SET_LCD: CLR EN CALL INIT_LCD ;初始化 LCD CALL DELAY1 MOV DPTR,#INFO1 ;指针指到显示信息1 MOV A,#1 ;显示在第一行 CALL LCD_SHOW MOV DPTR,#INFO2 ;指针指到显示信息2 MOV A,#2 ;显示在第二行 CALL LCD_SHOW RET;-----------------------------------------------------INFO1: DB " CALCULATOR ",0 ;LCD 第一行显示信息INFO2: DB " ",0 ;LCD 第二行显示信息;----------------------------------------------------INIT_LCD: ;8位I/O控制 LCD 接口初始化 MOV A,#38H ;双列显示,字形5*7点阵 CALL WCOM CALL DELAY1 MOV A,#38H ;双列显示,字形5*7点阵 CALL WCOM CALL DELAY1 MOV A,#38H ;双列显示,字形5*7点阵 CALL WCOM CALL DELAY1 MOV A,#0CH ;开显示,关光标, CALL WCOM CALL DELAY1 MOV A,#01H ;清除 LCD 显示屏 CALL WCOM CALL DELAY1 RET;----------------------------------------------------LCD_SHOW: ;在LCD的第一行或第二行显示信息字符
CJNE A,#1,LINE2 ;判断是否为第一行 LINE1: MOV A,#80H ;设置 LCD 的第一行地址 CALL WCOM ;写入命令 CALL CLR_LINE ;清除该行字符数据 MOV A,#80H ;设置 LCD 的第一行地址 CALL WCOM ;写入命令 JMP FILL LINE2: MOV A,#0C0H ;设置 LCD 的第二行地址 CALL WCOM ;写入命令 CALL CLR_LINE ;清除该行字符数据 MOV A,#0C0H ;设置 LCD 的第二行地址 CALL WCOM FILL: CLR A ;填入字符 MOVC A,@A+DPTR ;由信息区取出字符 CJNE A,#0,LC1 ;判断是否为结束码 RET LC1: CALL WDATA ;写入数据 INC DPTR ;指针加1 JMP FILL ;继续填入字符 RET ;---------------------------------------------------CLR_LINE: ;清除该行 LCD 的字符 MOV R0,#24 CL1: MOV A,#' ' CALL WDATA DJNZ R0,CL1 RET;-----------------------------------------------------; 写指令、数据使能子程序;-----------------------------------------------------WCOM: ;写指令使能 MOV P0,A CLR RS ;RS=L,RW=L,D0-D7=指令码,E=高脉冲 CLR RW SETB EN CALL DELAY0 CLR EN RETWDATA: ;写数据使能 MOV P0,A SETB RS ;RS=H,RW=L,D0-D7=数据,E=高脉冲 CLR RW SETB EN CALL DELAY0 CLR EN RET
DELAY0: MOV R7,#250 ;延时500微秒 DJNZ R7,$ RET;---------------------------------------------------;在 LCD 第二行显示字符;A=ASC DATA, B=LINE X POS;---------------------------------------------------LCDP2: ;在LCD的第二行显示字符 PUSH ACC ; MOV A,B ;设置显示地址 ADD A,#0C0H ;设置LCD的第二行地址 CALL WCOM ;写入命令 POP ACC ;由堆栈取出A CALL WDATA ;写入数据 RET;-----------------------------------------------------;矩阵键盘键值读取子程序;-----------------------------------------------------KEY_IN: MOV P1,#0F0H ;置列线为0,行线为1 MOV A,P1 ANL A,#0F0H MOV B,A MOV P1,#0FH ;置列线为1,行线为0 MOV A,P1 ANL A,#0FH ORL A,B ;高四位与低四位重新组合 CJNE A,#0FFH,KEY_IN1 ;0FFH为末按键 CLR 20H.0 RETKEY_IN1: MOV B,A MOV DPTR,#KEYTABLE MOV R3,#0FFHKEY_IN2: INC R3 MOV A,R3 MOVC A,@A+DPTR CJNE A,B,KEY_IN3 MOV A,R3 ;找到,取顺序码 MOV R5,#08H ;延时 CALL DELAY SETB 20H.0 RETKEY_IN3: CJNE A,#0FFH,KEY_IN2 ;末完,继续查 RET ;0FFH为结束码;------------------------;在指定位置显示符合子程序;------------------------CONV0: add A,#30h MOV B,X CALL LCDP2 retCONV1: MOV X,#4 MOV A,#2BH ;+ MOV B,X CALL LCDP2 RET
CONV2: MOV X,#4 MOV A,#2DH ;- MOV B,X CALL LCDP2 RETCONV3: MOV X,#4 MOV A,#2AH ;* MOV B,X CALL LCDP2 RETCONV4: MOV X,#4 MOV A,#2FH ;/ MOV B,X CALL LCDP2 RETCONV5: MOV X,#09H MOV A,#3DH ;= MOV B,X CALL LCDP2 RET;--------------------------;;--------------------------CONV: MOV A,R3 ANL A,#0FH ;取出低四位二进制数 PUSH ACC ;压入堆栈 CLR C ;C=0 SUBB A,#0AH ;减10 POP ACC ;弹出堆栈 JC ASCII0 ;该数小于10,转ASCII0 JMP ASCII1 ASCII0: ADD A,#30H ;小于10的数加上30H MOV B,X CALL LCDP2ASCII1: RET
;-------------------------------------------------------T_CONV:
MOV A,OUT_H ;取高位数 mov x,#11 cjne a,#00h,t_conv1 ;判高位数是否为0? setb 20h.6 ;为0,20h.6置1 jmp t_conv3 ;转取低位数 ;高位数不为0,则t_conv1: anl a,#0f0h ;判高位数的高四位是否为0? cjne a,#00h,t_conv2 ;不为0,2位数都显示 setb 20h.6 ;为0,20h.6置1,只显示低四位t_conv2: mov a,out_h CALL SHOW_DIG2 inc x clr 20h.6 ;清显示标记位
t_conv3: mov a,out_l ;取低位数 jnb 20h.6,t_conv5 ;高位数有显示,则不判低位数。 anl a,#0f0h ;高位数无显示,则判低位数。 cjne a,#00h,t_conv4 ;判低位数的高四位是否为0? setb 20h.6 ;为0,20h.6置1,只显示低四位 MOV A,OUT_L JMP T_CONV5T_conv4: CLR 20H.6 ;低位数不为0,2位数都显示 mov a,out_l
t_conv5: call show_dig2 clr 20h.6 ;清显示标记位 RET;----------------------------;在 LCD 的第二行显示数字与符号;----------------------------SHOW_DIG2: JNB 20H.5,DIG2 ;符号标记 MOV TEMP3,A MOV A,#2DH ;显示负号 MOV B,X CALL LCDP2 MOV A,TEMP3 INC X DIG2: MOV B,#16 ;设置被除数 DIV AB ;结果A存商数,B存余数 jnb 20h.6,dig3 ;显示位标记 mov a,#20h jmp dig4dig3: ADD A,#30H ;A为十位数,转换为字符dig4: PUSH B ;B放入堆栈暂存 MOV B,X ;设置 LCD 显示的位置 CALL LCDP2 ;由 LCD 显示出来 POP B ; MOV A,B ;B为个位数 ADD A,#30H ;转换为字符 INC X ;LCD 显示位置加1 MOV B,X ;设置 LCD 显示的位置 CALL LCDP2 ;由 LCD 显示出来 RET;--------------------------------------------------------;蜂鸣器响一声子程序;--------------------------------------------------------BEEP_BL: MOV R6,#100 BL1: CALL DEX1 CPL BEEP DJNZ R6,BL1 MOV R5,#50 CALL DELAY RET DEX1: MOV R7,#180 DEX2: NOP DJNZ R7,DEX2 RETDELAY: ;延时R5×10MS MOV R6,#50 D1: MOV R7,#100 DJNZ R7,$ DJNZ R6,D1 DJNZ R5,DELAY RET;-----------------------------------------------------DELAY1: ;延时5MS MOV R6,#25 D2: MOV R7,#100 DJNZ R7,$ DJNZ R6,D2 RET;-----------------------------------------------------KEYTABLE: DB 0eeH ,077H,0B7H,0D7H,07bh,0bbh,0dbh ,07dh,0bdh,0ddh,0e7h,0ebh,0edh, 07eh,0beh,0deh,0ffH;----------------------------------------------------- END

这个很简单。只要解码4*4,并运行即可


C51单片机4*4按键计算器 ,数码管上只显示结果的 ,P2口是某一位,P0口...
按下数字键,移位显示;按下运算键,保存当前数据,显示全零;按下数字键,移位显示;按下等号键,显示结果。--- 做计算器,用数码管显示,档次偏低,不值得费劲。应该用 LCD。用数码管显示,练习编写一个时钟、计数器、等等,就可以了。

用89c52单片机怎么做出可以的出负数的简单计算器?
可以用proteus做计算器的仿真,而且proteus里有一个计算器专用的键盘,使用时很方便很简单,就是4×4的矩阵键盘。

单片机简单C语言问题,实现一个个位加法计算器
你的问题应该出现在键盘处理不完善造成的,稍微修改了一下你试试。include <reg52.h> define uchar unsigned char define unit unsigned int define OPdata P0 \/\/十位数据口 define OPdata1 P1\/\/个位数据口 sbit se0=P3^6;\/\/十位选择 sbit se1=P3^7;\/\/个位选择 sbit Q=P2^6;sbit W=P2^...

AT89c51单片机液晶4乘4矩形简易计算器仿真图和源程序10以下的加减乘除...
用单片机、LCD1602和4×4按键,组成一个简易计算器,proteus中有一个计算器专用的按键,可实现10以下的加减乘除,仿真图如下。

想自己设计个计算器,可以进行一些简单数学运算的,学过电路atm52单片机...
主体思路是:单片机+键盘+显示 1、这是显示器件建议使用LCD602,价格较低,驱动容易编写(网上有很多例子)。2、键盘用矩阵式键盘,使用中断式动态扫描。(单片机书上一般都有相关例程)3、软件设计思路:中断后读取按键码-》延迟100毫秒左右-》再读取,如果二者一致,读取相应按键-》在LCD显示显示->再...

单片机做计算器能给详细解答吗?
\/\/程序测试通过 \/\/能使用的功能:输入K1(+,-,*,\/)K2,按=得到结果,然后按on\/c或0重新开始 \/\/不能输入K1+K2+K3或者类似的输入,这种输入导致程序出错 \/\/计算除法的时候不能显示小数,如5\/3得到的结果是1 include<reg52.h> unsigned char code tab[10]={0x3f,0x06,0x5b,0x4f,0x66...

单片机的简易计算器
单片机计算器 基本功能介绍:简单的加减乘除的运算。时间显示功能,而且能实现计算器模块和时间模块之间的任意切换。按键音却换功能。原理;多功能单片机计算器是一个实现加减乘除的和时间功能的计算器,主要的硬件组成由,一个AT89s52单片机芯片,一个LED液晶(1602液晶),一个4*4键盘,和4个特殊功能按键...

用89C51单片机设计4*4矩阵式键盘计算器程序 要汇编的
用89C51单片机设计4*4矩阵式键盘计算器程序 要汇编的 谢谢大神有谁会的,求教... 谢谢大神有谁会的,求教 展开  我来答 3个回答 #热议# 侵犯著作权如何界定?黄石佳诚家电维修 2012-12-13 · TA获得超过1394个赞 知道小有建树答主 回答量:1559 采纳率:93% 帮助的人:267万 我也去答题访问...

如何用51单片机做计算器(要求用C语言编程) 由于是新手所以没积分 对 ...
给你参考一下的,我最近做的:我的实验板上的键不够,所以只能做加法运算,而且两数之和不能大于十。嘿嘿,没错这个给某种人用的。\/\/*** myh.h ***有两个文件,一个是头文件myh.h一个是js.c include <reg52.h> typedef unsigned char uchar;typedef unsigned int uint;typedef bit BOOL...

利用51单片机制作LCM显示的简单计算器程序 C的
楼主,我给你一个代码,你参考一下和验证一下!用51单片机做的简单计算器的程序.\/***按键处理***\/ void KeyDeal(unsigned char Key){ if(Key!=0) \/\/判断 有无按键按下。{ switch(Key){ \/\/以下定义0~9的数字键。case 0x11: K=0; break;case 0x21: K=1; break;case 0x41: K...

庐江县17046802165: 用单片机怎么做计算器 -
缪福赛进: 1. 4X4键盘输入,点阵字符型液晶显示. 2. 由于所采用的浮点程序库的限制(MCU平台只找到这个……),浮点运算采用3字节二进制补码表示,有效数字6位.对于输入输出,采用3字节BCD码浮点数格式,有效数字只有4位,因此最终有效数...

庐江县17046802165: 单片机制作简易计算器需要哪些器件 -
缪福赛进: 电路不难,主要是程序比较难. 一个矩阵键盘,LCD1602液晶比较好点(用数据管比较麻烦,特别是动态扫描),其它没有什么,主要是运算,可以加个蜂鸣器 我有一个STM32开发板上用的2.4寸触摸液晶一个例程就是计算器,看了下程序比较难.

庐江县17046802165: 求助,怎样用单片机做计算器?
缪福赛进: 一、除法:divdllnbsp;nbsp;nbsp;nbsp;datanbsp;nbsp;nbsp;nbsp;20hnbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;;定义被除数单元divdlhnbsp;nbsp;nbsp;nbsp;datanbsp;nbsp;nbsp;nbsp;21hdivdhlnbsp;nbsp;nbsp;nbsp;datanbsp;nbsp;nbsp;...

庐江县17046802165: 请问如何用单片机做一个简单的计算器?需要哪些元器件和材料? -
缪福赛进: 简单元器件=单片机+1602LCD+4*4键盘

庐江县17046802165: 怎样用单片机实验板上的矩阵键盘和显示器编写一个简单的计算器,要求能一位数和两位数的加减乘除? -
缪福赛进: #include <reg51.h> #define uchar unsigned char long First,End; //定义全局变量void delay(int n) //***延时程序***// {int i,j;for(i=0;i<n;i++){for(j=0;j<50;j++);} }long add(long x,long y) //***加法程序***//{long z;z=x+y;return(z);}long sub(long x,...

庐江县17046802165: 如何用STC89C52单片机做一个计算器,用C语言编程,要求有过程步骤,详尽些,不要说用什么函数我要全部编程语 -
缪福赛进: 既然是用单片机做计算器,主要是确定功能和设计电路. 如输入部分用多少个按键,需不需要阵列? 输出部分用数码管或者点阵屏.最后才是编程实现.

庐江县17046802165: 怎么利用51单片机做一个简单计算器? -
缪福赛进: 你是要程序?自己写吧,又不难,用C语言写+、-、*、%不就可以,用lcd1602显示就行

庐江县17046802165: 我想用单片机做个加减法计算器,要求置数和结果都需要输入完成,当置数和结果全部正确时绿灯亮. -
缪福赛进: 150分······ 给个思路吧: 1.用7279芯片做键盘输入和显示 2.没了啊,之后的就直接用51运算和显示就行了 哦还有,输入错误需要检测的,比如用一个if来判定输入数字之后是什么,输入符号时候是什么等等

庐江县17046802165: 基于单片机的简易计算器设计 -
缪福赛进: 安装protues仿真软件,看自带的例子,里面正好有一个例子是这个,用LCD显示的

庐江县17046802165: 单片机,设计一个计算器,能够自定义按键键值,并能通过串口调试助手将执行结果显示到计算机上. -
缪福赛进: 你的这个题目范围太大了.限于篇幅无法在细节上一一讲明白.主要的思路如下:1. 硬件设计:单片机需要能够检测键是否按下,就需要搭建电路.通常情况下按键有两种方式:一种是直接将键通过电阻电容连接到单片机IO引脚上,这种方式适...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网