- //晶振=11.0592M
- //MCU=STC516RD+
- //************************************
- #include<reg51.h> //包括一個52標準內核的頭文件
- #define uchar unsigned char //定義一下方便使用
- #define uint unsigned int //定義一下方便使用
- uchar Distance; //定義Distance(距離)變量
- sbit Tr1=P1^4; //定義超聲波模塊的控制端(Tr)
- sbit Ec1=P1^5; //定義超聲波模塊的接收端(Ec)
- sbit Tr2=P1^6; //定義第二個超聲波模塊的控制端(Tr)
- sbit Ec2=P1^7; //定義第二個超聲波模塊的接收端(Ec)
- sbit IN1=P2^1; //定義L298n步進電機驅動芯片的IN1管腳由51MCU的P2^1管腳控制IN1對應控制OUT1電機驅動腳
- sbit IN2=P2^0; //定義L298n步進電機驅動芯片的IN2管腳由51MCU的P2^0管腳控制IN2對應控制OUT2電機驅動腳
- sbit IN3=P2^2; //定義L298n步進電機驅動芯片的IN3管腳由51MCU的P2^2管腳控制IN3對應控制OUT3電機驅動腳
- sbit IN4=P2^3; //定義L298n步進電機驅動芯片的IN4管腳由51MCU的P2^3管腳控制IN4對應控制OUT4電機驅動腳
- sbit ENA=P2^5; //定義L298n步進電機驅動芯片的ENA管腳由51MCU的P2^5管腳控制ENA腳是使能腳控制IN1,2腳輸入的高低電平是否有效
- sbit ENB=P2^4; //定義L298n步進電機驅動芯片的ENB管腳由51MCU的P2^4管腳控制ENA腳是使能腳控制IN3,4腳輸入的高低電平是否有效
- sbit RXd=P3^0;
- sbit hig=P3^1;
- sbit h=P3^2;
- void Delays1(uint x) //延時函數Delays..定義形參x為unsigned int 型
- {
- uint q,w; //定義實際參數q,w為unsigned int 型
- for(q=x;q>0;q--) //q=x,q小于0,q減一。如果q小于零則退出此語句
- for(w=110;w>0;w--); //w=110,w小于0,w減一。如果w小于零則退出此語句
- }
- void init1() //初始化函數init
- { //初始化Ec1=0;
- Ec1=0; //初始化Tr1=0;
- Tr1=0;
- }
- void Ranging1() //Ranging(測距)函數用于檢測出距離并控制電機做出相應的動作
- {
- while(1)
- {
- static uchar Num_Run=0;
- static uchar Num3=0; //定義unsigned char型局部變量Num3,并且只第一次執行時Num3=0,以后執行時不會再次初始,主要用于超聲波模塊的使能信號過后用來檢測接收端Ec1是否有高電平,或用于進入和退出while循環,,
- static uchar Choice=0;
- bit Bit_Num2; //定義bit型變量(51特有變量)Bit_Num2。。主要用于關閉定時器并進入下一個函數(檢測Ec1的脈寬長度)
- uchar Move1,Move2,Move3,Move4; //定義unsigned char變量Move(用來進入switch語句并選擇那種工作方式)
- if(Choice==2){Choice=0;}
- switch(Choice)
- {
- case 0:Tr1=1;Delays1(10);Tr1=0;Num3=1;break; //Tr1給高電平 //至少延時10微秒 //Tr1給低電平 //Num3給1
- case 1:Tr2=1;Delays1(10);Tr2=0;Num3=2;break;
- default:break;
- }
- Choice++;
- Bit_Num2=0; //Bit_Num2給0用于進入下一步while循環
- while(Num3==1) //當Num3檢測到定于1時進入本循環 //右邊的測距模塊檢測程序
- {
- while(Ec1==1) //當Ec1檢測等于1是進入本循環,當Ec1(接收信號的高電平脈寬結束后退出此循環)
- { //Bit_Num2給以用來鍵入笑一個if語句
- Bit_Num2=1; //打開定時器TR0進入定時器0中斷
- TR0=1;
- }
- if(Ec1==0&Bit_Num2==1) //如果Ec1等于0(超聲波測距模塊的接收端發送到高電平脈寬傳送完后)而且Bit_Num2等于1進入此語句
- {
- TR0=0; //關閉定時器
- if(Distance<20) //如果脈寬小于50微秒
- {
- Move1=0; //Move等于1
- }
- else if(Distance>60) //如果上一語句不成立則檢測此語句,如果脈寬的時間長度大于50微秒
- {
- uchar n;
- for(n=1;n>0;n--)
- {
- Move1++; //Move等于2
- }
- }
- else{};
- if(Distance<60&Distance>20)
- {
- uchar n;
- for(n=2;n>0;n--)
- {
- Move1++; //Move等于2
- }
- }
- Num3=0;
- }
- }
- while(Num3==2)
- {
- Distance=0;
- while(Ec2==1) //當Ec2檢測等于1是進入本循環,當Ec1(接收信號的高電平脈寬結束后退出此循環)
- {
- Bit_Num2=1; //Bit_Num2給以用來鍵入笑一個if語句
- TR0=1; //打開定時器TR0進入定時器0中斷
- }
- if(Ec2==0&Bit_Num2==1) //如果Ec1等于0(超聲波測距模塊的接收端發送到高電平脈寬傳送完后)而且Bit_Num2等于1進入此語句
- {
- TR0=0; //關閉定時器
- if(Distance<20) //如果脈寬小于50微秒
- {
- Move2=0;
- }
- else if(Distance>60) //如果上一語句不成立則檢測此語句,如果脈寬的時間長度大于50微秒
- {
- uchar n;
- for(n=1;n>0;n--)
- {
- Move2++;
- }
- }
- else{};
- if(Distance<60&Distance>20) //如果上一語句不成立則檢測此語句,如果脈寬的時間長度大于50微秒
- {
- uchar n;
- for(n=2;n>0;n--)
- {
- Move2++;
- }
- }
- Num_Run=1;
- Num3=0;
- }
- }
- if(Num_Run==1)
- {
- unsigned char Get[4][4]={{0x01,0x02,0x03,0x04},{0x05,0x06,0x07,0x08},{0x0a,0x0b,0x0c,0x0e},{0x0f,0x11,0x21,0x31}};
- switch(Get[Move1][Move2]) //檢測Move的值并進入相應的語句 //Move1=右邊。。//Move2=左邊
- {
- case 0x01:IN1=0;IN2=0;IN3=0;IN4=0;ENA=1;ENB=1;break; //如果Move等于0,則電機反轉,并給Distance清零,然后退出此語句 // 左前,右后
- case 0x02:IN1=1;IN2=0;IN3=0;IN4=1;ENA=1;ENB=1;break; //左后,右前
- case 0x05:IN1=0;IN2=1;IN3=1;IN4=0;ENA=1;ENB=1;break; //左前,右后
- case 0x06:IN1=0;IN2=0;IN3=0;IN4=0;ENA=1;ENB=1;break; //如果Move等于1,則電機正轉,并給Distance清零,然后退出此語句**//前進 //左前,右前
- case 0x0a:IN1=0;IN2=0;IN3=1;IN4=0;ENA=1;ENB=1;break; // 左前,右后
- case 0x0b:IN1=1;IN2=0;IN3=0;IN4=0;ENA=1;ENB=1;break; //左停,右后 case 0x0c:IN1=1;IN2=0;IN3=0;IN4=1;ENA=1;ENB=1;break;改為case 0x0b:IN1=0;IN2=0;IN3=1;IN4=0;ENA=1;ENB=1;break; 。。。如果有錯可以改回來
- case 0x0c:IN1=1;IN2=0;IN3=1;IN4=0;ENA=1;ENB=1;break; // 左前,右后 //
- case 0x03:IN1=1;IN2=0;IN3=0;IN4=0;ENA=1;ENB=1;break; //左后,右前
- case 0x07:IN1=0;IN2=0;IN3=1;IN4=0;ENA=1;ENB=1;break; //左前,右停
- default:break; //如果以上都不符合,則退出此語句,準備下一循環
- }
- Distance=0;
- Move1=0; //Move清零;
- Move2=0;
- Move3=0;
- Move4=0;
- Num_Run=0;
- }
- }
- }
- void open_time1() //定時器初始函數
- {
- TMOD=0x01; //確定工作方式位01,(內容自己上網查啊,大概是16位手動重裝計數器,,記不清了)
- TH0=(65536-1)/256; //確定一微秒記一次
- TL0=(65536-1)%256; //確定一微秒記一次
- EA=1; //打開總中斷
- ET0=1; //打開定時器0中斷
- TR0=0; //關閉定時器0
- }
- void q1() //main函數(主函數),,所有函數都從這個函數開始執行
- {
- init1(); //執行init函數
- open_time1(); //執行open_time函數
- while(1) //進入大循環(除非執行中斷函數否則永不退出)
- {
- Ranging1(); //執行Ranging函數
- }
- }
- /**********************/
- void Delays(uint x) //延時函數Delays..定義形參x為unsigned int 型
- {
- uint q,w; //定義實際參數q,w為unsigned int 型
- for(q=x;q>0;q--) //q=x,q小于0,q減一。如果q小于零則退出此語句
- for(w=110;w>0;w--); //w=110,w小于0,w減一。如果w小于零則退出此語句
- }
- void init() //初始化函數init
- { //初始化Ec1=0;
- Ec1=0; //初始化Tr1=0;
- Tr1=0;
- }
- void Ranging() //Ranging(測距)函數用于檢測出距離并控制電機做出相應的動作
- {
- while(1)
- {
- static uchar Num_Run=0;
- static uchar Num3=0; //定義unsigned char型局部變量Num3,并且只第一次執行時Num3=0,以后執行時不會再次初始,主要用于超聲波模塊的使能信號過后用來檢測接收端Ec1是否有高電平,或用于進入和退出while循環,,
- static uchar Choice=0;
- bit Bit_Num2; //定義bit型變量(51特有變量)Bit_Num2。。主要用于關閉定時器并進入下一個函數(檢測Ec1的脈寬長度)
- uchar Move1,Move2,Move3,Move4; //定義unsigned char變量Move(用來進入switch語句并選擇那種工作方式)
- if(Choice==2){Choice=0;}
- switch(Choice)
- {
- case 0:Tr1=1;Delays(10);Tr1=0;Num3=1;break; //Tr1給高電平 //至少延時10微秒 //Tr1給低電平 //Num3給1
- case 1:Tr2=1;Delays(10);Tr2=0;Num3=2;break;
- default:break;
- }
- Choice++;
- Bit_Num2=0; //Bit_Num2給0用于進入下一步while循環
- while(Num3==1) //當Num3檢測到定于1時進入本循環
- {
- while(Ec1==1) //當Ec1檢測等于1是進入本循環,當Ec1(接收信號的高電平脈寬結束后退出此循環)
- { //Bit_Num2給以用來鍵入笑一個if語句
- Bit_Num2=1; //打開定時器TR0進入定時器0中斷
- TR0=1;
- }
- if(Ec1==0&Bit_Num2==1) //如果Ec1等于0(超聲波測距模塊的接收端發送到高電平脈寬傳送完后)而且Bit_Num2等于1進入此語句
- {
- TR0=0; //關閉定時器
- if(Distance<20) //如果脈寬小于50微秒
- {
- Move1=0; //Move等于1
- }
- else if(Distance>30) //如果上一語句不成立則檢測此語句,如果脈寬的時間長度大于50微秒
- {
- uchar n;
- for(n=1;n>0;n--)
- {
- Move1++; //Move等于2
- }
- }
- else{};
- if(Distance<30&Distance>20)
- {
- uchar n;
- for(n=2;n>0;n--)
- {
- Move1++; //Move等于2
- }
- }
- Num3=0;
- }
- }
- while(Num3==2)
- {
- Distance=0;
- while(Ec2==1) //當Ec2檢測等于1是進入本循環,當Ec1(接收信號的高電平脈寬結束后退出此循環)
- {
- Bit_Num2=1; //Bit_Num2給以用來鍵入笑一個if語句
- TR0=1; //打開定時器TR0進入定時器0中斷
- }
- if(Ec2==0&Bit_Num2==1) //如果Ec1等于0(超聲波測距模塊的接收端發送到高電平脈寬傳送完后)而且Bit_Num2等于1進入此語句
- {
- TR0=0; //關閉定時器
- if(Distance<20) //如果脈寬小于50微秒
- {
- Move2=0;
- }
- else if(Distance>30) //如果上一語句不成立則檢測此語句,如果脈寬的時間長度大于50微秒
- {
- uchar n;
- for(n=1;n>0;n--)
- {
- Move2++;
- }
- }
- else{};
- if(Distance<30&Distance>20) //如果上一語句不成立則檢測此語句,如果脈寬的時間長度大于50微秒
- {
- uchar n;
- for(n=2;n>0;n--)
- {
- Move2++;
- }
- }
- Num_Run=1;
- Num3=0;
- }
- }
- if(Num_Run==1)
- {
- unsigned char Get[4][4]={{0x01,0x02,0x03,0x04},{0x05,0x06,0x07,0x08},{0x0a,0x0b,0x0c,0x0e},{0x0f,0x11,0x21,0x31}};
- switch(Get[Move1][Move2]) //檢測Move的值并進入相應的語句
- {
- case 0x01:IN1=1;IN2=0;IN3=0;IN4=1;ENA=1;ENB=1;break; //如果Move等于0,則電機反轉,并給Distance清零,然后退出此語句 //
- case 0x02:IN1=0;IN2=1;IN3=1;IN4=0;ENA=1;ENB=1;break;
- case 0x05:IN1=1;IN2=0;IN3=0;IN4=1;ENA=1;ENB=1;break; //左開右關
- case 0x06:IN1=1;IN2=0;IN3=1;IN4=0;ENA=1;ENB=1;break; //如果Move等于1,則電機正轉,并給Distance清零,然后退出此語句**//前進
- case 0x0a:IN1=1;IN2=0;IN3=0;IN4=1;ENA=1;ENB=1;break;
- case 0x0b:IN1=0;IN2=0;IN3=0;IN4=1;ENA=1;ENB=1;break;
- case 0x0c:IN1=1;IN2=0;IN3=0;IN4=1;ENA=1;ENB=1;break;
- case 0x03:IN1=0;IN2=1;IN3=1;IN4=0;ENA=1;ENB=1;break;
- case 0x07:IN1=1;IN2=0;IN3=0;IN4=0;ENA=1;ENB=1;break;
- default:break; //如果以上都不符合,則退出此語句,準備下一循環
- }
- Distance=0;
- Move1=0; //Move清零;
- Move2=0;
- Move3=0;
- Move4=0;
- Num_Run=0;
- }
- }
- }
- void open_time() //定時器初始函數
- {
- TMOD=0x01; //確定工作方式位01,(內容自己上網查啊,大概是16位手動重裝計數器,,記不清了)
- TH0=(65536-1)/256; //確定一微秒記一次
- TL0=(65536-1)%256; //確定一微秒記一次
- EA=1; //打開總中斷
- ET0=1; //打開定時器0中斷
- TR0=0; //關閉定時器0
- }
- void q2() //main函數(主函數),,所有函數都從這個函數開始執行
- {
- RXD=1;
- init(); //執行init函數
- open_time(); //執行open_time函數
- while(1) //進入大循環(除非執行中斷函數否則永不退出)
- {
- Ranging(); //執行Ranging函數
- }
- }
- void main()
- {
- hig=1;
- RXd=1;
- h=0;
- while(1)
- {
- unsigned char zz;
- unsigned int uu,ii;
- for(uu=9000;uu>0;uu--)
- for(ii=60;ii>0;ii--);
- if(RXd==0)
- {
- zz=1;
- }
- if(hig==0)
- {
- zz=2;
- }
- while(zz==1){q1();}
- while(zz==2){q2();}
- }
- }
- void time() interrupt 1 //定時器0中斷語句
- {
- TH0=(65536-1)/256; //重裝初值TH0=(65536-1)/256;
- TL0=(65536-1)%256; //重裝初值TL0=(65536-1)%256;
- Distance++; //每次走一步Distance加一
- if(Distance==65535) //如果Distance等于65535就進入此語句
- {
- Distance=0; //Distance的值清零
- }
- }
復制代碼
|