AT51 pid程序.docx
- 文档编号:9324786
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:14
- 大小:20.01KB
AT51 pid程序.docx
《AT51 pid程序.docx》由会员分享,可在线阅读,更多相关《AT51 pid程序.docx(14页珍藏版)》请在冰豆网上搜索。
AT51pid程序
用C51实现PID算法
时间:
2007-06-26 来源:
作者:
点击:
10431 字体大小:
【大中小】
-
关于PID的算法实现,很多书上都讲了。
但是,最近真正要用PID算法的时候,发现书上的代码在我们51上来实现还不是那么容易的事情。
简单的说来,就是不能直接调用。
仔细分析你可以发现,教材上的、网上现行的PID实现的C语言代码几乎都是用浮点型的数据来做的,可以想象,如果我们的计算使用浮点数据,那我们的51单片机来运行的话会有多痛苦。
所以,本人自己琢磨着弄了一个整型变量来实现了PID算法,由于是用整型数来做的,所以也不是很精确,但是对于很多的使用场合,这个精度也够了。
关于系数和采样电压全部是放大10倍处理的。
所以精度不是很高,但是也不是那么低,大部分的场合都够用了。
实在觉得精度不够,可以再放大10倍或者100倍处理,但是要注意不超出整个数据类型的范围就可以了。
本人做的是带死区控制的PID算法。
具体的参考代码参见下面:
typedefstructPIDValue
{
uint32Ek_Uint32[3]; //差值保存,给定和反馈的差值
uint8 EkFlag_Uint8[3]; //符号,1则对应的Ek[i]为负数,0为对应的Ek[i]为正数
uint8 KP_Uint8;
uint8 KI_Uint8;
uint8 KD_Uint8;
uint8 B_Uint8; //死区电压
uint8 KP; //显示修改的时候用
uint8 KI; //
uint8 KD; //
uint8 B; //
uint16 Uk_Uint16; //上一时刻的控制电压
}PIDValueStr;
PIDValueStrxdataPID;
/*******************************
**PID=Uk+(KP*E(k)-KI*E(k-1)+KD*E(k-2));
********************************/
void PIDProcess(void)
{
uint32idataTemp[3]; //
uint32idataPostSum; //正数和
uint32idataNegSum; //负数和
Temp[0]=0;
Temp[1]=0;
Temp[2]=0;
PostSum=0;
NegSum=0;
if(ADPool.Value_Uint16[UINADCH]>ADPool.Value_Uint16[UFADCH]) //给定大于反馈,则EK为正数
{
Temp[0]=ADPool.Value_Uint16[UINADCH]-ADPool.Value_Uint16[UFADCH]; //计算Ek[0]
if(Temp[0]>PID.B_Uint8)
{
//数值移位
PID.Ek_Uint32[2]=PID.Ek_Uint32[1];
PID.Ek_Uint32[1]=PID.Ek_Uint32[0];
PID.Ek_Uint32[0]=Temp[0];
//符号移位
PID.EkFlag_Uint8[2]=PID.EkFlag_Uint8[1];
PID.EkFlag_Uint8[1]=PID.EkFlag_Uint8[0];
PID.EkFlag_Uint8[0]=0; //当前EK为正数
Temp[0]=(uint32)PID.KP_Uint8*PID.Ek_Uint32[0]; //KP*EK0
Temp[1]=(uint32)PID.KI_Uint8*PID.Ek_Uint32[1]; //KI*EK1
Temp[2]=(uint32)PID.KD_Uint8*PID.Ek_Uint32[2]; //KD*EK2
}
}
else //反馈大于给定
{
Temp[0]=ADPool.Value_Uint16[UFADCH]-ADPool.Value_Uint16[UINADCH]; //计算Ek[0]
if(Temp[0]>PID.B_Uint8)
{
//数值移位
PID.Ek_Uint32[2]=PID.Ek_Uint32[1];
PID.Ek_Uint32[1]=PID.Ek_Uint32[0];
PID.Ek_Uint32[0]=Temp[0];
//符号移位
PID.EkFlag_Uint8[2]=PID.EkFlag_Uint8[1];
PID.EkFlag_Uint8[1]=PID.EkFlag_Uint8[0];
PID.EkFlag_Uint8[0]=1; //当前EK为负数
Temp[0]=(uint32)PID.KP_Uint8*PID.Ek_Uint32[0]; //KP*EK0
Temp[1]=(uint32)PID.KI_Uint8*PID.Ek_Uint32[1]; //KI*EK1
Temp[2]=(uint32)PID.KD_Uint8*PID.Ek_Uint32[2]; //KD*EK2
}
}
/*以下部分代码是讲所有的正数项叠加,负数项叠加*/
if(PID.EkFlag_Uint8[0]==0)
{
PostSum+=Temp[0]; //正数和
}
else
{
NegSum+=Temp[0]; //负数和
} //KP*EK0
if(PID.EkFlag_Uint8[1]!
=0)
{
PostSum+=Temp[1]; //正数和
}
else
{
NegSum+=Temp[1]; //负数和
} //-kI*EK1
if(PID.EkFlag_Uint8[2]==0)
{
PostSum+=Temp[2]; //正数和
}
else
{
NegSum+=Temp[2]; //负数和
} //KD*EK2
PostSum+=(uint32)PID.Uk_Uint16; //
if(PostSum>NegSum) //是否控制量为正数
{
Temp[0]=PostSum-NegSum;
if(Temp[0]<(uint32)ADPool.Value_Uint16[UMAXADCH]) //小于限幅值则为计算值输出
{
PID.Uk_Uint16=(uint16)Temp[0];
}
else
{
PID.Uk_Uint16=ADPool.Value_Uint16[UMAXADCH]; //否则为限幅值输出
}
}
else //控制量输出为负数,则输出0
{
PID.Uk_Uint16=0;
}
}
PD控温程序(汇编)
时间:
2006-09-20 来源:
作者:
点击:
1831 字体大小:
【大中小】
-
;此控温程序是采用PD控温方式,入口在:
BLXS 最大取值255 WFXS 最大取值255
; SDWDHH,SDWDHL 设定温度的16进制高低字节存储地址
; WDZHH,WDZHL 当前温度的16进制高低字节存储地址
;
; 出口在:
ZSJCSH 加热时间
; ZSJCSL 不加热时间
;
; ZSJCSH+ZSJCSL=200 则一个控温周期=200*基本定时周期
BCPCHH EQU 30H
BCPCHL EQU 31H
BLCSH EQU 32H
BLCSL EQU 33H
BLXS EQU 34H
WFXS EQU 35H
PCWFH EQU 36H
PCWFL EQU 37H
SCPCHH EQU 38H
SCPCHL EQU 39H
SDWDHH EQU 3AH
SDWDHL EQU 3BH
WDZHH EQU 3CH
WDZHL EQU 3DH
WFCSH EQU 3EH
WFCSL EQU 3FH
ZSJCSH EQU 40H
ZSJCSL EQU 41H
BLPCFH BIT 00H
SCBLPCFH BIT 01H
WFPCFH BIT 02H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;PID控温子程序需定义RAM SDWDHH SDWDHL WDZHL WDZHH BCPCHL BCPCHH SCPCHH SCPCHL
; BLXS WFXS PCWFH PCWFL WFCSL WFCSH BLCSL BLCSH ZSJCSH ZSJCSL
;
; 标志位 BLPCFH SCBLPCFH WFPCFH
PDJS:
;计算e(t)值
CLR C
MOV A,SDWDHL ;sdwdhh,sdwdhl 存设定温度带一位小数
MOV R7,WDZHL
SUBB A,R7
MOV BCPCHL,A ;存本次偏差低8位
MOV A,SDWDHH
MOV R7,WDZHH
SUBB A,R7
MOV BCPCHH,A ;存本次偏差高8位
JC BOOLL2
CLR BLPCFH ;清比例偏差符号
BOOLL3:
JB BLPCFH,JSSZ3 ;符号位为0表示正值,为1表示负值 本次比例偏差符号 为负不加热退出
JB SCBLPCFH,JSSZ2 ;符号位为0表示正值,为1表示负值 上次比例偏差符号
JMP JSSZ1
BOOLL2:
SETBBLPCFH
CLR C
MOV A,#0FFH
SUBB A,BCPCHL ;本次温度大于设定温度,求补锝实际数值e(t)
MOV BCPCHL,A
MOV A,#0FFH
SUBB A,BCPCHH
MOV BCPCHH,A
INC BCPCHL
JMP BOOLL3
JSSZ3:
MOV A,BCPCHL
MOV SCPCHL,A
MOV A,BCPCHH
MOV SCPCHH,A
JB BLPCFH,MLLP1232 ;将本次偏差数值与符号赋给上次保存地址
CLR SCBLPCFH
JMP fool2
MLLP1232:
SETB SCBLPCFH
jmp fool2
JSSZ2:
CLR C ;e(t)>0 e(t-1)<0
MOV A,BCPCHL ;计算e(t)-e(t-1)的结果,存入PCWFL,PCWFH中
ADDC A,SCPCHL
MOV PCWFL,A
MOV A,BCPCHH
ADDC A,SCPCHH
MOV PCWFH,A
CLR WFPCFH
JMP AOOL1
JSSZ1:
CLR C ;到此为止,本次e(t)值已算出,并有符号位,可判正负%%%%%%%%%%%%%%%%%%%%%%%
MOV A,BCPCHL ;计算e(t)-e(t-1)的结果,存入PCWFL,PCWFH中
SUBB A,SCPCHL ;e(t) e(t-1)都为正值
MOV PCWFL,A
MOV A,BCPCHH
SUBB A,SCPCHH
MOV PCWFH,A
CLR WFPCFH
JNC AOOL1 ;本次偏差>上次偏差,转走
SETB WFPCFH ;微分偏差符号置位
CLR C
MOV A,#0FFH
SUBB A,PCWFL ;本次偏差<上次偏差,求补锝实际数值
MOV PCWFL,A
MOV A,#0FFH
SUBB A,PCWFH
MOV PCWFH,A
INC PCWFL
AOOL1:
MOV A,BCPCHL
MOV SCPCHL,A
MOV A,BCPCHH
MOV SCPCHH,A
JB BLPCFH,MLLP1 ;将本次偏差数值与符号赋给上次保存地址
CLR SCBLPCFH
JMP MLLP2
MLLP1:
SETB SCBLPCFH
MLLP2:
MOV R2,BCPCHH
MOV R3,BCPCHL
MOV
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- AT51 pid程序 pid 程序
![提示](https://static.bdocx.com/images/bang_tan.gif)