⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pid.c

📁 51单片机使用汇编语言编制的PID算法程序
💻 C
字号:
;**********************************************************************
;最佳参数:(此参数仅适用本系统)
; 采样周期10MS时
; KP=AFH*2,KI=46H,KD=F9*8H
; 运算中以上参数全当小数处理
; 即实际参数为:KP=0.6836*2 =1.3672
; KI=0.2734
; KD=0.9727*8=7.7813
;HURGE
;200710251556
;
;*****************************定义变量存储区******************************
	PH     EQU 30H
	PM     EQU 31H
	PL     EQU 32H
	IH     EQU 33H
	IM     EQU 34H
	IL     EQU 35H
        DH     EQU 36H  
	DM     EQU 37H
	DL     EQU 38H
	KP     EQU 39H      ;P参数
	KI     EQU 3AH      ;I参数
	KD     EQU 3BH      ;D参数
	EK0    EQU 3CH
	EK1    EQU 3DH      
	PEKH   EQU 3EH
	OLDKEY EQU 3FH
	UK0H   EQU 40H
	UK0L   EQU 41H
	EI     EQU 42H
        PEKL   EQU 43H
        IEKH   EQU 44H
        IEKL   EQU 45H
        DEKH   EQU 46H
        DEKL   EQU 47H
        EKI    EQU 48H
        EK2    EQU 49H
        UK1H   EQU 4AH
        UK1L   EQU 4BH
;----------------------------------------------------------------------------
	ORG    0000H
  	AJMP   MAIN
	ORG    0003H		;外部中断0入口地址
	AJMP   AINT
	ORG    000BH	     ;定时器T0中断服务入口地址
	AJMP   T0INT
;*****************************************************-----------------------
;                              主程序  
;*****************************************************-----------------------
	ORG   100H
MAIN:	MOV   SP,#50H          ;初始化堆栈
	;初始化数据段
	MOV   PH,#07H   
	MOV   PM,#0H 
	MOV   PL,#0H
	MOV   IH,#02H
	MOV   IM,#08H
	MOV   IL,#0H
        MOV   DH,#09H
	MOV   DM,#09H
	MOV   DL,#06H
;******************************************	
	MOV   KP,#0AFH         ;P参数   (.AFH)*2=1.3672
	MOV   KI,#046H         ;I参数   (.46H)=0.2734
	MOV   KD,#0F9H         ;D参数   (.F9H)*8=7.7813
;*******************************************	
	MOV   EK0,#00H   	;e(0)
	MOV   EK1,#00H 		;e(-1)
	MOV   PEKH,#00H   	;
	MOV   OLDKEY,#00H 	;存按键值
	MOV   UK0H,#00H		;数据暂存
	MOV   UK0L,#00H    	
	MOV   EI,#50H          ;门限电压值
	MOV   PEKL,#00H
        MOV   IEKH,#00H
        MOV   IEKL,#00H
        MOV   DEKH,#00H
        MOV   DEKL,#00H
	MOV   EKI,#00H
	MOV   EK2,#00H
        MOV   UK1H,#00H
        MOV   UK1L,#00H
	MOV   R0,#30H
	MOV   R2,#00H
	MOV   R3,#00H
	MOV   R4,#00H
	MOV   R5,#00H
	MOV   R6,#00H
	MOV   R7,#00H
	MOV   TMOD,#01H      ;初始化定时器Xms
	MOV   TH0,#0E0H      
	MOV   TL0,#0BFH
	MOV   IE,#82H        ;开定时中断
	SETB  TR0            ;启用定时器0
	
MAINLOOP:
	LCALL DISP           ;调用显示
	LCALL KEYP
	JMP   MAINLOOP


;*****************************************************
;		中断处理
;*****************************************************
;---------------------10MS定时中断处理------------------
T0INT:	PUSH ACC 
	PUSH DPL
	PUSH DPH
	;启用AD转换
;*****************************************	
	;——方法1 地址方式
	MOV  DPTR,#3FFFH
	MOVX @DPTR,A
;_____________________
	;——方法2  IO方式
	CLR  P2.7
;	NOP
;	NOP
;	;AD转换start
;	CLR  P2.6
;	CLR  P3.6
;	NOP
;	NOP
;	SETB  P2.6
;	SETB  P3.6

	MOV   IE,#083H   ;开外部中断
