急求!!!哪位朋友指点下单片机程序题~~

急求!!!哪位朋友指点下单片机程序题~~,第1张

采用LCD1602两位显示的简单计算器程序,能够加减乘除,

;-------------------------------

;简单的计算器演示程序

;0-99之间的加、减、乘、除运算

;-------------------------------

;矩阵键盘定义:

;P10-P13为列线,P14-P17为行线

;出口:A、R3存键值

;-------------------------------

RELAY EQU P13

BEEP EQU P37

;-------------------------------

RS EQU P20

RW EQU P21

EN EQU P22

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,#00H

LOOP:

CALL KEY_IN ;送被(加、减、乘、除)数

JNB 20H0,LOOP ;键标记

CALL BEEP_BL

INC R1

CJNE R1,#01H,LOOP_1

MOV TEMP2,A ;高位

MOV X,#2

CALL CONV0

LOOP_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 LOOP0

LOOP_2:

MOV RES_H,TEMP2

AJMP LOOP0A

LOOP0: CALL KEY_IN

JNB 20H0,LOOP0

CALL BEEP_BL

LOOP0A: MOV A,R3 ;重装键值

CJNE A,#0AH,LOOP1 ;加运算

CALL CONV1

SETB 20H1 ;加运算标记

AJMP LOOP5

LOOP1: CJNE A,#0BH,LOOP2 ;减运算

CALL CONV2

SETB 20H2 ;减运算标记

AJMP LOOP5

LOOP2: CJNE A,#0CH,LOOP3 ;乘运算

CALL CONV3

SETB 20H3 ;乘运算标记

AJMP LOOP5

LOOP3: CJNE A,#0DH,LOOP4 ;除运算

CALL CONV4

SETB 20H4 ;除运算标记

AJMP LOOP5

LOOP4: CJNE A,#0FH,LOOP4A

AJMP MAIN

LOOP4A: AJMP LOOP0

LOOP5: MOV R1,#00H

MOV TEMP1,#00H

MOV TEMP2,#00H

CLR 20H0 ;送(加、减、乘、除)数

LOOP5A: CALL KEY_IN

JNB 20H0,LOOP5A

CALL BEEP_BL

CJNE A,#0FH,LOOP5B

AJMP MAIN

LOOP5B: INC R1

CJNE R1,#01H,LOOP5C

MOV TEMP2,A

MOV X,#6

CALL CONV0

LOOP5C: 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 LOOP6

LOOP5D: MOV RES_L,TEMP2

JMP LOOP6A

LOOP6: CALL KEY_IN

LOOP6A: MOV A,R3 ;重装键值

CJNE A,#0FH,LOOP6B

AJMP MAIN

LOOP6B: CJNE A,#0EH,LOOP6 ;显示(=)

CALL CONV5

CALL BEEP_BL ;显示运算结果

JNB 20H1,LOOP6C

CALL SUADD

LOOP6C: JNB 20H2,LOOP6D

CALL SUSUB

LOOP6D: JNB 20H3,LOOP6E

CALL SUMUL

LOOP6E: JNB 20H4,LOOP7

CALL SUDIV

LOOP7: 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 20H5 ;显示负号标记

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_H

BCDMUL:

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 DDBCDM

RETURN: MOV OUT_H,R3

MOV OUT_L,R2

CALL T_CONV

RET

DDBCDM: ;一位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_H

BCDDIV:

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 ;双列显示,字形57点阵

CALL WCOM

CALL DELAY1

MOV A,#38H ;双列显示,字形57点阵

CALL WCOM

CALL DELAY1

MOV A,#38H ;双列显示,字形57点阵

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

RET

WDATA: ;写数据使能

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 20H0

RET

KEY_IN1: MOV B,A

MOV DPTR,#KEYTABLE

MOV R3,#0FFH

KEY_IN2: INC R3

MOV A,R3

MOVC A,@A+DPTR

CJNE A,B,KEY_IN3

MOV A,R3 ;找到,取顺序码

MOV R5,#08H ;延时

CALL DELAY

SETB 20H0

RET

KEY_IN3: CJNE A,#0FFH,KEY_IN2 ;末完,继续查

RET ;0FFH为结束码

;------------------------

;在指定位置显示符合子程序

;------------------------

CONV0:

add A,#30h

MOV B,X

CALL LCDP2

ret

CONV1:

MOV X,#4

MOV A,#2BH ;+

MOV B,X

CALL LCDP2

RET

CONV2:

MOV X,#4

MOV A,#2DH ;-

MOV B,X

CALL LCDP2

RET

CONV3:

MOV X,#4

MOV A,#2AH ;

MOV B,X

CALL LCDP2

RET

CONV4:

MOV X,#4

MOV A,#2FH ;/

MOV B,X

CALL LCDP2

RET

CONV5:

MOV X,#09H

