c语言模拟超声波测距函数 树莓派超声波测距c语言程序

1602显示超声波测距的C语言程序和Proteus仿真图

#include"reg52.h"

成都网络公司-成都网站建设公司创新互联建站10多年经验成就非凡,专业从事成都网站建设、做网站,成都网页设计,成都网页制作,软文营销广告投放平台等。10多年来已成功提供全面的成都网站建设方案,打造行业特色的成都网站建设案例,建站热线:13518219792,我们期待您的来电!

#include"intrins.h"

#define uchar unsigned char //无符号8位

#define uint unsigned int //无符号16位

#define ulong unsigned long //无符号32位

sbit K1=P1^0; //按下K1后,开始测距

sbit LEDRed=P1^1; //测距指示灯,亮表示正在测距,灭表示测距完成

//sbit BEEP=P1^2; //报警测量超出范围

sbit Trig=P2^5; //HC-SR04触发信号输入

sbit Echo=P2^6; //HC-SR04回响信号输出

float xdata DistanceValue=0.0; //测量的距离值

float xdata SPEEDSOUND; //声速

float xdata XTALTIME; //单片机计数周期

uchar xdata stringBuf[6]; //数值转字符串缓冲

//LCD1602提示信息

uchar code Prompts[][16]=

{

{"Measure Distance"}, //测量距离

{"- Out of Range -"}, //超出测量范围

{"MAX range 400cm "}, //测距最大值400cm

{"MIN range 2cm "}, //测距最小值2cm

{" "}, //清屏

{" Press K1 Start "} //按键开始测量

};

uchar xdata DistanceText[]="Range: "; //测量结果字符串

uchar xdata TemperatureText[]="Temperature: ";//测量温度值

extern void LCD_Initialize(); //LCD初始化

extern void LCD_Display_String(uchar *, uchar); //字符串显示

extern void ReadTemperatureFromDS18B20(); //从DS18B20读取温度值

extern int xdata CurTempInteger;

//毫秒延时函数

void DelayMS(uint ms);

//20微秒延时函数

void Delay20us();

//HCSR04初始化

void HCSR04_Initialize();

//测量距离

float MeasuringDistance();

//测距的数值排序求平均

float DistanceStatistics();

//输出距离值到LCD1602上

void DisplayDistanceValue(float dat);

//将无符号的整数转成字符串,返回字符串长度,不包括'\0'结束符

uchar UnsigedIntToString(uint value);

//蜂鸣器

//void Beep(uchar time);

//显示温度值

void DisplayTemperatureValue();

void main()

{

LCD_Initialize();//LCD1602初始化

LCD_Display_String(Prompts[0],0x00);

LCD_Display_String(Prompts[5],0x40);

ReadTemperatureFromDS18B20(); //测温度

HCSR04_Initialize(); //HC-SR04初始化

while(1)

{

if(K1==0)

{

DelayMS(5);

if(K1==0)

{

//Beep(1);

while(K1==0);

LEDRed=0;

ReadTemperatureFromDS18B20();//测温度

DisplayTemperatureValue();

if(CurTempInteger14)

CurTempInteger=14;

else if(CurTempInteger26)

CurTempInteger=26;

SPEEDSOUND=334.1+CurTempInteger*0.61;//计算声速

DistanceValue=DistanceStatistics(); //测距并返回距离值

DisplayDistanceValue(DistanceValue); //显示距离值

LEDRed=1;

}

}

}

}

//测距的数值排序求平均

float DistanceStatistics()

{

uchar i,j;

float disData[7],t;

//连续测距

for(i=0;i7;i++)

{

disData=MeasuringDistance();

DelayMS(80);

}

//排序

for(j=0;j=6;j++)

{

for(i=0;i7-j;i++)

{

if(disDatadisData[i+1])

{

t=disData;

disData=disData[i+1];

disData[i+1]=t;

}

}

}

return (disData[2]+disData[3]+disData[4])/3;

}

//测量距离

float MeasuringDistance()

{

//最大定时时间约65ms

TH0=0;

TL0=0;

//生成20us的脉冲宽度的触发信号

Trig=1;

Delay20us();

Trig=0;

//等待回响信号变高电平

while(!Echo);

TR0=1; //启动定时器0

//等待回响信号变低电平

while(Echo);

TR0=0; //关闭定时器0

//返回距离值(mm)

return (SPEEDSOUND*XTALTIME*((float)TH0*256+(float)TL0))/2000;

}