;赋计数初值
	MOV   TH0,#0E0H 
	MOV   TL0,#0BFH

	POP  DPH
	POP  DPL
	POP  ACC
	RETI
;--------------------------------------------------------------
;---------------外部中断处理-----------------------------------
AINT:   PUSH ACC
	PUSH PSW
	PUSH DPL
	PUSH DPH  
	SETB PSW.3
	;AD运算  读AD转换值
;**********************************
	;——方法1 地址方式
;	MOV  DPTR,#3FFFH
;	NOP
;	MOVX  A,@DPTR

	;——方法2  IO方式
	CLR  P2.6
	CLR  P3.7
	NOP
	MOV  A,P0
	NOP
	SETB  P3.7
	SETB  P2.6
	;AD转换end
		
;----------------------
;	CLR   C
;	SUBB  A,#00H       ;误差修正

	MOV  IE,#82H       ;关外部中断
	ADD   A,#80H	;采样值转化为偏移二进制
;******************************************************************
;位置式PID算法,算法为UK0=UK1+(EK0-EK1)*KP+Kc*EK0*KI+(EK0-2EK1+EK2)*KD;当EKO不大于门限电压时,Kc取1,其他取0
;PID运算,R7为正负标志,EK0为本次误差,EK1为上次误差,EK2为上上次误差
;PEKL为P运算结果低位,PEKH为P运算结果高位
;IEKL为I运算结果低位,IEKH为I运算结果高位
;DEKL为D运算结果低位,DEKH为D运算结果高位
;UK0H为本次PID运算结果高位,UK0L为低位
;UK1H为上次PID运算结果高位,UK1L为低位
	MOV  EK0,A
;*****************比例运算*********************
PPP:	
	JNB  ACC.7,PP1
	MOV  R7,#01H     ;存负号标志
PP1:	CLR   C
	SUBB   A,EK1      ;EK0-EK1
	JNB  PSW.2,PP2    ;判断是否溢出并处理
	CJNE R7,#01H,PP3  ;判断正负溢出
	MOV  R7,#00H      ;清负标志
	MOV  A,#80H       ;正溢出给正最大值
	JMP  PP2          
PP3:    MOV  A,#7FH       ;负溢出给正负最小值
PP2:   	MOV  R7,#00H      ;无益出清负标志
	JNB  ACC.7,PPP0   ;判断EK0-EK1是否为负
	CPL  A            ;负值取其绝对值(取反加一)
	INC  A
	MOV  R7,#01H     ;值负标志
PPP0:   
	MOV  B,KP         ;运算完成2(EK0-EK1)*KP 通过1次左移运算实现
	MUL  AB     

	CLR  C   
	RLC  A
	MOV  PEKL,A     
	MOV  A,B
	RLC  A
	MOV  PEKH,A
	JNB  ACC.7,PPP1    ;运算有溢出给最大值,并结束左移运算
	MOV  PEKH,#7FH
	MOV  PEKL,#0FFH      
PPP1:	CJNE  R7,#01H,PP5  ;被乘数为负结果处理(还原为补码)
	MOV   R7,#00H
	MOV  A,PEKL        
	CPL  A             ;取反
	ADD  A,#01H        ;加一
	MOV  PEKL,A        ;送低位结果
	MOV A,PEKH
	CPL  A             ;取反
	ADDC A,#00H       ;加进位位
	MOV  PEKH,A        ;送高位结果
PP5:    ;比例运算结束

;***************************
;********积分运算********
III:	MOV  A,EK0
 	JNB  ACC.7,II1   ;判断正负
 	MOV  R7,#01H     ;置负标志
	CPL  A      ;负值取其绝对值(取反加一)
	INC  A
II1:
	MOV  B,KI  
	MUL  AB           ;EK0*KI
	MOV  IEKL,A
	MOV  IEKH,B 
	CJNE  R7,#01H,II3   ;EK0为负值的处理(还原成补码)
	MOV   R7,#00H
	MOV   A,IEKL
	CLR   C
	CPL   A
	ADD   A,#01H
	MOV   IEKL,A
	MOV   A,IEKH
	CPL   A
	ADDC  A,#00H
	MOV   IEKH,A
II3:   ;积分运算结束
 
;**************微分运算 *********
DDD:	MOV  A,EK0
	JNB  ACC.7,DD1
	MOV  R7,#01H     ;存负号标志
