51单片机电机pid控制系统程序
本程序来源网上,小编进行了简单修改,还未验证。
/*************************
应用背景:直流电机的额定功率12V,额定转速3000rpm,光码盘12孔,
晶振为12MHz,定时/计数器T0检测转速,用定时器T1进行定时,
P1.0控制直流电机的正反转,用P1.1控制电机的转速.
************************/
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
uchar timcount,PWMH,SpeedSet,SpeedDet;
uchar KP,KI,KD;
int e1,e2,e3,uk,duk;
sbit Dir = P1^0;
sbit PWM = P1^1;
//延时函数
void delay(uchar i)
{
uchar j;
for(;i>0;i--)
{
for(j=29;j;j--)
_nop_();
_nop_();
}
}
//延时函数,产生PWM波
void PWMout(uchar q)
{
PWM = 1;
delay(q);
PWM = 0;
delay(100-q);
}
void timer1() interrupt 3
{
TH1 = 0x3c; //(65536-50000)=15536= ox3c oxb0 即定时50ms
TL1 = 0xb0; //(65536-50000)=15536= ox3c oxb0 即定时50ms
if(--timcount==0)
{
timcount = 4;
TR0 = 0;
SpeedDet = TL0;
TL0 = 0;
TR0 = 1;
e1 = SpeedSet-SpeedDet;
duk = (KP*(e1-e2)+KI*e1+KD*(e1-2*e2+e3))/10; //误差的微分:(e1-2*e2+e3)=((e1-e2)-(e2-e3))/1
uk = uk+duk;
if(uk>100)
uk=100;
else if(uk<-100)
uk = -100;
if(uk<0)
{
PWMH = -uk;
Dir = 0;
}
else
{
PWMH =uk;
Dir = 1;
}
e3 = e2;
e2 = e1;
}
}
void main(void)
{
TMOD = 0x16; //T1工作于定时模式的方式一16位定时器;T0工作于计数模式的方式2八位自动重装模式。
TH0 = 0;//装载计数初始值为0
TL0 = 0;//装载计数初始值为0
TH1 = 0x3c;//(65536-50000)=15536= ox3c oxb0 即定时50ms
TL1 = 0xb0;//(65536-50000)=15536= ox3c oxb0 即定时50ms
timcount = 4; //
PWMH = 0; //PWM高电平时间初始为0
SpeedSet = 80;//设定期望值速度80
SpeedDet = 0; //速度偏移量
e1 = 0;//当前误差
e2 = 0;//上一次误差
e3 = 0;//上上次误差
KP =10; //比例系数
KI = 1;//积分系数
KD = 2;//微分系数
TR0 = 1; //打开定时器T0
TR1 = 1;//打开计数器T1
ET1 = 1;//允许中断T1
ET0 = 1;//允许中断T0
EA = 1;//打开总中断
while(1)
{
PWMout(PWMH); //电机运行速度
}
}