巡线车程序(完整版,也是最先的版本)

来源:互联网 发布:软件 系统架构图 编辑:程序博客网 时间:2024/06/07 07:00
#ifndef _Macro.h_#define _Macro.h_   #include <msp430x14x.h>#include <intrinsics.h>#define uchar unsigned char #define uint unsigned int#define one 11.11#define LMAX 1999#define RMAX 3999#define CPU_F ((double)8000000)#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))#define PC 20  // 比例放大系数#define IC 0    //积分放大系数#define DC 85    //大系数#define LEFTOUT    TACCR1#define RIGHTOUT   TACCR2#define SensorIn   P5IN#define F          5000//5000hz#define Period     (8000000/F)#define EnableLeftPos       P3OUT|=BIT1#define UnenableLeftPos     P3OUT&=~BIT1#define EnableLeftNeg       P3OUT|=BIT0#define UnenableLeftNeg     P3OUT&=~BIT0#define EnableRightPos      P3OUT|=BIT2#define UnenableRightPos    P3OUT&=~BIT2#define EnableRightNeg      P3OUT|=BIT3#define UnenableRightNeg    P3OUT&=~BIT3#define Basic_Left  100//百分之八十#define Basic_Right 100//Basic_Left#define MAX        (100)#define MIN        (-100)#define foreward   1#define backward   0#define max_speed  100#define min_speed  -100#define key        0#define left_1 1#define left_2 2#define left_3 3#define left_4 4#define left_5 5#define left_6 6#define left_7 7//右直角#define right_1 -1#define right_2 -2#define right_3 -3#define right_4 -4#define right_5 -5#define right_6 -6#define right_7 -7//左直角#endif 



#include "Macro.h"#include "sensor.h"void Motorstop(){  LEFTOUT=0;  RIGHTOUT=0;}void MotorLeft(int speed,int direction){  if(speed>max_speed)speed=max_speed;  if(direction==backward)//反转  {    EnableLeftNeg;    UnenableLeftPos;  }  else if(direction==foreward)//正转  {    EnableLeftPos;    UnenableLeftNeg;  }  LEFTOUT=Period/100*speed;}void MotorRight(int speed,int direction){  if(speed>max_speed)speed=max_speed;    if(direction==backward)//反转  {    EnableRightNeg;    UnenableRightPos;  }  else if(direction==foreward)//正转  {    EnableRightPos;    UnenableRightNeg;  }  RIGHTOUT=Period/100*speed;}void MotorDrive(int PIDout){  int speedleft,speedright;  speedleft=Basic_Left+PIDout;  speedright=Basic_Right-PIDout;    if(speedleft<0)    MotorLeft(speedleft,backward);//反转  else MotorLeft(speedleft,foreward);//正转    if(speedright<0)    MotorRight(speedright,backward);//反转  else MotorRight(speedright,foreward);//正转}void  Rangle(float angle){ // TBCTL|=TBCLR;  TBCCR1=LMAX+(unsigned int)(angle*one); }




