- #include<reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define u8 unsigned char
- #define u16 unsigned int
- uchar num;
- unsigned char irtime; //紅外用全局變量
- unsigned char IRcord[4]; //紅外按鍵對應碼值選對應功能的數組
- unsigned char irdata[33]; //存儲電平持續的時間的數組
- u16 EchoCnt;
- bit irpro_ok,irok; //位定義,用于判斷操作是否完成
- sbit in1=P1^0; //電機引腳定義
- sbit in2=P1^1;
- sbit in3=P1^2;
- sbit in4=P1^3;
- sbit IR=P3^2; //將IR位定義為P3.2引腳紅外模塊引腳
- sbit XUNJI0 =P2^2; //循跡模塊
- sbit XUNJI1 =P2^3;
- sbit Trig = P3^6; //超聲波模塊
- sbit Echo = P3^7;
- sbit XUNGUANG0 = P2^0; // 紅外尋光接口定義
- sbit XUNGUANG1 = P2^1;
- typedef enum
- {
- FORWARD=0,
- BACKUP,
- LEFT,
- RIGHT,
- STOP,
- ZHUANHUAN,
- XUNJI,
- BIZHANG,
- XUNGUANG,
- }MOTOR_DIR;
- void qianjin();
- void houtui();
- void zuozhuan();
- void youzhuan();
- void tingzhi();
- void DelayMs(u16 t); //延時函數
- void DelayUs(u16 i);
- void DcMotorContorl(MOTOR_DIR dir, u8 speed); // 小車直流電機控制,dir為方向,speed為速度
- void TIM0init(); //定時器0初始化
- void Ircordpro();
- void Ir_work();
- void HC04_Init();
- void HC04_Loop();
- void hongwaiyaokong(); //紅外遙控函數
- void lanya(); //藍牙遙控函數
- void xunji(); //循跡函數
- void bizhang(); //壁障函數
- void xunguang(); //尋光函數
- void init_t1() //初始化函數
- {
- TMOD=0x20; //設置定時器1為工作方式2
- TH1=0xfd; //波特率初始值
- TL1=0xfd;
- TR1=1; //定時器打開
- REN=1; //允許串行接受
- SM0=0; //串行口工作方式設置為1
- SM1=1;
- EA=1; //打開總中斷
- ES=1;
- }
- void main() //主函數
- {
- init_t1();
- while(1)
- {
- lanya();
- }
- }
- void EX0init(void) // 外部中斷初始化
- {
- IT0 = 1; //指定外部中斷0下降沿觸發,INT0 (P3.2)
- EX0 = 1; //允許外部中斷0
- EA = 1; //開總中斷
- }
- void ex0_isr (void) interrupt 0 using 0 //外部中斷0服務函數
- {
- static unsigned char i; //接收紅外信號處理
- static bit startflag; //是否開始處理標志位
- if(startflag)
- {
- if(irtime<63&&irtime>=33)//引導碼 TC9012的頭碼,9ms低電平+4.5ms高電平
- i=0;
- irdata[i]=irtime;//存儲每個電平的持續時間,用于以后判斷是0還是1
- irtime=0;
- i++;
- if(i==33)
- {
- irok=1;
- i=0;
- }
- }
- else
- {irtime=0;
- startflag=1;
- }
- }
- void tim0_isr (void) interrupt 1 using 1//定時器0中斷服務函數
- {
- irtime++; //用于計數2個下降沿之間的時間
- }
- void TIM0init(void)//定時器0初始化
- {
- TMOD=0x02;//定時器0工作方式2,TH0是重裝值,TL0是初值
- TH0=0x00; //重載值
- TL0=0x00; //初始化值
- ET0=1; //開中斷允許位
- TR0=1; //開啟定時器功能
- }
- void t1() interrupt 4//中斷服務函數
- {
- if(RI)
- {
- RI=0;
- num=SBUF-48; //將接收到的碼值轉換為十進制整數以選擇對應功能
- }
- }
- void HC04_Init(void) //初始化超聲波模塊
- {
- Trig = 0;
- Echo = 0;
- TMOD &=0X0f;
- TMOD |=0X10; //使用模式1,16位定時器1;
- TH1=0; //裝初值
- TL1=0;
- EA=1; //開總中斷
- ET1=1; //開定時器1中斷
- TR1=0; //定時器1
- }
- void HC04_Loop(void) //數據處理函數計算前方物體和小車的距離
- {
- Trig = 1;
- DelayUs(20);
- Trig = 0;
- while(Echo == 0);
- TH1=0;
- TL1=0;
- TR1=1;
- while(Echo == 1);
- EchoCnt = (TH1*256 + TL1)*1.7/100;
- }
- void lanya()
- {
- while(1)
- {
- switch(num)
- {
- case 1: qianjin();break; //前進
- case 2: zuozhuan();break; //左轉
- case 3: tingzhi();break; //停止
- case 4: youzhuan();break; //右轉
- case 5: houtui();break; //后退
- case 6: hongwaiyaokong();break; //啟動紅外遙控
- case 7: xunji();break; //啟動循跡功能
- case 8: bizhang();break; //啟動壁障功能
- case 9: xunguang();break; //啟動尋光功能
- default:break;
- }
- }
- }
- /*藍牙遙控電機程序*/
- void qianjin()
- {
- in1=1;
- in2=0;
- in3=1;
- in4=0;
- }
- void houtui()
- {
- in1=0;
- in2=1;
- in3=0;
- in4=1;
- }
- void zuozhuan()
- {
- in1=1;
- in2=0;
- in3=0;
- in4=0;
- }
- void youzhuan()
- {
- in1=0;
- in2=0;
- in3=1;
- in4=0;
- }
- void tingzhi()
- {
- in1=0;
- in2=0;
- in3=0;
- in4=0;
- }
- void hongwaiyaokong() // 紅外遙控函數
- {
- TIM0init();
- EX0init();
- while(1)
- {
- if(irok) //如果接收好了進行紅外處理 紅外解碼
- {
- Ircordpro();
- irok=0;
- }
- if(irpro_ok) //如果處理好后進行工作處理,執行對應功能
- {
- Ir_work();
- }
- }
- }
- void xunji() // 循跡函數
- {
- DelayMs(1000); // 默認延時,等待系統穩定
- while(1)
- {
- DcMotorContorl(FORWARD, 10);
- if((XUNJI0 == 1) && (XUNJI1 == 0)) // 尋跡右邊紅外檢測到黑線
- {
- DcMotorContorl(RIGHT, 14); // 小車往右邊走
- }
- else if((XUNJI0 == 0) && (XUNJI1 == 1)) // 小車左邊紅外檢測到黑線
- {
- DcMotorContorl(LEFT, 14); // 小車往左邊走
- }
- else if((XUNJI0 == 0) && (XUNJI1 == 0)) // 小車左右都沒有檢測到黑線
- {
- DcMotorContorl(FORWARD, 10); // 小車直走
- }
- }
- }
- void bizhang(void) //壁障函數
- {
- HC04_Init();
- while(1)
- {
- HC04_Loop(); //調用數據處理函數
- if(EchoCnt < 25) // 距離小于25CM
- {
- DcMotorContorl(STOP, 20); // 小車停止
- DcMotorContorl(RIGHT, 20); //小車右轉
- DelayUs(1500);
- if(EchoCnt < 25)
- {
- DcMotorContorl(STOP, 20); // 小車停止
- DcMotorContorl(RIGHT, 25); //小車右轉
- }
- else
- {
- DcMotorContorl(FORWARD, 20); // 小車前進
- }
- }
- else
- {
- DcMotorContorl(FORWARD, 20); // 小車前進
- }
- }
- }
- void xunguang(void) //尋光函數
- {
- DelayMs(1000); // 延時,等待系統穩定
- while(1)
- {
- if((XUNGUANG0 == 1) && (XUNGUANG1 == 0)) // 尋光右邊紅外檢測到光線
- {
- DcMotorContorl(RIGHT, 15); // 小車往右邊走
- }
- else if((XUNGUANG0 == 0) && (XUNGUANG1 == 1)) // 小車左邊紅外檢測到光線
- {
- DcMotorContorl(LEFT, 15); // 小車往左邊走
- }
- else if((XUNGUANG0 == 0) && (XUNGUANG1 == 0)) // 小車左右都有檢測到光線
- {
- DcMotorContorl(FORWARD, 20); // 小車直走
- }
- }
- }
- /*紅外遙控電機程序*/
- void DcMotorContorl(MOTOR_DIR dir,u8 speed)
- {
- switch(dir)
- {
- case FORWARD: // 前進
- in1 = 1;
- in2 = 0;
- in3 = 1;
- in4 = 0;
- break;
- case BACKUP: // 后退
- in1 = 0;
- in2 = 1;
- in3 = 0;
- in4 = 1;
- break;
- case LEFT: // 左轉
- in1 = 0;
- in2 = 1;
- in3 = 1;
- in4 = 0;
- break;
- case RIGHT: // 右轉
- in1 = 1;
- in2 = 0;
- in3 = 0;
- in4 = 1;
- break;
- case STOP: // 停止
- in1 = 0;
- in2 = 0;
- in3 = 0;
- in4 = 0;
- break;
- case ZHUANHUAN: //轉換功能
- lanya();
- break;
- case XUNJI: //循跡功能
- xunji();
- break;
- case BIZHANG: //壁障功能
- bizhang();
- break;
- case XUNGUANG: //尋光功能
- xunguang();
- break;
- default: // 其他
- in1 = 0;
- in2 = 0;
- in3 = 0;
- in4 = 0;
- break;
- }
- DelayMs(speed); // speed的值越大,速度越快
- in1 = 1;
- in2 = 1;
- in3 = 1;
- in4 = 1;
- DelayMs(25 - speed); // speed的值越大,延時時間越短,速度越快
- }
- void DelayMs(u16 t)
- {
- u16 i,j;
- for(i=0; i<t; i++)
- for(j=0; j<120; j++);
- }
- void DelayUs(u16 i)
- {
- while(--i);
- }
- void Ir_work(void) //紅外鍵值處理,紅外鍵值轉程序
- {
-
- switch(IRcord[2]) //判斷第三個數碼值
- {
- case 0x0c: // 數字1 //轉換為藍牙
- DcMotorContorl(ZHUANHUAN, 0);
- break;
- case 0x18: // 數字2
- DcMotorContorl(FORWARD, 20); // 小車直行
- break;
- case 0x5e: // 數字3
- DcMotorContorl(XUNJI, 0); //循跡功能
- break;
- case 0x08: // 數字4
- DcMotorContorl(LEFT, 20); // 小車左轉
- break;
- case 0x1c: // 數字5
- DcMotorContorl(STOP, 20); // 小車停止
- break;
- case 0x5a: // 數字6
- DcMotorContorl(RIGHT, 20); // 小車右轉
- break;
- case 0x42: // 數字7
- DcMotorContorl(BIZHANG, 0); //壁障功能
- break;
- case 0x52: // 數字8
- DcMotorContorl(BACKUP, 20); // 小車后退
- break;
- case 0x4a: // 數字9
- DcMotorContorl(XUNGUANG, 0); //尋光功能
- break;
- case 0x16: // 數字0
- break;
- case 0x46: // Mode
- DcMotorContorl(FORWARD, 20); // 小車直行
- break;
- case 0x40: // <-
- DcMotorContorl(STOP, 20); // 小車停止
- break;
- case 0x44: // >||
- DcMotorContorl(LEFT, 20); // 小車左轉
- break;
- case 0x43: //->
- DcMotorContorl(RIGHT, 20); // 小車右轉
- break;
- case 0x15: // VOL-
- DcMotorContorl(BACKUP, 20); // 小車后退
- break;
- default:
- break;
- }
- //irpro_ok=0;//處理完成標志
- }
- void Ircordpro(void) //紅外解碼碼值處理函數
- {
- unsigned char i, j, k;
- unsigned char cord,value;
- k=1;
- for(i=0;i<4;i++) //處理4個字節
- {
- for(j=1;j<=8;j++) //處理1個字節8位
- {
- cord=irdata[k];
- if(cord>7) //大于某值為1,這個和晶振有絕對關系,此值可以有一定誤差
- {
- value=value|0x80;
- }
- else
- {
- value=value;
- }
- if(j<8)
- {
- value=value>>1;
- }
- k++;
- }
- IRcord[i]=value;
- value=0;
- }
- irpro_ok=1; //處理完畢標志位置1
- }
復制代碼 |