D8251 EQU 8000H ;8251数据寄存器
C8251 EQU 8002H ;8251控制状态寄存器
CSAD1_0 EQU 80H ;软件示波器通道1
CSAD2_7 EQU 00A7H ;实验用AD,通道7,双极性接法-5V到5V
CS0832 EQU 00H ;DA0832
Ts EQU 03H ;采样周期=Ts*5ms,默认为15毫秒
Kp EQU 60 ;比例的100倍,精度为小数点后两位
Ti EQU 100 ;积分时间常数
Td EQU 30 ;微分时间常数
DATA SEGMENT ;数据段为空,不可定义数据段
DATA ENDS ;变量和常数请放在程序段或段地址8500H
STACK SEGMENT ;堆栈段为空,不可定义堆栈段
STACK ENDS ;堆栈监控程序已经设置好
CODE SEGMENT
ASSUME CS:CODE
START: ;代码段开始
MOV AX,8100H
MOV DS,AX ;数据在代码段内
MOV AX,7000H ;ES寻址8251
MOV ES,AX
mov dx, 0020h
mov al, 13h ;ICW1,边缘触发,一片8259
out dx, al
CALL DELAY2
mov dx, 0021h ;ICW2,IR0-IR7,08H-0FH
mov al, 08h ;注意8253定时器0接到8259的IR0
out dx, al ;中断号为8,中断矢量为32-35,即20H-21H放PC,22H-23H放CS
CALL DELAY2
mov dx, 0021h ;ICW4,缓冲方式
mov al, 0Fh
out dx, al
CALL DELAY2
mov dx, 0021h ;OCW1,开8253,timer0中断,屏蔽其他
mov al, 0FEH
out dx, al
CALL DELAY2
mov dx, 0020h ;OCW2,普通中断结束命令
mov al, 20h
out dx, al
mov dx, 0043H
mov al, 36H ;8253,mode3,timer0,先写低8位再写高8位,方波发生器
out dx, al
mov dx, 0040H
mov al, 000H ;低八位
out dx, al
mov al, 018H ;高八位
out dx, al ;8253,timer0,1800h,5ms
xor ax,ax
mov ds,ax ;中断向量的段地址为0000H
mov si, 0020H ;15号中断向量的PC
LEA AX,T0_INTERRUPT ;取中断服务子程序的有效地址
mov [si], ax
mov si, 0022H ;15号中断向量的CS
mov ax, 8100h ;中断服务子程序的段地址
mov [si], ax
mov ds,ax ;恢复数据段地址
MOV AX,Ts
MOV BX,Kp
IMUL BX
MOV BX,05H
IMUL BX
MOV BX,Ti
XOR DX,DX
DIV BX ;计算Ki=Kp*(Ts*5)/Ti
MOV WORD PTR DS:[Ki],AX ;其中Kp是比例系数的100倍,Ts的单位是5ms,
MOV AX,Td
MOV BX,Kp
IMUL BX
MOV BX,Ts
XOR DX,DX
DIV BX
MOV BX,5
XOR DX,DX
DIV BX
MOV WORD PTR DS:[Kd],AX ;计算Kd=Kp*Td/(Ts*5)
STI
WAIT_HERE:
JMP WAIT_HERE
T0_INTERRUPT: ;中断服务子程序
CLI ;关中断
DEC BYTE PTR DS:[COUNT]
JNZ L3
MOV BYTE PTR DS:[COUNT],Ts
CALL PID ;采样周期到,进行PID控制
L3:
MOV DX, CSAD1_0 ;写虚拟示波器CH1
OUT DX, AL
CALL DELAY2
IN AL, DX ;读虚拟示波器CH1
MOV ES:[D8251],AL ;回送数据
W_TXREADY:
MOV AL,ES:[C8251]
AND AL,01H
JZ W_TXREADY ;等待8251发送完成
INC DX
OUT DX, AL ;写虚拟示波器CH2
CALL DELAY2
IN AL, DX ;读虚拟示波器CH2
MOV ES:[D8251],AL ;回送数据
IRET
DELAY2:
MOV CX,64h ;延时子程序大于AD0809的转换时间100us
L2: LOOP L2
RET
PID:
MOV DX,CSAD2_7
OUT DX,AL
CALL DELAY2
IN AL,DX ;采样偏差e(k)
XOR AH,AH
ADD AX,0FF80H ;双极性接法,相当于SUB AX,80H
MOV WORD PTR DS:[E0],AX ;保存e(k)
ADD AX,WORD PTR DS:[ESUM] ;累加e(j)
MOV WORD PTR DS:[ESUM],AX
IMUL WORD PTR DS:[Ki] ;Ki*SUM(e(J))
PUSH AX
MOV AX,WORD PTR DS:[E0]
MOV BX,Kp
IMUL BX ;Kp*e(k)
PUSH AX
MOV AX,WORD PTR DS:[E0] ;Kd*[e(k)-e(k-1)]
SUB AX,WORD PTR DS:[E_1]
IMUL WORD PTR DS:[Kd]
POP DX
ADD AX,DX
POP DX
ADD AX,DX ;相加P、I、D
MOV BX,64H ;刚才Kp是比例的100倍,现在除以100
CWD
IDIV BX
ADD AX,80H ;双极性接法
CMP AX,0FFH
JLE L4
MOV AX,0FFH ;抗积分饱和
L4:
CMP AX,00H
JGE L5
XOR AX,AX ;抗积分饱和
L5:
XOR DX,DX
OUT DX,AL ;输出控制量
MOV AX,WORD PTR DS:[E0] ;更新e(k-1)
MOV WORD PTR DS:[E_1],AX
RET
COUNT: DB Ts ;临时计数
ESUM: DW 0 ;累加误差
Ki: DW 0
Kd: DW 0
E0: DW 0 ;e(k)
E_1: DW 0 ;e(k-1)
CODE ENDS
END START
在这个程序的基础上修改,设定一个值E,在取得采样偏差e(k)后取e(k)绝对值与E相比较,如e(k)≤E则继续调用PID部分进行PID控制,如e(k)>E,则改用PD控制(PD控制就是PID部分中去除Ki*SUM(e(J))这个部分)。
CPU是8088,寄存器初始化是SP=0300H CS=8000H DS=8000H SS=8000H ES=8000H IP=FFF0H FL=0000H
[此贴子已经被作者于2007-4-27 12:14:16编辑过]