//HCSR04初始化

void HCSR04_Initialize()

{

//计算单片机计数周期 晶振=11.953M 单位us

XTALTIME=12/11.953;

//温度25度时声速的值

SPEEDSOUND=334.1+25*0.61;

Trig=0;

Echo=0;

TMOD=0x01;

}

//输出距离值到LCD1602上

void DisplayDistanceValue(float dat)

{

uchar i=0,j=0,len;

uint value;

value=(uint)dat;

//范围检查大于4000mm和小于20mm都为超出测量范围

if(value4000)

{

LCD_Display_String(Prompts[1],0x00);

LCD_Display_String(Prompts[2],0x40);

//Beep(2);

}

else if(value20)

{

LCD_Display_String(Prompts[1],0x00);

LCD_Display_String(Prompts[3],0x40);

//Beep(2);

}

else

{

//将数值转换成字符串

len=UnsigedIntToString(value);

//保留1位小数

while(stringBuf!='\0')

{

if(len-j==1)

{

DistanceText[6+j]='.';

j++;

}else

{

DistanceText[6+j]=stringBuf;

i++;

j++;

}

}

DistanceText[6+j]='c';

j++;

DistanceText[6+j]='m';

i=7+j;

//剩余位置补空格

while(i16)

{

DistanceText=' ';

i++;

}

//LCD_Display_String(Prompts[0],0x00);

LCD_Display_String(DistanceText,0x40);

}

}

//显示温度值

void DisplayTemperatureValue()

{

TemperatureText[13]=CurTempInteger/10+'0';

TemperatureText[14]=CurTempInteger+'0';

TemperatureText[15]='C';

LCD_Display_String(TemperatureText,0x00);

}

//将无符号的整数转成字符串,返回字符串长度

uchar UnsigedIntToString(uint value)

{

uchar i=0,t,length;

//从个位开始转换

do

{

stringBuf='0'+value;

value=value/10;

i++;

}while(value!=0);

length=i;

//将字符串颠倒顺序

for(i=0;i(length/2);i++)

{

t=stringBuf;

stringBuf=stringBuf[length-i-1];

stringBuf[length-i-1]=t;

}

stringBuf[length]='\0';

return length;

}

//蜂鸣器

//延时函数 毫秒 @12.000MHz

void DelayMS(uint ms)

{

uchar i, j;

while(ms--)

{

_nop_();

i = 2;

j = 239;

do

{

while (--j);

}while (--i);

}

}

//延时函数 20微秒 @12.000MHz

void Delay20us()

{

uchar i;

_nop_();

i = 7;

while (--i);

}

//定时器0中断

void Timer0() interrupt 1

{

}

//DS18B20代码:

#include

#include

#define uchar unsigned char //无符号8位

#define uint unsigned int //无符号16位

//定义DS18B20端口DS18B20_DQ

sbit DS18B20_DQ = P2^7;

//当前采集的温度值整数部分

int xdata CurTempInteger;

//当前采集的温度值小数部分

int xdata CurTempDecimal;

void Delayus(uint count)

{

while (--count);

}

uchar Reset_DS18B20()

{

uchar status;

DS18B20_DQ=1;

Delayus(1);

//开始复位过程

DS18B20_DQ=0; //数据线拉低

Delayus(100); //延时480us-960us

DS18B20_DQ=1; //数据线拉高

Delayus(10); //延时15us-60us

status=DS18B20_DQ; //读取数据线上的状态

Delayus(120);

return status;

}

void WriteByteToDS18B20(uchar dat)

{

uchar i;

for(i=0;i8;i++)

{

DS18B20_DQ=0;

DS18B20_DQ=dat0x01; //发送1位数据

Delayus(15); //延时60us以上

DS18B20_DQ=1; //释放总线,等待总线恢复

dat=1; //准备下一位数据

}

}

uchar ReadByteFromDS18B20()