MOV A,#3DH ;=

MOV B,X

CALL LCDP2

RET

;--------------------------

;

;--------------------------

CONV:

;MOV X,#3 ;设置显示起始位置

MOV A,R3

ANL A,#0FH ;取出低四位二进制数

PUSH ACC ;压入堆栈

CLR C ;C=0

SUBB A,#0AH ;减10

POP ACC ;d出堆栈

JC ASCII0 ;该数小于10,转ASCII0

JMP ASCII1

;ADD A,#07H ;大于10的数加上37H

ASCII0: ADD A,#30H ;小于10的数加上30H

MOV B,X

CALL LCDP2

ASCII1: ;MOV A,R3

RET

;-------------------------------------------------------

T_CONV:

MOV A,OUT_H ;取高位数

mov x,#11

cjne a,#00h,t_conv1 ;判高位数是否为0?

setb 20h6 ;为0,20h6置1

jmp t_conv3 ;转取低位数

;高位数不为0,则

t_conv1: anl a,#0f0h ;判高位数的高四位是否为0?

cjne a,#00h,t_conv2 ;不为0,2位数都显示

setb 20h6 ;为0,20h6置1,只显示低四位

t_conv2: mov a,out_h

CALL SHOW_DIG2

inc x

clr 20h6 ;清显示标记位

t_conv3: mov a,out_l ;取低位数

jnb 20h6,t_conv5 ;高位数有显示,则不判低位数。

anl a,#0f0h ;高位数无显示,则判低位数。

cjne a,#00h,t_conv4 ;判低位数的高四位是否为0?

setb 20h6 ;为0,20h6置1,只显示低四位

MOV A,OUT_L

JMP T_CONV5

T_conv4: CLR 20H6 ;低位数不为0,2位数都显示

mov a,out_l

t_conv5: call show_dig2

clr 20h6 ;清显示标记位

RET

;----------------------------

;在 LCD 的第二行显示数字与符号

;----------------------------

SHOW_DIG2:

JNB 20H5,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 20h6,dig3 ;显示位标记

mov a,#20h

jmp dig4

dig3: 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

RET

DELAY: ;延时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,0EDH,0EBH,0E7H,0DEH ;0,1,2,3,4, 顺序码

DB 0DDH,0DBH,0D7H,0BEH,0BDH ;5,6,7,8,9,

DB 0BBH,0B7H,07EH,07DH,07BH ;A,B,C,D,E,

DB 077H,0FFH ;F 0FF为结束码

;-----------------------------------------------------

END

二进制的除法本质是通过重复减法运算实现

即通过重复”从被除数的高位依次取出每一位, 被取出的数据加上上次的减法结果2,

然后减去除数”的处理, 求出除法结果

假设:16位除以16位

被除数 R0R1 (占用2字节)

除数 R2R3 (占用2字节)

商 R0R1 (占用2字节) 这里需要说明, 此程序执行

结束以后, 商的结果保存在被除数中

余数 R4R5 (占用2字节)

移位次数 R6 (占用1字节) 这里需要说明, 其数值根据

被除数的位数定义, 这里为32

*** 作流程如下:

a) 余数清零

b) 判断除数是否为0, 如果为0, 是错误, 不再往下执行

c) 设定移位次数

d) 被除数左移1位, 溢出的最高位保存在进位标志C中, 再把余数左移1位, 把C(被除数溢出的最高位)放入余数的最低位

e) 余数与除数比较大小(余数减去除数):

余数 ≥ 除数(减法结果为正)时, 被除数的最低位, 赋值 1

余数 < 除数(减法结果为负时, 恢复到减法前的余数) 被除数的最低位, 赋值 0

f) 定移位次数递减

g) 直到移位次数为0, 否则重复d) ~ f)

假设32位除以16位

被除数R3R2R1R0

除数R5R4

余数R7R6

商也在R3R2R1R0中

计算开始的时候R7R6R3R2R1R0整体左移一位

然后余数R7R6与除数比较 如果大于除数 则r0最低位置一

依次循环32次

其他的多位除法类似 但是余数位数和除数位数要一致

; (r3r2r1r0) / (r5r4), 余数(r7r6)

div_4b: mov r7,#0

mov r6,#0

push cnt

mov cnt,#32

clr c

div_32_loop: mov a,r0

rlc a

mov r0,a

mov a,r1

rlc a

mov r1,a

mov a,r2

rlc a

mov r2,a

mov a,r3

rlc a

mov r3,a

mov a,r6

rlc a

mov r6,a

mov a,r7

rlc a

mov r7,a

clr c

mov a,r6

subb a,r4

mov b,a

mov a,r7

subb a,r5

jc div_4b_1

mov r6,b

mov r7,a

div_32: cpl c

djnz count,div_32_loop

mov a,r0

rlc a

mov r0,a

