#include<reg52.h> #define uchar unsigned char #define uint unsigned int #define m0 1//黑線m1,白線m0 #define m1 0 #define full_speed_left 40 //方便調節各個狀態的占空比,可用參數組: (30,35,6,25,30,68000,27000,500); #define full_speed_right 45 //(40,45,6,25,30,68000,27000,500); #define correct_speed 6 //校正時的低速輪的占空比 #define turn_speed_left 25 #define turn_speed_right 30 #define lenth 68000 //測試數據:10000--》100--》500--》2000--80000--76000--68000 #define width 27000 //500--》10-->2000--》60000--30000---》27000 #define check_right 500 //2000--》20--》200--》500#define midl left1 #define midr right5 uchar Duty_left,Duty_right,i=0,j=0; //左右占空比標志,取1--100 sbit IN1=P2^0; sbit IN2=P2^1; sbit IN3=P2^2; sbit IN4=P2^3; sbit ENA=P1^0; sbit ENB=P1^1; //循跡口五組紅外對管,依次對應從左往右第1,2,3,4,5五組 sbit left1 =P1^6; sbit left2 =P1^5; sbit mid3 =P1^4; sbit right4=P1^3; sbit right5=P1^2; void line_left(); void line_right(); void line_straight()reentrant; //---------------------------------------- void delay(long int Delay_time)//延時函數 { uint t=Delay_time; while(t--); } //----------------------------------------- void init() //定時器初始化 { left1=m0; //初始化 left2=m0; //白線位置 mid3 =m1; //黑線位置 right4=m0; right5=m0; TMOD|=0x01; TH0=(65536-66)/256; TL0=(65536-66)%256; EA=1; ET0=1; TR0=1; ENA=1; //使能端口,初始化 ENB=1; } void time0(void)interrupt 1 //中斷程序 { i++; //調速在中斷中執行 j++; if(i<=Duty_left) ENA=1; else ENA=0; if(i>100) {ENA=1;i=0;} if(j<=Duty_right) ENB=1; else ENB=0; if(j>100) {ENB=1;j=0;} TH0=(65536-66)/256; //取約150HZ,12M晶振,每次定時66us,分100次,這樣開頭定義的變量正好直接表示占空比的數值 TL0=(65536-66)%256; } //----------------------------------------------- void correct_left()//向左校正,賦值 { Duty_left =correct_speed; Duty_right=full_speed_right; IN1=1; IN2=0; IN3=1; IN4=0; } //------------------------------------------------ void correct_right()//向右校正,賦值 { Duty_left =full_speed_left; Duty_right=correct_speed; N1=1; IN2=0; IN3=1; IN4=0; } //-------------------------------------------------- void turn_left()//左轉,賦值 { Duty_left =turn_speed_left; Duty_right=turn_speed_right; IN1=0; //轉彎時一個正轉,一個反轉, IN2=1; IN3=1; IN4=0; } void turn_right()//右轉,賦值 { Duty_left =turn_speed_left; Duty_right=turn_speed_right; IN1=1; //轉彎時一個正轉,一個反轉, IN2=0; IN3=0; IN4=1; } //----------------------------------------------------- void straight() //直走,賦值 { Duty_left =full_speed_left; //左右電機占空比初始化,調節直線運動速度 Duty_right=full_speed_right; //鑒于左右輪電機內部阻力不同,故占空比取不同值,這組值需要單獨寫程序取值 IN1=1; IN2=0; IN3=1; IN4=0; } //----------------------------------------------------- void line_straight()reentrant //函數名后加reentrant可以遞歸調用,//一直走黑直線時 { straight(); if(right5==m1){line_right();} else if(left1==m1){line_left();} else if(left2==m1) //防止校正時,小車沖出過大,導致2,4號檢測管屏蔽了兩端檢測管的檢測,避免其走直線時出軌 while(left2==m1) {correct_left(); if(right5==m1) { line_right(); goto label3; } else if(left1==m1) {line_left(); goto label3;} } else if(right4==m1) //防止校正時,小車沖出過大,導致2,4號檢測管屏蔽了兩端檢測管的檢測,避免其走直線時出軌 while(right4==m1) {correct_right(); if(right5==m1) {correct_right(); if(right5==m1) { line_right(); goto label3;} else if(left1==m1) {line_left();goto label3;} } else if((left1==m0)&&(left2==m0)&&(mid3==m0)&&(right4==m0)&&(right5==m0)) { straight(); //delay(lenth); while(right4==m0) //本來應該是用mid3,但是為了提高靈敏度,選擇right4;向左時,可取left2對管 {turn_right();} if(mid3==m1) {line_straight();} label3: ; //什么都不做 } //------------------------------------------------------------------------- void line_right() //右邊有黑線時 { straight();//這里的直走是在不管紅外檢測結果的直行 delay(lenth); if(mid3==m1) { turn_right();//執行向右轉的賦值 label:delay(width); //由width值決定轉彎時mid3經過黑線寬度時所需要的時間 if(mid3==m0) while(right4==m0) {} else goto label; } else if(mid3==m0) { turn_right(); while(right4==m0) {} if(midr==m1) {line_straight();} } } //-----------------------------------------------------------------void line_left() //左邊出現黑線時 { while(left1==m1) { if(right5==m1) { line_right(); goto label2; } } delay(check_right);//左邊遇到黑線時,左邊出了黑線之后,繼續延時一段時間,判斷右邊是否遇到黑線, //若遇到黑線,執行line_right()函數 if(right5==m1) { line_right(); goto label2; } } delay(check_right);//左邊遇到黑線時,左邊出了黑線之后,繼續延時一段時間,判斷右邊是否遇到黑線, //若遇到黑線,執行line_right()函數 if(right5==m1) { line_right(); goto label2; } if((mid3==m1)||(left2==m1)||(right4==m1)){line_straight();} else { while(left2==m0) {turn_left();} if(midl==m1) line_straight(); } label2: ; } //-------------------------------------------------------------------- void detect_infrared() //循跡,紅外檢測 { if(right5==m1){line_right();} else if(left1==m1){line_left();} else if(left2==m1){correct_left();} else if(right4==m1){correct_right();} else line_straight(); } //-------------------------------------- void main(void)//主程序部分 { init(); while(1) //循環檢測紅外對管采集的電平信號 {detect_infrared();} }
|