#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
#include <stdio.h>
#include <MC9S12XS128.h>
#include <stdlib.h>
#include <math.h>
#pragma LINK_INFO DERIVATIVE "mc9s12xs128"
#define K 1
#define N 3
unsigned int i=0,j=0,m=0,n=0;
unsigned char str[]={'0'};
signed int b=0,c=0,d=0,e=0,f=0,g=0,spe=0,r=0,l,x3,y,z,x1,x2,x4;
int time;
int zd=0,flag;
int pp;
 /////////////////////////////////////
 //// 电机 PID 定义
 /////////////////////////////////////
int SetPoint=0; //设定目标 Desired Value
int FeedBack=0;
float KKp=1.5; //比例常数 Proportional Const
float KKi=0;
float KKd=0.6; //微分常数 Derivative Const
signed int EE0=0; //当前误差
signed int EE1=0; //Error[-1]
signed int EE2=0; //Error[-2]
signed int EError0=0,EError1=0;
signed int iiIncpid=0;
int sp=0;
///////////////////////////////
/// 舵机 PID 定义
//////////////////////////////
float Kp=3; //比例常数 Proportional Const
float Ki=1;
float Kd=4.2; //微分常数 Derivative Const
signed int E0=0 ; //当前误差
signed int E1=0; //Error[-1]
signed int E2=0; //Error[-2]
signed int Error0=0,Error1=0;
signed int iIncpid=0;
/////////////////////////////////////
 /////////////////////////////////////
 //// 电机 PID
 /////////////////////////////////////
 ////////////////////////////////////
unsigned int Getspeed(int cch1,int cch2 )
{
 EE0=cch1-cch2; //增量计算
 EError0=EE0-EE1;
 EError1=EE1-EE2;
 iiIncpid=(int)(KKi*EError0+KKp*EE0+KKd*(EError0-EError1));
 EE1=EE0;
 EE2=EE1; //存储误差,用于下次计算
 sp+=iiIncpid;
 if(sp>210)
 sp=210;
 if(sp<0)
 sp=0;
 return sp;
}
void sudu(int SetPoint)
{
 pp=Getspeed(SetPoint,FeedBack);
 PWMDTY2=pp;
}
//////////////////////////////
///////////////////////////////
/// 舵机 PID
//////////////////////////////
//////////////////////////////////////
int Pcrtl(int ch1,int ch2 )
{
 E0=ch1-0; //增量计算
 Error0=E0-E1;
 Error1=E1-E2;
 iIncpid=(int)(Ki*Error0+Kp*E0+Kd*(Error0-Error1));
 E1=E0;
 E2=E1; //存储误差,用于下次计算
 return iIncpid;
}
///////////////////////////////////////
void shache(int sha,int tim)
{
 PWMDTY3=sha;
 time=tim;
 PITCE_PCE1=1;
 PITINTE_PINTE1=1; //enable interupt channel 0
 zd=0;
}
////////////////////////////////////////
void vIOPortInit(void)
{
 DDRA=0X00; //PROT B 键盘输出
 PORTA=0X00;
 DDRB=0xff;
 DDRJ=0xFF; //PROTB
 PTJ=0X80;
}
void delayms(int ms) //40MHz--1ms
{
 int ii,jj;
 if (ms<1) ms=1;
 for(ii=0;ii<ms;ii++)
 for(jj=0;jj<0xff;jj++);
}
//////////////////////////////////
void SetBusCLK_64M(void)
{
 CLKSEL=0X00; //disengage PLL to system
 PLLCTL_PLLON=1; //turn on PLL
 SYNR =0xc0 | 0x07;
 REFDV=0xc0 | 0x01;
 POSTDIV=0x00; //pllclock=2*osc*(1+SYNR)/(1+REFDV)=80MHz;
 _asm(nop); //BUS CLOCK=64M
 _asm(nop);
 while(!(CRGFLG_LOCK==1));  //when pll is steady ,then use it;
 CLKSEL_PLLSEL =1;  //engage PLL to system;
}
void ECT_Init(void) /*ECT初始化,使用输入捕捉功能*/
{
 TIOS =0x00; //设为输入捕捉
 TSCR1=0x80; //定时器使能
 TSCR2=0x07;
 TIE=0b00000010; //开中断
 TCTL4=0b00001000; //0 ,1触发电平:
 //TCTL3=0b10101010;
}
///////////////////////
void PWMInit(void)
{
 PWME=0x00; //禁止PWM输出
 PWMPOL=0xff;
 PWMCLK=0x08;
 PWMCTL=0x10;
 PWMSCLB=80;
 PWMCAE=0x00; //左对齐
 PWMPRCLK=0x44; //PWM时钟CLOCKA,
 PWMPER01=40000;
 PWMPER3=250;
 PWMPER2=255;
 PWMDTY2=0;
 PWMDTY3=31;
 PWMDTY01=4675;
 PWME=0x0f; /*使能01,23通道*/
}
//////////////////////////
void SCI(void)
{
 SCI1BDH=0X01;
 SCI1BDL=0XA0;
 SCI1CR1=0X00;
 SCI1CR2=0X08;
}
void shacheV(int ch3)
{
 PWMDTY3=ch3;
 while(FeedBack>30);
 PWMDTY3=30;
 zd=0;
}
 void TERMIO_PutChar(unsigned char ch)
 {
 while(!(SCI1SR1&0x80)) ; //keep waiting when not empty
 SCI1DRL=ch;
 }
 unsigned char TERMIO_GetChar(void)
 {
 while(!(SCI1SR1&0x80)) ; //keep waiting when not empty
 return SCI1DRL;
 }
void un(unsigned char ch)
 {
 while(!(SCI1SR1&0X40))
 {
 }
 SCI1DRL=ch;
 }
