#include <REGX52.H> //包含51單片機相關的頭文件
#include <intrins.h>
sbit LeftIR=P3^5; //定義前方左側紅外探頭端口
sbit RightIR=P3^4; //定義前方右側紅外探頭端口
sbit IN1=P1^2; //定義左側電機驅動A端
sbit IN2=P1^3; //定義左側電機驅動B端
sbit IN3=P1^4; //定義右側電機驅動A端
sbit IN4=P1^5;
sbit EN1=P1^6;
sbit EN2=P1^0;
sbit Beep=P2^3; //定義蜂鳴器端口
sbit IRIN=P3^3; //定義紅外接收端口
sbit p00=P0^0; //LED
sbit p01=P0^1; //LED
sbit p02=P0^2; //LED
sbit p03=P0^3; //LED
sbit p04=P0^4; //LED
sbit p05=P0^5; //LED
sbit p06=P0^6; //LED
sbit p07=P0^7; //LED
sbit sda=P1^1;
sbit key=P3^2;
#define Left_moto_pwm P1_6 //PWM信號端
#define Right_moto_pwm P1_7 //PWM信號端
#define Left_moto_go {P1_2=1,P1_3=0;} //左電機向前走
#define Left_moto_back {P1_2=0,P1_3=1;} //左邊電機向后轉
#define Left_moto_Stop {P1_2=0,P1_3=0;} //左邊電機停轉
#define Right_moto_go {P1_4=1,P1_5=0;} //右邊電機向前走
#define Right_moto_back {P1_4=0,P1_5=1;} //右邊電機向后走
#define Right_moto_Stop {P1_4=0,P1_5=0;} //右邊電機停轉
unsigned char pwm_val_left =0;//變量定義
unsigned char push_val_left =0;// 左電機占空比N/20
unsigned char pwm_val_right =0;
unsigned char push_val_right=0;// 右電機占空比N/20
unsigned char code RecvData[]={0x19,0x18,0x52,0x5A,0x08,0x1C,0x16,0x45,0x46,0x47,0x0D,0x0E,0x00,0x0F};
unsigned char temp = 1;
unsigned char IRCOM[7];//接收數據緩沖區
unsigned int z;
bit Right_moto_stop=1;
bit Left_moto_stop =1;
unsigned int time3=0;
/*********************************************************************/
void tingzhi(void)
{
P1_2 = 0;
P1_3 = 0;
P1_4 = 0;
P1_5 = 0;
}
void qianjin(void)
{
push_val_left=3; //速度調節變量 0-20。。。0最小,20最大
push_val_right=3;
Left_moto_go ; //左電機往前走
Right_moto_go ; //右電機往前走
}
void houtui()
{
push_val_left=12; //速度調節變量 0-20。。。0最小,20最大
push_val_right=12;
Left_moto_back ; //左電機往前走
Right_moto_back ; //右電機往前走
}
void zuozhuan()
{
push_val_left=6;
push_val_right=12;
Right_moto_go ; //右電機往前走
Left_moto_back ; //左電機后走
}
void youzhuan()
{
push_val_left=12;
push_val_right=6;
Left_moto_go ; //左電機往前走
Right_moto_back ; //右電機往后走
}
/************************************************************************/
/* PWM調制電機轉速 */
/************************************************************************/
/* 左電機調速 */
/*調節push_val_left的值改變電機轉速,占空比 */
void pwm_out_left_moto(void)
{
if(Left_moto_stop)
{
if(pwm_val_left<=push_val_left)
{
Left_moto_pwm=1;
}
else
{
Left_moto_pwm=0;
}
if(pwm_val_left>=20)
pwm_val_left=0;
}
else
{
Left_moto_pwm=0;
}
}
/******************************************************************/
/* 右電機調速 */
void pwm_out_right_moto(void)
{
if(Right_moto_stop)
{
if(pwm_val_right<=push_val_right)
{
Right_moto_pwm=1;
}
else
{
Right_moto_pwm=0;
}
if(pwm_val_right>=20)
pwm_val_right=0;
}
else
{
Right_moto_pwm=0;
}
}
/***************************************************/
///*TIMER0中斷服務子函數產生PWM信號*/
void timer0()interrupt 1 using 2
{
TH0=0xFc;
TL0=0X18;
time3++;
pwm_val_left++;
pwm_val_right++;
pwm_out_left_moto();
pwm_out_right_moto();
}
void Timer1Init() //50毫秒@11.0592MHz
{
// AUXR &= 0xBF; //定時器時鐘12T模式
TMOD &= 0x0F; //設置定時器模式
TMOD |= 0x10; //設置定時器模式
TL1 = 0x00; //設置定時初值
TH1 = 0x4C; //設置定時初值
TF1 = 0; //清除TF1標志
EA=1;
ET1=1;
TR1 = 1; //定時器1開始計時
}
void Timer1() interrupt 3//晶振頻率是11.0592M
{
TH1=0X00; //給定時器賦初值,定時50ms
TL1=0x4C;
z++;
}
void Delay1ms(unsigned int i)
{
unsigned char j,k;
do{
j = 10;
do{
k = 50;
do{
_nop_();
}while(--k);
}while(--j);
}while(--i);
}
void delay_nus(unsigned int i) //延時:i>=12 ,i的最小延時單12 us
{
i=i/10;
while(--i);
}
void delay_nms(unsigned int n) //延時n ms
{
n=n+1;
while(--n)
delay_nus(900); //延時 1ms,同時進行補償
}
void delayms(unsigned char x) //0.14mS延時程序
{
unsigned char i; //定義臨時變量
while(x--) //延時時間循環
{
for (i = 0; i<13; i++) {} //14mS延時
}
}
void delay5(unsigned int i) //延時程序
{while(i--);}
void Delay1us ( int T )
{
while(T!=0)
{
_nop_();
T--;
}
}
void led_delay(void)
{
unsigned char i,j;
for(i=0;i<220;i++)
for(j=0;j<220;j++);
}
/*
void wudao(void)
{
Timer1Init();
while(1)
{
if(z>=3){
z=0;
tingzhi();
}
if(z>=60){
z=0;
qianjin();
}
if(z>=3){
z=0;
tingzhi();
}
if(z>=3){
z=0;
youzhuan();
}
if(z>=3){
z=0;
tingzhi();
}
if(z>=60){
z=0;
qianjin();
}
if(z>=3){
z=0;
tingzhi();
}
if(z>=3){
z=0;
youzhuan();
}
if(z>=3){
z=0;
tingzhi();
}
if(z>=60){
z=0;
qianjin();
}
if(z>=3){
z=0;
tingzhi();
}
if(z>=3){
z=0;
youzhuan();
}
if(z>=3){
z=0;
tingzhi();
}
if(z>=3){
z=0;
qianjin();
}
tingzhi();
}
}
*/
void wudao(void)
{
Timer1Init();//定時器1初始化
while(1)
{
tingzhi();
TR1=1;
while(z!=3);
TR1=0;
z=0;
qianjin();
TR1=1;
while(z!=60);
TR1=0;
z=0;
tingzhi();
TR1=1;
while(z!=3);
TR1=0;
z=0;
youzhuan();
TR1=1;
while(z!=3);
TR1=0;
z=0;
tingzhi();
TR1=1;
while(z!=3);
TR1=0;
z=0;
qianjin();
TR1=1;
while(z!=6);
TR1=0;
z=0;
tingzhi();
TR1=1;
while(z!=3);
TR1=0;
z=0;
youzhuan();
TR1=1;
while(z!=3);
TR1=0;
z=0;
tingzhi();
TR1=1;
while(z!=3);
TR1=0;
z=0;
qianjin();
TR1=1;
while(z!=60);
TR1=0;
z=0;
tingzhi();
TR1=1;
while(z!=3);
TR1=0;
z=0;
youzhuan();
TR1=1;
while(z!=3);
TR1=0;
z=0;
tingzhi();
TR1=1;
while(z!=3);
TR1=0;
z=0;
qianjin();
TR1=1;
while(z!=60);
TR1=0;
z=0;
tingzhi();
}
}
void forward(void)//兩邊
{
P0=0x7e;
led_delay();
P0=0xbd;
led_delay();
P0=0xdb;
led_delay();
P0=0xe7;
led_delay();
P0=0xe7;
led_delay();
P0=0xdb;
led_delay();
P0=0xbd;
led_delay();
P0=0x7e;
led_delay();
}
void Alter(void)//交替
{
P0=0xaa;
led_delay();
P0=0x55;
led_delay();
}
void backward(void)
{
P0=0x7f;
led_delay();
P0=0xbf;
led_delay();
P0=0xdf;
led_delay();
P0=0xef;
led_delay();
P0=0xf7;
led_delay();
P0=0xfb;
led_delay();
P0=0xfd;
led_delay();
P0=0xfe;
led_delay();
}
void blink(void)
{
P0=0xff;
led_delay();
P0=0x00;
led_delay();
}
void deng1() //流水燈
{p00=0;
p01=0;
delay5(5000);
p02=0;
p03=0;
delay5(5000);
p04=0;
p05=0;
delay5(5000);
p06=0;
p07=0;
delay5(5000);
p07=1;
p06=1;
delay5(5000);
p05=1;
p04=1;
delay5(5000);
p03=1;
p02=1;
delay5(5000);
p01=1;
p00=1;
delay5(5000);}
void deng2() //流水燈
{p00=0;
p01=1;
delay5(5000);
p02=0;
p03=1;
delay5(5000);
p04=0;
p05=1;
delay5(5000);
p06=0;
p07=1;
delay5(5000);
p07=0;
p06=1;
delay5(5000);
p05=0;
p04=1;
delay5(5000);
p03=0;
p02=1;
delay5(5000);
p01=0;
p00=1;
delay5(5000);}
void deng3() //流水燈
{p00=0;
p01=0;
delay5(5000);
p02=0;
p03=0;
delay5(5000);
p04=0;
p05=0;
delay5(5000);
p06=0;
p07=0;
delay5(5000);
p07=1;
p06=1;
delay5(5000);
p05=1;
p04=1;
delay5(5000);
p03=1;
p02=1;
delay5(5000);
p01=1;
p00=1;
delay5(5000);}
void deng4() //流水燈
{p00=1;
p01=1;
p02=1;
p03=1;
p04=1;
p05=1;
p06=1;
p07=1;
}
void Robot_Avoidance() //機器人避障子程序
{
if(LeftIR==1&&RightIR ==1) //LeftIRBZ RightIRBZ
{
deng1();
qianjin();
delay_nms (10);
// SB1=1;
}
else
{
if(LeftIR==1&&RightIR ==0) //右邊檢測到紅外信號
{
deng4();
youzhuan(); //右轉
delay_nms (300); //停止300MS 防止電機反相電壓沖擊 導致系統復位
deng1();
}
if(RightIR ==1&&LeftIR==0) //左邊檢測到紅外信號
{
deng4();
zuozhuan(); //左轉
delay_nms (300); //停止300MS 防止電機反相電壓沖擊 導致系統復位
deng1();
}
if(RightIR==0&&LeftIR==0) //兩邊傳感器同時檢測到紅外
{
// SB1=0;
deng4();
tingzhi(); //停止
delay_nms (300); //停止300MS 防止電機反相電壓沖擊 導致系統復位
houtui(); //調用電機后退函數
delay_nms (300); //后退50毫秒
youzhuan(); //調用電機右轉函數
delay_nms (400);
deng1();
}
}
qianjin();
}
void ControlCar_yaokong(unsigned char ConType) //定義電機控制子程序 (紅外遙控單獨設置一個 switch case 語句 )
{
tingzhi();
switch(ConType) //判斷用戶設定電機形式
{
case 1: //前進 //判斷用戶是否選擇形式1
{
tingzhi(); //進入前進之前 先停止一段時間 防止電機反向電壓沖擊主板 導致系統復位
Delay1ms(150);
// LeftLed = 0 ;
qianjin();
break;
}
case 2: //后退 //判斷用戶是否選擇形式2
{
tingzhi(); //進入后退之前 先停止一段時間 防止電機反向電壓沖擊主板 導致系統復位
Delay1ms(150);
// LeftLed = 1 ;
houtui(); //M2電機反轉
break;
}
case 3: //右轉 //判斷用戶是否選擇形式3
{
tingzhi(); //進入左轉之前 先停止一段時間 防止電機反向電壓沖擊主板 導致系統復位
Delay1ms(150);
youzhuan();
//M2電機正轉
break;
}
case 4: //左轉 //判斷用戶是否選擇形式4
{
tingzhi(); //進入右轉之前 先停止一段時間 防止電機反向電壓沖擊主板 導致系統復位
Delay1ms(150);
zuozhuan(); //M1電機正轉 //M2電機反轉
break;
}
case 5: //停止 //判斷用戶是否選擇形式8
{
tingzhi();
break; //退出當前選擇
}
case 6: //左轉 //判斷用戶是否選擇形式4
{
//進入右轉之前 先停止一段時間 防止電機反向電壓沖擊主板 導致系統復位
Robot_Avoidance();
break;
}
case 7: //停止 //判斷用戶是否選擇形式8
{
deng2();
break; //退出當前選擇
}
case 8: //停止 //判斷用戶是否選擇形式8
{
deng4();
break; //退出當前選擇
}
}
}
//----------紅外遙控-------------------------------------------------------------
void IR_IN() interrupt 2 using 0 //定義INT2外部中斷函數
{
unsigned char j,k,N=0; //定義臨時接收變量
EX1 = 0; //關閉外部中斷,防止再有信號到達
delayms(15); //延時時間,進行紅外消抖
if (IRIN==1) //判斷紅外信號是否消失
{
EX1 =1; //外部中斷開
return; //返回
}
while (!IRIN) //等IR變為高電平,跳過9ms的前導低電平信號。
{
delayms(1); //延時等待
}
for (j=0;j<4;j++) //采集紅外遙控器數據
{
for (k=0;k<8;k++) //分次采集8位數據
{
while (IRIN) //等 IR 變為低電平,跳過4.5ms的前導高電平信號。
{
delayms(1); //延時等待
}
while (!IRIN) //等 IR 變為高電平
{
delayms(1); //延時等待
}
while (IRIN) //計算IR高電平時長
{
delayms(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]==RecvData[j]) //進行鍵位對應
{
// ControlCar(j);
ControlCar_yaokong(j); //數碼管顯示相應數碼
}
}
EX1 = 1; //外部中斷開
}
void SendData ( unsigned char addr )
{
unsigned char i;
// EA = 0;/*發送時關掉中斷,防止中斷影響時序 */
sda = 1;/*開始拉搞 */
Delay1us ( 1000 );
sda = 0;/*開始引導碼*/
Delay1us ( 3000 );/*此處延時最少要大于2ms,此參數延時為310ms */
for ( i = 0; i < 8; i++ ) /*總共8位數據 */
{
sda = 1;
if ( addr & 0x01 ) /*3:1表示數據位1,每個位用兩個脈沖表示 */
{
Delay1us ( 500 );
sda = 0;
Delay1us ( 210 );
}
else /*1:3表示數據位0 ,每個位用兩個脈沖表示 */
{
Delay1us ( 210 );
sda = 0;
Delay1us ( 500 );
}
addr >>= 1;
}
sda = 1;
// EA = 1;
}
void Stop_Music()
{
SendData(0x0a);
SendData(0x13);
}
void Star_Music()
{
SendData(0x0a);
SendData(0x03);
SendData(0x0b);
wudao();
}
//-------------------------------------------------------------------------------------------------------
void main() //主程序入口
{
// bit RunFlag=0; //定義小車運行標志位
// LedFlash=3000; //對閃燈數據進行初始化
EX1=1; //同意開啟外部中斷1
IT1=1; //設定外部中斷1為低邊緣觸發類型
EA=1; //總中斷開啟
// ET1=1;
tingzhi();
//初始化小車運行狀態
while(1) //程序主循環
{
if(key == 0)
{
delay_nms(10);
if(key == 0)
{
temp++;
while(!key);
}
}
if(temp > 4)
{
temp = 1;
}
switch(temp)
{
case 1:tingzhi();
//forward();
Stop_Music();
break;
case 2:
Robot_Avoidance();EX1 = 0;break;
case 3:
EX1 = 1;break;
case 4:
Star_Music();
break;
}
}
}
|