汇编语言实现PID运算

更新时间:2023-11-23 13:07:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

//汇编语言实现PID运算,一阶二阶系统控制(含注释) //---------------------------------堆栈段--------------------------------- STACKS SEGMENT STACK

DW 128 DUP(?) //注意这里只有128个字节 STACKS ENDS

//---------------------------------数据段--------------------------------- DATAS SEGMENT //1.乘数运算数据存储区

MUL1 DW ? //存放被乘数 MUL2 DW ? //存放乘数

SHIFTTIME1 DB ? //存放 乘积需要向左移位的次数(若结果按照被乘数的小数位,此值大小为乘数小数位数)

PRODUCT DD ? //存放最终乘积 DIV1 DW ? //存放被除数 DIV2 DW ? //存放除数

SHIFTTIME2 DB ? //存放 商和余数需要向右移位的次数(此值大小为除数小数位数)

QUOTIENT DW ? //存放商(包含后四位的小数) REMAINDER DW ? //存放余数

DIV1DOT DW ? //小数部分移位后的值作为被除数,暂存值 QUOTIENTDOT DW ? //存放小数部分相除的商,暂存值

REMAINDERDOT DW ? //存放小数部分相除的余数,暂存值

ERROR2 DB 'DIV2=0,ERROR!',0AH,'$' //除0错误 SQUARE_TIME DW ? //开平方迭代次数

SQUARE1 DW ? //需要进行开方运算的变量

SHIFTTIME3 DB 0 //开方运算右移次数,为被开方数小数位数值的一半

SQUARE2 DW ? //开方运算的值

DISPLAYWORD DW ? //用于显示的字,做测试用 //取绝对值存储区

ABSNUM DW ? //被转换的数

ABSVAL DW ? //数转换完成后的数 //2.PID参数数据区

PV DW ? //被控量,可以提前给定一个量 SV DW 0010H //设定值,需要给定 UN DW ? //控制量

UNOV DW ? //若UN值溢出,高字部分放在UN2中 EN1 DW ? //前一控制周期(n-1)时刻偏差量 EN2 DW ? //后一控制周期n时刻偏差量 ENPRO DD ? //存放比例项 ENINT1 DW ? //累积偏差量 ENINT DD ? //存放积分项 ENDIFF DD ? //用于微分项

ENSUM DD ? //存放三项的和 //(1)PID 1 理想微分PID控制开环阶跃响应

KP1 DW 00A0H //比例系数 TI1 DW 0020H //积分时间常数 TD1 DW 0020H //微分时间常数 KD1 DW 0H //微分系数 TC1 DW 0008H //控制周期 //(2)PID 2 实际微分PID控制开环阶跃响应

KP2 DW 0010H //比例系数 TI2 DW 0020H TD2 DW 0020H KD2 DW 0020H 8000H

TC2 DW 0008H UD0 DD ? UD1 DD ? UD DD ? //(3)PID 3 闭环系统PID控制开环阶跃

SV1 DW 0100H KP DW ? TI DW ? TD DW ? KD DW ? 8000H

TC3 DW 0008H INTSEP DB ? 认为0

INTSEPVAL DW ? //主调节器的PID参数

//一阶系统PID的参数

KP3 DW 0070H TI3 DW 0050H TD3 DW 0001H KD3 DW 0001H 8000H

UN1 DW ? EN11 DW ? UD11 DW ? //副调节器的PID参数

KP4 DW 0050H TI4 DW 0050H TD4 DW 0000H KD4 DW 0050H 8000H

//积分时间常数 //微分时间常数

//微分系数 KP和KD的乘积不超过 //控制周期

//微分项前一状态值Ud(n-1) //存放微分项后一状态值Ud(n) //存放暂时的值 //闭环串级系统的设定值 //比例系数 //积分时间常数 //微分时间常数

//微分系数 KP和KD的乘积不超过 //控制周期

//积分分离是否开启,为1则开,为0则关,默 //积分分离值 //比例系数 //积分时间常数 //微分时间常数

//微分系数 KP和KD的乘积不超过 //主控制器的输出

//主调节器存储上一时刻误差 //存放上一时刻微分输出 //比例系数 //积分时间常数 //微分时间常数

//微分系数 KP和KD的乘积不超过 UN2 DW ? //副控制器的输出

EN21 DW ? // //副调节器存储上一时刻误差 UD21 DW ? //存放上一时刻微分输出 //3.被控对象数据存储区

KG DW ? //控制对象的增益 TG DW ? //控制对象的时间常数 //(1)一阶惯性环节

K1 DW 0010H //增益,按照KP的小数格式,最后四位为小数位

