什么是增量式PID算法?

什么是增量式PID算法?,第1张

1,PID增量式算法:是PID控制算法的一种,有滤波的选择,系统的动态过程加速的功能。

(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


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

原文地址: https://outofmemory.cn/yw/12383552.html

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

发表评论

登录后才能评论

评论列表(0条)

保存