/////////////////////////////
void ADInit(void)
{
 ATD0CTL1=0x00;
 ATD0CTL2=0X40; /* 使能AD,清除标志 */
 ATD0CTL3=0XB0; /* 队列长度为6,依次存入结果寄存器,继续转换 */
 ATD0CTL4=0X05; /* 8位精度,总线频率32分频 */
 ATD0CTL5=0X30; /* ,多通道,连续,从AD0开始转换*/
 ATD0DIEN=0x00; //禁止数字输入
}
////////////////////////////////
void PACN_init(void)
 {
 PACTL_PAEN=0;
 TSCR1=0X80; //快速清除flag:PAOVF PAIF
 TSCR2=0X03;
 PACNT=0;
 PACTL_PAEN=1; //启动脉冲累加器A
 PACTL_PAMOD=0; //事件计数方式
 PACTL_PEDGE=1; //PT7引脚上的出现上升沿时脉冲累加器计数器加1
 TSCR1_TEN =1;
 }
void Pit0_Init(void)
{
 PITCFLMT_PITE=0; //disable PIT
 PITCE_PCE0=1; //enable timer channel 0
 PITMUX_PMUX0=0; //ch0 connected to micro timer 0
 PITMTLD0=0X0F ; //micro time base 0 equals 255 clock cycles
 PITLD0=0XFFFF; //time-out period = (PITMTLD + 1) * (PITLD + 1) / fBUS.
 //时间计算
 //For example, for a 16 MHz bus clock, the maximum time-out period equals:
 //15 * 65536 * /64000000 = 0.01536s.
 PITINTE_PINTE0=1; //enable interupt channel 0
 PITCFLMT_PITE=1; //enable PIT
}
void Pit1_Init(void)
{
 PITCFLMT_PITE=0; //disable PIT
 //PITCE_PCE1=1; //enable timer channel 0
 PITMUX_PMUX1=0; //ch0 connected to micro timer 0
 PITMTLD1=0X0F ; //micro time base 0 equals 255 clock cycles
 PITLD1=0XFFFF; //time-out period = (PITMTLD + 1) * (PITLD + 1) / fBUS.
 //时间计算
 //For example, for a 16 MHz bus clock, the maximum time-out period equals:
 //15 * 65536 * /64000000 = 0.01536s.
 //PITINTE_PINTE1=1; //enable interupt channel 0
 PITCFLMT_PITE=1; //enable PIT
}
/////////////////////////////////////
void bustor(int x[],int n)
 {
 int i,j,m,k;
 for(i=1;i<=n-1;i++)
 {
 k=1;
 for(j=1;j<=n-i;j++)
 if(x[j]>x[j+1])
 {
 m=x[j];
 x[j]=x[j+1];
 x[j+1]=m;
 k=0;
 }
 if(k==1)
 break;
 }
 }
///////////////////////////
void kongzhi(void)
{
 vIOPortInit() ;
 SetBusCLK_64M() ;
 ADInit() ;
 SCI();
 PORTB=0X00;
 PWMInit();
 PACN_init();
 Pit0_Init();
 Pit1_Init();
 for(;;)
 {
 ECT_Init();
 while(!ATD0STAT0_SCF); /*等待当前队列转换完成*/
 b=ATD0DR0L;
 c=ATD0DR1L;
 d=ATD0DR2L;
 e=ATD0DR3L;
 f=ATD0DR4L;
 g=ATD0DR5L;
 //printf("x1=%d x2=%d FeedBack=%d EE0=%d iiIncpid=%d sp=%d b=%d c=%d ",x1,x2,FeedBack,EE0,iiIncpid,sp,b,c) ;
 if(b>0x10&&c>0x10)
 {
 x1=b-210;
 x2=c-210;
 if(d<e)
 x1=-x1;
 if(f<g)
 x2=-x2;
 y=Pcrtl(x1,x2);
 if(y>560)
 y=560;
 if(y<-450)
 y=-450;
 PWMDTY01=4675-y;
 //printf("x1=%d x2=%d",x1,x2);
 if(x2>80||x2<-80) //大弯道
 {
 if(zd==1&&FeedBack>78)
 {
 sudu(65);
 if(d>e)
 {
 PORTB=0XF0;
 shacheV(8);
 }
 else
 {
 PORTB=0X0F;
 shacheV(52);
 }
 }
 }
 else //直道
 {
 if(x1>50||x1<-50)
 {
 x4++;
 if(x4<60)
 sudu(60);
 else
 sudu(60);
 }
 else
 {
 zd=1;
 sudu(100);
 PWMDTY3=30;
 x4=0;
 }
 }
 }
 else
 sudu(65);
 }
 }
void main(void) {
 /* put your own code here */
  EnableInterrupts;
 kongzhi();
 for(;;) {
 _FEED_COP(); /* feeds the dog */
 } /* loop forever */
 /* please make sure that you never leave main */
}
///////////////////////////////////
#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt 9 T1CaptureInterrupt(void)
{ TFLG1=0b00000010;
 i++;
 PORTB=0xff-i;
 un(i);
 if(i>0x0c)
 {
 PTJ=0X00;
 }
}
 #pragma CODE_SEG DEFAULT
////////////////////////////////////////
 //////////////////////////////////
#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt 66 PIT0_ISR(void)
{  
 PITTF_PTF0=1; //CLER FLAG
 FeedBack=PACNT;
 PACNT=0;
}
 //////////////////////////////////
#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt 67 PIT1_ISR(void)
{  
 PITTF_PTF1=1; //CLER FLAG
 r++;
 if(r==time)
 { r=0;
 zd=0;
 PORTB=0XFF;
 PWMDTY3=30;
 PITCE_PCE1=0;
 PITINTE_PINTE1=0; //DISable interupt channel 0
 }
}