DD1:	CLR   C
	SUBB   A,EK1      ;EK0-EK1
	JNB  PSW.2,DD2    ;判断是否溢出并处理
	CJNE R7,#01H,DD3  ;判断正负溢出
	MOV  R7,#00H      ;清负标志
	MOV  A,#80H
	JMP  DD2
DD3:   	MOV  A,#7FH
DD2:   	MOV  R7,#00H      ;清负标志
	MOV  EKI,A
	MOV  A,EK2
	JNB  ACC.7,DD4
	MOV  R7,#01H     ;存负号标志
DD4:	CLR   C
	SUBB   A,EK1      ;EK2-EK1
	JNB  PSW.2,DD5    ;判断是否溢出并处理
	CJNE R7,#01H,DD6  ;判断正负溢出
	MOV  R7,#00H      ;清负标志
	MOV  A,#80H
	JMP  DD5
DD6:    MOV  A,#7FH
DD5:    MOV  R7,#00H      ;清负标志
	JNB  ACC.7,DD7
	MOV  R7,#01H
DD7:	ADD  A,EKI
	JNB  PSW.2,DDD1    ;判断是否溢出并处理
	CJNE R7,#01H,DDD2  ;判断正负溢出
	MOV  R7,#00H      ;清负标志
	MOV  A,#80H
	JMP  DDD1