{

uchar i,dat=0;

for(i=0;i8;i++)

{

DS18B20_DQ=0; //拉低总线,产生读信号

dat=1;

DS18B20_DQ=1; //释放总线,准备读1位数据

Delayus(2); //延时4us

if(DS18B20_DQ) dat|=0x80; //合并每位数据

Delayus(15); //延时60us

DS18B20_DQ=1; //拉高总线,准备读下1位数据

}

return dat;

}

void ReadTemperatureFromDS18B20()

{

uchar flag=0;//正负符号标志

//存储当前采集的温度值

uchar TempValue[]={0,0};

if(Reset_DS18B20())

{

CurTempInteger=255;

CurTempDecimal=0;

}

else

{

WriteByteToDS18B20(0xCC);//跳过ROM命令

WriteByteToDS18B20(0x44);//温度转换命令

Reset_DS18B20();//复位

WriteByteToDS18B20(0xCC);//跳过ROM命令

WriteByteToDS18B20(0xBE);//读取温度暂存器命令

TempValue[0]=ReadByteFromDS18B20();//先读低字节温度值

TempValue[1]=ReadByteFromDS18B20();//后读高字节温度值

Reset_DS18B20();//复位

//计算温度值

//先进行正温度与负温度判断,高5位全为1(0xF8)则为负数

if((TempValue[1]0xF8)==0xF8)

{

//负温度计算:取反加1,低字节为0时,高字节取反加1,否则不需要。

TempValue[1]=~TempValue[1];

TempValue[0]=~TempValue[0]+1;

if(TempValue[0]==0x00) TempValue[1]++;

flag=1;//负数标志

}

//将温度值分为整数和小数两部分存储(默认为12位精度)

CurTempInteger=((TempValue[1]0x07)4)|((TempValue[0]0xF0)4); if(flag) CurTempInteger=-CurTempInteger;

CurTempDecimal=(TempValue[0]0x0F)*625;

}

}

//LCD1602程序代码:

#include

#include

#define uchar unsigned char

#define uint unsigned int

#define Delay4us(){_nop_();_nop_();_nop_();_nop_();}

sbit LCD_RS=P2^0;

sbit LCD_RW=P2^1;

sbit LCD_EN=P2^2;

void LCDDelay(uint ms)

{

uchar i, j;

while(ms--)

{

_nop_();

i = 2;

j = 239;

do

{

while (--j);

}while (--i);

}

}

bit LCD_Busy_Check()

{

bit result;

LCD_RS=0; LCD_RW=1; LCD_EN=1;

Delay4us();

result=(bit)(P00x80);

LCD_EN=0;

return result;

}

void Write_LCD_Command(uchar cmd)

{

while(LCD_Busy_Check());

LCD_RS=0; LCD_RW=0; LCD_EN=0; _nop_(); _nop_();

P0=cmd; Delay4us();

LCD_EN=1; Delay4us(); LCD_EN=0;

}

void Write_LCD_Data(uchar dat)

{

while(LCD_Busy_Check());

LCD_RS=1;LCD_RW=0;LCD_EN=0;

P0=dat;Delay4us();

LCD_EN=1;Delay4us();LCD_EN=0;

}

void LCD_Set_POS(uchar pos)

{

Write_LCD_Command(pos|0x80);

}

void LCD_Initialize()

{

Write_LCD_Command(0x01); LCDDelay(5);

Write_LCD_Command(0x38); LCDDelay(5);

Write_LCD_Command(0x0C); LCDDelay(5);

Write_LCD_Command(0x06); LCDDelay(5);

}

void LCD_Display_String(uchar *str, uchar LineNo)

{

uchar k;

LCD_Set_POS(LineNo);

for(k=0;k16;k++)

{

Write_LCD_Data(str[k]);

}

}

void LCD_Display_OneChar(uchar Dat, uchar X, uchar Y)

{

Y = 0x01; //限制Y不能大于1(2行,0-1)

X = 0x0F; //限制X不能大于15(16个字符,0-15)

if(Y) {X |= 0x40;} //当要在第二行显示时地址码+0x40;

X |= 0x80; //算出指令码

Write_LCD_Command(X);

Write_LCD_Data(Dat);

}

51单片机 HC-SR04超声波测距 我写的C语言代码,请问

1、HC-SR04使用方法:给触发端子trig一个10us以上的高电平即可触发,触发后echo端子将接受到高电平,高电平的持续时间就是测距的往返时间。

