/******************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;
}
}
/******************************************************************************/
|