DDD2:   MOV   A,#7FH
DDD1:   MOV  R7,#00H      ;清负标志
	MOV   EKI,A        ;做(EK0-2EK1+EK2)
	JNB  ACC.7,DDD0   ;判断(EK0-2EK1+EK2是否为负
	CPL  A
	INC  A
	MOV  R7,#01H
DDD0:	MOV  B,KD         ;运算完成8(EK0-2EK1+EK2)*KD,通过3次左移运算实现
	MUL  AB
	CLR  C   
	RLC  A
	MOV  DEKL,A     
	MOV  A,B
	RLC  A
	MOV  DEKH,A
	JNB  ACC.7,DDD3     ;运算有溢出给最大值,并结束左移运算
	MOV  DEKH,#7FH
	MOV  DEKL,#0FFH
	JMP  DDD5        
DDD3:   MOV   A,DEKL
	CLR C
	RLC A
	MOV  DEKL,A
	MOV  A,DEKH
	RLC  A
	MOV  DEKH,A
	JNB  ACC.7,DDD4       ;运算有溢出给最大值,并结束左移运算
	MOV  DEKH,#7FH
	MOV  DEKL,#0FFH
	JMP  DDD5
DDD4:   MOV   A,DEKL
	CLR C
	RLC A
	MOV  DEKL,A
	MOV  A,DEKH
	RLC  A
	MOV  DEKH,A
	JNB  ACC.7,DDD5      ;运算有溢出给最大值
	MOV  DEKH,#7FH
	MOV  DEKL,#0FFH
DDD5: 	CJNE  R7,#01H,DDD6
	MOV   R7,#00H
	MOV  A,DEKL
	CLR  C
	CPL  A
	ADD  A,#01H
	MOV  DEKL,A
	MOV A,DEKH
	CPL  A
	ADDC A,#00H
	MOV  DEKH,A
DDD6: ;*********微分运算结束*********

;************求和运算*****************
	MOV  UK0H,UK1H  ;Uk(k-1)运算结果给UK0
 	MOV  UK0L,UK1L
	
	MOV  R1,#UK0H	;Uk(k-1)+P运算结果给UK0
	MOV  R0,#UK0L
 	MOV  R2,PEKL
	MOV  R3,PEKH
 	LCALL  FADD
 

	MOV  R1,#UK0H  ;Uk(k-1)+P+D运算结果给UK0
 	MOV  R0,#UK0L
 	MOV  R2,DEKL
 	MOV  R3,DEKH
 	LCALL  FADD
 
           
	MOV   A,EK0          ;门限比较
	JNB   ACC.7,UUUU0    ;判断正负
	CPL   A              ;负值取其绝对值(取反加一)
	INC   A
UUUU0:	CLR   C   
	SUBB  A,EI           ;门限电压为3FH
	JNC   UUU            ;过门限电压去掉积分项
	
	MOV  R1,#UK0H   
 	MOV  R0,#UK0L
 	MOV  R2,IEKL
 	MOV  R3,IEKH
 	LCALL  FADD 
	   ;Uk(k-1)+P+D+I运算结果给UK0
UUU:	;------存UK0值
	MOV  UK1H,UK0H
	MOV  UK1L,UK0L
;-----------进位处理-------
	MOV  A,UK0H
	JNB  ACC.7,UUU0  ;判断PID运算结果正负(判断高八位最高为是否为1)
	MOV  A,UK0L      ;为负时判断低八位是否为80H
	JB  ACC.7,SPID   ;低八位最高位大于80H时不进位
	MOV A,UK0H       
	CJNE  A,#80H,UKA2   ;判断高八位为80H时也不进位(进位则会溢出)
        JMP  SPID 
UKA2:   DEC  A              ;高八位小于80H时进位(进位即高八位减一因为是负数)
	MOV  UK0H,A
	JMP  SPID
UUU0:	MOV  A,UK0L         ;正数处理
	JNB  ACC.7,SPID     ;判断低位是否大于80H,不大不做进位处理
	MOV A,UK0H          ;判断高位是否为7FH,是不做进位处理(进位则溢出)
	CJNE  A,#7FH,UKA5 
	JMP  SPID
UKA5:   INC  A               ;低八位大于80H时进位(进位即高8位加一  正数)
	MOV  UK0H,A

SPID:	MOV   A,UK0H
END1:	ADD   A,#80H     ;回归原码	
;-----------------------PID运算结束------------------		
	;DA转换
	MOV DPTR,#0DFFFH
	MOVX  @DPTR,A
	MOV  EK2,EK1      
	MOV  EK1,EK0	
	POP  DPH   
	POP  DPL	
	POP  PSW  
	POP  ACC  
	RETI
;两位加法子程序,带溢出处理	
FADD:	;和运算程序,加数高位地址入口R1,低位R0,被加数高位入口R3,低位R2,出口高位地址入口R1,低位R0
	MOV  A,@R0
	CLR  C
	ADD  A,R2            ;完成低8位加 
	MOV  @R0,A   
	MOV  A,@R1           ;和送低位和入口地址
	JNB  ACC.7,FADD1     ;判断加数正负
	MOV  R7,#01H         ;置负标志
FADD1:	ADDC  A,R3           ;高8位加
        MOV  @R1,A            ;和送高位和入口地址
	JNB  PSW.2,FADD2    ;判断是否溢出并处理
	CJNE R7,#01H,FADD3  ;判断正负溢出
	MOV  R7,#00H      ;清负标志
	MOV  @R1,#80H     ;正溢出给正最大值
	MOV  @R0,#00H
	JMP  FADD2      
FADD3:  MOV   @R1,#7FH    ;负溢出给正最小值
	MOV   @R0,#0FFH
FADD2:	MOV  R7,#00H      ;清负标志
	RET
;**********************************************************OK
       ;键盘采样与处理子程序   R4设定标志 
;**********************************************************OK
;__________________________________-
KEYP: 	SETB  P1.7            ;延时
	NOP
	NOP   
	CLR   P1.7 
	CLR   RI  
	MOV   SCON,#10H       ;串行口工作与方式0	
REP1:	JNB   RI,REP1
	MOV   A,SBUF
	CJNE  A,OLDKEY,NEXT   ;判断按键是否结束
	LJMP  BACK
NEXT:	CJNE  A,#0DFH,NEXT1    ;运行键是否按下
	MOV   OLDKEY,A
       ;置运行
	SETB  TR0
	MOV   R4,#00H   
	LJMP  BACK2     
	  
NEXT1:	CJNE  A,#0FEH,NEXT2     ;设定键是否按下       
	MOV   R4,#01H           ;置设定标志
	CLR   TR0
           ;关AD转换
	LJMP  BACK
	
NEXT2: 	CJNE  A,#0FDH,NEXT3    ;切换键是否按下
	INC   R0
	INC   R0
	INC   R0
	CJNE  R0,#39H,N1
	MOV   R0,#30H
N1:	INC   R2
	CJNE  R2,#03H,NN1  
	MOV   R2,#00H
NN1:    
	LJMP   BACK

NEXT3:  CJNE   R4,#00H,NEXT4      ;是否设定
	LJMP    BACK

NEXT4: 	CJNE   A,#0FBH,NEXT5      ;位选键是否按下
	INC   R6
	CJNE  R6,#03H,N2
	MOV   R6,#00H
N2:    	
	MOV   OLDKEY,A
        LJMP   BACK1
	
NEXT5:  CJNE  A,#0F7H,NEXT6        ;上升键是否
	INC   @R1
	CJNE  @R1,#0AH,N3
	MOV   @R1,#00H
N3:     LJMP   BACK	

NEXT6:  CJNE  A,#0EFH,BACK3        ;下降键是否按下
	CJNE  @R1,#00H,N4
	MOV   @R1,#0AH
N4:     DEC   @R1
BACK3: 	LJMP  BACK

;_______----BACK2:PID参数转换程序-------------------_______________
BACK2:	;P参数转换
	MOV   A,PH
	MOV   B,#4
	DIV   AB
	MOV   R5,B
	MOV   B,#64H
	MUL   AB
	MOV   KP,A
	MOV   A,R5
	MOV   B,#0AH
	MUL   AB
	ADD   A,PM
	MOV   B,#4
	DIV   AB
	MOV   R5,B
	MOV   B,#0AH
	MUL   AB
	ADD   A,KP
	MOV   KP,A
	MOV   A,R5
	MOV   B,#0AH
	MUL   AB
	ADD   A,PL
	MOV   B,#4
	DIV   AB
	ADD   A,KP
	MOV   KP,A

	;I参数转换
	MOV  A,IH
	MOV  B,#4
	DIV  AB
	MOV  R5,B
	MOV  B,#64H
	MUL  AB
	MOV  KI,A
	MOV  A,R5
	MOV  B,#0AH
	MUL  AB
	ADD  A,IM
	MOV  B,#4
	DIV  AB
	MOV  R5,B
	MOV  B,#0AH
	MUL  AB
	ADD  A,KI
	MOV  KI,A
	MOV  A,R5
	MOV  B,#0AH
	MUL  AB
	ADD  A,IL
	MOV  B,#4
	DIV  AB
	ADD  A,KI
	MOV  KI,A
	
	;D参数转换
	MOV  A,DH
	MOV  B,#4
	DIV  AB
	MOV  R5,B
	MOV  B,#64H
	MUL  AB
	MOV  KD,A
	MOV  A,R5
	MOV  B,#0AH
	MUL  AB
	ADD  A,DM
	MOV  B,#4
	DIV  AB
	MOV  R5,B
	MOV  B,#0AH
	MUL  AB
	ADD  A,KD
	MOV  KD,A
	MOV  A,R5
	MOV  B,#0AH
	MUL  AB
	ADD  A,DL
	MOV  B,#4
	DIV  AB
	ADD  A,KD
	MOV  KD,A
	JMP   BACK1
BACK:   MOV   OLDKEY,A
BACK1:	MOV   A,R0
	ADD   A,R6
	MOV   R1,A
	RET

;*************************************************************88
;			显示程序				      88	
;*************************************************************88

DISP:
	MOV   DPTR,#TABLE
	MOV   A,R2
	ADD   A,#0AH
	MOVC  A,@A+DPTR
	MOV   P1,A
	SETB  P2.0
	CALL DELAY
	CLR   P2.0
	
	MOV   A,#0DH
	MOVC  A,@A+DPTR
	MOV   P1,A
	SETB  P2.1
	CALL DELAY
	CLR   P2.1
	
	MOV   A,@R0
	MOVC  A,@A+DPTR
	MOV   P1,A
	SETB  P2.2
	CALL DELAY
	CLR   P2.2
	INC   R0
	
	MOV   A,@R0 
	MOVC  A,@A+DPTR
	MOV   P1,A
	SETB   P2.3
	CALL DELAY
	CLR   P2.3
	INC   R0
	
	MOV   A,@R0
	MOVC  A,@A+DPTR
	MOV   P1,A
	SETB  P2.4
	CALL DELAY
	CLR   P2.4
	DEC   R0
	DEC   R0
	RET
	
DELAY:	MOV   R7,#30h
LOOP:	NOP
	DJNZ  R7,LOOP
	RET		
;;TT  DB   0FCH,18H,(1MS)     0F8H, 30H,(2MS)     0f6h,3ch(2.5MS)      0F4H,48H, (3MS)    0F0H,60H,(4MS)    0ECH,78H,  0E0H,0BFH (10MS)   0D8H,0F0H     ;采样周期存储区	
TABLE:	DB    3FH,06H,5BH,4FH,66H
	DB    6DH,7DH,07H,7FH,6FH,73H,30H,5EH,40H     ;分别为0 1 2 3 4  5 6 7 8 9 P I D - 的字形码
	END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -