#include<reg52.h>
#include <intrins.h>
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
sbit Sevro_moto_pwm = P2^6; //接舵機信號端輸入PWM信號調(diào)節(jié)速度
sbit ECHO= P1^1; //超聲波接口定義
sbit TRIG= P1^0; //超聲波接口定義
sbit PWM1 = P2^5; //左電機高電平
sbit PWM2 = P2^4; //右電機高電平
sbit IN1 = P2^3;
sbit IN2 = P2^2; //左電機
sbit IN3 = P2^1;
sbit IN4 = P2^0; //右電機
sbit A1 = P1^4; //左紅外避障模塊
sbit A2 = P2^7; //右紅外避障模塊
//sbit A3 = P1^2; //左紅外尋跡模塊
//sbit A4 = P1^3; //右紅外尋跡模塊
sbit K1 = P3^2; //功能轉(zhuǎn)換按鍵
sbit K2 = P3^3; //加速鍵
sbit K3 = P3^4; //減速鍵
u8 connt; //調(diào)速周期
u8 PWM_NO; //高電平時間
u8 a=0,c=0; //標志位
u8 COM;
u8 pwm_val_left = 0;//變量定義
u8 push_val_left ;//舵機歸中,產(chǎn)生約,1.5MS 信號
u32 S=0; //距離變量定義
u32 S1=0;
u32 S2=0;
u32 S3=0;
u32 S4=0;
u16 time=0; //時間變量
u16 timer=0; //延時基準變量
u8 non=0,t=0;
u8 pon=3; //數(shù)碼管顯示
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f};//顯示0~9的值
/************************************************************************/
void delay(u16 k) //延時函數(shù)
{
u16 x,y;
for(x=0;x<k;x++)
for(y=0;y<2000;y++);
}
void delay1(u16 j) //延時函數(shù)
{
u16 x,y;
for(x=0;x<j;x++)
for(y=0;y<120;y++);
}
/************************************************************************/
void Display(void) //掃描數(shù)碼管
{
P0=smgduan[pon];
if(K2==0) // 加速
{
delay1(10);
if(K2==0)
{
pon++;
PWM_NO--;
}
while(!K2); //松鍵檢測
}
if(K3==0) //減速
{
delay1(10);
if(K3==0)
{
pon--;
PWM_NO++;
}
while(!K3);
}
}
void SC() //剎車
{
IN1 = 0;
IN2 = 0;
IN3 = 0;
IN4 = 0;
}
void QJ() //前進
{
IN1 = 1;
IN2 = 0;
IN3 = 1;
IN4 = 0;
}
void HT() //后退
{
IN1 = 0;
IN2 = 1;
IN3 = 0;
IN4 = 1;
}
void ZZ1() //左大轉(zhuǎn)
{
IN1 = 0;
IN2 = 1;
IN3 = 1;
IN4 = 0;
}
void YZ1() //右大轉(zhuǎn)
{
IN1 = 1;
IN2 = 0;
IN3 = 0;
IN4 = 1;
}
/************************************************************************/
void StartModule() //啟動測距信號
{
TRIG=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
TRIG=0;
}
void InitUART(void) //串口中斷初始化函數(shù)
{
SCON=0x50; //設(shè)置為工作方式1
TMOD=0x20; //設(shè)置計數(shù)器工作方式2
PCON=0x00; //波特率不加倍
TH1=0xfd; //計數(shù)器初始值設(shè)置,注意波特率是9600的
TL1=0xfd;
ES=1; //打開接收中斷
EA=1; //打開總中斷
TR1=1; //打開計數(shù)器
}
/***************************************************/
void Conut(void) //計算距離
{
while(!ECHO); //當RX為零時等待
TR1=1; //開啟計數(shù)
while(ECHO); //當RX為1計數(shù)并等待
TR1=0; //關(guān)閉計數(shù)
time=TH1*256+TL1; //讀取脈寬長度
TH1=0;
TL1=0;
S=(time*1.7)/100; //算出來是CM
}
/************************************************************************/
void COMM( void )
{
push_val_left=23; //舵機向左轉(zhuǎn)90度
timer=0;
while(timer<=4000); //延時400MS讓舵機轉(zhuǎn)到其位置 4000
StartModule(); //啟動超聲波測距
Conut(); //計算距離
S2=S;
push_val_left=5; //舵機向右轉(zhuǎn)90度
timer=0;
while(timer<=4000); //延時400MS讓舵機轉(zhuǎn)到其位置
StartModule(); //啟動超聲波測距
Conut(); //計算距離
S4=S;
push_val_left=14; //舵機歸中
timer=0;
while(timer<=4000); //延時400MS讓舵機轉(zhuǎn)到其位置
StartModule(); //啟動超聲波測距
Conut(); //計算距離
S1=S;
if((S2<20)||(S4<20)||(S1<20)) //只要左右各有距離小于,20CM小車后退
{
HT(); //后退
timer=0;
while(timer<=4000);
}
if((S2<20)&&(S4<20)&&(S1<20)) //只要左右各有距離小于,20CM小車后退
{
HT(); //后退
timer=0;
while(timer<=4000);
}
if(S2>S4)
{
ZZ1(); //車的左邊比車的右邊距離小 右轉(zhuǎn)
timer=0;
while(timer<=4000);
}
else
{
YZ1(); //車的左邊比車的右邊距離大 左轉(zhuǎn)
timer=0;
while(timer<=4000);
}
}
/************************************************************************/
/* PWM調(diào)制舵機轉(zhuǎn)速 */
/************************************************************************/
/* 舵機調(diào)速 */
/*調(diào)節(jié)push_val_left的值改變電機轉(zhuǎn)速,占空比 */
void pwm_Servomoto(void)
{
if(pwm_val_left <= push_val_left)
Sevro_moto_pwm=1;
else
Sevro_moto_pwm=0;
if(pwm_val_left>=100)
pwm_val_left=0;
}
void minm() //按鈕控制功能轉(zhuǎn)換
{
COM=0;
if(K1==0)
{
delay1(10);
if(K1==0)
{
COM++;
}
while(!K1);
}
if(COM==4)
COM=0;
}
/***************************************************/
///*TIMER1中斷服務(wù)子函數(shù)產(chǎn)生PWM信號*/
void time0()interrupt 1
{
TH0=(65536-100)/256; //100US定時
TL0=(65536-100)%256;
timer++; //定時器100US為準。在這個基礎(chǔ)上延時
pwm_val_left++;
pwm_Servomoto();
t++;
if(t==5) //PWM調(diào)制左右電機速度
{
t=0;
non++;
}
if( non == PWM_NO )
{
PWM1 = 1;
PWM2 = 1;
}
if( non == connt )
{
non = 0;
if( PWM_NO != 0)
{
PWM1 = 0;
PWM2 = 0;
}
}
}
void lin() //避障功能
{
if(timer>=1000) //100MS檢測啟動檢測一次 1000
{
timer=0;
StartModule(); //啟動檢測
Conut(); //計算距離
if(S<=25) //距離小于30CM
{
SC(); //小車停止
COMM(); //方向函數(shù)
}
else
if(S>25) //距離大于,30CM往前走
QJ();
if(!A1)
{
SC();
delay1(20);
HT();
delay1(300);
SC();
COMM();
}
if(!A2)
{
SC();
delay1(20);
HT();
delay1(300);
SC();
COMM();
}
}
}
/***************************************************/
///*TIMER0中斷服務(wù)子函數(shù)產(chǎn)生PWM信號*/
void timer0()interrupt 3
{
}
/***************************************************/
void UARTInterrupt(void) interrupt 4 //串口中斷函數(shù)
{
unsigned char com;
if(a==1) //判斷能否執(zhí)行
{
if(RI==1)
com = SBUF; //暫存接收到的數(shù)據(jù)
RI=0;
}
P0=smgduan[pon];
switch(com) //接收到字符并要執(zhí)行的功能
{
case 0: QJ();break;
case 1: SC();break;
case 2: ZZ1();break;
case 3: YZ1();break;
case 4: HT();break;
case 5: pon++;PWM_NO--;break;
case 6: pon--;PWM_NO++;break;
}
}
void main(void)
{
IP=0x10;
TMOD=0X11;
TH0=(65536-100)/256; //100US定時
TL0=(65536-100)%256;
TR0= 1;
ET0= 1;
EA = 1;
connt = 20; //PWM的一個周期
PWM_NO = 16; //調(diào)速,數(shù)值越大速度越慢
delay(100);
push_val_left=14;
while(1) /*無限循環(huán)*/
{
Display();
minm();
switch(COM) //接收到字符并要執(zhí)行的功能
{
case 0:TH1=0;TL1=0;ET1= 1; lin();break;
case 1:SC();InitUART();ET1= 0;a=1;while(1);break;
default:break;
}
}
}
|