//下面是小车的程序。。用定时器A来输出两路PWM波。//选用输出模式7(首先输出高电平。在TAR=CCRX时,电平自动变低。这样可以输出任意占空比的PWM波)//    传感器接在P5口,电机的驱动接在P3口。#include "Macro.h"#include "motor.h"typedef struct p{  float  error_1;//上次的误差  float sumerror;}PID;PID Pid;PID *pid=&Pid;uchar detection,sample=0,corner,k,flag,tt=0;int weight1[]={-8,-5,-3,-2,0,2,3,5,8};//传感器的权值float sensorin;int num,tag=1;void IO_inti()//io口初始化{  P1SEL|=BIT2+BIT3;//p1为定时器输出端。  P1DIR|=BIT2+BIT3;//设置为输出模式。P5为传感器输入。  P3DIR|=BIT0+BIT1+BIT2+BIT3+BIT4;//0,1,2,3,作为电机控制的输出端,其他的作为传感器的输入端  P5DIR=0X00;//P5为传感器输入端。设置P5为输入端。普通IO口。  P5SEL=0x00;      P2DIR=0X00;//输入    P2IE|=BIT3;  P2IES|=BIT3;    P6DIR=0XFF;//纯粹是为了调试用的。  P6OUT=0X00;  }void delay(int t){  unsigned int i;  while(t--)  {    i=65535;    while(i--);  }}void CLK_inti()//时钟初始化{  BCSCTL1=0X00;//打开XT2  do{    IFG1&=~OFIFG;    for(int i=0x20;i>0;i--);  }while((IFG1&OFIFG)==OFIFG);//如果起震失败。。继续起震。知道成功为止  BCSCTL2=0X00;  BCSCTL2|=SELM_2|SELS;//mclk,sMCLK的时钟源为XT2,0分频。}void PID_inti()//PID初始化 {  pid->error_1=0;  pid->sumerror=0;}void PWM_inti()//PWM初始化{  TACTL|=TASSEL_2|ID_0|MC_1|TACLR;//时钟源采用SMCLK,增计数模式。清空TAR,0分频  TACCR0=8000000/F;//0分频。所以Period=8000000/5000  TACCTL1|=OUTMOD_7;//两个PWM输出口的输出模式。  TACCTL2|=OUTMOD_7;//  LEFTOUT=0;  RIGHTOUT=0;}float abs(float a){  return a<0?-a:a;}void timer_inti()//用定时器B1来确定采样周期{  TBCTL|=TBSSEL_2|CNTL_0|ID_3|MC_1|TBCLR;//定时器B:SMCLK,16位,8分频,增计数  TBCCTL0|=CCIE;//使能timerb1的中断。  TBCCR0=5000;//八分频,1MHz,5000表示5ms。  _EINT();//打开总中断。}void num_inti(){  sensorin=0;  num=0;}void inti()//总初始化函数{  PID_inti();  CLK_inti();  PWM_inti();  IO_inti();  timer_inti();  num_inti();}float ReadSensor2(){  int state=0,i,num=0;  float sum=0;  static float output=0;  state=P3IN&0X80;  state<<=1;  state|=P5IN;  for(i=0;i<9;i++)    if(((1<<i)&state)==0)    {      sum+=weight1[i];      num++;    }      if(num>0&&num<7)//不是全白或者全黑   {     corner=0;     if(num>=3)     {       corner=1;       if(sum>0)         output=10;       else output=-10;       return output;     }     output=sum/num;   }   else if(num>=7)//如果是全黑。   {     flag++;     return output=0;   }   return output;}void Avoid(int time,int lspeed,int ldirection,int rspeed,int rdirection){  int state=0;  MotorLeft(lspeed,ldirection);//左转出去,n  delay(time);  MotorRight(lspeed,ldirection);  MotorLeft(rspeed,rdirection);  do{//右转,直到传感器压线。  state=P3IN&0X80;  state<<=1;  state|=P5IN;  }while(state==0X1FF);  PID_inti();//PID初始化}int  PIDCal(float error)//PID计算。位置式。{  float output,derror;      pid->sumerror+=error;    derror=(error-pid->error_1);    output=error*PC+derror*DC;    pid->error_1=error;  return (int)(output+0.5);}void main( void ){  WDTCTL=WDTHOLD+WDTPW;//close the watch dog;  inti();  sample=0;  corner=0;  flag=0;  detection=0;  while(1)  {    if(sample)    {      sensorin=ReadSensor2();      if(flag==1)//下坡,用定时器定时。到坡底后减速,只有第一次扫到黑线后才要减速。      {       // P6OUT=0X81;        WDTCTL=(WDTPW+WDTTMSEL+WDTCNTCL);        IE1|=WDTIE;        flag++;        continue;      }      if(corner)//如果是直角,      {        int state=0;        MotorLeft(100,1);//向前冲一段时间,然后再转。避免误判        MotorRight(100,1);delay_ms(20);        if(sensorin>0)//如果是右直角        {            MotorLeft(100,1);            MotorRight(30,0);         }         else//如果是左直角         {            MotorRight(100,1);             MotorLeft(30,0);          }          do          {            state=0;            state=P3IN&0X80;            state<<=1;            state|=P5IN;               }while(state==0x1ff);          continue;        }      MotorDrive(PIDCal(sensorin));      sample=0;    }    else if(!(P2IN&0X10)&&!detection)//壁障    {      detection=1;      P6OUT=0XF0;      MotorLeft(100,0);      MotorRight(100,0);      delay_ms(50);      if(pid->sumerror<0)      Avoid(5,60,0,100,1);//先左转,再右转      else Avoid(5,100,1,60,0);//先右转,再左转    }  }}#pragma vector=TIMERB0_VECTOR__interrupt void TimerB()//控制采样周期,大概10ms,中断正常。。{  sample=1;}#pragma vector=PORT2_VECTOR//用外部中断来判断并且处理避障__interrupt void Outside()//最后的抓取。用定时器B才给舵机输出PWM波{  if(P2IFG&BIT3)  {    P2IFG&=~BIT3;  //  P6OUT=0X07;    TBCTL|=TBSSEL_2|CNTL_0|ID_3|MC_1|TBCLR|TBIE;//定时器B:SMCLK,16位,4分频,增计数    TBCCR0=39999;//0分频。所以Period=8000000/500=16000    TBCCTL1|=OUTMOD_7;//两个PWM输出口的输出模式。    TBCCR1=0;    P4DIR|=BIT1;    P4SEL|=BIT1;    MotorLeft(0,1);//停止    MotorRight(0,1);    delay_ms(50);//延迟    Rangle(0);//夹住东西    delay_ms(300);    MotorLeft(100,0);//后退    MotorRight(100,0);    delay_ms(200);//延迟    MotorLeft(0,0);    MotorRight(0,0);    while(1);//死循环,结束。  }}#pragma vector=WDT_VECTOR__interrupt void wdtch(){  static int xx=0;  if(++xx==300)  {  //  P6OUT=0x01;    MotorLeft(100,0);    MotorRight(100,0);    delay_ms(160);    WDTCTL=WDTHOLD+WDTPW;    IE1&=~WDTIE;    xx=0;    tag=0;  }}


原创粉丝点击