T1 DW 0020H //惯性时间常数,最后四位为小数 PV2 DW ? //一阶系统的输出 TC DW 0008H //控制周期

//(2)二阶惯性环节,与一阶一起构成二阶系统,K1,T1,K2,T2四个系数

K2 DW 0010H //增益,按照KP的小数格式,最后四位为小数位

T2 DW 0020H //惯性时间常数,最后四位为小数 PV1 DW ? //二阶系统的输出

PV3 DW ? //二阶系统中两个一阶系统之间的输出值 DATAS ENDS

//----------------------------------代码段--------------------------------- CODES SEGMENT

ASSUME CS:CODES,DS:DATAS START: MOV AX,DATAS //初始化 MOV DS,AX

//PID1 理想微分开环阶跃响应

MOV CX,200 //PID计算次数 MOV PV,0000H //开环阶跃效应,第一周期输入为0,故PV设置为SV的值

CALL PIDINT LOOP1:

//MOV BX,WORD PTR ENPRO+2 //MOV DISPLAYWORD,BX //CALL DISPLAYS

//MOV BX,WORD PTR ENPRO //MOV DISPLAYWORD,BX //CALL DISPLAYS

//MOV AX,WORD PTR ENINT+2 //MOV DISPLAYWORD,AX //CALL DISPLAYS

//MOV AX,WORD PTR ENINT //MOV DISPLAYWORD,AX //CALL DISPLAYS

//MOV BX,WORD PTR ENDIFF+2

//MOV DISPLAYWORD,BX //CALL DISPLAYS

//MOV BX,WORD PTR ENDIFF //MOV DISPLAYWORD,BX //CALL DISPLAYS

//MOV INTSEP,0 //开启积分分离 //MOV INTSEPVAL,0008H CALL PIDG1 MOV AX,PV2

MOV DISPLAYWORD,AX

CALL DISPLAYS //显示被控量PV的值 //CALL PIDG1 //MOV AX,PV2

//MOV DISPLAYWORD,AX //CALL DISPLAYS MOV DL,0AH MOV AH,02H INT 21H //CALL PID2

//MOV PV,0H //从第二个周期开始PV值设为0,用于阶跃响应

DEC CX JNZ LOOP1

//用于测试乘法部分

//MOV MUL1,1000H //MOV MUL2,0030H //MOV SHIFTTIME1,4 //CALL MULTIPLICATION

//MOV AX,WORD PTR PRODUCT //MOV BX,WORD PTR PRODUCT+2 //MOV DISPLAYWORD,BX //CALL DISPLAYS

//MOV DISPLAYWORD,AX //CALL DISPLAYS //用于测试除法部分

//MOV DIV1,0078H //为被除数和除数赋值 //MOV DIV2,0050H //MOV SHIFTTIME2,4 //CALL DIVISION

//MOV AX,TC1 //调用乘法,获得Td除以Tc乘以Kp //MOV DIV1,AX //MOV AX,TI1

//MOV DIV2,AX

//MOV SHIFTTIME2,4 //左移4位,按照Td的小数格式形成结果

//CALL DIVISION

//MOV AX,QUOTIENT

//MOV DISPLAYWORD,AX //查看商的值 //CALL DISPLAYS

//MOV AX,REMAINDER

//MOV DISPLAYWORD,AX //用于测试,查看余数的值 //CALL // MOV //MOV //MOV //MOV //MOV //CALL //MOV //MOV //MOV //MOV //CALL //MOV //MOV //MOV //MOV //MOV //CALL //MOV //MOV //CALL //测试开平方部分

//MOV //MOV //CALL //MOV //MOV //CALL //测试数值转换部分:

//MOV //MOV //CALL //MOV //MOV DISPLAYS

AX,TC1 //调用除法和乘法,获得Tc除以Ti乘以Kp DIV1,AX AX,TI1 DIV2,AX

SHIFTTIME2,4 DIVISION

AX,QUOTIENT //左移4位,按照Tc的小数格式形成结果 MUL2,AX MUL1,1000H SHIFTTIME1,4 MULTIPLICATION

AX,WORD PTR PRODUCT MUL1,AX AX,KP1 MUL2,AX

SHIFTTIME1,4 MULTIPLICATION

AX,WORD PTR PRODUCT DISPLAYWORD,AX DISPLAYS SQUARE_TIME,10 //迭代次数为100次 SQUARE1,14H //被开放数为19 SQUARE

AX,SQUARE2

DISPLAYWORD, AX DISPLAYS AX,8011H ABSNUM,AX ABSOLUTE AX,ABSVAL

DISPLAYWORD,AX

//各存储单元清0,为PID运算做准备 PIDINT PROC

