/*********课程设计*********
课题:小型直流电机PID控制
******************************
自动化1304
*******************************/
#include<reg52.h>
extern void HD7279A_SEND(unsigned char comm);
extern char KEY_SCAN();
sbit PWM=P1^7;
sbit key1=P1^0;
sbit key2=P1^2;
int Key_flag=0;
int flag=0;
int pidtimer0=0,pwmtimer0=0,num=0;
int setspeed=0,speed=0,allspeed=0;
typedef struct PID
{
int SetPoint;//设定目标Desired Value
long SumError;//误差累计
double Proportion;//比例常数Proportional Const
double Integral;//积分常数Integral const
double Derivative;//微分常数Derivative Const
int LastError;//Error[-1]
int PrevError;//Error[-2]
}PID;
static PID sPID;
static PID *sptr = &sPID;
void display() //数码显示
{
unsigned char datas[8];
unsigned char b;
datas[0]=num/1000;
datas[1]=num%1000/100;
datas[2]=num%100/10;
datas[3]=num%10;
datas[4]=setspeed/1000;
datas[5]=setspeed%1000/100;
datas[6]=setspeed%100/10;
datas[7]=setspeed%10;
for(b=0;b<8;b++)
{
HD7279A_SEND(0x80|(7-b));//WEI
HD7279A_SEND(datas[b]);
}
}
void delay(unsigned int a)
{
unsigned int i,j;
for(i=0;i<a;i++)
for(j=0;j<200;j++);
}
void Scankey(void)
{
if(key1==0)
{
delay(30); //消抖
if(key1==0)
{
setspeed=setspeed+10;
}
while(!key1) ; //松手检查
}
if(key2==0)
{
delay(30);
if(key2==0)
{
setspeed=setspeed-10;
}
while(!key2) ;
}
if(setspeed>=215) setspeed=215;
}
/*
Initialize PID Structrue PID参数初始化
*/
void IncPIDInit(void)
{
sptr->SumError = 0;
sptr->LastError = 0;//Error[-1]
sptr->PrevError = 0;//Error[-2]
sptr->Proportion =0.7;//比例常数Proportional Const
sptr->Integral = 0.5;//积分常数Integral Const
sptr->Derivative = 0;//微分常数Derivative Const
sptr->SetPoint = 0;
}
/*
增量式PID计算部分
*/
int IncPIDCalc(int NextPoint)
{
int iError,iIncpid;//当前误差
sptr->SetPoint =setspeed;
iError = sptr->SetPoint-NextPoint;//增量计算
iIncpid=sptr->Proportion*(iError-sptr->LastError)+
sptr->Integral*iError+
sptr->Derivative*(iError-2*sptr->LastError+sptr->PrevError);//增量计算
//存储误差,用于下次计算
sptr->PrevError = sptr->LastError;
sptr->LastError = iError;
//返回增量值
return(iIncpid);
}
/**********计数器0初始化**********/
void timer0_init(void)
{
TMOD=0x01;
TH0=0X0FC;
TL0=0X66 ;//定时器0定时1ms
IT0=1;
EX0=1;
TR0=1;
ET0=1;
EA=1;//EA=0 总中断
}
void main(void)
{
IncPIDInit();
timer0_init();
setspeed=150; //0~215
while(1)
{
Scankey();
}
}
void Getspeed(void) interrupt 0
{
num++;
}
void Timer0(void) interrupt 1//1ms
{
pwmtimer0++;
pidtimer0++;
if(pwmtimer0<=speed) PWM=1;
else PWM=0;
if(pwmtimer0>=255) pwmtimer0=0; //PWM T=255MS
if(pidtimer0==400) //PID T=400MS
{
display();
sptr->SumError=sptr->SumError+IncPIDCalc(num);
speed=sptr->SumError*1;
pidtimer0=0;
num=0;
}
TH0=0X0FC;
TL0=0X66 ;//定时器0定时1ms
}
评论0
最新资源