51寻迹小车
集成了紅外通信,超聲波停車,尋跡,斑馬線,迷宮的51單片機智能小車
小車可以通過紅外實現小車最基本的前進、倒車、左右轉向以及調速
、進入尋跡、迷宮、斑馬線、超聲波模式
如果接線或者調試方面有問題請聯系作者
#include"reg51.h" #include "intrins.h" typedef unsigned int u16; typedef unsigned char u8;typedef unsigned long u32;sbit QIN1=P1^0;// P1.0輸出pwm sbit QIN2=P1^1;// P1.1輸出pwm sbit QIN3=P1^2;// P1.2輸出pwm sbit QIN4=P1^3;// P1.3輸出pwm sbit HIN1=P1^4;// P1.4輸出pwm sbit HIN2=P1^5;// P1.5輸出pwm sbit HIN3=P1^6;// P1.6輸出pwm sbit HIN4=P1^7;// P1.7輸出pwmsbit IRIN=P3^2; // 紅外口為3.2 中斷0sbit k1=P2^0; //尋跡模塊k1位 sbit k2=P2^1; //尋跡模塊k2位 sbit k3=P2^2; //尋跡模塊k3位 sbit k4=P2^4; //尋跡模塊k4位 sbit k5=P2^5; //尋跡模塊k5位sbit Echo = P3^0; //超聲波發射端 sbit Trig = P3^1; //超聲波接受端u8 i; // 定義占空比的變量 u16 count,count2,count3,count4; //pwm占空比(速度大小)u16 read1,read2; u8 Time;u8 IrValue[6]; //紅外接收數組u8 m=0,n=2,z=0,x=0;u8 d=0,b=0,c=0; u16 tme = 0; //超聲波時間變量 u16 s = 0; //超聲波測距后的距離 u16 flg = 0; void StartModule(); void t0(); void Conut();/********基本延時函數*******/ void delay(int u) {while(u--); } /****小車轉向需要的一些延時函數****/ void delayk2(int i) {while(i){i--;if((k2==0)||(k3==0)||(k4==0))i=0; } }void delayk3(int p) {while(p){p--;if(k3==0)p=0; } } void delayk4(int o) {while(o){o--;if((k4==0)||(k3==0)||(k2==0))o=0; } }void delayk5(int j) {while(j){j--;if(k3==0||k4==0)j=0; } }void delayk6(int l) {while(l){l--;if(k3==0||k2==0)l=0; } } void delayk7(int y) {while(y){y--;if(k1==0||k4==0||k3==0||k5==0||k2==0)y=0; } }/********小車運行狀態*******/ void fast_run() //直行 {count=30; count2=30; count3=0; count4=0; }void run() //高速直行 {count=70; count2=70; count3=0; count4=0;} void srun() //中速直行 {count=50; count2=50; count3=0; count4=0;} /****調試后需要的一些特殊轉向狀態****/ void bit_left() { count=30; count2=0; count3=0; count4=45; } void bit_right() { count=0; count2=30; count3=45; count4=0; } void middle_left() { count=35; count2=0; count3=0; count4=45; } void middle_right() { count=0; count2=35; count3=45; count4=0; } void left() { count=50; count2=0; count3=0; count4=40; } void right() { count=0; count2=50; count3=40; count4=0; } void behind_left() { count=40; count2=0; count3=0; count4=50; } void behind_right() { count=0; count2=40; count3=50; count4=0; }void back() //倒退 {count=0; count2=0; count3=30; count4=30; }void zdt() //從左面掉頭 {count=50;count2=0;count3=0;count4=50; } void dt() //從右面掉頭 {count=0;count2=50;count3=50;count4=0; } void stop() //停車 { count=0; count2=0; count3=0; count4=0; } /******走尋跡的函數****/ void xunji() { u8 flag; if((k1==1)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==1)) //沒檢測到,先直行再判斷,flag=9時back; { z++; if(z>=80){ if(x==1){flag=13;x=0;}if(x==2){ flag=14;x=0; }if(x==0);flag=8;}elseflag=0;}if((k1==1)&&(k2==1)&&(k3==0)&&(k4==1)&&(k5==1)) //中間感應到,直行 { flag=0; z=0; }if((k1==1)&&(k2==0)&&(k3==1)&&(k4==1)&&(k5==1)) //直行發生偏轉,微調{flag=1; z=0;}if((k1==1)&&(k2==1)&&(k3==1)&&(k4==0)&&(k5==1)) //直行發生偏轉,微調{ flag=2; z=0;} if((k1==0)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==1)) //大幅度左轉{flag=9; z=0; }if ((k1==1)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==0)) //大幅度右轉{flag=10; z=0;}if(((k1==1)&&(k2==0)&&(k3==0)&&(k4==0)&&(k5==1))||((k1==1)&&(k2==0)&&(k3==1)&&(k4==0)&&(k5==1))|| ((k1==0)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==0))|| ((k1==0)&&(k2==1)&&(k3==1)&&(k4==0)&&(k5==1))|| ((k1==1)&&(k2==0)&&(k3==1)&&(k4==1)&&(k5==0))|| ((k1==1)&&(k2==0)&&(k3==0)&&(k4==1)&&(k5==1))|| ((k1==1)&&(k2==1)&&(k3==0)&&(k4==0)&&(k5==1))) //意外情況,往前一點flag=5;if((k1==0)&&(k2==0)&&(k3==1)&&(k4==1)&&(k5==1)) //behind左轉flag=6;if((k1==1)&&(k2==1)&&(k3==1)&&(k4==0)&&(k5==0)) //behind右轉flag=7;if((k1==0)&&(k3==0)&&(k4==1)&&(k5==1)) //直角轉向,左轉{if(k2==0)flag=3;elseflag=11; x=1;}if((k1==1)&&(k2==1)&&(k3==0)&&(k5==0)) //直角轉向,右轉 { if(k4==0)flag=4;elseflag=12;x=2; }switch(flag) { case(0):{fast_run();break;} case(1):{bit_left();delayk3(500);break;} case(2):{bit_right();delayk3(500);break;} case(3):{delay(350);middle_left();delay(4);delayk2(3000);stop();delay(5);break;} case(4):{delay(350);middle_right();delay(400);delayk4(3000);stop();delay(5);break;} case(5):{fast_run();break; } case(6):{middle_left();delayk3(500);break;} case(7):{middle_right();delayk3(500);break;} case(8):{back(); delayk3(3000);delay(100);break;} case(9):{middle_left();delayk5(500);break;} case(10):{middle_right();delayk6(500);break;} case(11):{delay(500);while(!k3);behind_left();delayk6(2000);break;} case(12):{delay(500);while(!k3);behind_right();delayk5(2000);break;} case(13):{back();delayk3(300);delay(100);zdt();delayk6();stop();delay(5);} case(14):{back();delayk3(300);delay(100);dt();delayk5();stop();delay(5);} default:{run();delay(50);stop();delay(50);break;} } }/*****斑馬線函數*****/ void xuxian() { u8 flag; if((k1==1)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==1)) //沒檢測到,先直行再判斷,flag=9時back; { z++; if(z>=80)flag=8;elseflag=0;}if((k1==1)&&(k2==1)&&(k3==0)&&(k4==1)&&(k5==1)) //中間感應到,直行 { flag=0; z=0; }if((k1==1)&&(k2==0)&&(k3==1)&&(k4==1)&&(k5==1)) //直行發生偏轉,微調{flag=1; z=0;}if((k1==1)&&(k2==1)&&(k3==1)&&(k4==0)&&(k5==1)) //直行發生偏轉,微調{ flag=2; z=0;} if((k1==0)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==1)) //大幅度左轉{flag=9; z=0; }if ((k1==1)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==0)) //大幅度右轉{flag=10; z=0;}if(((k1==1)&&(k2==0)&&(k3==0)&&(k4==0)&&(k5==1))||((k1==1)&&(k2==0)&&(k3==1)&&(k4==0)&&(k5==1))|| ((k1==0)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==0))|| ((k1==0)&&(k2==1)&&(k3==1)&&(k4==0)&&(k5==1))|| ((k1==1)&&(k2==0)&&(k3==1)&&(k4==1)&&(k5==0))|| ((k1==1)&&(k2==0)&&(k3==0)&&(k4==1)&&(k5==1))|| ((k1==1)&&(k2==1)&&(k3==0)&&(k4==0)&&(k5==1))) //意外情況,往前一點flag=5;if((k1==0)&&(k2==0)&&(k3==1)&&(k4==1)&&(k5==1)) //behind左轉flag=6;if((k1==1)&&(k2==1)&&(k3==1)&&(k4==0)&&(k5==0)) //behind右轉flag=7;if((k1==0)&&(k3==0)&&(k4==1)&&(k5==1)) //直角轉向,左轉{if(k2==0)flag=3;elseflag=11; }if((k1==1)&&(k2==1)&&(k3==0)&&(k5==0)) //直角轉向,右轉 { if(k4==0)flag=4;elseflag=12; }switch(flag) { case(0):{run();break;} case(1):{bit_left();delayk5(500);break;} case(2):{bit_right();delayk6(500);break;} case(3):{delay(150);left();delay(200);delayk2(3000);stop();delay(5);break;} case(4):{delay(150);right();delay(200);delayk4(3000);stop();delay(5);break;} case(5):{fast_run();break; } case(6):{middle_left();delayk3(500);break;} case(7):{middle_right();delayk3(500);break;} case(8):{back(); delayk7(3000);delay(100);break;} case(9):{middle_left();delayk5(1000);break;} case(10):{middle_right();delayk6(1000);break;} case(11):{delay(200);left();delay(200);delayk2(3000);stop();delay(5);break;} case(12):{delay(200);right();delay(200);delayk4(3000);stop();delay(5);break;} default:{run();delay(50);stop();delay(50);break;} } }/******迷宮函數****/ void migong() { u8 cun,s=0;if((k1==1)&&(k2==1)&&(k3==0)&&(k4==1)&&(k5==1)){ cun=0; z=0; }if((k1==1)&&(k2==0)&&(k3==1)&&(k4==1)&&(k5==1)){ cun=8; z=0; }if((k1==1)&&(k2==1)&&(k3==1)&&(k4==0)&&(k5==1)){ cun=9; z=0; }if((k1==1)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==1)) //沒檢測到,先直行再判斷,flag=9時back; { z++; if(z>=30)cun=10;elsecun=0;}if((k1==0)&&(k2==0)&&(k3==0)&&(k4==0)&&(k5==0)){while(!((k1==1)&&(k2==1)&&(k3==0)&&(k4==1)&&(k5==1))){s++;}if((k1==1)&&(k2==1)&&(k3==0)&&(k4==1)&&(k5==1))cun=2;else if((d==1)&&(b==0)){cun=2; d=0; b=0; }else if((d==0)&&(b==1)){cun=3; d=0; b=0; }else cun=2; }if((k1==0)&&(k2==0)&&(k3==0)&&(k4==1)&&(k5==1)){delay(200);if((k1==1)&&(k2==1)&&(k3==0)&&(k4==1)&&(k5==1)){ cun=4; d++;}else { cun=5; d=0; b=0; }}if((k1==1)&&(k2==1)&&(k3==0)&&(k4==0)&&(k5==0)){delay(200);if((k1==1)&&(k2==1)&&(k3==0)&&(k4==1)&&(k5==1)){ cun=6; b++;} else { cun=7; d=0; b=0; }} switch(cun) { case(0):{fast_run();break;} case(1):{middle_right();delay(400);delayk5(2000);stop();delay(5);break;} case(2):{middle_left();delay(600);delayk2(2000);stop();delay(5);break;} case(3):{middle_right();delay(600);delayk2(2000);stop();delay(5);break;} case(4):{delay(50);middle_left();delay(500);delayk6(2000);stop();delay(5);break;} case(5):{delay(150);middle_left();delay(400);delayk2(2000);stop();delay(5);break;} case(6):{delay(50);middle_right();delay(500);delayk5(2000);stop();delay(5);break;} case(7):{delay(150);middle_right();delay(400);delayk2(2000);stop();delay(5);break;} case(8):{bit_left();delayk3(500);break;} case(9):{bit_right();delayk3(500);break;} case(10):{dt();break;}default:{run();delay(50);stop();delay(50);break;} }}/******************* * 功能:打開需要用到的中斷 * 用到的中斷:定時器0、1 工作方式1 16位定時器模式 * 外部終端0 *********************/ void timer() {TMOD=0x11;//定時器0工作方式1TH0=0xff;//(65536-10)/256;//賦初值定時TL0=0xf7;//(65536-10)%256;//0.01msTH1=0;TL1=0;EA=1;//開總中斷ET0=1;//開定時器0中斷ET1=1;TR0=1;//啟動定時器0 IT0=1;EX0=1;IRIN=1; }/********************************* *功能:接收紅外信號并改為小車的運行狀態 *輸入:外部中斷0 *********************************/void readjs() {if(IrValue[2]!=0) {read1=(IrValue[2]/16);read2=(IrValue[2]%16); if((read1==4)&&(read2==0)){ count+=10; count2+=10;n=2; count3=0;count4=0;if(count>=100)count=100;if(count2>=100)count2=100;}if((read1==1)&&(read2==9)){ if(count==0||count2==0){n=2; } else{count -= 10;count2 -= 10;n = 1; count3 = 0;count4 = 0;n = 2;if(count<=9)count=0;if(count2<=9)count2=0;}}if((read1==0)&&(read2==9)){count3=40;count=0;count4=0;count2=40;n=2;}if((read1==0)&&(read2==7)){count=40;count4=40;count2=0;count3=0;n=2;}if((read1==1)&&(read2==12)){count=100;count2=100;count3=0;count4=0;n=2;}if((read1==1)&&(read2==8)){m=0;n=2; count=40;count2=40;count3=0;count4=0;}if((read1==5)&&(read2==2)){m=1;n=2;count3=50;count4=50;count=0;count2=0;}if((read1==1)&&(read2==5)){count=0;count2=0;count3=0;count4=0; n=2;}if((read1==4)&&(read2==4)){n=0; } if((read1==4)&&(read2==7)){n=1; }if((read1==4)&&(read2==3)){n=3;count=30;count2=30;count3=0;count4=0; }if((read1==4)&&(read2==2)){n=4; }IrValue[2]=0;} }/*******主函數****/ void main() { timer(); //調用中斷打開函數while(1) { readjs(); /調用紅外函數,注:要放在循環中不然無法使用 switch(n) { case(0):{xunji();break;} case(1):{migong();break;} case(3):{StartModule();while(!Echo); //當RX為零時等待TR1=1; //開啟while(Echo); //當RX為定時并等待TR1=0; //關閉Conut();break;} //計算 case(4):{xuxian();break;} default:{break;} } } }/****定時器0溢出利用pwm調4個電機的速度***/ void tim0() interrupt 1 {//TR0=0;//賦初值時,關閉定時器TH0=0xff;//(65536-10)/256;//賦初值定時TL0=0xf7;//(65536-10)%256;//0.01ms,因為一個周期1us//TR0=1;//打開定時器i++;if(i>=100) //1khzi=0; if(i<=count) //占空比%30,可改{QIN2=0; HIN4=0;} else {QIN2=1; HIN4=1;}if(i<=count2) //占空比%30,可改{QIN4=0; HIN2=0; } else { QIN4=1;HIN2=1;}if(i<=count3) //占空比%30,可改{QIN1=0; HIN3=0;} else {QIN1=1; HIN3=1;}if(i<=count4) //占空比%30,可改{QIN3=0; HIN1=0; } else { QIN3=1;HIN1=1;}} /******超聲波啟動(發射超聲波)*****/void StartModule() //啟動模塊 {Trig=1; //啟動一次模塊_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();Trig=0; } void t0() interrupt 3 //T0中斷用來計數器溢出,超過測距范圍 {flg=1; //中斷溢出標志 } /*****計算小車前端到障礙物的距離*****/void Conut() {tme=TH1*0x100+TL1;TH1=0;TL1=0;s=(tme/58.0/100.0)*1000; if((s>=4000)||flg==1) //超出測量范圍顯示“-”{ flg=0;}else if(s<=1000){count=0;count2=0;count3=0;count4=0;} }/***紅外接收函數***/void ReadIr() interrupt 0 {u8 j,k;u16 err;Time=0; delay(700); //7msif(IRIN==0) //確認是否真的接收到正確的信號{ err=1000; //1000*10us=10ms,超過說明接收到錯誤的信號/*當兩個條件都為真是循環,如果有一個條件為假的時候跳出循環,免得程序出錯的時侯,程序死在這里*/ while((IRIN==0)&&(err>0)) //等待前面9ms的低電平過去 { delay(1);err--;} if(IRIN==1) //如果正確等到9ms低電平{err=500;while((IRIN==1)&&(err>0)) //等待4.5ms的起始高電平過去{delay(1);err--;}for(k=0;k<4;k++) //共有4組數據{ for(j=0;j<8;j++) //接收一組數據{err=60; while((IRIN==0)&&(err>0))//等待信號前面的560us低電平過去{delay(1);err--;}err=500;while((IRIN==1)&&(err>0)) //計算高電平的時間長度。{delay(10); //0.1msTime++;err--;if(Time>30){return;}}IrValue[k]>>=1; //k表示第幾組數據if(Time>=8) //如果高電平出現大于565us,那么是1{IrValue[k]|=0x80;}Time=0; //用完時間要重新賦值 }}}if(IrValue[2]!=~IrValue[3]){return;}} }總結
- 上一篇: IPGUARD卸载客户端方法
- 下一篇: PS与qq热键设置雷同