MOV EN1,0 //初始误差置0 MOV EN2,0

MOV EN11,0 //串级控制误差清0 MOV EN21,0

MOV UN,0 //控制量清0

MOV UNOV,0 //控制量溢出位清0

MOV WORD PTR ENPRO,0 //比例项低字清0 MOV WORD PTR ENPRO+2,0 //比例项高字清0 MOV ENINT1,0 //误差累积清0

MOV WORD PTR ENINT,0 //积分项低字清0 MOV WORD PTR ENINT+2,0 //积分项高字清0 MOV WORD PTR ENDIFF,0 //微分项低字清0 MOV WORD PTR ENDIFF+2,0 //微分项高字清0 MOV WORD PTR ENSUM,0 //三项和低字清0 MOV WORD PTR ENSUM+2,0 //三项和高字清0

MOV WORD PTR UD0,0 //微分项前一状态清0,用于实际微分中

MOV WORD PTR UD0+2,0

MOV WORD PTR UD1,0 //微分项前一状态清0,用于实际微分中

MOV WORD PTR UD1+2,0

MOV PV1,0 //一阶系统控制量清0 MOV PV2,0 //二阶系统控制量清0 MOV PV3,0 MOV UN1,0

MOV UN2,0 //串级系统中的被控量清0 MOV INTSEP,0 //积分分离初始化为关闭状态 RET PIDINT ENDP

//-----------------------PID1计算子程序---------------------

//调用前请为设定值SV赋值,PID的计算结果存储在控制量PV当中,验证作业(1) PID1 PROC

PUSH AX PUSH BX PUSH CX //PID计算过程

MOV AX,TD1 //调用乘除法,获得Td除以Tc乘以Kp MOV DIV1,AX MOV AX,TC1 MOV DIV2,AX

MOV SHIFTTIME2,4 //左移4位,按照Td的小数格式形成结果

CALL DIVISION

MOV AX,QUOTIENT

MOV MUL1,AX //商作为被乘数 MOV AX,KP1 MOV MUL2,AX

MOV SHIFTTIME1,4 CALL MULTIPLICATION

MOV AX,WORD PTR PRODUCT //假定乘积不超过16位△ PUSH AX //Td除以Tc乘以Kp的结果压入堆栈

MOV MOV MOV MOV MOV CALL MOV MOV MOV MOV MOV CALL MOV PUSH //

MOV MOV SUB MOV MOV MOV 的小数格式显示

MOV MOV CALL MOV MOV MOV MOV ENPRO双字中

//-------------//MOV MOV 项过早溢出△

ADD AX,TC1 //调用除法和乘法,获得Tc除以Ti乘以Kp DIV1,AX AX,TI1 DIV2,AX

SHIFTTIME2,4 DIVISION

AX,QUOTIENT //TC除以TI的结果作为被乘数 MUL1,AX AX,KP1 MUL2,AX

SHIFTTIME1,4 MULTIPLICATION

AX,WORD PTR PRODUCT

AX //Tc除以Ti乘以Kp的结果压入堆栈 AX,SV //取设定值和控制量的值 BX,PV

AX,BX //获得设定值与控制量之间的偏差 EN2,AX //偏差赋给当前误差值EN2

MUL1,AX //利用当前误差EN2计算比例项

BX,KP1 //比例项计算开始,Kp作为乘数,结果按照En MUL2,BX

SHIFTTIME1,4

MULTIPLICATION //调用乘法,获得比例项 AX,WORD PTR PRODUCT+2 WORD PTR ENPRO+2,AX AX,WORD PTR PRODUCT

WORD PTR ENPRO,AX //比例项计算完成,结果存在AX,EN2 //积分项计算开始

AX,0030H //此处积分的误差项用一个小值代替,防止积分 ENINT1,AX //误差累积

MOV AX,ENINT1 // 误差累积作为第一个乘数 MOV MUL1,AX

POP AX //弹出Tc除以Ti的商作为乘数 MOV MUL2,AX

MOV SHIFTTIME1,4 CALL MULTIPLICATION

MOV AX,WORD PTR PRODUCT+2 MOV WORD PTR ENINT+2,AX MOV AX,WORD PTR PRODUCT

MOV ENINT双字中

MOV SUB MOV POP MOV MOV CALL MOV MOV MOV MOV ENDIFF双字中 //结尾工作 CLC

MOV 和积分

ADD MOV MOV ADC MOV CLC

MOV ADD MOV MOV ADC MOV 加

MOV MOV MOV WORD PTR ENINT,AX //积分项计算完成,结果存在 AX,EN2 //微分项计算开始 AX,EN1 //计算前后误差的差值 MUL1,AX

