|
;;;;;;;;;;;;;;
;; By 朱葛峻
;;;;;;;;;;;;;;
.386P
IOY0 EQU 3000H
IOY1 EQU 3040H
IOY2 EQU 3080H
IOY3 EQU 30C0H
DATAS SEGMENT use16
__Show_End_ DB 13,10,13,10,13,10,13,10,13,10,13,10,'Mission Accomplished',13,10,'$'
;;;;;;;;;;;;;;
;;显示
;;;;;;;;;;;;;;
;ID参数显示段
__Show_ DB 'P: '
P_Para DB '00000'
DB 13,10,'I: '
I_Para DB '00000'
DB 13,10,'D: '
D_Para DB '00000'
DB 13,10,13,10
DB 'Give Speed: '
Num_Give_speed DB '10000'
DB 13,10
DB 'Current Speed: '
Num_Cur_speed DB '10000'
DB 13,10,'$'
;;;;;;;;;;;;;;
;;PID
;;;;;;;;;;;;;;
;三次数值
in_e_0 DW 0 ; 偏差输入
in_e_1 DW 0
in_e_2 DW 0
;PID系数
KP DB 5 ; 比例
KI DB 5 ; 积分
KD DB 5 ; 微分
;归一化参数
A0 DB 0 ;
A1 DB 0 ;
A2 DB 0 ;
;最后一次数值
Last_Var DW 0 ; 正负判断最高位
;;;;;;;;;;;;;;
;;控制变量
;;;;;;;;;;;;;;
;编码器返回值
SPEED_READ DW 0 ; 编码器返回值
;给定速度
SPEED_Give DW 0 ; 给定速度
; __TEST DW 0
;;;;;;;;;;;;;;
;;硬件控制
;;;;;;;;;;;;;;
;; 32 bits I/O
_32_IO_ DW IOY3
;; 读取类型包括:编码器返回数值
;; 写出类型包括,电机使能信号
;; OE RD
;; 锁存: 0 1 B 01B 1H
;; 清零: 0 0 B 00B 0H
;; 计数: 1 1 B 11B 3H
;;;;;;;;;;;;;;
;; 8254控制
;;;;;;;;;;;;;;
PC_8254_PIT_ DW 40H
PC_8254_Mode_ DW 43H
PC_Timer_Num DW 0FFFFH
__Num_Counter_Judge_ DW 0
_8254_ DW IOY2
_8254_Pcounter_ DW IOY2+00H*4 ;8254计数器0端口地址
_8254_PWM_Timer_ DW IOY2+01H*4 ;8254计数器1端口地址
_8254_PWM_Pluse_ DW IOY2+02H*4 ;8254计数器2端口地址
_8254_MODE_ DW IOY2+03H*4 ;8254控制寄存器端口地址
_Inter_Restart DW 0020H
PIT_CS_BAK_ DW 0 ; 存储当前CS
PIT_IP_BAK_ DW 0 ; 存储当前IP
PIT_IM_BAK_ DB 0 ; 存储当前flags
UART_Far DW IOY1 ;8251串口
UART_DATA DW IOY0+00H*4 ;8251数据寄存器
UART_MODE DW IOY0+01H*4 ;8251方式控制寄存器
CodeSeg_end DB 0 ;程序完成标志
CodeSeg_UnEnd_show DB 13,10,'Code Undone,Timer is not enough.','$'
;UART
;ADC连续给定
;按键给定 by IO32
DATAS ENDS
STACKS SEGMENT
DB 512 dup (0)
STACKS ENDS
CODES SEGMENT use16
ASSUME CS:CODES,DSATAS,SS:STACKS
START:
mov ax,0000H ; 引入中断向量表
mov es,ax
mov ax,stacks
mov ss,ax
MOV AX,DATAS
MOV DS,AX
CLI
;;;;;;;;;;;;;;;;;;;;;;;;
;; 中断向量存储
;;;;;;;;;;;;;;;;;;;;;;;;
mov ax,0000H
mov es,ax
mov di,_Inter_Restart
mov ax,es:[di]
mov PIT_IP_BAK_,ax
add di,2
mov ax,es:[di]
mov PIT_CS_BAK_,ax
in al,21H
mov PIT_IM_BAK_,al
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 周期中断设置
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov di,_Inter_Restart
mov ax,offset __PIT_Check_Bak_
mov es:[di],ax
add di,2
mov ax,SEG __PIT_Check_Bak_
mov es:[di],ax
mov al,PIT_IM_BAK_
and al,7FH
out 21H,al
mov ax,0
mov bx,0
mov cx,0
mov dx,0
;;;;;;;;;;;;;;;;;;;;;;;;
;; 更改PC8254
;;;;;;;;;;;;;;;;;;;;;;;;
mov dx,PC_8254_Mode_
mov al,36H
out dx,al
mov dx,PC_8254_PIT_
mov al,0FFH
out dx,al
mov al,011H
out dx,al
;;;;;;;;;;;;;;;;;;;;;;;;
;; 参数归一
;;;;;;;;;;;;;;;;;;;;;;;;
;; A0 = P + I + D
mov al,KP
add al,KI
add al,KD
mov A0,al
;; - A1 = P + 2 * D
mov al,KP
add al,KD
add al,KD
mov A1,al ; movsx
;; A2 = D
mov al,KD
mov A2,al
;;;;;;;;;;;;;;;;;;;;;;;;
;; PWM生成器初始化
;;;;;;;;;;;;;;;;;;;;;;;;
call __PWM_10kGen_ ; 10k 时钟信号
mov ax,0
call __10k_PWM_PluseGen_
;;;;;;;;;;;;;;;;;;;;;;;;
;; 编码器计数初始化
;;;;;;;;;;;;;;;;;;;;;;;;
mov dx,_8254_MODE_
mov al,00110000B
out dx,al
mov dx,_8254_Pcounter_
mov al,0FFH
out dx,al
mov al,0FFH
out dx,al
;;;;;;;;;;;;;;;;;;;;;;;;
;; UART初始化
;;;;;;;;;;;;;;;;;;;;;;;;
STI
__PIT_Cur_:
;;;;;;;;;;;;;;;;;;;;;;;;
;; 显示数据
;;;;;;;;;;;;;;;;;;;;;;;;
mov ax,0
mov bx,0
mov cx,0
mov dx,0
mov dx,offset P_Para
mov al,KP
call __five_dec_savseg_
mov dx,offset I_Para
mov al,KI
call __five_dec_savseg_
mov dx,offset D_Para
mov al,KD
call __five_dec_savseg_
mov dx,offset Num_Give_speed
mov ax,SPEED_Give
call __five_dec_savseg_
mov dx,offset Num_Cur_speed
mov ax,SPEED_READ
call __five_dec_savseg_
MOV DX,OFFSET __Show_
MOV AH,9
INT 21H
mov ah,2
mov bh,0
mov dh,0
mov dl,0
int 10H
;; 按键连续给定
mov ah,1
int 16H
jnz __Quit
jmp __PIT_Cur_
__Quit:
MOV DX,OFFSET __Show_End_
MOV AH,9
INT 21H
CLI
;;;;;;;;;;;;;;;;;;;;;;;;
;; 中断向量还原
;;;;;;;;;;;;;;;;;;;;;;;;
mov ax,0000H
mov es,ax
mov di,_Inter_Restart
mov ax,PIT_IP_BAK_
mov es:[di],ax
add di,2
mov ax,PIT_CS_BAK_
mov es:[di],ax
mov al,PIT_IM_BAK_
out 21H,al
MOV AH,4CH
INT 21H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PIT中断
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
__PIT_Check_Bak_ proc near
push ax
push bx
push cx
push dx
push si
;; 取脉冲计数
;;;;;;;;;;;;;;;;;;;;;;;;
;; 速度读取
;;;;;;;;;;;;;;;;;;;;;;;;
mov dx,_32_IO_
mov al,01H
out dx,al
mov al,00H
out dx,al
in ax,dx
mov SPEED_READ,ax
mov al,11H
out dx,al
mov al,20H
out 20H,al
;;;;;;;;;;;;;;;;;;;;;;;;
;; 速度修正
;;;;;;;;;;;;;;;;;;;;;;;;
mov ax,SPEED_READ ; 实际速度
mov bx,SPEED_Give ; 给定速度
sub bx,ax ; 得出偏差 bx
call __push_pid_para_
call __pid_GetPluse_ ; 需要修改
;; 测试用代码
;;;;;;;;;;;;;;;;;;;;;;;;
;; 远程监控 by UART
;;;;;;;;;;;;;;;;;;;;;;;;
pop si
pop dx
pop cx
pop bx
pop ax
iret
__PIT_Check_Bak_ endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 取负值
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 输入参数:ax
__Gen_b0Num_ proc near
not ax
add ax,1
ret
__Gen_b0Num_ endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 负值解码
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 输入参数:ax
__Gen_MoNum_ proc near
; mov ax,1000
; call __Gen_b0Num_
sub ax,1
not ax
; call __show_Reg_Word_
ret
__Gen_MoNum_ endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PWM 生成器 时钟信号10k
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 引入频率来自CPLD,1Mhz
;; 无输入输出 分频:100
__PWM_10kGen_ proc near
; 信号频率
push ax
push dx
mov dx,_8254_MODE_
mov al,01010100B ; 配置方式二,比率发生器 ; 产生固定的频率周期
out dx,al
mov dx,_8254_PWM_Timer_
mov al,100
out dx,al
pop dx
pop ax
ret
__PWM_10kGen_ endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PWM 生成器 脉宽调制
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; CLK来自CPLD 10000
;; 输入信号为 ax , 10000 数
;; 除去初始化不单独使用
__10k_PWM_PluseGen_ proc near
; 计算分频数值
push ax
push dx
push bx
mov bx,0
mov dx,0
mov bh,ah
mov bl,al
mov dx,_8254_MODE_
mov al,10110010B ; 配置方式一, PWM生成器
out dx,al
mov dx,_8254_PWM_Pluse_
mov al,bl
out dx,al
mov al,bh
out dx,al
pop bx
pop dx
pop ax
ret
__10k_PWM_PluseGen_ endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PID程序段
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 引入参数:bx
__push_pid_para_ proc near
push bx
push bx
mov Last_Var,bx
mov bx,in_e_0
push bx
mov bx,in_e_1
mov in_e_2,bx
pop bx
mov in_e_1,bx
pop bx
mov in_e_0,bx
pop bx
ret
__push_pid_para_ endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PID程序段
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 引入参数:无
;; 输出参数:ax
__pid_GetPluse_ proc near
push dx
push bx
mov bh,0
mov bl,A0
mov ax,in_e_0
call __signed16_mul_
push ax ; 压入A0相关数据
mov bh,0
mov bl,A1
mov ax,in_e_1
call __signed16_mul_
not ax
add ax,1
push ax ; 压入A1相关数据
mov bh,0
mov bl,A2
mov ax,in_e_2
call __signed16_mul_
push ax ; 压入A2相关数据
mov ax,0
mov bx,0
pop ax
pop bx
add ax,bx
pop bx
add ax,bx
mov bx,ax
and bx,08000H
cmp bx,0
jz __pid_GetPluse_Zheng_ ; 正数判定
call __Gen_MoNum_
push ax
mov dx,_32_IO_
mov ax,1
out dx,ax
jmp __pid_GetPluse_Out_Pluse
__pid_GetPluse_Zheng_:
push ax
mov dx,_32_IO_
mov ax,0
out dx,ax
__pid_GetPluse_Out_Pluse:
pop ax
call __10k_PWM_PluseGen_
pop bx
pop dx
ret
__pid_GetPluse_ endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 有符号数相乘
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 输入ax,bx
__signed16_mul_ proc near
push dx
push ax
push bx
mov dx,0
and ax,08000H
and bx,08000H
shr ax,15
shr bx,15
mov dx,bx
add ax,dx
cmp ax,1
jnz __signed16_mul_fu_ ; 不相等
mov dx,1 ; 负数
jmp __signed16_mul_mul_
__signed16_mul_fu_:
mov dx,0 ; 正数
__signed16_mul_mul_:
cmp bx,0 ; 正数
pop bx
jz __signed16_MoBx_
not bx
add bx,1
__signed16_MoBx_:
cmp ax,0 ; 正数
pop ax
jz __signed16_MoAx_
not ax
add ax,1
__signed16_MoAx_:
mul bx
cmp dx,0 ; 正数
jz __signed16_Last_
call __Gen_b0Num_
__signed16_Last_:
pop dx
ret
__signed16_mul_ endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 功能函数段:显示:数显范围 0 ~ 65535
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 输入参数为 ax
;; 输出参数保证不变
__five_dec_show_ proc near
push dx
push bx
push ax
mov dx,0
mov bx,10000
; 压入实参
push ax
div bx
; 得出万位
pop bx ; 弹出原始数据
push ax ; 压入万位
mov dx,10000
mul dx
; 得出X0000
sub bx,ax ; 除去万位
push bx ; 压入0XXXX
mov ax,bx ; 置入0XXXX
mov bx,1000
div bx
pop bx ; 弹出数据
push ax ; 压入千位
mov dx,1000
mul dx
sub bx,ax ; 除去千位
push bx ; 压入XXX
mov ax,bx
mov bx,100
div bx
pop bx ; 弹出数据
push ax ; 压入百位
mov dx,100
mul dx
sub bx,ax ; 得出数据 0XX
mov ax,bx
mov dl,10
div dl
push ax
and ax,00FFH ; 保留十位
pop bx ; 弹出数据
push ax ; 压入十位
and bx,0FF00H
mov al,bh
push ax ; 压入个位
;此处需要弹出五位
pop ax
mov dl,al
pop ax
mov dh,al
pop ax
mov bl,al
pop ax
mov bh,al
pop ax
;; 万 千 百 十 壹
;; al bh bl dh dl
call __show_Dec_
mov al,bh
call __show_Dec_
mov al,bl
call __show_Dec_
mov al,dh
call __show_Dec_
mov al,dl
call __show_Dec_
pop ax
pop bx
pop dx
ret
__five_dec_show_ endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 功能函数段:转存字符串五位
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 输入参数为 ax - 数字
;; 输入参数为 dx - 字符串地址
;; 输出参数保证不变
__five_dec_savseg_ proc near
push dx
push cx
push bx
push ax
push si
push dx
mov dx,0
mov bx,10000
; 压入实参
push ax
div bx
; 得出万位
pop bx ; 弹出原始数据
push ax ; 压入万位
mov dx,10000
mul dx
; 得出X0000
sub bx,ax ; 除去万位
push bx ; 压入0XXXX
mov ax,bx ; 置入0XXXX
mov bx,1000
div bx
pop bx ; 弹出数据
push ax ; 压入千位
mov dx,1000
mul dx
sub bx,ax ; 除去千位
push bx ; 压入XXX
mov ax,bx
mov bx,100
div bx
pop bx ; 弹出数据
push ax ; 压入百位
mov dx,100
mul dx
sub bx,ax ; 得出数据 0XX
mov ax,bx
mov dl,10
div dl
push ax
and ax,00FFH ; 保留十位
pop bx ; 弹出数据
push ax ; 压入十位
and bx,0FF00H
mov al,bh
push ax ; 压入个位
;此处需要弹出五位
pop ax
mov cl,al
pop ax
mov ch,al
pop ax
mov dl,al
pop ax
mov dh,al
pop ax
;; 万 千 百 十 壹
;; al dh dl ch cl
pop bx
mov si,0
cmp al,0
jne __five_dec_savseg_wan_
cmp dh,0
jne __five_dec_savseg_qian_
cmp dl,0
jne __five_dec_savseg_bai_
cmp ch,0
jne __five_dec_savseg_shi_
;cmp cl,0
jmp __five_dec_savseg_yi_
__five_dec_savseg_wan_:
mov DS:[bx],al
mov ax,bx
call __seg_num2charBin_
add bx,1
add si,1
__five_dec_savseg_qian_:
mov DS:[bx],dh
mov ax,bx
call __seg_num2charBin_
add bx,1
add si,1
__five_dec_savseg_bai_:
mov DS:[bx],dl
mov ax,bx
call __seg_num2charBin_
add bx,1
add si,1
__five_dec_savseg_shi_:
mov DS:[bx],ch
mov ax,bx
call __seg_num2charBin_
add bx,1
add si,1
__five_dec_savseg_yi_:
mov DS:[bx],cl
mov ax,bx
call __seg_num2charBin_
add bx,1
add si,1
__five_dec_judge_null_:
cmp si,5
jb __five_dec_show_null_
jnb __five_dec_show_end_
__five_dec_show_null_:
mov al,32
mov DS:[bx],al
add si,1
add bx,1
jmp __five_dec_judge_null_
__five_dec_show_end_:
pop si
pop ax
pop bx
pop cx
pop dx
ret
__five_dec_savseg_ endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;功能函数段:ByteR显示:数显范围 0 ~ 255
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;传入寄存器为AX,要求必须小于Byte
;;传出寄存器为AX,传出数据为原始数据,其余寄存器不变
;;要求:必须>100,或者是若<100,则0XX(以后更新)
__ByteR_show_ PROC near
push bx
mov bx,0
push ax
push ax ; 压入原始数据
mov bl,100
div bl
; al 为 百位数
pop bx ; 弹出原始数据
and ax,00FFH
push ax ; 压入百位数
mov bh,100
mul bh
sub bl,al ; 得出2位十进制数据 => bl
mov al,bl
mov bl,10
div bl
pop bx ; 弹出百位数
mov bh,al ; 十位数压入 bh
mov al,bl ; 百位数
call __show_Dec_
mov al,bh
call __show_Dec_
mov al,ah
call __show_Dec_
pop ax
pop bx
RET
__ByteR_show_ ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;功能函数段:显示0 ~ 9
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;传入寄存器为al
__show_Dec_ PROC near
push dx
ADD AL,30H
PUSH BX
PUSH AX
mov dl,al
MOV AH,02H
int 21H
POP AX
POP BX
pop dx
RET
__show_Dec_ ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;功能函数段:显示0 ~ F
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;传入寄存器为al
;;传出数据保证不变
__show_Bin_ PROC near
push dx
push ax
push bx
and al,0FH
cmp al,10
jnb __show_Bin_change_AF
add al,'0'
jmp __show_Bin_show
__show_Bin_change_AF:
sub al,10
add al,'A'
__show_Bin_show:
mov ah,02H
mov dl,al
int 21H
pop bx
pop ax
pop dx
RET
__show_Bin_ ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;功能函数段:显示寄存器Hex
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;传入寄存器为al
;;传出保持不变
__show_Reg_Byte_ Proc near
push ax
push bx
push ax
and al,0F0H
mov cl,4
shr al,cl
call __show_Bin_
pop ax
and al,0FH
call __show_Bin_
pop bx
pop ax
ret
__show_Reg_Byte_ Endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;功能函数段:显示寄存器Hex
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;传入寄存器为ax
;;传出保持不变
__show_Reg_Word_ Proc near
push ax
push bx
push ax
mov al,ah
call __show_Reg_Byte_
pop ax
call __show_Reg_Byte_
pop bx
pop ax
ret
__show_Reg_Word_ Endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;功能函数段:改变段中数据
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;传入寄存器为 ax - 地址
;;传出数据保证不变
__seg_num2charBin_ PROC near
push ax
push bx
mov bx,ax
mov al,DS:[bx]
and al,0FH
cmp al,10
jnb ___seg_num2charBin_change_AF
add al,'0'
jmp ___seg_num2charBin_show
___seg_num2charBin_change_AF:
sub al,10
add al,'A'
___seg_num2charBin_show:
mov DS:[bx],al
pop bx
pop ax
RET
__seg_num2charBin_ ENDP
CODES ENDS
END START
|
评分
-
1
查看全部评分
-
|