- #include <reg52.h> //包含51單片機相關的頭文件
- #define bint unsigned int //重定義無符號整數類型
- #define char unsigned char //重定義無符號字符類型
- char code Roadshow[]={0x03,0x9F,0x25,0x0D,0x99, //定義數碼管顯示數據
- 0x49,0x41,0x1F,0x01,0x19};//0,1,2,3,4,5,6,7,8,9
- char code Recitative[]={0x07,0x0A,0x1B,0x1F,0x0C,0x0D,0x0E,0x00,0x0F,0x19};
- char IRCOM[7];
- static unsigned int Led Flash; //定義閃動頻率計數變量
- unsigned char Run Flag=0; //定義運行標志位
- bit Enable Light=0; //定義指示燈使能位
- /***********完成基本數據變量定義**************/
- bit S1State=P1^0; //定義S1狀態標志位
- bit S2State=P1^1; //定義S2狀態標志位
- bit B1State=P1^2; //定義B1狀態標志位
- bit Instate=P1^3; //定義IR狀態標志位
- bit Understate=P1^4; //定義運行停止標志位
- bit Attestation=P1^5; //定義Frontier狀態標志位
- bit Interstate=P1^6; //定義Lefter狀態標志位
- bit Rightist=P1^7; //定義Rightist狀態標志位
- /*************完成狀態指示燈定義*************/
- bit S1=P3^2; //定義S1按鍵端口
- bit S2=P3^4; //定義S2按鍵端口
- /*************完成按鍵端口的定義*************/
- bit Left Led=P2^0; //定義前方左側指示燈端口
- bit Right Led=P0^7; //定義前方右側指示燈端口
- /*************完成前方指示燈端口定義*********/
- bit Lefter=P3^5; //定義前方左側紅外探頭
- bit Right=P3^6; //定義前主右側紅外探頭
- bit Frontier=P3^7; //定義正前方紅外探頭
- /*************完成紅外探頭端口定義***********/
- bit M1A=P0^0; //定義電機1正向端口
- bit M1B=P0^1; //定義電機1反向端口
- bit M2A=P0^2; //定義電機2正向端口
- bit M2B=P0^3; //定義電機2反向端口
- /*************完成電機端口定義***************/
- bit B1=P0^4; //定義話筒傳感器端口
- bit RL1=P0^5; //定義光敏電阻端口
- bit SB1=P0^6; //定義蜂鳴端口
- /*********完成話筒,光敏電阻,蜂鳴器.端口定義**/
- bit IRIN=P3^3; //定義紅外接收端口
- /*********完成紅外接收端口的定義*************/
- #define Shortstop P2 //定義數碼管顯示端口
- extern void Control(char Archetype); //聲明小車控制子程序
- void delay(unsigned char x) //0.14mS延時程序
- {
- unsigned char i; //定義臨時變量
- while(x--) //延時時間循環
- {
- for (i = 0; i<13; i++) {} //14mS延時
- }
- }
- void Delay() //定義延時子程序
- { bint Daytime=30000; //定義延時時間變量
- while(Daytime--); //開始進行延時循環
- return; //子程序返回
- }
- void Control(char Archetype) //定義小車控制子程序
- {
- M1A=0; //將電機1正向電平置低
- M1B=0; //將電機1反向電平置低
- M2A=0; //將電機2正向電平置低
- M2B=0; //將電機2反向電平置低
- Left Led=1; //關閉前方左側指示燈
- Right Led=1; //關閉前方右側指示燈
- Delay(); //將此狀態延時一段時間
- switch(Archetype) //判斷小車控制指令類型
- { case 1: //前進 //判斷是否是前進
- { M1A=1; //將電機1正向端口置高
- M2A=1; //將電機2正向端口置高
- Shortstop=Roadshow[1]; //數碼管顯示前進狀態
- break; //退出判斷
- }
- case 2: //后退 //判斷是否是后退
- { M1B=1; //將電機1反向端口置高
- M2B=1; //將電機2反向端口置高
- Shortstop=Roadshow[2]; //數碼管顯示后退狀態
- Right Led=0; //將前方右側指示燈置低(亮)
- Left Led=0; //將前方左側指示燈置低(亮)
- break; //退出判斷
- }
- case 3: //左轉 //判斷是否是左轉
- { M1B=1; //將電機1反向端口置高
- M2A=1; //將電機2正向端口置高
- Shortstop=Roadshow[3]; //數碼管顯示左轉狀態
- Left Led=0; //將前方左側指示燈置低(亮)
- break; //退出判斷
- }
- case 4: //右轉 //判斷是否是右轉
- { M1A=1; //將電機1正向端口置高
- M2B=1; //將電機2反向端口置高
- Shortstop=Roadshow[4]; //數碼管顯示右轉狀態
- Right Led=0; //將前方右側指示燈置低(亮)
- break; //退出判斷
- }
- default: //默認情況下的判斷
- {
- break; //直接退出判斷
- }
- }
- }
- void Biobreak() interrupt 4 //定義串口通信子程序
- {unsigned char Recitative; //定義串口數據接收變量
- if(RI==1) //判斷是否接收數據
- { Recitative=SBUF; //將接收到的數據放入暫時變量
- if(Recitative<10) //判斷接收到的數據是否小于10
- {
- Shortstop=Roadshow[Recitative]; //將接收到的數據通過數碼管顯示出來
- Control(Recitative); //將串口數據置于小于狀態
- }
- SBUF=Recitative; //向電腦返回當前接收到的數據
- RI=0; //清除接收中斷標志位
- }
- if(TI==1) //判斷是否是發送中斷
- {
- TI=0; //清除發送中斷標志位
- }
- }
- void IR_IN() interrupt 2 using 0 //定義INT2外部中斷函數
- {
- unsigned char j,k,N=0; //定義臨時接收變量
-
- EX1 = 0; //關閉外部中斷,防止再有信號到達
- delay(15); //延時時間,進行紅外消抖
- if (IRIN==1) //判斷紅外信號是否消失
- {
- EX1 =1; //外部中斷開
- return; //返回
- }
-
- while (!IRIN) //等IR變為高電平,跳過9ms的前導低電平信號。
- {
- delay(1); //延時等待
- }
- for (j=0;j<4;j++) //采集紅外遙控器數據
- {
- for (k=0;k<8;k++) //分次采集8位數據
- {
- while (IRIN) //等 IR 變為低電平,跳過4.5ms的前導高電平信號。
- {
- delay(1); //延時等待
- }
-
- while (!IRIN) //等 IR 變為高電平
- {
- delay(1); //延時等待
- }
-
- while (IRIN) //計算IR高電平時長
- {
- delay(1); //延時等待
- N++; //計數器加加
- if (N>=30) //判斷計數器累加值
- {
- EX1=1; //打開外部中斷功能
- return; //返回
- }
- }
-
- IRCOM[j]=IRCOM[j] >> 1; //進行數據位移操作并自動補零
-
- if (N>=8) //判斷數據長度
- {
- IRCOM[j] = IRCOM[j] | 0x80; //數據最高位補1
- }
- N=0; //清零位數計錄器
- }
- }
-
- if (IRCOM[2]!=~IRCOM[3]) //判斷地址碼是否相同
- {
- EX1=1; //打開外部中斷
- return; //返回
- }
- for(j=0;j<10;j++) //循環進行鍵碼解析
- {
- if(IRCOM[2]==Recitative[j]) //進行鍵位對應
- {
- P2=Roadshow[j]; //數碼管顯示相應數碼
- }
- }
-
- switch(IRCOM[2])
- {
- case 0x1A: //前進
- {
- Control(1); //小車前進
- break;
- }
- case 0x05: //后退
- {
- Control(2); //小車后退
- break;
- }
- case 0x01: //左轉
- {
- Control(3); //小車左轉
- break;
- }
- case 0x03: //右轉
- {
- Control(4); //小車右轉
- break;
- }
- case 0x12: //電源
- {
- Control(5); //停止
- break;
- }
-
- }
-
- EX1 = 1; //外部中斷開
- }
- void main(void) //主程序入口
- {
- bit Flagella=0; //定義可執行位變量
-
- Led Flash=3000; //對閃燈數據進行初始化
- TMOD=0x01; //選擇定時器0為兩個16位定時器
- TH0=0xFF; //對定時器進行計數值進行初始化
- TL0=0x49; //同上,時間大約為25uS
- TR0=1; //同意開始定時器0
- EX1=1; //同意開啟外部中斷1
- IT1=1; //設定外部中斷1為低邊緣觸發類型
- ET0=0;
- SCON=80; //設置串口模式為8位數據
- TMOD=33; //設置定時/計數器模式
- TH1=0xFD; //給定時器1高八位初始化初值
- TL1=0xFD; //給定時器1低八位初始化初值
- TR1=1; //開啟定時器1
- ES=1; //開啟串口通信功能
- REN=1; //開啟接收中斷標志
- EA=1; //總中斷開啟
- Control(1); //將小車置于前進狀態
- Shortstop=Roadshow[0]; //數碼管顯示數字0
- while(1) //程序主循環
- {
-
- while(Led Flash--) //閃燈總延時
- {
- if(RL1==0) //判斷光敏電阻的狀態
- { Right Led=1; //將前方右側指示燈點亮
- Left Led=1; //將前方左側指示燈點亮
- }
- else //在光敏電阻為不通的狀態下
- {
- Right Led=0; //將前方右側指示燈熄滅
- Left Led=0; //將前方左側指示燈熄滅
- }
- if(IRIN==0) //判斷延時期間是否有紅外信號輸入
- {Flagella=1; //將可執行標志位置1
- }
- if(S1==0) //判斷是否有S1按下
- {
- Control(8); //將小車置于停止狀態
- Run Flag=1; //改變小車運行狀態標志位
- S1State=!S1State; //改變S1按鍵標志位
- Soto Extrusion; //跳轉到Extrusion標簽
- }
- if(S2==0) //判斷是否有S2按下
- {
- Control(1); //將小車置于前進狀態
- Run Flag=0; //改變小車運行狀態標志位
- S2State=!S2State; //改變S2按鍵標志位
- Soto Extrusion; //跳轉到Extrusion標簽
- }
- Attestation=Frontier; //前方紅外指示燈顯示正前方紅外探頭狀態
- Interstate=Lefter; //左側紅外指示燈顯示前方左側紅外探頭狀態
- Rightist=Right; //右側紅外指示燈顯示前主右側紅外探頭狀態
- if(Frontier==0 || Lefter==1 || Right==1) //判斷正前方,前左側,前右側紅外探頭狀態
- {Control(2); //改變小車狀態為后退
- SB1=!SB1; //將蜂鳴器取反
- Delay(); //調用延時子程序
- SB1=!SB1; //將蜂鳴器取反
- Delay(); //調用延時子程序
- SB1=!SB1; //將蜂鳴器取反
- Delay(); //調用延時子程序
- SB1=!SB1; //將蜂鳴器取反
- Delay(); //調用延時子程序
- SB1=!SB1; //將蜂鳴器取反
- Delay(); //調用延時子程序
- SB1=!SB1; //將蜂鳴器取反
- Delay(); //調用延時子程序
- SB1=!SB1; //將蜂鳴器取反
- Control(3); //改變小車左轉狀態
- Delay(); //調用延時子程序
- SB1=!SB1; //將蜂鳴器取反
- Delay(); //調用延時子程序
- SB1=!SB1; //將蜂鳴器取反
- Delay(); //調用延時子程序
- SB1=!SB1; //將蜂鳴器取反
- Delay(); //調用延時子程序
- SB1=!SB1; //將蜂鳴器取反
- Delay(); //調用延時子程序
- SB1=!SB1; //將蜂鳴器取反
- Control(1); //改變小車為前進狀態
- SB1=1; //關閉蜂鳴器聲音
- }
-
- if(B1==0) //判斷是否有話筒信號輸入
- { if(Run Flag==0) //判斷小車當前的運行標志位
- { Control(8); //將小車置于停止狀態
- Run Flag=1; //改變小車運行標志位
- }
- else
- { Control(1); //將小車置于前進狀態
- Run Flag=0; //改變小車運行標志位
- }
- B1State=!B1State; //將話筒信號指示燈取反
- }
- }
- Extrusion: //跳轉標簽
-
- Understate=!Understate; //改變小車運行停止狀態標志位
-
- }
- }
復制代碼
|