超声波程序
本人收藏的的一些超声波程序,希望对大家有用(还有原理图,需要的话去我空间去下):
程序一:
#include
#define uchar unsigned char
#define uint unsigned int
#define count 4
uchar data IRcode[4]; //定义一个4字节的数组用来存储代码 uchar table[4];
uchar enled[4]={0x1f,0x2f,0x4f,0x8f};
uchar CodeTemp,temp,tt; //编码字节缓存变量
uchar
i,j,k,temp,timeH,timeL,succeed_flag,flag,h,h1,h2,a,key,key1,key2; //延时用的循环变量
uint distance,distance1,time; //距离,time
sbit IRsignal=P3^2; //HS0038接收头OUT 端直接连P3.2(INT0) sbit come=P3^3;
sbit d=P1^1;//发送码
sbit BZ=P1^0;
sbit s=P3^7;//38k
sbit ss=P3^6;//38k
uchar m;// 开关控制
//sbit n=P2;//电机反转
code unsigned char seg7code[10]={0xa0,0xbb,0x62,0x2a,0x39,0x2c,0x24,0xba,0x20,0x28}; //显示段码
/**************************** 定时器0中断 ************************/ void timer0() interrupt 1
{
TH0=(65536-count)/256;
TL0=(65536-count)%256;
s=~s;//产生38K 信号
ss=~ss;//
tt++;//发送超声波个数
}
/**************************** 延时0.9ms 子程序 ************************/
void Delay0_9ms(void)
{
uchar j,k;
for(j=18;j>0;j--)
for(k=20;k>0;k--);
}
/***************************延时1ms 子程序**********************/ void Delay1ms(void)
{
uchar i,j;
for(i=2;i>0;i--)
for(j=230;j>0;j--);
}
/***************************延时4.5ms 子程序**********************/ void Delay4_5ms(void)
{
uchar i,j;
for(i=10;i>0;i--)
for(j=225;j>0;j--);
}
/**************************** 解码延时子程序 ************************/
void Delay(void)
{
uchar i,j,k;
for(i=100;i>0;i--)
for(j=100;j>0;j--)
for(k=3;k>0;k--);
}
/**************************** 显示延时子程序 ************************/
void ledDelay(unsigned int tc) //延时程序
{
unsigned int i,j;
for(i=0;i
for(j=0;j
}
/************************************************ ****************/ //定时器1中断, 用做超声波测距无回波
void timer1() interrupt 3
{
TR1=0;
ET1=0;
EX1=0;
TH1=0;
TL1=0;
}
/***********************显示程序*********************/
void Led(int date) //显示函数
{ int i;
table[0]=date/1000;
table[1]=date/100%10;
table[2]=date/10%10;
table[3]=date%10;
date=0;
for(i=0;i
{
P2=enled[i%4]&m;//P2口高四位控制数码管,低位陪分控制继电器 P0=seg7code[table[i%4]]; //取出千位数,查表,输出。
ledDelay(15);
}
}
/*******************************************************************/ //外部中断1,用做判断超声波回波电平说明测试成功
void int1() interrupt 2 // 外部中断1是0号
{
EX1=0;//关闭外部中断1
TR1=0;
ET1=0;
succeed_flag=1;//测试成功标志
}
/****************************超声波测路子函数***********************/
void sound()
{ ET0=1;TR0=1;//开38K 超声波输入端
while(tt!=1); //发送几个脉冲的超声
tt=0;//清零重新计数
ET0=0;TR0=0;
tt=0;//清零重新计数
TF1=0;//计数溢出标志
TH1=0;//定时器1清零
TL1=0;// 定时器1清零
ET1=1;//开定时器1
TR1=1;//启动定时器1
EX1=1;//打开外部中断1
succeed_flag=0;
while(EX1==1);//等待回波标志
if(succeed_flag==1)//测试成功
{time=TH1*256+TL1;//回波响应时间
distance=time*1.72/100;//换算成路程
Led(distance);//显示测到的距离
EX1=1;//开中断1
}
if(succeed_flag==0)//测试不成功或超出时间
{
Led(3333);//表示测不到回波
}
}
/****************************红外解码******************************/ /******************** 中断0解码服务子程序 ********************/ void int0(void) interrupt 0 using 2
{
EA = 0;//??? 可以这样,跳入中断,但仍可对P3.2(INT0)进行电平变化的读取
for(k=0;k
{
Delay0_9ms();
if (IRsignal==1) //如果0.9ms 后IRsignal=1,说明不是引导码 {
k=10;
break;
}
else if(k==9) //如果 持续了10×0.9ms=9ms的低电平,说明是引导码
{
while(IRsignal==0);
Delay4_5ms(); //跳过持续4.5ms 的高电平
for(i=0;i
{
for(j=1;j
{
while(IRsignal==0); //等待上升沿 此处用得很好:因为0.56ms 的低电平(接收时)是代码0与1的相同部分
Delay0_9ms(); //从上升沿那一时刻开始延时0.9ms (因为0.9介于0.56(=1.125-0.56)与1.69(=2.25-0.56)之间),再判断IRsignal if(IRsignal==1) //如果IRsignal 是"1", 高位置"1" ,并向右移一位
{
Delay1ms(); //为什么要延时1ms 呢?因为要使IRsignal 跳至低电平(即0.56ms 的0与1相同部分上)
CodeTemp=CodeTemp|0x80; //此处的算法很好
if(j>1;
}
else if(j
{CodeTemp=CodeTemp>>1;}//如果IRsignal 是"0", 则直接向右移一位,自动补"0"
}
IRcode[i]=CodeTemp;
CodeTemp=0;
}
for(i=0;i
{
SBUF=IRcode[i]; //引导码 地址码 数据码 数据反码 while(!TI); //等待一个字节发送完毕
TI=0;
}
Delay();
}
}
switch(IRcode[2]) //数据位
{
case 69:m=0xfe;break;//电机上升
case 70:m=0xff;break;//电机停止
case 71:m=0xfc;break;//电机下降
case 22:a=0;break;
case 25:key=1;break;//功能键
case 12:a=1;;break;
case 24:a=2;;break;
case 94:a=3;;break;
case 8: a=4;;break;
case 28:a=5;;break;
case 90:a=6;;break;
case 66:a=7;;break;
case 82:a=8;;break;
case 74:a=9;;break;
}
EA = 1;//开总中断
}
/*******************************************************************/ /***********************初始化程序*********************/
void initUart(void)
{
TMOD |= 0x11; //定时器T1,T0都用方式1,16位
PCON |= 0x80;
TH1=0;//定时器T1 高位初始化
TL1=0;//定时器T1 低位初始化
ET1=1;//开定时器1
TR1 =1; //用时才启动
//TMOD=0x01;
TH0=(65536-count)/256;// 定时器T0 初值
TL0=(65536-count)%256; //
EA=1;//开总中断
ET0=0;//先关上38KHz ,用到的时候再开
TR0=0; //先关上38KHz ,用到的时候再开
}
/*******************************************************************/ /*******************************************************************/ //设置电机到达的高度
void scankey()
{
while(IRcode[2]==25)
{ Led(1111); //显示1111表示进入了功能菜单
while(IRcode[2]!=25)
{ BZ=1;//开掉蜂鸣器
h1=10*a;//设置10位
IRcode[2]=1;//进入个位标志
Led(h1);//显示设置多少十
while(IRcode[2]!=1)
{ h=h1+a;//十位加个位
Led(h);//显示设置到达的高度
key1=1;//作用用于退出死循环
if(IRcode[2]==25)//再次按功能键则完成设置
{break;}
}
}
if(key1==1)// 退出死循环
{key1=0;
IRcode[2]=0;
break;
}
}
}
/*****************************高度判断函数******************************/
void high()
{
if(95
IRcode[2]=0;//清零红外接收的数据
m=0xff; //关电机
BZ=0;//开蜂鸣器
Delay();
BZ=1;// 关
}
}
/*******************************************************************/ /**************************主程序*************************/
void main()
{
P2=0xFF;//数码管测试
ledDelay(1);
P2=0xff;
initUart();
IT1=1;
IT0 = 1;//INT0为负边沿触发, (1:负边沿触发,0:低电平触发)
EX0 = 1;//外部中断INT0开, (1:开, 0:关 )
EA = 1;//开所有中断
CodeTemp = 0;//初始化红外编码字节缓存变量
temp=0;
tt=0;
m=0xff;
h=1;
while(1)
{ sound();//调超声测距函数测距
SBUF=P3; //P3口信息返回
if(!TI)
{ TI=0;
}
high();//高度判断
scankey();// 如果按的功能键则进入此函数
}
}
程序二:
//超声波模块程序
//超声波模块程序
//Trig = P2^0
//Echo = P3^2
#include
#define uchar unsigned char
#define uint unsigned int
//
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//
void delay_20us()
{
uchar a ;
for(a=0;a
}
//*************************************************************** //显示数据转换程序
void display(uint temp)
{
uchar ge,shi,bai;
bai=temp/100;
shi=(temp%100)/10;
ge=temp%10;
wela=1;
P0=0xf7;
wela=0;
dula=1;
P0=table[bai];
dula=0;
delay(1);
dula=1;
P0=0x00; //关位码
dula=0;
wela=1;
P0=0xef;
wela=0;
dula=1;
P0=table[shi];
dula=0;
delay(1);
dula=1;
P0=0x00; //关位码
dula=0;
dula=1;
P0=table[ge];
dula=0;
wela=1;
P0=0xdf;
wela=0;
delay(1);
dula=1;
P0=0x00; //关位码
dula=0;
}
//*************************************************************** void main()
{
uint distance;
test =0;
Trig=0; //首先拉低脉冲输入引脚
EA=1; //打开总中断0
TMOD=0x10; //定时器1,16位工作方式
while(1)
{
EA=0; //关总中断
Trig=1; //超声波输入端
delay_20us(); //延时20us
Trig=0; //产生一个20us 的脉冲
while(Echo==0); //等待Echo 回波引脚变高电平
succeed_flag=0; //清测量成功标志
EA=1;
EX0=1; //打开外部中断0
TH1=0; //定时器1清零
TL1=0; //定时器1清零
TF1=0; //计数溢出标志
TR1=1; //启动定时器1
delay(20); //等待测量的结果
TR1=0; //关闭定时器1
EX0=0; //关闭外部中断0
if(succeed_flag==1)
{
time=timeH*256+timeL;
distance=time*0.172; //厘米
display(distance);
}
if(succeed_flag==0)
{
distance=0; //没有回波则清零 test = !test; //测试灯变化
}
}
}
//*************************************************************** //外部中断0,用做判断回波电平
void exter() interrupt 0 // 外部中断0是0号
{
timeH =TH1; //取出定时器的值
timeL =TL1; //取出定时器的值
succeed_flag=1;//至成功测量的标志
EX0=0; //关闭外部中断
}
//**************************************************************** //定时器1中断, 用做超声波测距计时
void timer1() interrupt 3 //
{
TH1=0;
TL1=0;
}
程序三:
#include
#include
#define uchar unsigned char
#define uint unsigned int
unsigned int time;
unsigned int S,s_false;
unsigned long num1;
bit flag ;
sbit Trig =P3^6;//定义引脚
sbit Echo=P3^7;
sbit lcdrs=P2^0;//命令数据
sbit lcdrw=P2^1;//读写
sbit lcde=P2^2;//能
sbit led=P3^5;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*void delay_20us()
{
uchar a ;
for(a=0;a
}
*/
//*************************************************************** void write_com(unsigned char com)
{
lcdrs=0;
P0=com;
delay(5);
lcde=1;
delay(5);
lcde=0;
}
void write_data(unsigned char zifu)
{
lcdrs=1;
P0=zifu;
delay(5);
lcde=1;
delay(5);
lcde=0;
}
void write_temp(uint t_emp)
{
uchar qian,bai,shi,ge;
qian=t_emp/1000;
bai=(t_emp%1000)/100;
shi=(t_emp%100)/10;
ge=t_emp%10;
write_com(0x80);
write_data(0x30+qian);
delay(1);
write_data(0x30+bai);
delay(1);
write_data(0x30+shi);
delay(1);
write_data(0x30+ge);
delay(1);
delay(100);
}
/********************************************************/
void T0_time() interrupt 1 //T0中断用来计数器溢出, 超过测距范围
{
flag=0; //中断溢出标志, 失败
TH0=0;
TL0=0;
TR0=0; //关闭计数 }
/********************************************************/
void T1_timer() interrupt 3 //中断
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
num1++;
if (num1==20)
{
num1=0;
led=~led;
}
}
void StartModule() //
{
Trig=1; //
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_(); 启动模块启动一次模块
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
Trig=0;
}
/********************************************************/
void Count(void)
{
time=TH0*256+TL0;
TH0=0;
TL0=0;
S=(time*1.7)/100; //算出来是CM
if(((S=600))||flag==0) //超出测量范围显示“-”失败
{
// flag=1;
s_false=1000;
write_com(0x80);
write_data('e');
delay(5);
write_data('r');
delay(5);
write_data('r');
delay(5);
write_data('o');
delay(5);
write_data('r');
delay(5);
// write_temp(s_false);
}
else
{
write_temp(S);
}
}
/********************************************************/
/********************************************************/ void init()
{
lcde=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
lcdrw=0;
}
//*************************************************************** void main()
{
// unsigned char TempCyc;
delay(500); //启动等待,等LCM 讲入工作状态
lcdrw=0;
init(); //LCM初始化
delay(500); //延时片刻(可不要)
while(1)
{
TMOD=0x11; //设T0为方式1,GATE=1; TH0=0;
TL0=0;
ET0=1; //允许T0中断
ET1=1;
TR1=1;
EA=1; //开启总中断
Trig=0;
Echo=0;
while(1)
{
StartModule();
flag=1;
// while(!Echo); //
while((!Echo)&&flag); //
断flag 跳出等待
TR0=1; //
while(Echo&&flag); //
TR0=0; //
Count(); //
delay(120); //80MS
}
}
}
程序四:
#include
#include
#define uchar unsigned char
#define uint unsigned int
unsigned int time;
unsigned int S,s_false;
unsigned long num1; 当echo 为零时等待 当echo 为零时等待, 中开启计数 当echo 为1计数并等待关闭计数 计算
bit flag ;
sbit Trig =P3^6;//定义引脚
sbit Echo=P3^7;
sbit lcdrs=P2^0;//命令数据
sbit lcdrw=P2^1;//读写
sbit lcde=P2^2;//能
sbit led=P3^5;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*void delay_20us()
{
uchar a ;
for(a=0;a
}
*/
//*************************************************************** void write_com(unsigned char com)
{
lcdrs=0;
P0=com;
delay(5);
lcde=1;
delay(5);
lcde=0;
}
void write_data(unsigned char zifu)
{
lcdrs=1;
P0=zifu;
delay(5);
lcde=1;
delay(5);
lcde=0;
}
void write_temp(uint t_emp)
{
uchar qian,bai,shi,ge;
qian=t_emp/1000;
bai=(t_emp%1000)/100;
shi=(t_emp%100)/10;
ge=t_emp%10;
write_com(0x80);
write_data(0x30+qian);
delay(1);
write_data(0x30+bai);
delay(1);
write_data(0x30+shi);
delay(1);
write_data(0x30+ge);
delay(1);
delay(100);
}
/********************************************************/
void T0_time() interrupt 1 //T0中断用来计数器溢出, 超过测距范围
{
flag=0; //中断溢出标志, 失败
TH0=0;
TL0=0;
TR0=0; //关闭计数 }
/********************************************************/
void T1_timer() interrupt 3 //中断
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
num1++;
if (num1==20)
{
num1=0;
led=~led;
}
}
void StartModule() //启动模块
{
Trig=1; //启动一次模块 _nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
Trig=0;
}
/********************************************************/
void Count(void)
{
time=TH0*256+TL0;
TH0=0;
TL0=0;
S=(time*1.7)/100; //算出来是CM
if(((S=600))||flag==0) //超出测量范围显示“-”失败
{
// flag=1;
s_false=1000;
write_com(0x80);
write_data('e');
delay(5);
write_data('r');
delay(5);
write_data('r');
delay(5);
write_data('o');
delay(5);
write_data('r');
delay(5);
// write_temp(s_false);
}
else
{
write_temp(S);
}
}
/********************************************************/
/********************************************************/
void init()
{
lcde=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
lcdrw=0;
}
//*************************************************************** void main()
{
// unsigned char TempCyc;
delay(500); //启动等待,等LCM 讲入工作状态
lcdrw=0;
init(); //LCM初始化
delay(500); //延时片刻(可不要)
while(1)
{
TMOD=0x11; //设T0为方式1,GATE=1; TH0=0;
TL0=0;
ET0=1; //允许T0中断
ET1=1;
TR1=1;
EA=1; //开启总中断
Trig=0;
Echo=0;
while(1)
{
StartModule();
flag=1;
// while(!Echo); //当echo 为零时等待 while((!Echo)&&flag); //当echo 为零时等待, 中断flag 跳出等待
TR0=1; //开启计数
while(Echo&&flag); //当echo 为1计数并等待 TR0=0; //关闭计数 Count(); //计算
delay(120); //80MS
}
}
}