AX //弹出Td除以Tc的商作为乘数 MUL2,AX

SHIFTTIME1,4 MULTIPLICATION

AX,WORD PTR PRODUCT+2 WORD PTR ENDIFF+2,AX AX,WORD PTR PRODUCT

WORD PTR ENDIFF,AX //微分项计算完成,结果存在 AX,WORD PTR ENPRO //计算三项的和,首先是比例AX,WORD PTR ENINT

WORD PTR ENSUM,AX //低字的和放入低字 AX,WORD PTR ENPRO+2 AX,WORD PTR ENINT+2

WORD PTR ENSUM+2,AX //高字的和放入高字 AX,WORD PTR ENSUM //加入微分项 AX,WORD PTR ENDIFF

WORD PTR ENSUM,AX //低字的和放入低字 AX,WORD PTR ENSUM+2 AX,WORD PTR ENDIFF+2

WORD PTR ENSUM+2,AX //高字的和放入高字,三项相 AX,WORD PTR ENSUM+2 //UN溢出量赋值为UNOV UNOV,AX

DISPLAYWORD,AX

CALL DISPLAYS

MOV AX,WORD PTR ENSUM

MOV UN,AX //此处UN和PV相同,不含控制对象 MOV AX,EN2

MOV EN1,AX //当前误差覆盖上一次误差 MOV AX,UN

MOV DISPLAYWORD,AX CALL DISPLAYS //每两个数形成一个换行

MOV DL,0AH // 每次调用显示时生成换行 MOV AH,02H INT 21H

//MOV DISPLAYWORD,CX //有这两句就不死循环,没有就死循环

//CALL DISPLAYS //DEC CX

//JNZ LOOP_PID5 POP CX POP BX POP AX RET PID1 ENDP

//-----------------------PID2计算子程序--------------------- //调用前请为设定值SV赋值,PID2的计算结果存储在控制量PV当中,用来验证内容(2) PID2 PROC

PUSH AX //初始状态保存,压入堆栈 PUSH BX PUSH CX MOV AX,0

MOV WORD PTR UD,AX //每次调用PID2,暂存值UD清0

MOV WORD PTR UD+2,AX MOV AX,SV //设定值 SUB AX,PV //被控量 MOV EN2,AX

MOV BX,EN2 //获取n时刻的误差

SUB BX,EN1 //与(n-1)时刻的误差做差,误差增量存在BX中

MOV MUL1,BX //--------------此处为了演示,把误差值调小 //MOV MUL1,0100H

MOV AX,KP2 //与KP2相乘 MOV MUL2,AX

MOV SHIFTTIME1,4

CALL MULTIPLICATION

MOV AX,WORD PTR PRODUCT+2 MOV WORD PTR ENPRO+2,AX MOV AX,WORD PTR PRODUCT

MOV WORD PTR ENPRO,AX //比例项计算完成,结果存在ENPRO双字中

MOV AX,KP2 //计算微分项,首先计算KP乘以KD MOV MUL1,AX MOV AX,KD2 MOV MUL2,AX

MOV SHIFTTIME1,4 CALL MULTIPLICATION

MOV AX,WORD PTR PRODUCT //假定KP2和KD2的乘积不超过16位 △

MOV MUL1,BX //乘积再和误差增量做乘积 MOV MUL2,AX

MOV SHIFTTIME1,4 CALL MULTIPLICATION

MOV AX,WORD PTR PRODUCT+2 MOV WORD PTR UD+2,AX

MOV AX,WORD PTR PRODUCT

MOV WORD PTR UD,AX //微分第二项计算完成,结果暂时保存在UD双字中

// 此时的UD只在第二个周期时有数值,其余周期为0 CLC //与第一项UD0相加 MOV AX,WORD PTR UD

ADD AX,WORD PTR UD0 //低字部分相加

MOV WORD PTR UD,AX //存放在暂存值WORD PTR UD中

MOV AX,WORD PTR UD+2 //高字部分相加 ADC AX,WORD PTR UD0+2

MOV WORD PTR UD+2,AX //暂存在双字UD中,至此,微分的乘数计算完成

//此时UD已经和UD0相加结合起来,从第二个周期开始的前若干个周期有数值

MOV AX,KD2 //计算括号外的乘数值 MOV MUL1,AX MOV AX,TC2 MOV MUL2,AX

MOV SHIFTTIME1,4 CALL MULTIPLICATION

MOV AX,WORD PTR PRODUCT //KD2和TC2的乘积存放在AX中

ADD AX,TD2 //乘积加上TD2作为分母

MOV DIV2,AX // MOV AX,TD2

MOV DIV1,AX //TD2作为分子 MOV SHIFTTIME2,4 CALL DIVISION

MOV AX,QUOTIENT //商作为计算微分项的乘数 MOV MUL2,AX

MOV AX,WORD PTR UD //UD中的暂存值作为被乘数 MOV MUL1,AX

MOV SHIFTTIME1,4 CALL MULTIPLICATION

MOV AX,WORD PTR PRODUCT+2

MOV WORD PTR UD1+2,AX //微分项前项计算完成,存放在UD1双字中

MOV AX,WORD PTR PRODUCT MOV WORD PTR UD1,AX CLC

SUB AX,WORD PTR UD0 MOV WORD PTR ENDIFF,AX

MOV AX,WORD PTR UD1+2 SBB AX,WORD PTR UD0+2

MOV WORD PTR ENDIFF+2,AX //至此微分项计算完成

MOV AX,KP2

MOV MUL1,AX //开始计算积分项 MOV AX,TC2 MOV MUL2,AX

MOV SHIFTTIME1,4 CALL MULTIPLICATION

MOV AX,WORD PTR PRODUCT MOV DIV1,AX MOV AX,TI2 MOV DIV2,AX

MOV SHIFTTIME2,4 CALL DIVISION

MOV AX,QUOTIENT

MOV MUL2,AX //作为乘数 MOV AX,EN2 //-------------此处为了演示,把误差值改小 //MOV AX,0100H MOV MUL1,AX

MOV SHIFTTIME1,4 CALL MULTIPLICATION

MOV AX,WORD PTR PRODUCT+2 MOV WORD PTR ENINT+2,AX MOV AX,WORD PTR PRODUCT

MOV WORD PTR ENINT,AX //积分项计算完成 CLC //把三项相加 MOV AX,WORD PTR ENSUM ADD AX,WORD PTR ENPRO MOV BX,WORD PTR ENSUM+2

ADC BX,WORD PTR ENPRO+2 //比例项加入 CLC

ADD AX,WORD PTR ENDIFF

ADC BX,WORD PTR ENDIFF+2 //微分项加入 CLC

ADD AX,WORD PTR ENINT

ADC BX,WORD PTR ENINT+2 //微分项加入 MOV WORD PTR ENSUM,AX //结果保存

MOV UN,AX //若UN不溢出,即ENSUM+2存储的值为0,则只要输出UN即可 △

MOV UNOV,BX //溢出量保存在UNOV中 //把UN的结果显示到屏幕上 MOV AX,UNOV

MOV DISPLAYWORD,AX CALL DISPLAYS MOV AX,UN

MOV DISPLAYWORD,AX CALL DISPLAYS

MOV DL,0AH // 每次调用显示时生成换行 MOV AH,02H INT 21H

//结尾处进行变量的替换为下次计算做准备 MOV AX,WORD PTR UD1+2 MOV WORD PTR UD0+2,AX MOV AX,WORD PTR UD1

MOV WORD PTR UD0,AX //UD1取代上一时刻的UD0 MOV AX,EN2 // 误差替换 MOV EN1,AX

POP CX POP BX POP AX RET PID2 ENDP

//-----------------------PID3计算子程序--------------------- //真正在闭环系统中采用的PID控制算法

//为四个参数赋具体值,误差存储在EN2,EN1中

//调用前请为设定值SV和被控量PV赋值,PID3的计算结果存储在控制量PV当中,算法与PID2相同

//PID算法需要利用到的PV,SV,EN1,UD0,UN,引用PID时注意保存 PID3 PROC

PUSH AX //初始状态保存,压入堆栈 PUSH BX PUSH CX MOV AX,0

MOV 清0

MOV MOV SUB MOV MOV SUB 中

MOV MOV MOV MOV CALL MOV MOV MOV MOV ENPRO双字中

MOV MOV MOV MOV MOV CALL MOV 过16位

MOV MOV MOV CALL MOV MOV MOV MOV WORD PTR UD,AX //每次调用PID3,暂存值UD WORD PTR UD+2,AX AX,SV //设定值 AX,PV //被控量 EN2,AX

BX,EN2 //获取n时刻的误差

BX,EN1 //与(n-1)时刻的误差做差,误差增量存在BX MUL1,BX

AX,KP //与KP相乘 MUL2,AX

SHIFTTIME1,4 MULTIPLICATION

AX,WORD PTR PRODUCT+2 WORD PTR ENPRO+2,AX AX,WORD PTR PRODUCT

WORD PTR ENPRO,AX //比例项计算完成,结果存在 AX,KP //计算微分项,首先计算KP乘以KD MUL1,AX AX,KD MUL2,AX

SHIFTTIME1,4 MULTIPLICATION

