/******************SL-51B實驗開發板例程(超聲波測距1602顯示)******************
注意:用杜邦線將超聲波模塊的VCC接開發板5V對外供電接口
用杜邦線將超聲波模塊的GND接開發板GND
用杜邦線將超聲波模塊的Trig接單片機的P1.5
用杜邦線將超聲波模塊的Echo接單片機的P1.6
舵機黃線 PWM信號輸出P2^2 (舵機程序)
/**********************************包含頭文件**********************************/
#include <reg51.h>
#define LCD_Data P0
#define Busy 0x80
/************************************宏定義************************************/
#define SPEED_30C 3495 //30攝氏度時的聲速,聲速V= 331.5 + 0.6*溫度;
#define SPEED_23C 3453 //23攝氏度時的聲速,聲速V= 331.5 + 0.6*溫度;
/************************************位定義************************************/
sbit ECHO = P1^6; //回聲接收端口
sbit TRIG = P1^5; //超聲觸發端口
sbit BEEP = P2^3; //蜂鳴器
sbit LCD_RS = P1^0;
sbit LCD_RW = P1^1;
sbit LCD_E = P2^5;
sbit DU = P2^0;
sbit WE = P2^1;
sbit pwm =P2^2 ; //黃線 PWM信號輸出P0^1 (舵機程序)
sbit jia =P3^0; //角度增加按鍵檢測IO口 上:k1 (舵機程序)
sbit jan =P3^1; //角度減少按鍵檢測IO口 下:k2 (舵機程序)
sbit go =P3^7; // 開始:k8 (舵機程序)
sbit sp =P3^6; // 停止:k7 (舵機程序)
/********************************定義變量和數組********************************/
long int distance = 0; //距離變量
unsigned char count; //0.5ms次數標識(舵機程序)
unsigned char jd; //角度標識(舵機程序)
unsigned char code table0[] = {" SL-51A "};
unsigned char code table1[] = {" NO ECHO "};
unsigned char code table2[] = {"Distance:xxx.xcm"};
unsigned char count; //同上
unsigned int xh; //(舵機程序)
void Delay5Ms(void);
void delay(int In,int Out);
void WriteDataLCD(unsigned char WDLCD);
void WriteCommandLCD(unsigned char WCLCD,BuysC);
unsigned char ReadDataLCD(void);
unsigned char ReadStatusLCD(void);
void LCDInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
/******************************************************************************/
/* 函數名稱 : Delay_xMs */
/* 函數描述 : 延時函數 */
/* 輸入參數 : x */
/* 參數描述 : 延時時間 */
/* 返回值 : 無 */
/******************************************************************************/
void Delay_xMs(unsigned int x)
{
unsigned int i,j;
for(i = 0;i < x;i++ )
{
for(j = 0;j < 3;j++ )
{;}
}
}
/******************************************************************************/
/* 函數名稱 : delayt */
/* 函數描述 : 延時函數 */
/* 輸入參數 : x */
/* 參數描述 : 延時時間數據 */
/* 返回值 : 無 */
/******************************************************************************/
void delayt(unsigned int x)
{
unsigned char j;
while(x-- > 0)
{
for(j = 0;j < 125;j++)
{;}
}
}
/*************************5ms延時函數***************************/
void Delay5Ms(void)
{
unsigned int TempCyc = 3552;
while(TempCyc--);
}
/**************************延遲函數*****************************/
void delay(int In,int Out)
{
int i,j;
for( i = 0;i < In;i++ )
{
for( j = 0;j < Out;j++ )
{;}
}
}
/******************************************************************************/
/* 函數名稱 : Alarm */
/* 函數描述 : 蜂鳴器發聲函數 */
/* 輸入參數 : t */
/* 參數描述 : 發聲的次數 */
/* 返回值 : 無 */
/******************************************************************************/
void Alarm(unsigned char t)
{
unsigned char i;
for(i = 0;i < t;i++)
{
BEEP = 0;
delay(10,1000);
BEEP = 1;
delay(10,1000);
}
}
/******************************************************************************/
/* 函數名稱 : Init_timer */
/* 函數描述 : 初始化單片機函數 */
/* 輸入參數 : 無 */
/* 參數描述 : 無 */
/* 返回值 : 無 */
/******************************************************************************/
void Init_timer(void)
{
TMOD = 0x01; //定時器2初始化,設置為16位自動重裝模式
TL0 = 0x66;
TH0 = 0xfc; //1ms
ET0 = 1; //開定時器2
EA = 1; //總中斷使能
}
/******************************************************************************/
/* 函數名稱 : Init_Parameter */
/* 函數描述 : 初始化參數和IO口函數 */
/* 輸入參數 : 無 */
/* 參數描述 : 無 */
/* 返回值 : 無 */
/******************************************************************************/
void Init_Parameter(void)
{
TRIG = 1;
ECHO = 1;
count = 0;
distance = 0;
}
/******************************************************************************/
/* 函數名稱 : display */
/* 函數描述 : 顯示數字 */
/* 輸入參數 : number,address */
/* 參數描述 : number寫入的數據 */
/* 返回值 : 無 */
/******************************************************************************/
void display(int number)
{
unsigned char b,c,d,e;
b = (number/1000);
c = (number/100)%10;
d = (number/10)%10;
e = number%10;
DisplayOneChar(9,1,(0x30+b));
DisplayOneChar(10,1,(0x30+c));
DisplayOneChar(11,1,(0x30+d));
DisplayOneChar(13,1,(0x30+e));
}
/******************************************************************************/
/* 函數名稱 : Trig_SuperSonic */
/* 函數描述 : 發出聲波函數 */
/* 輸入參數 : 無 */
/* 參數描述 : 無 */
/* 返回值 : 無 */
/******************************************************************************/
void Trig_SuperSonic(void)//出發聲波
{
TRIG = 1;
delayt(1);
TRIG = 0;
}
/******************************************************************************/
/* 函數名稱 : Measure_Distance */
/* 函數描述 : 計算距離函數 */
/* 輸入參數 : 無 */
/* 參數描述 : 無 */
/* 返回值 : 無 */
/******************************************************************************/
void Measure_Distance(void)
{
unsigned char l;
unsigned int h,y;
TR0 = 1;
while(ECHO)
{
;
}
TR0 = 0;
l = TL0;
h = TH0;
y = (h << 8) + l;
y = y - 0xfc66; //us部分
distance = y + 1000 * count; //計算總時間
TL0 = 0x66;
TH0 = 0xfc;
delayt(30);
distance = SPEED_30C * distance / 20000;
}
/**************************寫數據函數***************************/
void WriteDataLCD(unsigned char WDLCD)
{
ReadStatusLCD(); //檢測忙
LCD_Data = WDLCD;
LCD_RS = 1;
LCD_RW = 0;
LCD_E = 0; //若晶振速度太高可以在這后加小的延時
LCD_E = 0; //延時
LCD_E = 1;
}
/*************************寫指令函數****************************/
void WriteCommandLCD(unsigned char WCLCD,BuysC) //BuysC為0時忽略忙檢測
{
if (BuysC) ReadStatusLCD(); //根據需要檢測忙
LCD_Data = WCLCD;
LCD_RS = 0;
LCD_RW = 0;
LCD_E = 0;
LCD_E = 0;
LCD_E = 1;
}
/**************************讀數據函數***************************/
unsigned char ReadDataLCD(void)
{
LCD_RS = 1;
LCD_RW = 1;
LCD_E = 0;
LCD_E = 0;
LCD_E = 1;
return(LCD_Data);
}
/**************************讀狀態函數***************************/
unsigned char ReadStatusLCD(void)
{
LCD_Data = 0xFF;
LCD_RS = 0;
LCD_RW = 1;
LCD_E = 0;
LCD_E = 0;
LCD_E = 1;
while (LCD_Data & Busy); //檢測忙信號
return(LCD_Data);
}
/***************************LCD初始化***************************/
void LCDInit(void) //LCD初始化
{
LCD_Data = 0;
WriteCommandLCD(0x38,0); //三次顯示模式設置,不檢測忙信號
Delay5Ms();
WriteCommandLCD(0x38,0);
Delay5Ms();
WriteCommandLCD(0x38,0);
Delay5Ms();
WriteCommandLCD(0x38,1); //顯示模式設置, 開始要求每次檢測忙信號
WriteCommandLCD(0x08,1); //關閉顯示
WriteCommandLCD(0x01,1); //顯示清屏
WriteCommandLCD(0x06,1); //顯示光標移動設置
WriteCommandLCD(0x0C,1); //顯示開及光標設置
}
/****************************清屏 函數********************************/
void LCD_Clear(void)
{
WriteCommandLCD(0x01,1);
Delay5Ms();
}
/**********************按指定位置顯示一個字符*********************/
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //當要顯示第二行時地址碼+0x40;
X |= 0x80; //算出指令碼
WriteCommandLCD(X, 0); //這里不檢測忙信號,發送地址碼
WriteDataLCD(DData);
}
/***********************按指定位置顯示一串字符********************/
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
unsigned char ListLength;
ListLength = 0;
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
while (DData[ListLength]>=0x20) //若到達字串尾則退出
{
if (X <= 0xF) //X坐標應小于0xF
{
DisplayOneChar(X, Y, DData[ListLength]); //顯示單個字符
ListLength++;
X++;
}
}
}
/***********************舵機函數*******************************************************/
void Time0_Init() //定時器初始化
{
TMOD = 0x01; //定時器0工作在方式1
IE = 0x82;
TH0 = 0xfe;
TL0 = 0x33; //11.0592MZ晶振,0.5ms
TR0=1; //定時器開始
}
void Time0_Int() interrupt 1 //中斷程序
{
TH0 = 0xfe; //重新賦值
TL0 = 0x33;
if(count< jd) //判斷0.5ms次數是否小于角度標識
pwm=1; //確實小于,PWM輸出高電平
else
pwm=0; //大于則輸出低電平
count=(count+1); //0.5ms次數加1
count=count%40; //次數始終保持為40 即保持周期為20ms
}
void keyscan() //按鍵掃描
{
if(jia==0) //角度增加按鍵是否按下
{
delay(10); //按下延時,消抖
if(jia==0) //確實按下
{
jd++; //角度標識加1
count=0; //按鍵按下 則20ms周期從新開始
if(jd==6)
jd=5; //已經是180度,則保持
while(jia==0); //等待按鍵放開
}
}
if(jan==0) //角度減小按鍵是否按下
{
delay(10);
if(jan==0)
{
jd--; //角度標識減1
count=0;
if(jd==0)
jd=1; //已經是0度,則保持
while(jan==0);
}
}
}
void xhcan()
{
if(go==0) // 按鍵是否按下
{
delay(10); //按下延時,消抖
if(go==0) //確實按下
{
xh=1; //
while(go==0); //等待按鍵放開
}
}
if(sp==0) // 按鍵是否按下
{
delay(10); //按下延時,消抖
if(sp==0) //確實按下
{
xh=0; //
while(sp==0); //等待按鍵放開
}
}
}
/******************************************************************************/
/* 函數名稱 : main */
/* 函數描述 : 主函數 */
/* 輸入參數 : 無 */
/* 參數描述 : 無 */
/* 返回值 : 無 */
/******************************************************************************/
void main(void)
{
DU=1;
P0=0x00;
DU=0;
BEEP=0;
delay(50,100);
BEEP=1;
delay(50,100);
BEEP=0;
delay(50,100);
BEEP=1;
LCDInit();
Init_timer();
Init_Parameter();
Alarm(5);
DisplayListChar(0,0,table0);
DisplayListChar(0,1,table1);
jd=0; //(舵機程序)
count=0; //(舵機程序)
Time0_Init(); //(舵機程序)
while(1)
{
Trig_SuperSonic(); //觸發超聲波發射
while(ECHO == 0) //等待回聲
{
;
}
Measure_Distance(); //計算脈寬并轉換為距離
DisplayListChar(0,1,table2);
display(distance); //顯示距離
Init_Parameter(); // 參數重新初始化
delayt(100); //延時,兩次發射之間要至少有10ms間隔
keyscan(); //按鍵掃描
xhcan(); //(舵機程序)
while(xh) //(舵機程序)
{
jd=4;
delay(100,100);
jd=3;
delay(100,100);
jd=2;
delay(100,100);
jd=1;
delay(100,100);
jd=2;
delay(100,100);
jd=3;
delay(100,100);
jd=4;
delay(100,100);
jd=5;
delay(100,100);
jd=6;
xhcan();
}
}
}
/******************************************************************************/
/* 函數名稱 : timer0 */
/* 函數描述 : T0中斷處理函數 */
/* 輸入參數 : 無 */
/* 參數描述 : 無 */
/* 返回值 : 無 */
/******************************************************************************/
void timer0 (void) interrupt 1
{
TF0 = 0;
TL0 = 0x66;
TH0 = 0xfc;
count++;
if(count == 18)//超聲波回聲脈寬最多18ms
{
TR0 =0;
TL0 = 0x66;
TH0 = 0xfc;
count = 0;
}
}
/******************************************************************************/
|