mov a,r1

rlc a

mov r1,a

mov a,r2

rlc a

mov r2,a

mov a,r3

rlc a

mov r3,a

pop cnt

ret

第二种方法 循环相减

移位相减的方法是仿照人们做除法的竖式编写,执行速度较快,但是计算的原理,一般人不好理解,难以让大家推广到更多的字节。故此下面采用循环相减的思路来编写程序。

设计思路:所谓除法,就是要求出在被除数中,含有多少个除数。那么就用被除数连续的减去除数,直到不够减为止,够减的次数,就是商,不够减的数值,就是余数。

比如:8/3,就是

第1次:8-3=5

第2次:5-3=2

2不够减3了,故8/3=2余2

下列程序,对数值范围的要求很宽松,被除数、除数和商,都可以是16位数,这比网上常见的16位除8位的除法程序,适用面要广得多。

注意,除数为0的问题,应该在主程序中进行检测。

;-------------------------------------

;16位/16位的子程序

;被除数:R2R3、除数:R4R5;商:DPTR、余数:R2R3。

;占用:A、B。

;-------------------------------------

R23DIVR45:

MOV DPTR, #0

D_LOOP:

CLR C

MOV A, R3

SUBB A, R5

MOV B, A

MOV A, R2

SUBB A, R4 ;R2R3-R4R5

JC DIV_E ;有借位转移

INC DPTR

MOV R3, B

MOV R2, A

SJMP D_LOOP

DIV_E:

RET ;不够减就结束

;-------------------------------------

;完

你看看是否对你有帮助。

>

版本 2

程序集 窗口程序集1

子程序 _按钮1_被单击

判断开始 (编辑框2内容 = “+”)

编辑框4内容 = 到文本 (到数值 (编辑框1内容) + 到数值 (编辑框3内容))

判断 (编辑框2内容 = “-”)

编辑框4内容 = 到文本 (到数值 (编辑框1内容) - 到数值 (编辑框3内容))

判断 (编辑框2内容 = “”)

编辑框4内容 = 到文本 (到数值 (编辑框1内容) × 到数值 (编辑框3内容))

判断 (编辑框2内容 = “/”)

编辑框4内容 = 到文本 (到数值 (编辑框1内容) ÷ 到数值 (编辑框3内容))

默认

信息框 (“此计算器仅支持+ - × ÷ ”, 0, )

判断结束

可以参考下面的代码:

#include <stdioh>

int main()

{

int m, n, r;

scanf ("%d%d", &m, &n);

if (m>n){r=m, m=n, n=r;}

r=n%m;

while (r!=0){

n = m;

m = r;

r = n%m;

}

printf ("%d\n", m);

return 0;

}

扩展资料:

函数 scanf() 是从标准输入流stdin(标准输入设备,一般指向键盘)中读内容的通用子程序,可以说明的格式读入多个字符,并保存在对应地址的变量中。

函数的第一个参数是格式字符串,它指定了输入的格式,并按照格式说明符解析输入对应位置的信息并存储于可变参数列表中对应的指针所指位置。每一个指针要求非空,并且与字符串中的格式符一一顺次对应。

参考资料来源:百度百科-scanf (计算机语言函数)

参考资料来源:百度百科-while (循环语句及英文单词)

乘以2是常见的,乘以3的也有;

乘以4,不像,请给出程序来分析一下。

---------------------

看明白了。

这书的作者,把各个程序的分支,写成了“调用子程序+转移指令”的形式,所以才有了如此“笨重”的散转方法。

且看它的分支表:

TABLE:

ACALL PRADD ;转加法子程序 从“TABLE +0”是第O个分支

SJMP PREND ;转结束

ACALL PRSUB ;转减法子程序 从“TABLE +4”是第一个分支

SJMP PREND ;转结束

ACALL PRMUL ;转乘法子程序 从“TABLE +8”是第二个分支

SJMP PREND ;转结束

ACALL PRDIV ;转除法子程序 从“TABLE +12”是第三个分支

SJMP PREND ;转结束

…… 从“TABLE +…………

……

它的每个分支,都是使用了两条2字节的指令,所以各分支,相差4个字节;如果要根据分支的号码,找到对应的地址,就应该乘以4。

这种4字节形式的分支表,所能容纳的分支数目,明显少于2字节的分支表。这种笨方法,也写成书,真是不可思议。

以上就是关于急求!!!哪位朋友指点下单片机程序题~~全部的内容,包括:急求!!!哪位朋友指点下单片机程序题~~、在汇编除法中:移位相减是怎么样的原理啊,程序看了几天了还是看不懂,哪位兄弟告诉我,本人感激涕零、怎么用易语言编一个加减乘除法啊,我已经设置好窗口了等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9741388.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-01
下一篇 2023-05-01

发表评论

登录后才能评论

评论列表(0条)

保存