2、例程:

#includereg52.h

#define uchar unsigned char

#define uint unsigned int

/*位定义*/

sbit CHUFA=P0^1;    //位定义超声波触发端(10us以上高电平触发)

sbit JIESHOU=P0^3;    //接收端(接受高电平)

sbit BEEP=P2^0;        //蜂鸣器

sbit OUT0=P3^2;        //外部中断0

uchar JS_FLAG;        //接收标志

uint CF_TIME,t0,t1,shu;

/*函数声明*/

void timer0();        

void int0();

void display(uint);

main(){

CHUFA=0;        //初始化拉低触发端和接收端电平

JIESHOU=0;

JS_FLAG=0;        

CF_TIME=15;        //初始化触发时间(大于10us)

TMOD=0x11;        //定时器方式选择

EA=1;             //开总中断

ET0=1;            //开定时器0中断

EX0=1;             //开外部中断0

IT0=0;             //外部中断选择下降沿触发

//JIESHOU=1;

while(1){

OUT0=JIESHOU;      //外部中断0被赋值为接收端信号,当出现下降沿是触发外部中断0

if(JS_FLAG==0){        //如果没有接收到高电平则触发

CHUFA=1;

while(CF_TIME--);    //10us以上高电平触发传感器

}

if(JIESHOU==1){        

TR0=1;            //如果接收端收到高电平则启动定时器

JS_FLAG=1;         //并且标志位置1

BEEP=0;            //蜂鸣器响    

}

display(t1);    //显示测量时间(秒)

}

}

/*定时器0中断程序*/

void timer0() interrupt 1{    

TH0=(65536-10000)/256;    //装初值 10ms

TL0=(65536-10000)%256;

t0++;                    //每进入一次中断t0加1    

}

/*外部中断0中断程序*/

void int0() interrupt 0{

TR0=0;            //一旦进入外部中断0,说明接收端收到下降沿信号。关闭定时器0

JS_FLAG=0;        //接收标志位置0

BEEP=1;               //关闭蜂鸣器

t1=t0*10/1000;    //测量时间为 进入定时器中断次数t0乘以每次时间10ms,除以1000化为秒为单位

t0=0;            //t0清零

}

/*数码管显数函数*/

void display(uint shu){

//数码管显示函数

}

求一个51 超声波测距 C语言的完整程序,高分求

//晶振=8M

//MCU=STC10F04XE

//P0.0-P0.6共阳数码管引脚

//Trig  = P1^0

//Echo  = P3^2

#include reg52.h     //包括一个52标准内核的头文件

#define uchar unsigned char //定义一下方便使用

#define uint  unsigned int

#define ulong unsigned long

//***********************************************

sfr  CLK_DIV = 0x97; //为STC单片机定义,系统时钟分频

//为STC单片机的IO口设置地址定义

sfr   P0M1   = 0X93;

sfr   P0M0   = 0X94;

sfr   P1M1   = 0X91;

sfr   P1M0   = 0X92;

sfr P2M1   = 0X95;

sfr P2M0   = 0X96;

//***********************************************

sbit Trig  = P1^0; //产生脉冲引脚

sbit Echo  = P3^2; //回波引脚

sbit test  = P1^1; //测试用引脚