AX,WORD PTR PRODUCT //假定KP和KD的乘积不超 MUL1,BX //乘积再和误差增量做乘积 MUL2,AX

SHIFTTIME1,4 MULTIPLICATION

AX,WORD PTR PRODUCT+2 WORD PTR UD+2,AX

AX,WORD PTR PRODUCT

WORD PTR UD,AX //微分第二项计算完成,结果暂

时保存在UD双字中

// 此时的UD只在第二个周期时有数值,其余周期为0 CLC //与第一项UD0相加 MOV AX,WORD PTR UD

ADD AX,WORD PTR UD0 //低字部分相加

MOV WORD PTR UD,AX //存放在暂存值WORD PTR UD中

MOV AX,WORD PTR UD+2 //高字部分相加 ADC AX,WORD PTR UD0+2

MOV WORD PTR UD+2,AX //暂存在双字UD中,至此,微分的被乘数计算完成

//此时UD已经和UD0相加结合起来,从第二个周期开始的前若干个周期有数值

MOV AX,KD //计算括号外的乘数值 MOV MUL1,AX MOV AX,TC MOV MUL2,AX

MOV SHIFTTIME1,4 CALL MULTIPLICATION

MOV AX,WORD PTR PRODUCT //KD和TC的乘积存放在AX中

ADD AX,TD //乘积加上TD作为分母 MOV DIV2,AX // MOV AX,TD

MOV DIV1,AX //TD作为分子 MOV SHIFTTIME2,4 CALL DIVISION

MOV AX,QUOTIENT //商作为计算微分项的乘数 MOV MUL2,AX

MOV AX,WORD PTR UD //UD中的暂存值作为被乘数 MOV MUL1,AX

MOV SHIFTTIME1,4 CALL MULTIPLICATION

MOV AX,WORD PTR PRODUCT+2

MOV WORD PTR UD1+2,AX //微分项前项计算完成,存放在UD1双字中

MOV AX,WORD PTR PRODUCT MOV WORD PTR UD1,AX CLC

SUB AX,WORD PTR UD0 MOV WORD PTR ENDIFF,AX MOV AX,WORD PTR UD1+2 SBB AX,WORD PTR UD0+2

MOV WORD PTR ENDIFF+2,AX //至此微分项计算完成

MOV AX,KP

MOV MUL1,AX //开始计算积分项 MOV AX,TC MOV MUL2,AX

MOV SHIFTTIME1,4 CALL MULTIPLICATION

MOV AX,WORD PTR PRODUCT MOV DIV1,AX MOV AX,TI MOV MOV CALL MOV MOV MOV MOV MOV CALL MOV MOV MOV MOV CLC MOV 果对UN的累加

ADD MOV ADC CLC

ADD ADC CLC

MOV CMP 项

JZ MOV MOV MOV CMP 超过积分分离值

JBE JMP INTSEP1: ADD DIV2,AX

SHIFTTIME2,4 DIVISION

AX,QUOTIENT

MUL2,AX //作为乘数 AX,EN2 MUL1,AX

SHIFTTIME1,4 MULTIPLICATION

AX,WORD PTR PRODUCT+2 WORD PTR ENINT+2,AX AX,WORD PTR PRODUCT

WORD PTR ENINT,AX //积分项计算完成 //把三项相加

AX,WORD PTR ENSUM //对ENSUM累加,相同于结 AX,WORD PTR ENPRO BX,WORD PTR ENSUM+2

BX,WORD PTR ENPRO+2 //比例项加入 AX,WORD PTR ENDIFF

BX,WORD PTR ENDIFF+2 //微分项加入 CH,INTSEP

CH,0 //为0,说明没有启用积分分离,则需要加入积分INTSEP1 CX,EN2

ABSNUM,CX //对误差求绝对值 CX,ABSVAL

CX,INTSEPVAL //否则,开启积分分离,判断是否INTSEP1 //分离值大于等于误差时,需要PID控制 INTSEP2 //分离值小于误差时,则只用PD控制 AX,WORD PTR ENINT

ADC BX,WORD PTR ENINT+2 //微分项加入 INTSEP2: MOV WORD PTR ENSUM,AX //结果保存 MOV WORD PTR ENSUM+2,BX MOV UN,AX

MOV UNOV,BX //之前和PID2完全一样,把控制量结果存入UN和UNOV

//限幅环节

// AND BX,8000H //高位和0相与 // JZ LOOP_PID1

// MOV UN,-100 //不为0,说明输出为负数,此时限幅下限为-100 // JMP LOOP_PID2

