|
/*請將此程序下載到U2
啟動鍵為U2P32
停止鍵為U2P33
有可能會出現黑線傳感器感應不到黑線的情況,是因為黑線傳感器的靈敏度調得太高了
應該調低靈敏度,這樣才能檢測到黑線.因為靈敏度太高,黑色反射的紅外光都能被傳感
器識別,導致檢測失敗.應該把黑線傳感器上的可調電阻逆時針調節,這樣就能把靈敏
度調低(順時針調節的時候是調高)*/
#include <at89x52.h>
#define uchar unsigned char
#define uint unsigned int
void motor_r_z(void);//右邊電動機正轉
void motor_l_z(void);//左邊電動機正轉
void motor_r_f(void);//右邊電動機反轉
void motor_l_f(void);//左邊電動機反轉
void go(uchar,uchar);//小車前進
void stop(void);//小車停止
sbit IN1=P3^6;//L298N的IN1接到P2.5
sbit IN2=P3^7;//L298N的IN2接到P2.4
sbit IN3=P2^7;//L298N的IN3接到P2.1
sbit IN4=P2^6;//L298N的IN4接到P2.2
sbit ENA=P3^4;//L298N的ENA接到P2.0
sbit ENB=P3^5;//L298N的ENB接到P2.2
sbit left_k=P1^2;//小車左轉信號輸入端為P0.5,P0.5為1時說明已經檢測到黑線
sbit right_k=P1^3;//小車左轉信號輸入端為P0.4,P0.4為1時說明已經檢測到黑線
sbit start_k=P3^2;//啟動按鍵為U2P32
sbit stop_k=P3^3;//停止按鍵為U2P33
sbit sound=P2^4;//蜂鳴器接到了P2.4上,P2.4為低電平的時候,蜂鳴器響。
uchar data t_0;//每產生一次T0定時器中斷的時候t_0加1
uchar data motor_r;//motor_r用于存放右邊電機轉速和轉向的數據
uchar data motor_l;//motor_l用于存放左邊電機轉速和轉向的數據
uchar data Speed_Parameters;
//**延時子程序**///
void delay_1ms(uint n)
{
uint i,j;
for(j=n;j>0;j--)
for(i=20;i>0;i--);
}
/*******初始化函數***********/
void ini(void)
{
////T0初始化///
TMOD=0x01; //T0工作在方式1
TH0=0xff; //裝入T0初值
TL0=0xf6;
TR0=1;//開T0中斷
ET0=1;//T0允許中斷
EA=1;
P0=0Xff;
//////////////////////
t_0=0;
/////////////////////
P2=0xff;
P3=0XFF;
P1=0XFF;
sound=0;
delay_1ms(100);//蜂鳴器響100ms
sound=1;
}
///蜂鳴器響///
void Sound(void)
{
sound=0;
delay_1ms(60);
sound=1;
}
/****啟動處理函數****/
void start(void)
{
uchar a;
aa:while(start_k);//防抖程序
for(a=0;a<50;a++)
{
delay_1ms(1);
while(start_k)
goto aa;
}
Sound();//調用蜂鳴器發音程序
go(0x64,0x64);//全速直行
}
void go(uchar left_motor,uchar right_motor)//直行
{
Speed_Parameters=right_motor;//給速度參數賦值
motor_r_z();//調用右邊電機正轉函數
Speed_Parameters=left_motor;
motor_l_z();//調用左邊電機正轉函數
}
void motor_r_z(void)//右邊電動機正轉
{
motor_r=0x64+Speed_Parameters;
ENA=1;
}
void motor_l_z(void)//左邊電動機正轉
{
motor_l=0x64-Speed_Parameters;
ENB=1;
}
void stop(void)
{
ENB=0;
ENA=0;
}
/*********T0中斷服務程序*****************/
/*********PWM產生***********************/
void time0(void) interrupt 1 using 2
{
TR0=0;//停止T0計數
TH0=0xff;//當晶振頻率是12M時,每隔0.01ms中斷一次,200次中斷為PWM信號輸出的周期,
TL0=0xf6;//PWM信號的頻率=1000/(200*0.01ms)=500HZ
++t_0;//產生一次中斷t_0加1
ACC=t_0;//將t_0的值賦值給ACC
CY=0;//清零CY
ACC-=motor_r;//用ACC減去右邊電動機的參數(此參數決定了右邊電機的轉向和速度)
if(CY==1)//判斷CY是否置1,如果為1,說明ACC-motor_r已經為負數,置位了CY
{
IN1=1;//IN1由原來的0變成了1
IN2=0;//IN2由原來的1變成了0
goto PWM_2;
}
IN1=0;//如果CY不等于1,IN1=0,IN2=1
IN2=1;
PWM_2:
ACC=t_0;//重新將t_0的值賦值給ACC
CY=0;//清零CY
ACC-=motor_l;//用ACC減去左邊電動機的參數(此參數決定了左邊電機的轉向和速度)
if(CY==1)//判斷CY是否置1,如果為1,說明ACC-motor_l已經為負數,置位了CY
{
IN3=1;//IN3由原來的0變成了1
IN4=0;//IN4由原來的1變成了0
goto HIGHT;
}
IN3=0;//如果CY不等于1,IN3=0,IN4=1
IN4=1;
HIGHT:
//ACC=t_0; //重新將t_0的值賦值給ACC
if(t_0!=0xc8)//判斷t_0的值是否不等于200
goto EXIT;//如果不等于200,程序指針指向EXIT執行程序
ACC=0;//如果t_0的值等于200,清零ACC和t_0
t_0=ACC;
EXIT:
TR0=1;//打開TO計數
}
void main(void)
{
uchar a;
ini();//調用初始化函數
start();//調用啟動處理函數
////判斷左傳感器狀態////
while(1)
{
aa:
while(!left_k)//判斷左邊傳感器的值是否為0
goto bb;//如果是0,程序指針指向標號bb,執行程序
P0_0=0;//如果是1,點亮P1.0上連接的發光二極管
// Sound();
while(left_k)//如果left_k的值一直為1,不斷的循環執行 go(0x00,0x64);小車左轉 直到left_k的值為0為止。
go(0x00,0x64);//0x00,0x64分別代表左右電動機的轉速,兩個值的取值為0x00到0x64之間,0x00最慢。0x64最快
//0x00,0x64這兩個值不一樣代表兩個電機向前轉的速度不同,小車將拐彎
go(0x40,0x40);//執行到這句說明left_k已經為1,說明左傳感器已經離開了黑線。小車直線前進
//0x40,0x40這連個值同表示小車執行這個函數時將向前走,用戶可以自任意修改這些數值,達到小車走黑線
//最穩定的效果,建議不要取得太大(十六進制0x64是最大,其實也就是十進制數的100),也就是速度等級
//為0到100個等級。
P0_0=1;//關閉LED指示燈
////判斷右傳感器狀態////
bb:
while(!right_k)//判斷右傳感器的值是否為0
goto cc;//如果是0,程序指針指向標號cc,執行程序
P0_1=0;//如果是1,點亮P1.1上連接的發光二極管
// Sound();
while(right_k)//如果right_k的值一直為1,不斷的循環執行go(0x64,0x0);;小車右轉 直到right_k的值為0為止
go(0x64,0x0);
go(0x40,0x40);//執行到這句說明right_k已經為1,說明左傳感器已經離開了黑線。小車直線前進
P0_1=1;//關閉LED指示燈
///判斷是否按下停止按鈕//////
cc:
while(stop_k)//判斷停止鍵是否按下,按下的時候stop_k為1
goto aa;////如果是1,程序指針指向標號aa,執行程序
for(a=0;a<20;a++)//如果是0,進入防抖程序
{
delay_1ms(1);
while(stop_k)//判斷20次stop_k是否為1
goto cc;//如果是1,程序指針指向標號cc,執行程序
}
stop();//20次判斷之后stop_k都是0,立馬停止兩個電動機
start();//跳到啟動處理函數,執行程序。
}
}
|
-
-
00 走黑線源程序.zip
2019-7-26 20:26 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
21.51 KB, 下載次數: 6, 下載積分: 黑幣 -5
|