#include <reg52.h>//單片機(jī)頭文件 #include <intrins.h> #include <string.h> #include <stdio.h> #include <stdarg.h> //va_list 的頭文件 #define uchar unsigned char #define uint unsigned int sbit RS = P3^5; sbit RW = P3^6; sbit EN = P3^7; sbit RX = P3^3; //超聲波接收 sbit TX = P3^2; //超聲波發(fā)射 static bit flag = 0; /********************尋跡模塊IO口定義*********************************/ sbit xun_ll = P0^4; //從左到右第1個(gè) sbit xun_l = P0^3; //從左到右第2個(gè) sbit xun_z = P0^2; //從左到右第3個(gè) sbit xun_r = P0^1; //從左到右第4個(gè) sbit xun_rr = P0^0; //從左到右第5個(gè) /********************LN298電機(jī)驅(qū)動(dòng)IO口定義*********************************/ sbit qu_ll = P2^0; //左邊電機(jī)控制IN1 sbit qu_zl = P2^1; //左邊電機(jī)控制IN2 sbit qu_zr = P2^2; //右邊電機(jī)控制IN1 sbit qu_rr = P2^3; //右邊電機(jī)控制IN2 #define RS_H RS = 1 #define RS_L RS= 0 #define RW_H RW = 1 #define RW_L RW = 0 #define EN_H EN = 1 #define EN_L EN = 0 #define READ_DATA P1 void DelayMs(unsigned int z) //1ms延時(shí)函數(shù) { unsigned int x; for(;z>0;z--) for(x=110;x>0;x--); } void LCDWriteCom(unsigned char com) { RS_L; RW_L; READ_DATA= com; EN_H; DelayMs(5); EN_L; } void LCDWriteData(unsigned char dat) { RS_H; RW_L; READ_DATA= dat; EN_H; DelayMs(5); EN_L; } /******************************************************************************* **函數(shù)名稱(chēng):LCD_Write_str() **函數(shù)功能:在LCD上寫(xiě)入一串字符 **輸入 口:hang : 要寫(xiě)入的行,add 要寫(xiě)入列 *s要寫(xiě)入的指針數(shù)組 **輸出 口:無(wú) **返回 值:無(wú) **備 注:strlen()是引用庫(kù)函數(shù)string.h ,可以求出數(shù)組的長(zhǎng)度 **日 期:2014.2.22 *******************************************************************************/ void LcdWriteStr(unsigned charhang,unsigned char add,char*s) { unsigned char i; unsigned char length = 0; if(hang==1) LCDWriteCom(0x80+add); else LCDWriteCom(0x80+0x40+add); length = strlen(s); for(i=0;i<length;i++) LCDWriteData(*s++); //指針?biāo)屯陻?shù)據(jù)后自加一 } /*void LcdWriteChar(unsigned charhang,unsigned char add,char Ch) { if(hang== 1)LCDWriteCom(0x80+add); elseLCDWriteCom(0x80+0x40+add); LCDWriteData(Ch); }*/ //能像printf一樣使用 void Lcd1602Printf( unsigned char x, unsignedchar y, unsigned char *p,...) { charidata LcdBuf[17]; va_list ap; va_start(ap, p); vsprintf(LcdBuf,p,ap); va_end(ap); LcdWriteStr(x,y,LcdBuf); } void Init_1602(void) { LCDWriteCom(0x38); LCDWriteCom(0x0c); LCDWriteCom(0x06); LCDWriteCom(0x01); DelayMs(2); //Lcd1602Printf(1,0,"Lcd1602 Normal"); //測(cè)試液晶1602顯示用 Normal:正常 } //觸發(fā)一個(gè)高電平時(shí)間 static void StartModule(void) //啟動(dòng)模塊 { TX=1; //啟動(dòng)一次模塊 _nop_();_nop_();_nop_(); _nop_(); _nop_(); _nop_();_nop_(); _nop_();_nop_();_nop_(); _nop_(); _nop_(); _nop_();_nop_(); _nop_();_nop_();_nop_(); _nop_(); _nop_(); _nop_();_nop_(); TX=0; } /******************************************************************************* * Function Name : Conut * Description : 取出定時(shí)器的值,并通過(guò)計(jì)算得到距離,返回距離到調(diào)用函數(shù) * Input : None * Output : None * Return : 計(jì)算得到的距離 * Attention : 當(dāng)距離大于5m時(shí),返回3個(gè)8,表示超出量程 *******************************************************************************/ static int Conut(void) { uintS,time; time=TH0*256+TL0; TH0=0; TL0=0; S=(time*1.7)/100; //算出來(lái)是CM if((S>=500)||flag==1)//超出測(cè)量范圍 , 親測(cè)可以達(dá)到6M多一點(diǎn)點(diǎn),不過(guò) { //跳動(dòng)的很厲厲害,現(xiàn)改為5M flag = 0; S = 888; } returnS; } /******************************************************************************* * Function Name : GetDis * Description : 發(fā)出一個(gè)10us的高電平脈沖,得到超聲波測(cè)出的距離 * Input : None * Output : None * Return : S 測(cè)得的距離,Uint型變量,比如返回124,則表示為1.24M * Attention : 調(diào)用的函數(shù)有:StartModule,Conut *******************************************************************************/ int GetDis(void) { StartModule(); //給一個(gè)高電平觸發(fā)脈沖 while(!RX)xunnji(); //當(dāng)RX為零時(shí)等待 TR0=1; //開(kāi)啟計(jì)數(shù) while(RX)xunnji(); //當(dāng)RX為1計(jì)數(shù)并等待 TR0=0; returnConut(); //計(jì)算 } //定時(shí)器初始化 static void Timer0Init(void) { TMOD&= 0xf0; TMOD|= 0x01; //設(shè)T0為方式1, TH0=0; TL0=0; ET0=1; //允許T0中斷 EA=1; //開(kāi)啟總中斷 } /******************************************************************************* * Function Name : CsbInit * Description : 超聲波初始化函數(shù) * Input : None * Output : None * Return : None * Attention : 調(diào)用的函數(shù)有:Timer0Init ,只調(diào)用了一個(gè)定時(shí)器初始化 *******************************************************************************/ void CsbInit(void) { Timer0Init(); } /************************** 定時(shí)器0中斷服務(wù)函數(shù) *******************************/ void zd0() interrupt 1 //T0中斷用來(lái)計(jì)數(shù)器溢出,超過(guò)測(cè)距范圍 { flag=1; //中斷溢出標(biāo)志 } /***********************小車(chē)前進(jìn)函數(shù)************************/ void go() { qu_ll= 1; qu_zl= 0; qu_zr= 0; qu_rr= 1; } // /***********************小車(chē)后退函數(shù)************************/ // void back() // { // qu_ll= 0; // qu_zl= 1; // qu_zr= 1; // qu_rr= 0; // } /***********************小車(chē)左轉(zhuǎn)函數(shù) 只有一個(gè)輪子動(dòng)************************/ void left() { qu_ll= 0; qu_zl= 0; qu_zr= 0; qu_rr= 1; } /***********************小車(chē)左轉(zhuǎn)函數(shù) 左邊輪子后退 右邊輪子前進(jìn)************************/ void left_s() { qu_ll= 0; qu_zl= 1; qu_zr= 0; qu_rr= 1; } /***********************小車(chē)停下函數(shù)************************/ void stop() { qu_ll= 0; qu_zl= 0; qu_zr= 0; qu_rr= 0; } /***********************小車(chē)右轉(zhuǎn)函數(shù) 只有一個(gè)輪子動(dòng)************************/ void right() { qu_ll= 1; qu_zl= 0; qu_zr= 0; qu_rr= 0; } /***********************小車(chē)右轉(zhuǎn)函數(shù) 左邊輪子前進(jìn) 右邊輪子后退************************/ void right_s() { qu_ll= 1; qu_zl= 0; qu_zr= 1; qu_rr= 0; } void che_90_180_break(uchar dat) { uchari_z = 0; while(1) //循環(huán)等待中間尋跡傳感器到黑線(xiàn)上 { if(xun_z == 0) //如果中間那尋跡傳感器到了黑線(xiàn)上,要讓小車(chē)停下來(lái)前進(jìn)了 { i_z++; //消去干擾 if(i_z>= 10) //10次之后就確定尋跡模塊的中間傳感器到黑線(xiàn)上了 { if(dat == L) //如果是左轉(zhuǎn)90度就讓右轉(zhuǎn)的方法制動(dòng) right_s(); else left_s(); //如果是右轉(zhuǎn)90度就讓左轉(zhuǎn)的方法制動(dòng) DelayMs(50); go(); break; //break退出while(1)這個(gè)死循環(huán) } } else //沒(méi)有在黑錢(qián)上就給i_z變量清零 { i_z= 0; } } } /***********************小車(chē)左轉(zhuǎn)90度************************/ void left_s_90_while() //小車(chē)向左轉(zhuǎn)90度 { go(); //前進(jìn)一小會(huì)讓小車(chē)轉(zhuǎn)90度時(shí)剛好讓黑線(xiàn)在小車(chē)的中間 DelayMs(120); left_s(); //左轉(zhuǎn)90度注意這個(gè)延時(shí)不能太長(zhǎng) 只要能讓尋跡模塊中間的傳感離開(kāi)黑線(xiàn)就好 DelayMs(180); che_90_180_break(L); } /***********************小車(chē)向右轉(zhuǎn)90度************************/ void right_s_90_while() // { go(); //前進(jìn)一小會(huì)讓小車(chē)轉(zhuǎn)90度時(shí)剛好讓黑線(xiàn)在小車(chē)的中間 DelayMs(120); right_s(); //左轉(zhuǎn)90度注意這個(gè)延時(shí)不能太長(zhǎng) 只要能讓尋跡模塊中間的傳感離開(kāi)黑線(xiàn)就好 DelayMs(180); che_90_180_break(R); } // 白線(xiàn)為 1 黑線(xiàn)為 0 void xunnji() { if((xun_ll==1)&& (xun_l==1) && (xun_z==0) && (xun_r==1) &&(xun_rr==1)) { go(); //小車(chē)前進(jìn) } if((xun_ll==0)&& (xun_l==0) && (xun_z==0) && (xun_r==0) &&(xun_rr==0)) { stop(); } if(((xun_ll==1)&& (xun_l==1) && (xun_z==0) && (xun_rr==1)) || ((xun_ll==1) && (xun_l==1)&& (xun_z==1) && (xun_rr==1)) || ((xun_ll==1) && (xun_z==1)&& (xun_rr==0)) || ((xun_ll==1) && (xun_l==1)&& (xun_z==1) && ( (xun_rr==0))) { right(); } if(((xun_ll==1)&& (xun_l==0) && (xun_r==1) && (xun_rr==1)) || ((xun_ll==0) && (xun_l==0)&& (xun_z==1) && (xun_rr==1)) || ((xun_ll==0) && (xun_l==1)&& && (xun_r==1)&& (xun_rr==1))) { left(); } if((xun_ll==1)&& (xun_z==0) && (xun_rr==0)) { go(); DelayMs(1); if((xun_ll==1) &&(xun_z==0)&& (xun_rr==0)) { right_s_90_while(); } } if((xun_ll==0)&& (xun_l==0) && (xun_rr==1)) { go(); DelayMs(1); if((xun_ll==0) && (xun_l==0)&& (xun_rr==1)) { left_s_90_while(); } } } void main(void) { intDis = 0; InitTimer(); Init_1602(); CsbInit(); Dis= GetDis(); while(1) { xunnji(); if(bTime_500Ms) { bTime_500Ms= 0 ; Dis= GetDis(); Lcd1602Printf(2,3,"Dis= %4.2f",Dis/100.0); if(Dis< 24) { right_s(); DelayMs(500); } } } }
|