uchar code SEG7[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//数码管0-9

uint distance[4];  //测距接收缓冲区

uchar ge,shi,bai,temp,flag,outcomeH,outcomeL,i;  //自定义寄存器

bit succeed_flag;  //测量成功标志

//********函数声明

void conversion(uint temp_data);

void delay_20us();

//void pai_xu();

void main(void)   // 主程序

{  uint distance_data,a,b;

uchar CONT_1;  

CLK_DIV=0X03; //系统时钟为1/8晶振(pdf-45页)

P0M1 = 0;   //将io口设置为推挽输出

P1M1 = 0;

P2M1 = 0;

P0M0 = 0XFF;

P1M0 = 0XFF;

P2M0 = 0XFF;

i=0;

flag=0;

test =0;

Trig=0;       //首先拉低脉冲输入引脚

TMOD=0x11;    //定时器0,定时器1,16位工作方式

TR0=1;      //启动定时器0

IT0=0;        //由高电平变低电平,触发外部中断

ET0=1;        //打开定时器0中断

//ET1=1;        //打开定时器1中断

EX0=0;        //关闭外部中断

EA=1;         //打开总中断0 

while(1)         //程序循环

{

EA=0;

Trig=1;

delay_20us();

Trig=0;         //产生一个20us的脉冲,在Trig引脚 

while(Echo==0); //等待Echo回波引脚变高电平

succeed_flag=0; //清测量成功标志

EX0=1;          //打开外部中断

TH1=0;          //定时器1清零

TL1=0;          //定时器1清零

TF1=0;          //

TR1=1;          //启动定时器1

EA=1;

while(TH1 30);//等待测量的结果,周期65.535毫秒(可用中断实现) 

TR1=0;          //关闭定时器1

EX0=0;          //关闭外部中断

if(succeed_flag==1)

{  

distance_data=outcomeH;                //测量结果的高8位

distance_data=8;                   //放入16位的高8位

distance_data=distance_data|outcomeL;//与低8位合并成为16位结果数据

distance_data*=12;                  //因为定时器默认为12分频

distance_data/=58;                   //微秒的单位除以58等于厘米

}                                      //为什么除以58等于厘米,  Y米=(X秒*344)/2

// X秒=( 2*Y米)/344 ==》X秒=0.0058*Y米 ==》厘米=微秒/58

if(succeed_flag==0)

{

distance_data=0;                    //没有回波则清零

test = !test;                       //测试灯变化

}

///       distance[i]=distance_data; //将测量结果的数据放入缓冲区

///        i++;

///  if(i==3)

///      {

///        distance_data=(distance[0]+distance[1]+distance[2]+distance[3])/4;

///        pai_xu();

///        distance_data=distance[1];

a=distance_data;

if(b==a) CONT_1=0;

if(b!=a) CONT_1++;

if(CONT_1=3)

{ CONT_1=0;

b=a;

conversion(b);

}      

///   i=0;

///  }     

}

}

//***************************************************************

//外部中断0,用做判断回波电平

INTO_()  interrupt 0   // 外部中断是0号

{   

outcomeH =TH1;    //取出定时器的值

outcomeL =TL1;    //取出定时器的值

succeed_flag=1;   //至成功测量的标志

EX0=0;            //关闭外部中断

}

//****************************************************************

//定时器0中断,用做显示

timer0() interrupt 1  // 定时器0中断是1号

{

TH0=0xfd; //写入定时器0初始值

TL0=0x77;   

switch(flag)  

{case 0x00:P0=ge; P2=0xfd;flag++;break;

case 0x01:P0=shi;P2=0xfe;flag++;break;

case 0x02:P0=bai;P2=0xfb;flag=0;break;

}

}

//*****************************************************************

/*

//定时器1中断,用做超声波测距计时

timer1() interrupt 3  // 定时器0中断是1号

{

TH1=0;

TL1=0;

}

*/

//******************************************************************

//显示数据转换程序

void conversion(uint temp_data) 

uchar ge_data,shi_data,bai_data ;

bai_data=temp_data/100 ;

temp_data=temp_data%100;   //取余运算

shi_data=temp_data/10 ;

temp_data=temp_data%10;   //取余运算

ge_data=temp_data;

bai_data=SEG7[bai_data];

shi_data=SEG7[shi_data];

ge_data =SEG7[ge_data];

EA=0;

bai = bai_data;

shi = shi_data;

ge  = ge_data ;

EA=1;

}

//******************************************************************

void delay_20us()

{  uchar bt ;

for(bt=0;bt100;bt++);

}

/*

void pai_xu()

{  uint t;

if (distance[0]distance[1])

{t=distance[0];distance[0]=distance[1];distance[1]=t;} /*交换值

if(distance[0]distance[2])

{t=distance[2];distance[2]=distance[0];distance[0]=t;} /*交换值

if(distance[1]distance[2])

{t=distance[1];distance[1]=distance[2];distance[2]=t;} /*交换值 

}

*/

这是个用过的程序,引脚和参数你自己调一下吧,附件里有1602显示的内容,希望对你有用。


网站名称:c语言模拟超声波测距函数 树莓派超声波测距c语言程序
当前地址:http://scjbc.cn/article/doopsee.html

其他资讯