(1)滤波的选择:可以对输入加一个前置滤波启模备器,使得进入控制算法的给定值不突悄毁变,而是有一定惯性延迟的缓码握变量。
(2)系统的动态过程加速:如果被控量继续偏离给定值,则这两项符号相同,而当被控量向给定值方向变化时,则这两项的符号相反。由于这一性质,当被控量接近给定值的时候,反号的比例作用阻碍了积分作用,因而避免了积分超调以及随之带来的振荡,这显然是有利于控制的。但如果被控量远未接近给定值,仅刚开始向给定值变化时,由于比例和积分反向,将会减慢控制过程。
2,PID增量算法的饱和作用及其抑制:在PID增量算法中,由于执行元件本身是机械或物理的积分储存单元,如果给定值发生突变时,由算法的比例部分和微分部分计算出的控制增量可能比较大,如果该值超过了执行元件所允许的最大限度,那么实际上执行的控制增量将时受到限制时的值,多余的部分将丢失,将使系统的动态过程变长,因此,需要采取一定的措施改善这种情况。
增量式PID:
typedef struct{float scope //输出限幅量
float aim //目标输出量
float real_out //实际输出量
float Kp
float Ki
float Kd
float e0 //当前误差
float e1 //上一次误差
float e2 //上上次误差
}PID_Type
#define min(a, 陆伍罩b) (a<b? a:b)
#define max(a, b) (a>b? a:b)
#define limiter(x, a, b) (min(max(x, a), b))
#define exchange(a, b, tmp) (tmp=a, a=b, b=tmp)
#define myabs(x) ((x<0)? -x:x)
float pid_acc(PID_Type *pid)
{
float out
float ep, ei, ed
pid->e0 = pid->aim - pid->real_out
ep = pid->e0 - pid->e1
橘让ei = pid->e0
ed = pid->e0 - 2*pid->e1 早闹+ pid->e2
out = pid->Kp*ep + pid->Ki*ei + pid->Kd*ed
out = limiter(out, -pid->scope, pid->scope)
pid->e2 = pid->e1
pid->e1 = pid->e0
return out
}
位置式PID:
typedef struct{float scope //输出限幅量
float aim //目标输出量
float real_out //反馈输出量
float Kp
float Ki
float Kd
float Sum
float e0 //当前误差
float e1 //上一次误差
}PID_Type
#define max(a, b) (a>b? a:b)
#define min(a, b) (a<b? a:b)
#define limiter(x, a, b) (min(max(x, a), b))
float pid_pos(PID_Type *p)
{
float pe, ie, de
float out = 0
p->e0 = p->aim - p->real_out //计算当前误差
p->Sum += p->e0 //误差积分
de = p->e0 - p->e1 //误差微分
pe = p->e0
ie = p->Sum
p->e1 = p->e0
out = pe*(p->Kp) + ie*(p->Ki) + de*(p->Kd)
out = limiter(out, -p->scope, p->scope) //输出限幅
return out
}
亲手移植到我的stm32小车上 调试3个参数后正常使用。
********增量式PID控制算法程序***********T、TD、TI、KP依次从30H,33H,36H,39H开始。
A,B,C的值依次存在BLOCK1,BLOCK2,BLOCK3的地址里
这里R(k)给的是定值
ORG 0000H
BLOCK1 EQU 43H A,B ,C
BLOCK2 EQU 46H
BLOCK3 EQU 49H
UK EQU 4CH 存结果UK
RK EQU 50H
EK EQU 53H 存放偏差值E(k)的始址
EK1 EQU 56H 存放E(k-1)的始址
EK2 EQU 59H 存放E(k-2)的始址
CK EQU 5CH 采汪岁样数据始址
BUFF EQU 60H 暂存区
BUFF1 EQU 63H
BUFF2 EQU 66H
REC EQU 69H
TEST:
MOV RK,#01H 常数Rk的BCD码浮点数
MOV RK+1,#12H 1.25
MOV RK+2,#50H
MOV 3CH,#01H 常数1的BCD码浮点数
MOV 3DH,#10H
MOV 3EH,#00H
MOV 40H,#01H 常数2的BCD码浮点数
MOV 41H,#20H
MOV 42H,#00H
MOV 30H,#01H T的困或睁BCD 码浮点数
MOV 31H,#23H 2.34
MOV 32H,#40H
MOV 33H,#01H Td的BCD码浮点数
MOV 34H,#35H 3.54
MOV 35H,#40H
MOV 36H,#01H Ti的BCD码团物浮点数
MOV 37H,#11H 1.12
MOV 38H,#20H
MOV 39H,#01H Kp的BCD码浮点数
MOV 3AH,#12H 1.25
MOV 3BH,#50H
MOV R0,#RK 指向BCD码浮点 *** 作数
LCALL BTOF 将其转换成二进制浮点 *** 作数
MOV R0,#3CH
LCALL BTOF
MOV R0,#40H
LCALL BTOF
MOV R0,#39H
LCALL BTOF
MOV R0,#36H 指向BCD码浮点 *** 作数Ti
LCALL BTOF 将其转换成二进制浮点 *** 作数
MOV R0,#33H 指向BCD码浮点 *** 作数Td
LCALL BTOF 将其转换成二进制浮点 *** 作数
MOV R0,#30H 指向BCD码浮点 *** 作数T
LCALL BTOF 将其转换成二进制浮点 *** 作数
MOV R1, #BUFF1 保存30H中的值 即T值
LCALL FMOVR0
MOV R1, #36H 计算A值(1+T/Ti+Td/T).Kp
LCALL FDIV
MOV R1,#3CH 常数1
LCALL FADD
MOV R0,#33H 保存33H中的值
MOV R1,#BUFF
LCALL FMOVR0
MOV R1,#BUFF1
LCALL FDIV
MOV R1,#30H 30H里存的是T/Ti+1
LCALL FADD
MOV R1,#39H
LCALL FMUL
MOV R1 ,#BLOCK1 将结果保存在BLOCK1中
LCALL FMOVR0
MOV R1,#BUFF1 30H恢复原值
MOV R0,#30H
LCALL FMOV
MOV R1,#BUFF 33H恢复原值
MOV R0,#33H
LCALL FMOV
MOV R0,#40H 计算B的值Kp.(1+2.Td/T)
MOV R1,#33H
LCALL FMUL
MOV R1,#30H
LCALL FDIV
MOV R1,#3CH
LCALL FADD
MOV R1,#39H
LCALL FMUL
MOV R1,#BLOCK2 保存B值到BLOCK2中
LCALL FMOVR0
MOV R0,#39H 计算C的值Kp.Td/T
MOV R1,#33H
LCALL FMUL
MOV R1,#30H
LCALL FDIV
MOV R1,#BLOCK3 保存C值到BLOCK3中
LCALL FMOVR0
MOV R0,#EK1 将EK1,EK2设初值0
LCALL FCLR
MOV R0,#EK2
LCALL FCLR
MOV REC,#03H 设置采样次数
LOOP: MOV CK,#7eH 采样数据暂时给了一个定值
MOV CK+1,#21H 0.002112
MOV CK+2,#12H
MOV R0,#CK
LCALL BTOF
MOV R0,#RK 保存R(k)中的值
MOV R1,#BUFF
LCALL FMOVR0
MOV R1,#CK
LCALL FSUB 计算R(k)-C(k)的值送给E(k)
MOV R1,#EK
LCALL FMOVR0
MOV R1,#BUFF 恢复RK的值 释放BUFF
MOV R0,#RK
LCALL FMOV
MOV R0,#BLOCK2 将B.e(k-1)的值暂存在BUFF1中
MOV R1,#BUFF 保存B
LCALL FMOVR0
MOV R1,#EK1
LCALL FMUL
MOV R1,#BUFF1
LCALL FMOVR0
MOV R1,#BUFF 恢复B释放BUFF
LCALL FMOV
MOV R0,#BLOCK3 将C.e(K-2)的值暂存在BUFF2中
MOV R1,#BUFF 保存C
LCALL FMOVR0
MOV R1,#EK2
LCALL FMUL
MOV R1,#BUFF2
LCALL FMOVR0
MOV R1,#BUFF 恢复C释放BUFF
LCALL FMOV
MOV R0,#BLOCK1 A.E(k)
MOV R1,#BUFF
LCALL FMOVR0
MOV R1,#EK
LCALL FMUL
MOV R1,#BUFF1 计算Uk值A.E(k)-B.E(k-1)+C.E(k-2)
LCALL FSUB
MOV R1,#BUFF2
LCALL FADD
MOV R1,#UK 保存结果到UK中
LCALL FMOVR0
MOV R1,#BUFF 恢复A 释放BUFF
LCALL FMOV
MOV R0,#UK UK转换成BCD码浮点数输出
LCALL FTOB
MOV R1,#EK1 将E(k-1)-->E(k-2),E(k)-->E(k-1)
MOV R0,#EK2
LCALL FMOV
MOV R1,#EK
MOV R0,#EK1
LCALL FMOV
LCALL DELAY 等待采样时刻
DJNZ REC,NEXT1
SJMP $
NEXT1: LJMP LOOP
DELAY: MOV R7,#02H
DELAY1: MOV R6,#0FFH
DELAY2: DJNZ R6,DELAY2
DJNZ R7,DELAY1
RET
(1) 标号: FSDT 功能:浮点数格式化
入口条件:待格式化浮点 *** 作数在[R0]中。
出口信息:已格式化浮点 *** 作数仍在[R0]中。
影响资源:PSW、A、R2、R3、R4、位1FH 堆栈需求: 6字节
FSDT: LCALL MVR0 将待格式化 *** 作数传送到第一工作区中
LCALL RLN 通过左规完成格式化
LJMP MOV0 将已格式化浮点 *** 作数传回到[R0]中
(2) 标号: FADD 功能:浮点数加法
入口条件:被加数在[R0]中,加数在[R1]中。
出口信息:OV=0时,和仍在[R0]中,OV=1时,溢出。
影响资源:PSW、A、B、R2~R7、位1EH、1FH 堆栈需求: 6字节
FADD: CLR F0 设立加法标志
SJMP AS 计算代数和
(3) 标号: FSUB 功能:浮点数减法
入口条件:被减数在[R0]中,减数在[R1]中。
出口信息:OV=0时,差仍在[R0]中,OV=1时,溢出。
影响资源:PSW、A、B、R2~R7、位1EH、1FH 堆栈需求:6字节
FSUB: SETB F0 设立减法标志
AS: LCALL MVR1 计算代数和。先将[R1]传送到第二工作区
MOV C,F0 用加减标志来校正第二 *** 作数的有效符号
CLR A ********???应加的一条语句
RRC A
XRL A,@R1
MOV C,ACC.7
ASN: MOV 1EH,C 将第二 *** 作数的有效符号存入位1EH中
XRL A,@R0 与第一 *** 作数的符号比较
RLC A
MOV F0,C 保存比较结果
LCALL MVR0 将[R0]传送到第一工作区中
LCALL AS1 在工作寄存器中完成代数运算
MOV0: INC R0 将结果传回到[R0]中的子程序入口
INC R0
MOV A,R4 传回尾数的低字节
MOV @R0,A
DEC R0
MOV A,R3 传回尾数的高字节
MOV @R0,A
DEC R0
MOV A,R2 取结果的阶码
MOV C,1FH 取结果的数符
MOV ACC.7,C 拼入阶码中
MOV @R0,A
CLR ACC.7 不考虑数符
CLR OV 清除溢出标志
CJNE A,#3FH,MV01阶码是否上溢? ******** 应为#40H
SETB OV 设立溢出标志
MV01: MOV A,@R0 取出带数符的阶码
RET
MVR0: MOV A,@R0 将[R0]传送到第一工作区中的子程序
MOV C,ACC.7 将数符保存在位1FH中
MOV 1FH,C
MOV C,ACC.6 将阶码扩充为8bit补码
MOV ACC.7,C
MOV R2,A 存放在R2中
INC R0
MOV A,@R0 将尾数高字节存放在R3中
MOV R3,A
INC R0
MOV A,@R0 将尾数低字节存放在R4中
MOV R4,A
DEC R0 恢复数据指针
DEC R0
RET
MVR1: MOV A,@R1 将[R1]传送到第二工作区中的子程序
MOV C,ACC.7 将数符保存在位1EH中
MOV 1EH,C
MOV C,ACC.6 将阶码扩充为8bit补码
MOV ACC.7,C
MOV R5,A 存放在R5中
INC R1
MOV A,@R1 将尾数高字节存放在R6中
MOV R6,A
INC R1
MOV A,@R1 将尾数低字节存放在R7中
MOV R7,A
DEC R1 恢复数据指针
DEC R1
RET
AS1: MOV A,R6 读取第二 *** 作数尾数高字节
ORL A,R7
JZ AS2 第二 *** 作数为零,不必运算
MOV A,R3 读取第一 *** 作数尾数高字节
ORL A,R4
JNZ EQ
MOV A,R6 第一 *** 作数为零,结果以第二 *** 作数为准
MOV R3,A
MOV A,R7
MOV R4,A
MOV A,R5
MOV R2,A
MOV C,1EH
MOV 1FH,C
AS2: RET
EQ: MOV A,R2 对阶,比较两个 *** 作数的阶码
XRL A,R5
JZ AS4 阶码相同,对阶结束
JB ACC.7,EQ3阶符互异
MOV A,R2 阶符相同,比较大小
CLR C
SUBB A,R5
JC EQ4
EQ2: CLR C 第二 *** 作数右规一次
MOV A,R6 尾数缩小一半
RRC A
MOV R6,A
MOV A,R7
RRC A
MOV R7,A
INC R5 阶码加一
ORL A,R6 尾数为零否?
JNZ EQ 尾数不为零,继续对阶
MOV A,R2 尾数为零,提前结束对阶
MOV R5,A
SJMP AS4
EQ3: MOV A,R2 判断第一 *** 作数阶符
JNB ACC.7,EQ2如为正,右规第二 *** 作数
EQ4: CLR C
LCALL RR1 第一 *** 作数右规一次
ORL A,R3 尾数为零否?
JNZ EQ 不为零,继续对阶
MOV A,R5 尾数为零,提前结束对阶
MOV R2,A
AS4: JB F0,AS5 尾数加减判断
MOV A,R4 尾数相加
ADD A,R7
MOV R4,A
MOV A,R3
ADDC A,R6
MOV R3,A
JNC AS2
LJMP RR1 有进位,右规一次
AS5: CLR C 比较绝对值大小
MOV A,R4
SUBB A,R7
MOV B,A
MOV A,R3
SUBB A,R6
JC AS6
MOV R4,B 第一尾数减第二尾数
MOV R3,A
LJMP RLN 结果规格化
AS6: CPL 1FH 结果的符号与第一 *** 作数相反
CLR C 结果的绝对值为第二尾数减第一尾数
MOV A,R7
SUBB A,R4
MOV R4,A
MOV A,R6
SUBB A,R3
MOV R3,A
RLN: MOV A,R3 浮点数规格化
ORL A,R4 尾数为零否?
JNZ RLN1
MOV R2,#0C1H阶码取最小值 ******??应为#C0H
RET
RLN1: MOV A,R3
JB ACC.7,RLN2尾数最高位为一否?
CLR C 不为一,左规一次
LCALL RL1
SJMP RLN 继续判断
RLN2: CLR OV 规格化结束
RET
RL1: MOV A,R4 第一 *** 作数左规一次
RLC A 尾数扩大一倍
MOV R4,A
MOV A,R3
RLC A
MOV R3,A
DEC R2 阶码减一
CJNE R2,#0C0H,RL1E阶码下溢否? ***** 应改为CJNE R2,#0BFH,RL1E;
CLR A
MOV R3,A 阶码下溢, *** 作数以零计
MOV R4,A
MOV R2,#0C1H ******应改为MOV R2,#0C0H
RL1E: CLR OV
RET
RR1: MOV A,R3 第一 *** 作数右规一次
RRC A 尾数缩小一半
MOV R3,A
MOV A,R4
RRC A
MOV R4,A
INC R2 阶码加一
CLR OV 清溢出标志
CJNE R2,#40H,RR1E阶码上溢否?
MOV R2,#3FH 阶码溢出
SETB OV
RR1E: RET
(4) 标号: FMUL 功能:浮点数乘法
入口条件:被乘数在[R0]中,乘数在[R1]中。
出口信息:OV=0时,积仍在[R0]中,OV=1时,溢出。
影响资源:PSW、A、B、R2~R7、位1EH、1FH 堆栈需求:6字节
FMUL: LCALL MVR0 将[R0]传送到第一工作区中
MOV A,@R0
XRL A,@R1 比较两个 *** 作数的符号
RLC A
MOV 1FH,C 保存积的符号
LCALL MUL0 计算积的绝对值
LJMP MOV0 将结果传回到[R0]中
MUL0: LCALL MVR1 将[R1]传送到第二工作区中
MUL1: MOV A,R3 第一尾数为零否?
ORL A,R4
JZ MUL6
MOV A,R6 第二尾数为零否?
ORL A,R7
JZ MUL5
MOV A,R7 计算R3R4×R6R7-→R3R4
MOV B,R4
MUL AB
MOV A,B
XCH A,R7
MOV B,R3
MUL AB
ADD A,R7
MOV R7,A
CLR A
ADDC A,B
XCH A,R4
MOV B,R6
MUL AB
ADD A,R7
MOV R7,A
MOV A,B
ADDC A,R4
MOV R4,A
CLR A
RLC A
XCH A,R3
MOV B,R6
MUL AB
ADD A,R4
MOV R4,A
MOV A,B
ADDC A,R3
MOV R3,A
JB ACC.7,MUL2积为规格化数否? R7四舍五入
MOV A,R7 左规一次
RLC A
MOV R7,A
LCALL RL1
MUL2: MOV A,R7
JNB ACC.7,MUL3
INC R4
MOV A,R4
JNZ MUL3
INC R3
MOV A,R3
JNZ MUL3
MOV R3,#80H
INC R2
MUL3: MOV A,R2 求积的阶码
ADD A,R5
MD: MOV R2,A 阶码溢出判断
JB ACC.7,MUL4
JNB ACC.6,MUL6
MOV R2,#3FH 阶码上溢,设立标志
SETB OV
RET
MUL4: JB ACC.6,MUL6
MUL5: CLR A 结果清零(因子为零或阶码下溢)
MOV R3,A
MOV R4,A
MOV R2,#41H
MUL6: CLR OV
RET
(5) 标号: FDIV 功能:浮点数除法
入口条件:被除数在[R0]中,除数在[R1]中。
出口信息:OV=0时,商仍在[R0]中,OV=1时,溢出。
影响资源:PSW、A、B、R2~R7、位1EH、1FH 堆栈需求: 5字节
FDIV: INC R0
MOV A,@R0
INC R0
ORL A,@R0
DEC R0
DEC R0
JNZ DIV1
MOV @R0,#41H被除数为零,不必运算
CLR OV
RET
DIV1: INC R1
MOV A,@R1
INC R1
ORL A,@R1
DEC R1
DEC R1
JNZ DIV2
SETB OV 除数为零,溢出
RET
DIV2: LCALL MVR0 将[R0]传送到第一工作区中
MOV A,@R0
XRL A,@R1 比较两个 *** 作数的符号
RLC A
MOV 1FH,C 保存结果的符号
LCALL MVR1 将[R1]传送到第二工作区中
LCALL DIV3 调用工作区浮点除法
LJMP MOV0 回传结果
DIV3: CLR C 比较尾数的大小
MOV A,R4
SUBB A,R7
MOV A,R3
SUBB A,R6
JC DIV4
LCALL RR1 被除数右规一次
SJMP DIV3
DIV4: CLR A 借用R0R1R2作工作寄存器
XCH A,R0 清零并保护之
PUSH ACC
CLR A
XCH A,R1
PUSH ACC
MOV A,R2
PUSH ACC
MOV B,#10H 除法运算,R3R4/R6R7-→R0R1
DIV5: CLR C
MOV A,R1
RLC A
MOV R1,A
MOV A,R0
RLC A
MOV R0,A
MOV A,R4
RLC A
MOV R4,A
XCH A,R3
RLC A
XCH A,R3
MOV F0,C
CLR C
SUBB A,R7
MOV R2,A
MOV A,R3
SUBB A,R6
ANL C,/F0
JC DIV6
MOV R3,A
MOV A,R2
MOV R4,A
INC R1
DIV6: DJNZ B,DIV5
MOV A,R6 四舍五入
CLR C
RRC A
SUBB A,R3
CLR A
ADDC A,R1 将结果存回R3R4
MOV R4,A
CLR A
ADDC A,R0
MOV R3,A
POP ACC 恢复R0R1R2
MOV R2,A
POP ACC
MOV R1,A
POP ACC
MOV R0,A
MOV A,R2 计算商的阶码
CLR C
SUBB A,R5
LCALL MD 阶码检验
LJMP RLN 规格化
(6) 标号: FCLR 功能:浮点数清零
入口条件: *** 作数在[R0]中。
出口信息: *** 作数被清零。
影响资源:A 堆栈需求: 2字节
FCLR: INC R0
INC R0
CLR A
MOV @R0,A
DEC R0
MOV @R0,A
DEC R0
MOV @R0,#41H
RET
(7) 标号: FZER 功能:浮点数判零
入口条件: *** 作数在[R0]中。
出口信息:若累加器A为零,则 *** 作数[R0]为零,否则不为零。
影响资源:A 堆栈需求: 2字节
FZER: INC R0
INC R0
MOV A,@R0
DEC R0
ORL A,@R0
DEC R0
JNZ ZERO
MOV @R0,#41H
ZERO: RET
(8) 标号: FMOV 功能:浮点数传送
入口条件:源 *** 作数在[R1]中,目标地址为[R0]。
出口信息:[R0]=[R1],[R1]不变。
影响资源:A 堆栈需求: 2字节
FMOV: INC R0
INC R0
INC R1
INC R1
MOV A,@R1
MOV @R0,A
DEC R0
DEC R1
MOV A,@R1
MOV @R0,A
DEC R0
DEC R1
MOV A,@R1
MOV @R0,A
RET
(8.1) 标号: FMOVR0 功能:浮点数传送
入口条件:源 *** 作数在[R0]中,目标地址为[R1]。
出口信息:[R1]=[R0],[R0]不变。
影响资源:A 堆栈需求: 2字节
FMOVR0: INC R1
INC R1
INC R0
INC R0
MOV A,@R0
MOV @R1,A
DEC R1
DEC R0
MOV A,@R0
MOV @R1,A
DEC R1
DEC R0
MOV A,@R0
MOV @R1,A
RET
(24)标号: DTOF 功能:双字节十六进制定点数转换成格式化浮点数
入口条件:双字节定点数的绝对值在[R0]中,数符在位1FH中,整数部分的位数在A中。
出口信息:转换成格式化浮点数在[R0]中(三字节)。
影响资源:PSW、A、R2、R3、R4、位1FH 堆栈需求: 6字节
DTOF: MOV R2,A 按整数的位数初始化阶码
MOV A,@R0 将定点数作尾数
MOV R3,A
INC R0
MOV A,@R0
MOV R4,A
DEC R0
LCALL RLN 进行规格化
LJMP MOV0 传送结果到[R0]中
(25) 标号: FTOD 功能:格式化浮点数转换成双字节定点数
入口条件:格式化浮点 *** 作数在[R0]中。
出口信息:OV=1时溢出,OV=0时转换成功:定点数的绝对值在[R0]中(双字节),数符
在位1FH中,F0=1 时为整数,CY=1时为一字节整数一字节小数,否则为纯小数。
影响资源:PSW、A、B、R2、R3、R4、位1FH 堆栈需求: 6字节
FTOD: LCALL MVR0 将[R0]传送到第一工作区
MOV A,R2
JZ FTD4 阶码为零,纯小数
JB ACC.7,FTD4阶码为负,纯小数
SETB C
SUBB A,#10H
JC FTD1
SETB OV 阶码大于16,溢出
RET
FTD1: SETB C
MOV A,R2
SUBB A,#8 阶码大于8否?
JC FTD3
FTD2: MOV B,#10H 阶码大于8,按双字节整数转换
LCALL FTD8
SETB F0 设立双字节整数标志
CLR C
CLR OV
RET
FTD3: MOV B,#8 按一字节整数一字节小数转换
LCALL FTD8
SETB C 设立一字节整数一字节小数标志
CLR F0
CLR OV
RET
FTD4: MOV B,#0 按纯小数转换
LCALL FTD8
CLR OV 设立纯小数标志
CLR F0
CLR C
RET
FTD8: MOV A,R2 按规定的整数位数进行右规***阶码是扩展后的值
CJNE A,B,FTD9
MOV A,R3 将双字节结果传送到[R0]中
MOV @R0,A
INC R0
MOV A,R4
MOV @R0,A
DEC R0
RET
FTD9: CLR C
LCALL RR1 右规一次
SJMP FTD8
(26) 标号: BTOF 功能:浮点BCD码转换成格式化浮点数
入口条件:浮点BCD码 *** 作数在[R0]中。
出口信息:转换成的格式化浮点数仍在[R0]中。
影响资源:PSW、A、B、R2~R7、位1DH~1FH 堆栈需求:6字节
BTOF: INC R0 判断是否为零。
INC R0
MOV A,@R0
MOV R7,A
DEC R0
MOV A,@R0
MOV R6,A
DEC R0
ORL A,R7
JNZ BTF0
MOV @R0,#41H为零,转换结束。
RET
BTF0: MOV A,@R0
MOV C,ACC.7
MOV 1DH,C 保存数符。
CLR 1FH 以绝对值进行转换。
MOV C,ACC.6 扩充阶码为八位。
MOV ACC.7,C
MOV @R0,A
JNC BTF1
ADD A,#19 是否小于1E-19?
JC BTF2
MOV @R0,#41H 小于1E-19时以0计。
INC R0
MOV @R0,#0
INC R0
MOV @R0,#0
DEC R0
DEC R0
RET
BTF1: SUBB A,#19
JC BTF2
MOV A,#3FH 大于1E19时封顶。
MOV C,1DH
MOV ACC.7,C
MOV @R0,A
INC R0
MOV @R0,#0FFH
INC R0
MOV @R0,#0FFH
DEC R0
DEC R0
RET
BTF2: CLR A 准备将BCD码尾数转换成十六进制浮点数。
MOV R4,A
MOV R3,A
MOV R2,#10H 至少两个字节。
BTF3: MOV A,R7
ADD A,R7
DA A
MOV R7,A
MOV A,R6
ADDC A,R6
DA A
MOV R6,A
MOV A,R4
RLC A
MOV R4,A
MOV A,R3
RLC A
MOV R3,A
DEC R2
JNB ACC.7,BTF3直到尾数规格化。
MOV A,R6 四舍五入。
ADD A,#0B0H ******加#80H,也可以
CLR A
ADDC A,R4
MOV R4,A
CLR A
ADDC A,R3
MOV R3,A
JNC BTF4
MOV R3,#80H ****有进位右规一次
INC R2
BTF4: MOV DPTR,#BTFL准备查表得到十进制阶码对应的浮点数。
MOV A,@R0
ADD A,#19 计算表格偏移量。
MOV B,#3
MUL AB
ADD A,DPL
MOV DPL,A
JNC BTF5
INC DPH
BTF5: CLR A 查表。
MOVC A,@A+DPTR
MOV C,ACC.6
MOV ACC.7,C
MOV R5,A
MOV A,#1
MOVC A,@A+DPTR
MOV R6,A
MOV A,#2
MOVC A,@A+DPTR
MOV R7,A
LCALL MUL1 将阶码对应的浮点数和尾数对应的浮点数相乘。
MOV C,1DH 取出数符。
MOV 1FH,C
LJMP MOV0 传送转换结果。
(27) 标号: FTOB 功能:格式化浮点数转换成浮点BCD码
入口条件:格式化浮点 *** 作数在[R0]中。
出口信息:转换成的浮点BCD码仍在[R0]中。
影响资源:PSW、A、B、R2~R7、位1DH~1FH 堆栈需求:6字节
FTOB: INC R0
MOV A,@R0
INC R0
ORL A,@R0
DEC R0
DEC R0
JNZ FTB0
MOV @R0,#41H
RET
FTB0: MOV A,@R0
MOV C,ACC.7
MOV 1DH,C
CLR ACC.7
MOV @R0,A
LCALL MVR0
MOV DPTR,#BFL0绝对值大于或等于1时的查表起点。
MOV B,#0 十的0次幂。
MOV A,R2
JNB ACC.7,FTB1
MOV DPTR,#BTFL绝对值小于1E-6时的查表起点。
MOV B,#0EDH 十的-19次幂。
ADD A,#16
JNC FTB1
MOV DPTR,#BFLN绝对值大于或等于1E-6时的查表起点。
MOV B,#0FAH 十的-6次幂。
FTB1: CLR A 查表,找到一个比待转换浮点数大的整数幂。
MOVC A,@A+DPTR
MOV C,ACC.6
MOV ACC.7,C
MOV R5,A
MOV A,#1
MOVC A,@A+DPTR
MOV R6,A
MOV A,#2
MOVC A,@A+DPTR
MOV R7,A
MOV A,R5 和待转换浮点数比较。
CLR C
SUBB A,R2
JB ACC.7,FTB2差为负数。
JNZ FTB3
MOV A,R6
CLR C
SUBB A,R3
JC FTB2
JNZ FTB3
MOV A,R7
CLR C
SUBB A,R4
JC FTB2
JNZ FTB3
MOV R5,B 正好是表格中的数。
INC R5 幂加一。
MOV R6,#10H 尾数为0·1000。
MOV R7,#0
SJMP FTB6 传送转换结果。
FTB2: INC DPTR 准备表格下一项。
INC DPTR
INC DPTR
INC B 幂加一。
SJMP FTB1
FTB3: PUSH B 保存幂值。
LCALL DIV3 相除,得到一个二进制浮点数的纯小数。
FTB4: MOV A,R2 取阶码。
JZ FTB5 为零吗?
CLR C
LCALL RR1 右规。
SJMP FTB4
FTB5: POP ACC 取出幂值。
MOV R5,A 作为十进制浮点数的阶码。
LCALL HB2 转换尾数的十分位和百分位。
MOV R6,A
LCALL HB2 转换尾数的千分位和万分位。
MOV R7,A
MOV A,R3 四舍五入。
RLC A
CLR A
ADDC A,R7
DA A
MOV R7,A
CLR A
ADDC A,R6
DA A
MOV R6,A
JNC FTB6
MOV R6,#10H
INC R5
FTB6: INC R0 存放转换结果。
INC R0
MOV A,R7
MOV @R0,A
DEC R0
MOV A,R6
MOV @R0,A
DEC R0
MOV A,R5
MOV C,1DH 取出数符。
MOV ACC.7,C
MOV @R0,A
RET
HB2: MOV A,R4 尾数扩大100倍。
MOV B,#100
MUL AB
MOV R4,A
MOV A,B
XCH A,R3
MOV B,#100
MUL AB
ADD A,R3
MOV R3,A
JNC HB21
INC B
HB21: MOV A,B 将整数部分转换成BCD码。
MOV B,#10
DIV AB
SWAP A
ORL A,B
RET
BTFL: DB 41H,0ECH,1EH 1.0000E-19
DB 45H,93H,93H 1.0000E-18
DB 48H,0B8H,78H 1.0000E-17
DB 4BH,0E6H,96H 1.0000E-16
DB 4FH,90H,1DH 1.0000E-15
DB 52H,0B4H,25H 1.0000E-14
DB 55H,0E1H,2EH 1.0000E-13
DB 59H,8CH,0BDH 1.0000E-12
DB 5CH,0AFH,0ECH 1.0000E-11
DB 5FH,0DBH,0E7H 1.0000E-10
DB 63H,89H,70H 1.0000E-9
DB 66H,0ABH,0CCH 1.0000E-8
DB 69H,0D6H,0C0H 1.0000E-7
BFLN: DB 6DH,86H,38H 1.0000E-6
DB 70H,0A7H,0C6H 1.0000E-5
DB 73H,0D1H,0B7H 1.0000E-4
DB 77H,83H,12H 1.0000E-3
DB 7AH,0A3H,0D7H 1.0000E-2
DB 7DH,0CCH,0CDH 1.0000E-1
BFL0: DB 1,80H,00H 1.0000
DB 4,0A0H,00H ;1.0000E1
DB 7,0C8H,00H 1.0000E2
DB 0AH,0FAH,00H 1.0000E3
DB 0EH,9CH,40H 1.0000E4
DB 11H,0C3H,50H 1.0000E5
DB 14H,0F4H,24H 1.0000E6
DB 18H,98H,97H 1.0000E7
DB 1BH,0BEH,0BCH 1.0000E8
DB 1EH,0EEH,6BH 1.0000E9
DB 22H,95H,03H 1.0000E10
DB 25H,0BAH,44H 1.0000E11
DB 28H,0E8H,0D5H 1.0000E12
DB 2CH,91H,85H 1.0000E13
DB 2FH,0B5H,0E6H 1.0000E14
DB 32H,0E3H,60H 1.0000E15
DB 36H,8EH,1CH 1.0000E16
DB 39H,31H,0A3H 1.0000E17
DB 3CH,0DEH,0BH 1.0000E18
DB 40H,8AH,0C7H 1.0000E19
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)