#include "reg52.h"
#include "string.h"
#include "stdio.h"
#include <stdlib.h>
#define uchar unsigned char
#define uint unsigned int
sbit motor=P2^6;
uint Hrspeed; //速度标志
uchar cycount; //速度采样值
uint count1,count2; //外部中断中的数
uint count; //定时器中的数
unsigned char PWM;//目标值
long int PointPwm;
float Pvalue=7,Ivalue=0.1,Dvalue=0.7;///6.5
static data ErrorNum=0.0,en=0.0,en1=0.0,en2=0.0;
unsigned char PointSpeed=0;
unsigned char idata Txbuff[10];
unsigned char spdflag;//速度命令标志
unsigned char Rxbuff[10],Rxcount;//接收加减速命令
unsigned char idata PIDdata[20],PIDcount,getok;//接收PID参数值
unsigned char spdflag,pidflag;//速度与PID参数接收标志
unsigned char Pdata[5],Idata[5],Ddata[5];
float now = 0,bef = 0,bbef = 0; //本次采样值,上次采样值,上上次采样值
float err_now,err_bef,err_bbef; //当前偏差,上次偏差,上上次偏差
float error_add = 0; //所有偏差之和
unsigned char timerok;
void delay(uchar x);
void delay(uchar x)
{ uint y;
for(;x>0;x--)
{
for(y=100;y>0;y--)
{};
}
}
/************************外部中断初始化***************************/
void Exti0_Init(void) //外部中断0初始化
{
EA=1;
EX0=1;
IT0=1;
}
void Timer0_Init(void) //定时器0初始化
{
TMOD|=0X01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
ET0=1;
TR0=1;//启动定时器1
}
void InitTimer1(void)
{
TMOD|= 0x10;
TH1 = 0x0FE;
TL1 = 0x0C;
EA = 1;
ET1 = 1;
TR1 = 1;
}
/**********************串口初始化***********************/
void InitUART(void)
{
PCON &= 0x7F; //波特率不倍速 SMOD=0
SCON = 0x50; //方式1,8位数据,可变波特率,接收允许
T2CON = 0x34;
RCAP2H = 0xFF;
RCAP2L = 0xDC;
TH2 = 0xFF;
TL2 = 0xDC;
EA=1; //总中断打开,采用查询法时不用打开中断
ES = 1; //串口中断开关,采用查询法时不用打开中断
}
/*
* UART 发送一字节
*/
void UART_send_byte(char dat)
{
SBUF = dat;
while (TI == 0);
TI = 0;
}
/*
* UART 发送字符串
*/
void UART_send_string(unsigned char *buf)
{
while (*buf != '\0')
{
UART_send_byte(*buf++);
}
}
int PID_ADD(int setpoint,int achieved) //增量式PID
{
long int result,TempResult;
int change;
err_now = setpoint - achieved;
err_bef = setpoint - bef;
err_bbef = setpoint - bbef;
change = Pvalue*(err_now) + Ivalue*err_now + Dvalue*(err_now - 2*err_bef + err_bbef);
TempResult=(long int)(change/20);
result=TempResult;
return(TempResult);
}
//**********PID算法******
long int PID(int setpoint,int achieved)
{
long int result,TempResult;
en=setpoint-achieved;
ErrorNum=Pvalue*en;-Ivalue*(en-en1)+Dvalue*(en1-en2);
TempResult=(long int)(ErrorNum/20);
result=TempResult;
en2=en1;
en1=en;
return result;
}
void speed_change(void)
{
if(Rxcount>=2)
{
if(Rxbuff[0]=='S')//速度交替指令
{
if(Rxbuff[1]=='1')//代表加速
{
PointSpeed+=10;//
if(PointSpeed>60)
PointSpeed=60;
Rxbuff[0]=0;Rxbuff[1]=0;
}
if(Rxbuff[1]=='0')//代表减速
{
PointSpeed-=10;//
if(PointSpeed<=10)
PointSpeed=10;
Rxbuff[0]=0;Rxbuff[1]=0;
}
if(Rxbuff[1]=='8')//代表停止
{
PointSpeed=0;//
Rxbuff[0]=0;Rxbuff[1]=0;
}
}
Rxcount=0;
spdflag=0;
}
}
void PID_change(void)
{
unsigned char i,j;
if(PIDdata[PIDcount]=='D')//获取到最后一位
{
for(i=0;i<PIDcount;i++)
{
if(PIDdata[i]=='P')
{
j=i;
break;
}
Pdata[i]=PIDdata[i+1];//去掉首字母C
}
Pdata[4]=0;
for(i=j;i<PIDcount;i++)
{
if(PIDdata[i]=='I')
{
j=i;
break;
}
Idata[i-j]=PIDdata[i+1];//去掉首字母P
}
Idata[4]=0;
for(i=j;i<PIDcount;i++)
{
if(PIDdata[i]=='D')
break;
Ddata[i-j]=PIDdata[i+1];//去掉首字母P
}
Ddata[4]=0;
Pvalue=atof(Pdata);
Ivalue=atof(Idata);
Dvalue=atof(Ddata);
pidflag=0;
PIDcount=0;
getok=1;
}
else
{
PIDcount++;
}
}
void main()
{
Exti0_Init();
InitUART();
Timer0_Init();
InitTimer1();
delay(100);
while(1)
{
speed_change();
if(timerok)
{
bbef = bef;
bef = now;
now = Hrspeed;
timerok=0;
}
if(PointSpeed)
{
PointPwm+=PID_ADD(PointSpeed,Hrspeed);
// PointPwm+=PID(PointSpeed,Hrspeed);
if( PointPwm<0)
PointPwm=20;
if(PointPwm>255)
PointPwm=250;
}
else
PointPwm=0;
Txbuff[0]='S';
Txbuff[3]=PointSpeed/10%10+0x30;
Txbuff[4]=PointSpeed%10+0x30;
Txbuff[5]=getok+0x30;
Txbuff[6]=0;
/*
if(getok)
{
getok=0;
UART_send_string(Ddata);
}
*/
UART_send_string(Txbuff);
getok=0;
delay(500);
}
}
void ex0()interrupt 0 //外部中断0
{
count++;
cycount++; //霍尔值
if(count==10)
{
count=0;
count2++; //10个脉冲 ,算1m
}
}
void timer0()interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count1++;
if(count1==20)//时间,1s
{
Hrspeed=cycount; //霍尔转换出来的速度值
cycount=0;//1s清除
count1=0;//清除1s
Txbuff[1]=Hrspeed/10%10+0x30;
Txbuff[2]=Hrspeed%10+0x30;
timerok=1;
}
}
void Timer1Interrupt(void) interrupt 3
{
PWM++;
TH1 = 0x0FF;
TL1 = 0x9C;
if(PWM>PointPwm)
motor=1;
else
motor=0;
}
void UARTInterrupt(void) interrupt 4
{
if(RI)
{
ES=0;
Rxbuff[Rxcount]=SBUF;//获取指令数据
if(Rxbuff[Rxcount]=='S')//表明获取到了速度指令
{
spdflag=1;
Rxcount=0;
}
if(spdflag)
{
Rxcount++;
}
////////////////////////////////////////////////
PIDdata[PIDcount]=SBUF;//获取PID参数值
if(PIDdata[PIDcount]=='C')
{
pidflag=1;
PIDcount=0;
}
if(pidflag)
PID_change();
RI = 0;
ES=1;
}
}