|
超聲波避障小車(chē),紅外遙控小車(chē)上下左右運(yùn)動(dòng)仿真
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.gif (200.9 KB, 下載次數(shù): 51)
下載附件
2022-12-30 06:01 上傳
1.png (46.83 KB, 下載次數(shù): 54)
下載附件
2022-12-30 05:33 上傳
2.png (35.63 KB, 下載次數(shù): 53)
下載附件
2022-12-30 05:33 上傳
單片機(jī)源程序如下:
- #include <reg52.h> //51頭文件
- #include <intrins.h> //包含nop等系統(tǒng)函數(shù)
- #define uchar unsigned char
- #define uint unsigned int
- /*紅外*/
- #define JINGZHEN 12
- #define TIME0TH ((65536-100*JINGZHEN/12)&0xff00)>>8 //12M晶振機(jī)械周期0.25us,100us,紅外遙控
- #define TIME0TL ((65536-100*JINGZHEN/12)&0xff)
- unsigned char count0 = 50;
- unsigned char count1 = 0;
- sbit EN = P2^5;
- uint IrCount=0,Show=0,Cont=0;
- uchar IRDATBUF[32];
- uchar IrDat[5]={0,0,0,0,0};
- uchar IrStart=0,IrDatCount=0;
- code uchar BitMsk[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,};
- /*電機(jī)驅(qū)動(dòng)IO定義*/
- sbit IN1 = P1^2; //為1 左電機(jī)反轉(zhuǎn)
- sbit IN2 = P1^3; //為1 左電機(jī)正轉(zhuǎn)
- sbit IN3 = P1^6; //為1 右電機(jī)正轉(zhuǎn)
- sbit IN4 = P1^7; //為1 右電機(jī)反轉(zhuǎn)
- sbit EN1 = P1^4; //為1 左電機(jī)使能
- sbit EN2 = P1^5; //為1 右電機(jī)使能
- /*按鍵定義*/
- sbit key_s2 = P3^0;
- sbit beep = P2^3;//蜂鳴器
- sbit RX = P2^0;//ECHO超聲波模塊回響端
- sbit TX = P2^1;//TRIG超聲波模塊觸發(fā)端
- sbit LCM_RW = P3^6; //定義LCD引腳
- sbit LCM_RS = P3^5;
- sbit LCM_E = P3^4;
- sbit servorControl =P2^7; //舵機(jī)的控制引腳
- #define lcddata P0 //定義液晶屏數(shù)據(jù)口
- #define Busy 0x80 //用于檢測(cè)LCM狀態(tài)字中的Busy標(biāo)識(shí)
- #define left_motor_en EN1 = 1 //左電機(jī)使能
- #define right_motor_en EN2 = 1 //右電機(jī)使能
- #define left_motor_stops IN1 = 0, IN2 = 0//左電機(jī)停止
- #define right_motor_stops IN3 = 0, IN4 = 0//右電機(jī)停止
- #define left_motor_go IN1 = 0, IN2 = 1//左電機(jī)正傳
- #define left_motor_back IN1 = 1, IN2 = 0//左電機(jī)反轉(zhuǎn)
- #define right_motor_go IN3 = 1, IN4 = 0//右電機(jī)正傳
- #define right_motor_back IN3 = 0, IN4 = 1//右電機(jī)反轉(zhuǎn)
- unsigned char pwm_left_val = 38;//左電機(jī)占空比值 取值范圍0-80,0最快
- unsigned char pwm_right_val = 44;//右電機(jī)
- unsigned char pwm_t;//周期
- unsigned int time = 0;//傳輸時(shí)間
- unsigned long S = 0;//距離
- bit flag = 0;//超出測(cè)量范圍標(biāo)志位
- bit flag1=0;//舵機(jī)模塊計(jì)數(shù)標(biāo)志
- uchar control=5; //控制舵機(jī)轉(zhuǎn)角
- uchar servorTime=0; //控制舵機(jī)脈沖占空比
- uchar lFlag=0;//左方向是否有障礙的標(biāo)志
- uchar rFlag=0;//右方向是否有障礙的標(biāo)志
- uint ldistance=0,rdistance=0;//左右邊長(zhǎng)度
- unsigned char code tishi[] ="the distance is:";//LCD1602顯示格式
- unsigned char code ASCII[13] = "0123456789.cm";
- unsigned char code table[]=" howfar:000.0cm";
- unsigned char code table1[]=" Out of range ";
- unsigned char disbuff[4] = { 0,0,0,0};//距離顯示緩存
-
- bit flagg=0; //切換正常避障模式和遙控模式
- void delay(unsigned int z)//毫秒級(jí)延時(shí)
- {
- unsigned int x,y;
- for(x = z; x > 0; x--)
- for(y = 114; y > 0 ; y--);
- }
- void Delay10us(unsigned char i) //10us延時(shí)函數(shù) 啟動(dòng)超聲波模塊時(shí)使用
- {
- unsigned char j;
- do{
- j = 10;
- do{
- _nop_();
- }while(--j);
- }while(--i);
- }
-
- /************************************LCD1602液晶屏驅(qū)動(dòng)函數(shù)************************************************/
- /******************讀狀態(tài)**********************/
- unsigned char readstatus(void)
- {
- lcddata = 0xFF;
- LCM_RS = 0;
- Delay10us(1);
- LCM_RW = 1;
- Delay10us(1);
- do{
- LCM_E = 0;
- Delay10us(1);
- LCM_E = 0;
- Delay10us(1);
- LCM_E = 1;
- Delay10us(1);
- }
- while (lcddata & Busy); //檢測(cè)忙信號(hào)
- return(lcddata);
- }
- /****************寫(xiě)數(shù)據(jù)************************/
- void writedata(unsigned char datas)
- {
- readstatus(); //檢測(cè)忙
- lcddata = datas;
- LCM_RS = 1;
- Delay10us(1);
- LCM_RW = 0;
- Delay10us(1);
- LCM_E = 0; //若晶振速度太高可以在這后加小的延時(shí)
- Delay10us(1);
- LCM_E = 0; //延時(shí)
- Delay10us(1);
- LCM_E = 1;
- Delay10us(1);
- }
- /***************寫(xiě)指令*************************/
- void writecom(unsigned char WCLCM,BuysC) //BuysC為0時(shí)忽略忙檢測(cè)
- {
- if (BuysC) readstatus(); //根據(jù)需要檢測(cè)忙
- lcddata = WCLCM;
- LCM_RS = 0;
- Delay10us(1);
- LCM_RW = 0;
- Delay10us(1);
- LCM_E = 0;
- Delay10us(1);
- LCM_E = 0;
- Delay10us(1);
- LCM_E = 1;
- Delay10us(1);
- }
- /*******************初始化******************/
- void lcdinition(void)
- {
- lcddata = 0;
- writecom(0x38,0); //三次顯示模式設(shè)置,不檢測(cè)忙信號(hào)
- delay(5);
- writecom(0x38,0);
- delay(5);
- writecom(0x38,0);
- delay(5);
- writecom(0x38,1); //顯示模式設(shè)置,開(kāi)始要求每次檢測(cè)忙信號(hào)
- writecom(0x08,1); //關(guān)閉顯示
- writecom(0x01,1); //顯示清屏
- writecom(0x06,1); // 顯示光標(biāo)移動(dòng)設(shè)置
- writecom(0x0c,1); // 顯示開(kāi)及光標(biāo)設(shè)置
- }
- /*******************按指定位置顯示一個(gè)字符*****/
- void DisplayOneChar(unsigned char x, unsigned char y, unsigned char data2)
- {
- y &= 0x1;
- x&= 0xF; //限制X不能大于15,Y不能大于1
- if (y) x |= 0x40; //當(dāng)要顯示第二行時(shí)地址碼+0x40;
- x |= 0x80; //算出指令碼
- writecom(x, 1); //發(fā)命令字
- writedata(data2); //發(fā)數(shù)據(jù)
- }
- /******************按指定位置顯示一串字符*******/
- void DisplayListChar(unsigned char x, unsigned char y, unsigned char code *DData)
- {
- unsigned char ListLength;
- ListLength = 0;
- y &= 0x1;
- x &= 0xF; //不能大于15,y不能大于1
- while (DData[ListLength]>0x19) //若到達(dá)字串尾則退出
- {
- if (x <= 0xF) //坐標(biāo)應(yīng)小于0xF
- {
- DisplayOneChar(x, y, DData[ListLength]); //顯示單個(gè)字符
- ListLength++;
- x++;
- }
- }
- }
- /***************************************************************************/
-
- /*小車(chē)前進(jìn)*/
- void forward(uint m)
- {
- left_motor_go; //左電機(jī)前進(jìn)
- right_motor_go; //右電機(jī)前進(jìn)
- delay(m);
- }
- /*PWM控制使能 小車(chē)后退*/
- void backward(uint m)
- {
- left_motor_back; //左電機(jī)后退
- right_motor_back; //右電機(jī)后退
- delay(m);
- }
- /*小車(chē)停止*/
- void stop(uint m)
- {
- right_motor_stops;//右電機(jī)停止
- left_motor_stops; //左電機(jī)停止
- delay(m);
- }
- /*小車(chē)左轉(zhuǎn)*/
- void left_rapidly(uint m)
- {
- left_motor_back;
- right_motor_go;
- delay(m);
- }
- /*小車(chē)右轉(zhuǎn)*/
- void right_rapidly(uint m)
- {
- right_motor_back;
- left_motor_go;
- delay(m);
- }
- /*判斷S2是否被按下*/
- void keyscan()
- {
- for(;;) //死循環(huán)
- {
- if(key_s2 == 0)// 實(shí)時(shí)檢測(cè)S2按鍵是否被按下
- {
- delay(5); //軟件消抖
- if(key_s2 == 0)//再檢測(cè)S2是否被按下
- {
- while(!key_s2);//松手檢測(cè)
- beep = 0; //使能有源蜂鳴器
- delay(200);//200毫秒延時(shí)
- beep = 1; //關(guān)閉有源蜂鳴器
- break; //退出FOR死循環(huán)
- }
- }
- }
- }
- /*LCD顯示所測(cè)結(jié)果*/
- void xianshi( )
- {
- if((S>=4000)||flag==1) //超出測(cè)量范圍
- {
- flag=0;
- DisplayListChar(0, 1, table1);
- }
- else
- {
- disbuff[0]=S/1000; //距離數(shù)值千位
- disbuff[1]=S%1000/100;//距離數(shù)值百位
- disbuff[2]=S%100/10;//距離數(shù)值十位
- disbuff[3]=S%10; //距離數(shù)值個(gè)位
- DisplayListChar(0, 1, table);
- DisplayOneChar(9, 1, ASCII[disbuff[0]]);
- DisplayOneChar(10, 1, ASCII[disbuff[1]]);
- DisplayOneChar(11, 1, ASCII[disbuff[2]]);
- DisplayOneChar(12, 1, ASCII[10]);
- DisplayOneChar(13, 1, ASCII[disbuff[3]]);
- DisplayOneChar(14, 1, ASCII[11]);
- DisplayOneChar(15, 1, ASCII[12]);
- }
- }
- void qidongceju() //啟動(dòng)超聲波模塊
- {
- TX=1; //啟動(dòng)一次模塊
- Delay10us(2); //延時(shí)20us
- TX=0;
- }
- /*計(jì)算超聲波所測(cè)距離并顯示*/
- uint ceju()
- {
- TH0=0;
- TL0=0;
- qidongceju();
- while(!RX); //當(dāng)RX(ECHO信號(hào)回響)為零時(shí)等待
- TR0=1; //開(kāi)啟計(jì)數(shù)
- while(RX); //當(dāng)RX為1計(jì)數(shù)并等待
- TR0=0; //關(guān)閉計(jì)數(shù)
- time=TH0*256+TL0;
- S=(float)(time*1.085)*0.16; //單位為MM
- if(S<=400)
- return 1; //距離小于400mm時(shí)返回1
- else
- return 0;
- }
- void duoji(uchar m) //舵機(jī)轉(zhuǎn)向定義
- {
- control=m;
- servorTime=0;
- flag1=1;
- delay(100);
- flag1=0;
- delay(100); //延時(shí),降低轉(zhuǎn)向速度
- }
- /*超聲波避障*/
- void avoid()
- {
- if(S < 400)//設(shè)置避障距離 ,單位毫米 剎車(chē)距離
- {
- beep = 0;//使能蜂鳴器
- stop();//停車(chē)
- do{
- xianshi();
- duoji(18); //使舵機(jī)向左擺動(dòng)
- lFlag=ceju();
- xianshi();
- ldistance=S;
- duoji(8); //使舵機(jī)向右擺動(dòng)
- rFlag=ceju();
- xianshi();
- rdistance=S;
- duoji(13);//控制舵機(jī)使超聲波模塊正對(duì)前方
- backward(200);
- if(rdistance>ldistance)
- {
- right_rapidly(10);
- }
- if(ldistance>rdistance)
- {
- left_rapidly(10);
- }
- }while(lFlag==1&&rFlag==1);//當(dāng)前方、左右側(cè)都有障礙物
- if(lFlag==0&&rFlag==1) //左側(cè)沒(méi)有障礙物,右側(cè)有
- {
- left_rapidly(80);
- }
- else if(rFlag==0&&lFlag==1)//右側(cè)沒(méi)有障礙物,左側(cè)有
- {
- right_rapidly(80);
- }
- else if(rFlag==0&&lFlag==0)//兩側(cè)都沒(méi)有障礙物,默認(rèn)向前走
- {
- forward();
- }
- }
- else{
- forward();
- beep=1;
- }
- }
- void inition1()
- {
- TMOD = 0x21;//定時(shí)器1工作模式2,8位自動(dòng)重裝;
- TH0 = 0;//定時(shí)器0工作模式1,16位定時(shí)用于產(chǎn)生PWM,T0用測(cè)ECH0脈沖長(zhǎng)度
- TL0 = 0;//T0,16位定時(shí)計(jì)數(shù)用于記錄ECHO高電平時(shí)間
- ET0 = 1;
- TH1 = 155;
- TL1 = 155; //100HZ T1
- ET1 = 1;
- TR1 = 1;
- EA = 1;
- }
- void inition2()
- {
- TMOD |= 0x011;
- TH0 = TIME0TH;
- TL0 = TIME0TL;
- ET0=1;
- TR0=1;
- ET1=1;
- TR1=1;
- IT0 = 1; //下降沿
- EX0 = 1;
- EA=1;
- }
- void scan()
- {
- if(Show==1)
- {
- Show=0;
- Cont=0;
- switch (IrDat[3])
- {
- case 0x12://go
- forward(1);
- break;
- case 0x0b://back
- backward(1);
- break;
- case 0x1a://right
- right_rapidly(1);
- break;
- case 0x1e://left
- right_rapidly(1);
- break;
-
- }
- }
- }
- void main()
- {
- lcdinition();
- delay(5);
- DisplayListChar(0, 0, tishi);//1602第一行顯示tishi數(shù)組內(nèi)容
- DisplayListChar(0, 1, table);//1602第二行顯示table數(shù)組內(nèi)容
- keyscan();//等待按下S2啟動(dòng)小車(chē)
- TX = 0;
- if(flagg==0)
- inition1();
- else
- {
- inition2();
- }
- while(1)
- {
- if(flagg==0){
- duoji(13);//控制舵機(jī)使超聲波模塊正對(duì)前方
- ceju();
- xianshi();
- avoid(); }
- else
- {
- scan();
- }
- }
- }
- /*定時(shí)器1中斷輸出PWM信號(hào)*/
- ……………………
- …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
Keil代碼與Proteus8.13仿真下載:
紅外超聲波舵機(jī)避障小車(chē)仿真和代碼.zip
(145.18 KB, 下載次數(shù): 90)
2022-12-29 21:56 上傳
點(diǎn)擊文件名下載附件
代碼和仿真
|
評(píng)分
-
查看全部評(píng)分
|