標題: 希望哪位大神幫我寫一下詳細的解釋 [打印本頁]
作者: 123456lkjhn 時間: 2017-4-30 12:47
標題: 希望哪位大神幫我寫一下詳細的解釋
#include <reg52.h>//單片機頭文件
#include <intrins.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h> //va_list 的頭文件
#define uchar unsigned char
#define uint unsigned int
sbit RS = P3^5;
sbit RW = P3^6;
sbit EN = P3^7;
sbit RX = P3^3; //超聲波接收
sbit TX = P3^2; //超聲波發(fā)射
static bit flag = 0;
/********************尋跡模塊IO口定義*********************************/
sbit xun_ll = P0^4; //從左到右第1個
sbit xun_l = P0^3; //從左到右第2個
sbit xun_z = P0^2; //從左到右第3個
sbit xun_r = P0^1; //從左到右第4個
sbit xun_rr = P0^0; //從左到右第5個
/********************LN298電機驅動IO口定義*********************************/
sbit qu_ll = P2^0; //左邊電機控制IN1
sbit qu_zl = P2^1; //左邊電機控制IN2
sbit qu_zr = P2^2; //右邊電機控制IN1
sbit qu_rr = P2^3; //右邊電機控制IN2
#define RS_H RS = 1
#define RS_L RS= 0
#define RW_H RW = 1
#define RW_L RW = 0
#define EN_H EN = 1
#define EN_L EN = 0
#define READ_DATA P1
void DelayMs(unsigned int z) //1ms延時函數
{
unsigned int x;
for(;z>0;z--)
for(x=110;x>0;x--);
}
void LCDWriteCom(unsigned char com)
{
RS_L;
RW_L;
READ_DATA= com;
EN_H;
DelayMs(5);
EN_L;
}
void LCDWriteData(unsigned char dat)
{
RS_H;
RW_L;
READ_DATA= dat;
EN_H;
DelayMs(5);
EN_L;
}
/*******************************************************************************
**函數名稱:LCD_Write_str()
**函數功能:在LCD上寫入一串字符
**輸入 口:hang : 要寫入的行,add 要寫入列 *s要寫入的指針數組
**輸出 口:無
**返回 值:無
**備 注:strlen()是引用庫函數string.h ,可以求出數組的長度
**日 期:2014.2.22
*******************************************************************************/
void LcdWriteStr(unsigned charhang,unsigned char add,char*s)
{
unsigned char i;
unsigned char length = 0;
if(hang==1)
LCDWriteCom(0x80+add);
else
LCDWriteCom(0x80+0x40+add);
length = strlen(s);
for(i=0;i<length;i++)
LCDWriteData(*s++); //指針送完數據后自加一
}
/*void LcdWriteChar(unsigned charhang,unsigned char add,char Ch)
{
if(hang== 1)LCDWriteCom(0x80+add);
elseLCDWriteCom(0x80+0x40+add);
LCDWriteData(Ch);
}*/
//能像printf一樣使用
void Lcd1602Printf( unsigned char x, unsignedchar y, unsigned char *p,...)
{
charidata LcdBuf[17];
va_list ap;
va_start(ap, p);
vsprintf(LcdBuf,p,ap);
va_end(ap);
LcdWriteStr(x,y,LcdBuf);
}
void Init_1602(void)
{
LCDWriteCom(0x38);
LCDWriteCom(0x0c);
LCDWriteCom(0x06);
LCDWriteCom(0x01);
DelayMs(2);
//Lcd1602Printf(1,0,"Lcd1602 Normal"); //測試液晶1602顯示用 Normal:正常
}
//觸發(fā)一個高電平時間
static void StartModule(void) //啟動模塊
{
TX=1; //啟動一次模塊
_nop_();_nop_();_nop_(); _nop_(); _nop_(); _nop_();_nop_();
_nop_();_nop_();_nop_(); _nop_(); _nop_(); _nop_();_nop_();
_nop_();_nop_();_nop_(); _nop_(); _nop_(); _nop_();_nop_();
TX=0;
}
/*******************************************************************************
* Function Name : Conut
* Description : 取出定時器的值,并通過計算得到距離,返回距離到調用函數
* Input : None
* Output : None
* Return : 計算得到的距離
* Attention : 當距離大于5m時,返回3個8,表示超出量程
*******************************************************************************/
static int Conut(void)
{
uintS,time;
time=TH0*256+TL0;
TH0=0;
TL0=0;
S=(time*1.7)/100; //算出來是CM
if((S>=500)||flag==1)//超出測量范圍 , 親測可以達到6M多一點點,不過
{ //跳動的很厲厲害,現改為5M
flag = 0;
S = 888;
}
returnS;
}
/*******************************************************************************
* Function Name : GetDis
* Description : 發(fā)出一個10us的高電平脈沖,得到超聲波測出的距離
* Input : None
* Output : None
* Return : S 測得的距離,Uint型變量,比如返回124,則表示為1.24M
* Attention : 調用的函數有:StartModule,Conut
*******************************************************************************/
int GetDis(void)
{
StartModule(); //給一個高電平觸發(fā)脈沖
while(!RX)xunnji(); //當RX為零時等待
TR0=1; //開啟計數
while(RX)xunnji(); //當RX為1計數并等待
TR0=0;
returnConut(); //計算
}
//定時器初始化
static void Timer0Init(void)
{
TMOD&= 0xf0;
TMOD|= 0x01; //設T0為方式1,
TH0=0;
TL0=0;
ET0=1; //允許T0中斷
EA=1; //開啟總中斷
}
/*******************************************************************************
* Function Name : CsbInit
* Description : 超聲波初始化函數
* Input : None
* Output : None
* Return : None
* Attention : 調用的函數有:Timer0Init ,只調用了一個定時器初始化
*******************************************************************************/
void CsbInit(void)
{
Timer0Init();
}
/************************** 定時器0中斷服務函數 *******************************/
void zd0() interrupt 1 //T0中斷用來計數器溢出,超過測距范圍
{
flag=1; //中斷溢出標志
}
/***********************小車前進函數************************/
void go()
{
qu_ll= 1;
qu_zl= 0;
qu_zr= 0;
qu_rr= 1;
}
// /***********************小車后退函數************************/
// void back()
// {
// qu_ll= 0;
// qu_zl= 1;
// qu_zr= 1;
// qu_rr= 0;
// }
/***********************小車左轉函數 只有一個輪子動************************/
void left()
{
qu_ll= 0;
qu_zl= 0;
qu_zr= 0;
qu_rr= 1;
}
/***********************小車左轉函數 左邊輪子后退 右邊輪子前進************************/
void left_s()
{
qu_ll= 0;
qu_zl= 1;
qu_zr= 0;
qu_rr= 1;
}
/***********************小車停下函數************************/
void stop()
{
qu_ll= 0;
qu_zl= 0;
qu_zr= 0;
qu_rr= 0;
}
/***********************小車右轉函數 只有一個輪子動************************/
void right()
{
qu_ll= 1;
qu_zl= 0;
qu_zr= 0;
qu_rr= 0;
}
/***********************小車右轉函數 左邊輪子前進 右邊輪子后退************************/
void right_s()
{
qu_ll= 1;
qu_zl= 0;
qu_zr= 1;
qu_rr= 0;
}
void che_90_180_break(uchar dat)
{
uchari_z = 0;
while(1) //循環(huán)等待中間尋跡傳感器到黑線上
{
if(xun_z == 0) //如果中間那尋跡傳感器到了黑線上,要讓小車停下來前進了
{
i_z++; //消去干擾
if(i_z>= 10) //10次之后就確定尋跡模塊的中間傳感器到黑線上了
{
if(dat == L) //如果是左轉90度就讓右轉的方法制動
right_s();
else
left_s(); //如果是右轉90度就讓左轉的方法制動
DelayMs(50);
go();
break; //break退出while(1)這個死循環(huán)
}
}
else //沒有在黑錢上就給i_z變量清零
{
i_z= 0;
}
}
}
/***********************小車左轉90度************************/
void left_s_90_while() //小車向左轉90度
{
go(); //前進一小會讓小車轉90度時剛好讓黑線在小車的中間
DelayMs(120);
left_s(); //左轉90度注意這個延時不能太長 只要能讓尋跡模塊中間的傳感離開黑線就好
DelayMs(180);
che_90_180_break(L);
}
/***********************小車向右轉90度************************/
void right_s_90_while() //
{
go(); //前進一小會讓小車轉90度時剛好讓黑線在小車的中間
DelayMs(120);
right_s(); //左轉90度注意這個延時不能太長 只要能讓尋跡模塊中間的傳感離開黑線就好
DelayMs(180);
che_90_180_break(R);
}
// 白線為 1 黑線為 0
void xunnji()
{
if((xun_ll==1)&& (xun_l==1) && (xun_z==0) && (xun_r==1) &&(xun_rr==1))
{
go(); //小車前進
}
if((xun_ll==0)&& (xun_l==0) && (xun_z==0) && (xun_r==0) &&(xun_rr==0))
{
stop();
}
if(((xun_ll==1)&& (xun_l==1) && (xun_z==0) && (xun_rr==1)) ||
((xun_ll==1) && (xun_l==1)&& (xun_z==1) && (xun_rr==1)) ||
((xun_ll==1) && (xun_z==1)&& (xun_rr==0)) ||
((xun_ll==1) && (xun_l==1)&& (xun_z==1) && ( (xun_rr==0)))
{
right();
}
if(((xun_ll==1)&& (xun_l==0) && (xun_r==1) && (xun_rr==1)) ||
((xun_ll==0) && (xun_l==0)&& (xun_z==1) && (xun_rr==1)) ||
((xun_ll==0) && (xun_l==1)&& && (xun_r==1)&& (xun_rr==1)))
{
left();
}
if((xun_ll==1)&& (xun_z==0) && (xun_rr==0))
{
go();
DelayMs(1);
if((xun_ll==1) &&(xun_z==0)&& (xun_rr==0))
{
right_s_90_while();
}
}
if((xun_ll==0)&& (xun_l==0) && (xun_rr==1))
{
go();
DelayMs(1);
if((xun_ll==0) && (xun_l==0)&& (xun_rr==1))
{
left_s_90_while();
}
}
}
void main(void)
{
intDis = 0;
InitTimer();
Init_1602();
CsbInit();
Dis= GetDis();
while(1)
{
xunnji();
if(bTime_500Ms)
{
bTime_500Ms= 0 ;
Dis= GetDis();
Lcd1602Printf(2,3,"Dis= %4.2f",Dis/100.0);
if(Dis< 24)
{
right_s();
DelayMs(500);
}
}
}
}
| 歡迎光臨 (http://www.raoushi.com/bbs/) |
Powered by Discuz! X3.1 |