// LOOP_PID1: MOV BX,UNOV //输出为正数的条件下继续比较 // CMP BX,0 //看高位是否有正值 // JZ LOOP_PID3

// MOV UN,0064H //高位字不为0说明结果高于上限,直接赋上限值100

// JMP LOOP_PID2

//AND AX,8000H //高位和0相与 //JZ LOOP_PID3 //MOV AX,0001H //MOV UN,AX //JMP LOOP_PID2

// LOOP_PID3: MOV AX,UN //正数,且只有低位字有数值的条件下继续比较

// CMP AX,0064H

// JB LOOP_PID2 //小于100时,UN赋值为该值, 不用改 // MOV UN,0064H

//和PID2算法一样,此处为下一控制周期计算做准备 LOOP_PID2: MOV AX,WORD PTR UD1+2 MOV WORD PTR UD0+2,AX MOV AX,WORD PTR UD1

MOV WORD PTR UD0,AX //UD1取代上一时刻的UD0 MOV AX,EN2 // 误差替换 MOV EN1,AX

POP CX //堆栈值弹出,恢复寄存器原来的值 POP BX POP AX RET PID3 ENDP

//-----------------------一阶闭环响应子程序----------------------- //设定值仍为SV的值 PIDG1 PROC

MOV AX,KP3 //为PID的参数赋值 MOV KP,AX MOV AX,KD3 MOV KD,AX MOV AX,TI3 MOV TI,AX MOV AX,TD3 MOV TD,AX

MOV AX,PV2 //此处的被控量为一阶系统的被控量PV2 MOV PV,AX

CALL PID3 //首先调用PID3算法

MOV AX,K1 //进入一阶系统自身的算法 MOV KG,AX //赋值 MOV AX,T1 MOV TG,AX

MOV AX,PV2 //把上次计算得到的PV2带入一阶系统 MOV PV,AX

CALL G1 //调用一阶惯性环节,得到新的PV MOV AX,PV

MOV PV2,AX //把输出值存在PV2中 //MOV DISPLAYWORD,AX

//CALL DISPLAYS //显示被控量PV的值

//MOV DL,0AH // 每次调用显示时生成换行 //MOV AH,02H //INT 21H RET PIDG1 ENDP

//----------------------串级控制子程序---------------------

//被控对象有两个,副调节器负责一阶系统,主调节器负责二阶系统 PIDCAS PROC

//进入主控制器的计算 MOV AX,PV1

MOV PV,AX //为PV和SV赋值,SV是整个系统的设定值 MOV AX,SV1 MOV SV,AX

MOV AX,KP3 //为副调节器参数赋值 MOV KP,AX MOV AX,TI3 MOV TI,AX MOV AX,TD3 MOV TD,AX MOV AX,KD3 MOV KD,AX

MOV AX,EN11 //把一阶系统上一时刻的误差带入PID

MOV EN1,AX MOV AX,UN1

MOV WORD PTR ENSUM,AX //上时刻的UN赋值给ENSUM,然后进行累加

MOV AX,UD11 //存储上次运行的微分项 MOV WORD PTR UD0,AX CALL PID3

MOV AX,WORD PTR UD0 //存储上次运行的微分项 MOV UD11,AX MOV AX,EN1

MOV EN11,AX //误差作为上一时刻的值保存 MOV AX,UN

MOV UN1,AX //获得控制量的值,存入UN1 //至此主控制器计算完成,得到UN1 //计算内环,也就是副调节器的值

MOV SV,AX //设定值为主调节器的输出UN1 MOV AX,PV2 //被控量为PV2 MOV PV,AX

MOV AX,KP4 //为副调节器参数赋值 MOV KP,AX MOV AX,TI4 MOV TI,AX MOV AX,TD4 MOV TD,AX MOV AX,KD4 MOV KD,AX

MOV AX,EN21 //把一阶系统上一时刻的误差带入PID MOV EN1,AX MOV AX,UN2

MOV WORD PTR ENSUM,AX //上时刻的UN赋值给ENSUM,然后进行累加

// PID算法需要保存的值有U(n-1)和e(n-1)和Ud(n-1) MOV AX,UD21 //存储上次运行的微分项 MOV WORD PTR UD0,AX CALL PID3

MOV AX,WORD PTR UD0 //存储上次运行的微分项 MOV UD21,AX MOV AX,EN1

MOV EN21,AX //误差作为上一时刻的值保存 MOV AX,UN

MOV UN2,AX //获得控制量的值,存入UN2 //一阶PID控制器完成,得到的结果存入UN2

MOV AX,K1 //进入一阶系统自身的算法 MOV KG,AX //赋值

MOV AX,T1 MOV TG,AX

MOV AX,PV2 //给PV赋上一时刻得到的值 MOV PV,AX

