7.3查表程序
单片机应用系统中,查表程序是一种常见的程序。查表程序实现查表算法,该方法把事先计算或试验数据按一定顺序编成表格,存于程序存储器内,然后根据输入参数值,从表中取得结果。查表程序可以完成数据补偿、计算和转换等功能。
用于查表的专用指令有两条:
MOVC A,@A+DPTR
MOVC A,@A+PC
1)用DPTR作为基址的查表操作的3个步骤
◆先把数据表格表头地址存入DPTR。
◆然后把要查得的数在表中相对于表头地址的偏移量送入累加器A。
◆最后执行MOVC A,@A+DPTR,把查表结果送累加器A。
2)用PC作为基址的查表操作的3个步骤
◆用传送指令把所查数据的项数送入累加器A。
◆使用ADD A,#data指令对累加器进行修改,data值由下式确定:
PC当前值+data=数据表头地址
其中data值等于查表指令和数据表格之间的字节数。
◆用指令MOVC A,@A+PC完成查表。
例:设有一个循环检测报警器装置,需要对16路输入进行控制,每路有一个最大允许值,该值为双字节数。控制时,需要根据测量的路数,找出该路的最大允许值,看输入值是否大于最大允许值,如大于则报警。
1)题目分析
取路数为x(0≤x≤15),y为最大允许值,放在数据表格中。根据x查出y。由于y值为双字节,所以需要执行两次查表指令。
2)硬件资源分配
R2:循环检测路数x
R3、R4:存放查表结果y
3)参考程序
TBI: MOV A,R2 ;输入路数x的值
ADD A,R2 ;x乘2与双字节y相对应
MOV R3,A ;保存指针
ADD A,#06 ;查表指令与数据表头第1字节之间相差6字节
MOVC A,@A+PC ;查第1字节
XCH A,R3
ADD A,#03 ; 查表指令与数据表头第2字节之间相差3字节
MOV R4,A
RET
TABI: DW 1520,3721,4642,2705
DW 3483,32657,453,88690
DW 1000,322,4523,6483
DW 13145,64326,23561,9512
4)程序说明
上述查表程序有一个局限,表格长度不能超过255字节。当表格长度大于255字节时,必须使用MOVC A,@A+DPTR,并且需要对DPH、DPL进行运算处理,求出表格的地址,下面举例说明。
例:在温控系统中,检测的电压与温度成非线性关系,为此要做线型化补偿。测得的电压由A/D转换为10二进制数。根据试验测得数据构成温度线型化补偿表。
1)题目分析
采样电压值x为输入,根据x查出线型温度值y为输出。
2)硬件资源分配
R2、R3:查表前放采用电压值x为输入,查表后放温度值y
DPTR:数据表格地址指针
3)参考程序
CHAB: MOV DPTR,#TAB ;赋值表头地址
MOV A,R3
CLR C
RLC A ;乘以2与双字节y相对应
MOV R3,A
XCH A,R2
RLC A
XCH A,R2
ADD A,DPL ;计算查表地址
MOV DPL,A
MOV A,DPH
ADDC A,R2
MOV DPH,A
CLR A
MOVC A,@A+DPTR ;查y值高字节
MOV R2,A
CLR A
INC DPTR
MOVC A,@A+DPTR ;查y值低字节
MOV R3,A
RET
TAB: DW …
4)程序说明
由于采样电压值x为双字节使用指令MOVC A,@A+DPTR时,不能直接用A作变址寄存器,需要先把DPH和DPL加上x,进行双字节加法处理,然后累加器A清0,再执行查表指令。
例:已知R0低4位是一个十六进制数(0~F中的一个),请编写能把它转换成相应的ASCII码并送入R0的程序。
本题给出3种求解方案:两种是计算求解,一种是查表求解,请自行比较它们的优劣。
计算求解1
1)题目分析
由ASCII码字符表可知,0~9的ASCII码为30H~39H,A~F的ASCII码为41H~46H。因此,计算求解的思路是:若(R0)≤9,则R0内容只需加30H,若(R0)≥9,则R0需加37H。
2)参考程序
ORG 0100H
MOV A,R0 ;取转换值
ANL A,#0FH ;屏蔽高4位
CJNE A,#10,NEXT1
NEXT1:JNC NEXT2 ;A>9则转NEXT2
ADD A,#30H ;若A<10则A←(A)+30H
SJMP DONE
NEXT2:ADD A,#37H ; A←(A)+37H
DONE: MOV R0,A
SJMP $
END
计算求解2
1)题目分析
先把R0中内容加上90H,并做十进制调整,然后再用ADDC指令使R0中内容加上40H,也做十进制调整,所得结果即为ASCII码。当(R0)<10时,相当于R0中内容加了30H,当(R0)≥10时,加90H做十进制调整后,低4位加到高4位变位0A0H,对高4位进一步调整到00H,最后使用ADDC指令(Cy=1)加上40H实际上相当于加上41H。
2)参考程序
ORG 0100H
ABH: MOV A,R0 ;取转换值到A
ANL A,#0FH ;屏蔽高4位
ADD A,#90H ;A内容加90H
DA A ;十进制调整
ADDC A,#40H ;A内容加40H
DA A ;十进制调整
MOV R0,A ;存转换结果
RET
END
查表求解
1)题目分析
查表求解时,两条查表指令可任选其一。
2)参考程序
ORG 0100H
MOV A,R0 ;取转换值
ANL A,#0FH ;屏蔽高4位
ADD A,#03H ;计算偏移量
MOVC A,@A+PC ;查表
MOV R0,A ;存结果
SJMP $
ASCT: DB '0', '1', '2', '3'
DB '4', '5', '6', '7'
DB '8', '9', 'A', 'B'
DB 'C', 'D', 'E', 'F'
END
由以上3种解题方法可见,使用查表法比较简单,不需要判断和计算,可直接使用查表指令进行ASCII码转换。
7.4分支程序
分支程序的特点是程序中含有控制转移指令。由于转移指令分为无条件转移指令和条件转移指令,所以分支程序也可分为无条件分支程序和条件分支程序。
条件分支程序根据不同的条件,执行不同的程序段。MCS51单片机中用来判断分支条件的指令有JZ、JNZ、CJNE、JC、JNC、JB和JNB等。无条件分支程序使用跳转指令LJMP、AJMP、SJMP或散转指令JMP。
7.4.1条件分支转移程序
例:两个无符号数比较(两分支)。内部RAM的20H单元和30H单元各存放了一个8位无符号数,请比较这两个数的大小,比较结果用相应的LED显示。如下:
若(20H)>=(30H),则P1.0管脚连接的LED发光;
若(20H)<(30H),则P1.1管脚连接的LED发光;
1)题意分析
本例是典型的条件分支程序,根据两个无符号数的比较结果(判断条件),程序可以选择两个流向之中的某一个,分别点亮相应的LED。
比较两个无符号数常用的方法是将两个数相减X-Y,然后判断有否借位Cy,若Cy=0,无借位,X >= Y;若Cy=1,有借位,X<Y。程序的流程图如图7-5所示。
图7-5 两数比较流程图
2)参考程序
X DATA 20H ;数据地址赋值伪指令DATA
Y DATA 30H
ORG 0000H
MOV A,X ;(X) →A
CLR C ;Cy=0
SUBB A,Y ;带借位减法,A-(Y)-Cy→A
JC L1 ;Cy=1,转移到 L1
CLR P1.0 ;Cy=0,(20H)>=(30H),点亮P1.0连接的LED
SJMP FIN ;直接跳转到结束等待
L1: CLR P1.1 ;(20H)<(30H),点亮P1.1连接的LED
FIN: SJMP $
END
3)执行结果
执行该程序之前,利用单片机开发系统先往内部RAM的20H和30H单元存放两个无符号数(可以任意设定),执行后观察点亮的LED是否和存放的数据大小相一致。
例:两个有符号数比较(三分支程序)。内部RAM的20H单元和30H单元各存放了一个8位有符号数,请比较这两个数的大小,比较结果用LED显示。结果如下:
若(20H)=(30H),则P1.0管脚连接的LED发光;
若(20H)>(30H),则P1.1管脚连接的LED发光;
若(20H)<(30H),则P1.2管脚连接的LED发光。
1)题意分析
有符号数在计算机中的表示方式与无符号数是不相同的:正数以原码形式表示,负数以补码形式表示,8位二进制数的补码所能表示的数值范围为+127~-128。
计算机本身无法区分一串二进制码组成的数字是有符号数或无符号数,也无法区分它是程序指令还是一个数据。编程员必须对程序中出现的每一个数据的含义非常清楚,并按此选择相应的操作。例如:数据FEH看作无符号数其值为254,看作有符号数为-2。
比较两个有符号数X和Y大小要比无符号数麻烦得多。这里提供一种比较思路如下:先判别两个有符号数X和Y的符号,如果X、Y两数符号相反,则非负数大;如果X、Y两数符号相同,将两数相减X-Y,根据借位标志 Cy进行判断即可。这一比较过程如图7-6所示。
图7-6 两个有符号数X、Y比较流程图
2)参考程序
X DATA 20H
Y DATA 30H
ORG 0000H
MOV A,X
XRL A,Y ;(X)与(Y)进行异或操作
JB ACC.7,NEXT1 ;累加器A的第7位为1,二数符号不同,转移到NEXT1
MOV A,X
CJNE A,Y,NEQL ;(X)<>(Y),转移到NEQL
CLR P1.0 ;(X)=(Y),点亮P1.0连接的LED
SJMP FIN
NEQL: JC XXY ;(X)<(Y),转移到XXY
SJMP XDY ;否则,(X)>(Y),转移到XDY
NEXT1:MOV A,X
JNB ACC.7,XDY ;判断(X)的最高位D7,以确定其正负
XXY: CLR P1.2 ;(X)<(Y),点亮P1.2连接的LED
SJMP FIN
XDY: CLR P1.1 ;(X)>(Y),点亮P1.1连接的LED
FIN: SJMP $
END
3)程序说明
◆判断两个有符号数符号异同的方法
本例中使用逻辑异或指令,将(X)与(Y)进行异或操作,那么(X)的符号位(X)7与(Y)的符号位(Y)7异或,结果如下:
若(X)7与(Y)7相同, 则(X)7 ⊕(Y)7=0
若(X)7与(Y)7不相同,则(X)7 ⊕(Y)7=1
本例中,(X)与(Y)的异或结果存放在累加器A中,因此判断ACC.7是否为零即可知道两个数的符号相同与否。
◆比较两个有符号数的其它方法
除了本例中使用的比较两个有符号数的方法之外,我们还可以利用溢出标志OV的状态来判断两个有符号数的大小。具体算法如下:
若X-Y为正数,则 OV=0 时 X>Y
OV=1 时 X<Y
若X-Y为负数,则 OV=0 时 X<Y
OV=1 时 X>Y