MOV AX,UN2 //给UN赋上一时刻得到的值 MOV UN,AX CALL G1 MOV AX,PV MOV PV2,AX

//一阶对象完成,进入二阶对象 MOV UN,AX

CALL G2 //调用G2时不需要为参数赋值,得到PV1 RET

//二阶系统输出为PV1 PIDCAS ENDP

//----------------------被控对象子程序---------------------- //一阶惯性系统G1

//使用时需要为KG和KT赋值,在K1,T1处更改即可

//输入为控制量UN,输出为被控量PV,通过差分运算获得二者的转换关系 //PV(n)={[(TG/TC)-1]×PV(n-1)+KG×UN}/(TG/TC)

//≈[(TG/TC)×PV(n-1)+KG×UN]/(TG/TC)≈PV(n-1)+k×UN,其中k=(KG×TC)/TG //需要保存好上时刻的PV值 G1 PROC

PUSH AX

MOV AX,KG //首先计算KG×TC MOV MUL1,AX MOV AX,TC MOV MUL2,AX

MOV SHIFTTIME1,4 CALL MULTIPLICATION

MOV AX,WORD PTR PRODUCT

MOV DIV1,AX //计算(KG×TC)/TG MOV AX,TG MOV DIV2,AX

MOV SHIFTTIME2,4 CALL DIVISION

MOV AX,QUOTIENT //得到商的值,存在AX中 MOV MUL2,AX //利用该商乘以UN,此处不知道UN是否溢出,是否考虑UN2△

MOV AX,UN //利用UN的值 MOV MUL1,AX

MOV SHIFTTIME1,4 CALL MULTIPLICATION

MOV AX,WORD PTR PRODUCT //第二项计算完成

ADD PV,AX //和上一时刻的PV值相加,得到的值存放在PV中

POP AX RET G1 ENDP //二阶惯性系统G2

//两个一阶系统的串联,构成二阶系统,系数有所不同

//调用时不需要在为系数赋值,在K1,T1,K2,T2处更改数值即可,计算需要赋UN的值 G2 PROC

PUSH AX

MOV AX,K1 //为KG和TG赋值 MOV KG,AX MOV AX,T1 MOV TG,AX MOV AX,PV3 MOV PV,AX CALL G1

MOV AX,PV //获得此时一阶系统的响应 MOV PV3,AX //保存PV的值给PV3 MOV UN,AX //第二个一阶系统 MOV AX,K2 //为KG和TG赋值 MOV KG,AX MOV AX,T2 MOV TG,AX MOV AX,PV1 MOV PV,AX

CALL G1 //调用一阶系统 MOV AX,PV

MOV PV1,AX //保存PV的值给PV1 //二阶系统计算完成,输出结果为PV1或PV POP AX RET G2 ENDP

//-----------------------显示字子程序----------------------- DISPLAYS PROC

PUSH CX //压入堆栈,保存各寄存器的值 PUSH BX

PUSH AX //调用AH=02的功能,改变了AX的值 //MOV DL,0AH // 每次调用显示时生成换行 //MOV AH,02H //INT 21H

MOV CL,4 //移位次数CL赋值为4,每4位显示一次 MOV BX,DISPLAYWORD //BX为要显示的字

MOV CH,4 //CH用作计数

LOOP_DISPLAY: ROL BX,CL //BX循环移位四次 MOV AX,BX //AX作为运算量 AND AX,0FH CMP AL,0AH

JB LOOP_DISPLAY1 //若小于10,则直接加30H即可转换为ASCII码

ADD AL,07H

LOOP_DISPLAY1: ADD AL,30H //转化为ASCII码 MOV DL,AL MOV AH,02H INT 21H DEC CH

JNZ LOOP_DISPLAY //不为0时,继续显示 POP AX POP BX POP CX RET DISPLAYS ENDP

//---------------------------------------------------------------------------- CODES ENDS

END START

MOV CH,4 //CH用作计数

LOOP_DISPLAY: ROL BX,CL //BX循环移位四次 MOV AX,BX //AX作为运算量 AND AX,0FH CMP AL,0AH

JB LOOP_DISPLAY1 //若小于10,则直接加30H即可转换为ASCII码

ADD AL,07H

LOOP_DISPLAY1: ADD AL,30H //转化为ASCII码 MOV DL,AL MOV AH,02H INT 21H DEC CH

JNZ LOOP_DISPLAY //不为0时,继续显示 POP AX POP BX POP CX RET DISPLAYS ENDP

//---------------------------------------------------------------------------- CODES ENDS

END START

本文来源:https://www.bwwdw.com/article/bqct.html

Top