迪文科技论坛

 找回密码
 立即注册
搜索
查看: 84|回复: 0

【分享】文武骏杰组超声波测距

[复制链接]

1

主题

0

回帖

34

积分

新手上路

Rank: 1

积分
34
发表于 2024-9-11 22:46:51 | 显示全部楼层 |阅读模式
为了使移动机器人能自动避障行走,就必须装备测距系统,以使其及时获取距障碍物的距离信息(距离和方向)。介绍了三方向(前、左、右)超声波测距系统,就是为机器人了解其前方、左侧和右侧的环境而提供一个运动距离信息。在超声波测距中,通常因温度和时间检测的误差,使得测距的精度不高。
功能介绍
超声波测距主要应用于倒车提醒、建筑工地、工业现场等的距离测量
超声波在气体、液体及固体中以不同速度传播,定向性好、能量集中、传输过程中衰减较小、反射能力较强。超声波能以一定速度定向传播、遇障碍物后形成反射,利用这一特性,通过测定超声波往返所用时间就可计算出实际距离,从而实现无接触测量物体距离。超声波测距迅速、方便,且不受光线等因素影响,广泛应用于水文液位测量、建筑施工工地的测量、现场的位置监控、振动仪车辆倒车障碍物的检测、移动机器入探测定位等领域。本文设计的数字式超声波测距仪通过对超声波往返时间内输入到计数器特定频率的时钟脉冲进行计数,进而显示对应的测量距离。
硬件介绍
超声波测距模块:
超声波测距模块有好多种类型,比较常用的有URM37超声波传感器默认是232接口,可以调为TTL接口,URM05大功率超声波传感器测试距离能到10米,算是测试距离比较远的一款了,另外还有比较常用的国外的几款SRF系列的超声波模块,超声波模块精度能到1cm
界面设计
file:///C:/Users/%E9%A3%8E%E6%B2%99/AppData/Local/Temp/ksohtml6652/wps1.png代码设计
Main.c
#include "sys.h"
#include "chaoshengbo.h"

#define START_WIN_TEMP_VP                                0x2000   //控件:数据变量

u16 val;

void main(void)
{   
        time0Init(); //超声波定时器初始化
        sys_init();//系统初始化        
        while(1)
        {
                Get_Val(); //获取超声波距离
                if(val)   //如果数据有效
                {
                        sys_write_vp(START_WIN_TEMP_VP,(u8*)&val,1);//将数据显示在控件
                }
                sys_delay_about_ms(300);    //延时1000ms
        }
}
Sys.c
#include "sys.h"


static idata u16 delay_tick = 0; //用来实现精确延时的



//核心寄存器初始化
void sys_cpu_init()
{
        EA = 0;
        RS0 = 0;
        RS1 = 0;

        CKCON = 0x00;
        T2CON = 0x70;
        DPC = 0x00;
        PAGESEL = 0x01;
        D_PAGESEL = 0x02; //DATA RAM  0x8000-0xFFFF
        MUX_SEL = 0x00;   //UART2,UART3关闭,WDT关闭
        RAMMODE = 0x00;
        PORTDRV = 0x01;   //驱动强度+/-8mA
        IEN0 = 0x00;      //关闭所有中断
        IEN1 = 0x00;
        IEN2 = 0x00;
        IP0 = 0x00;       //中断优先级默认
        IP1 = 0x00;

        WDT_OFF();              //关闭开门狗
}


//定时器2初始化,定时间隔为1ms
void sys_timer2_init()
{
        T2CON = 0x70;
        TH2 = 0x00;
        TL2 = 0x00;

        TRL2H = 0xBC;        //1ms的定时器
        TRL2L = 0xCD;      

        IEN0 |= 0x20;        //启动定时器2
        TR2 = 0x01;
        EA = 1;
}


//系统初始化
void sys_init()
{
        sys_cpu_init();//核心寄存器初始化
        sys_timer2_init();//定时器2初始化
}


//软件大致延时,单位ms
//如果修改了优化等级,那么此函数内部的参数需要重新调试
void sys_delay_about_ms(u16 ms)
{
        u16 i,j;
        for(i=0;i<ms;i++)
                        for(j=0;j<3000;j++);   
}


//软件大致延时,单位us
//如果修改了优化等级,那么此函数内部的参数需要重新调试
void sys_delay_about_us(u8 us)
{
        u8 i,j;
        for(i=0;i<us;i++)
                        for(j=0;j<5;j++);   
}


//利用定时器2进行精确延时,单位ms
void sys_delay_ms(u16 ms)
{
        delay_tick = ms;
        while(delay_tick);
}


//DGUS中的VP变量数据
//addr:就是直接传入DGUS中的地址
//buf:缓冲区
//len:读取的字数,一个字等于2个字节
void sys_read_vp(u16 addr,u8* buf,u16 len)
{   
        u8 i;

        i = (u8)(addr&0x01);
        addr >>= 1;
        ADR_H = 0x00;
        ADR_M = (u8)(addr>>8);
        ADR_L = (u8)addr;
        ADR_INC = 0x01;
        RAMMODE = 0xAF;
        while(APP_ACK==0);
        while(len>0)
        {   
                APP_EN=1;
                while(APP_EN==1);
                if((i==0)&&(len>0))   
                {   
                        *buf++ = DATA3;
                        *buf++ = DATA2;                     
                        i = 1;
                        len--;        
                }
                if((i==1)&&(len>0))   
                {   
                        *buf++ = DATA1;
                        *buf++ = DATA0;                     
                        i = 0;
                        len--;        
                }
        }
        RAMMODE = 0x00;
}


//DGUS中的VP变量数据
//addr:就是直接传入DGUS中的地址
//buf:缓冲区
//len:被发送数据的字数,一个字等于2个字节
void sys_write_vp(u16 addr,u8* buf,u16 len)
{   
        u8 i;  

        i = (u8)(addr&0x01);
        addr >>= 1;
        ADR_H = 0x00;
        ADR_M = (u8)(addr>>8);
        ADR_L = (u8)addr;   
        ADR_INC = 0x01;
        RAMMODE = 0x8F;
        while(APP_ACK==0);
        if(i && len>0)
        {        
                RAMMODE = 0x83;        
                DATA1 = *buf++;               
                DATA0 = *buf++;        
                APP_EN = 1;        
                while(APP_EN==1);
                len--;
        }
        RAMMODE = 0x8F;
        while(len>=2)
        {        
                DATA3 = *buf++;               
                DATA2 = *buf++;
                DATA1 = *buf++;               
                DATA0 = *buf++;
                APP_EN = 1;
                while(APP_EN==1);
                len -= 2;
        }
        if(len)
        {        
                RAMMODE = 0x8C;
                DATA3 = *buf++;               
                DATA2 = *buf++;
                APP_EN = 1;
                while(APP_EN==1);
        }
        RAMMODE = 0x00;
}


//定时器2中断服务程序
void sys_timer2_isr()        interrupt 5
{
        TF2=0;//清除定时器2的中断标志位

        //精准延时处理
        if(delay_tick)
                delay_tick--;
}
Sys.h
#ifndef __SYS_H__
#define __SYS_H__
#include "t5los8051.h"

//类型重定义
typedef unsigned char   u8;
typedef unsigned short  u16;
typedef unsigned long   u32;
typedef signed char     s8;
typedef signed short    s16;
typedef signed long     s32;

//看门狗宏定义
#define        WDT_ON()                                MUX_SEL|=0x02                //开启看门狗
#define        WDT_OFF()                                MUX_SEL&=0xFD                //关闭看门狗
#define        WDT_RST()                                MUX_SEL|=0x01                //喂狗

//系统主频和1ms定时数值定义
#define FOSC                                     206438400UL
#define T1MS                                    (65536-FOSC/12/1000)




//函数申明
void sys_init(void);
void sys_delay_about_ms(u16 ms);
void sys_delay_about_us(u8 us);
void sys_delay_ms(u16 ms);
void sys_read_vp(u16 addr,u8* buf,u16 len);
void sys_write_vp(u16 addr,u8* buf,u16 len);

#endif
T5l
#ifndef __T5LOS8051_H__
#define __T5LOS8051_H__


sfr        P0                =        0x80;                /********PO*******/
sfr        SP                =        0x81;                /********堆栈指针*******/
sfr DPL                =        0x82;                /********DPTR数据指针*******/
sfr DPH                =        0x83;                /********DPTR数据指针*******/
sfr PCON        =        0x87;                /********.7 UART2波特率设置*******/
sfr TCON        =        0x88;                /********T0 T1控制寄存器*******/

sbit        TF1 =        TCON^7;                /********T1中断触发*******/
sbit        TR1        =        TCON^6;               
sbit        TF0        =        TCON^5;                /********T0中断触发*******/
sbit        TR0        =        TCON^4;
sbit        IE1        =        TCON^3;                /********外部中断1*******/
sbit        IT1        =        TCON^2;                /********外部中断1触发方式        0:低电平触发                1:下降沿触发*******/
sbit        IE0        =        TCON^1;                /********外部中断0*******/
sbit        IT0        =        TCON^0;                /********外部中断0触发方式        0:低电平触发                1:下降沿触发*******/

sfr        TMOD        =        0x89;                /********T0 T1模式选择,8051*******/
sfr        TH0         =        0x8C;               
sfr TL0         =        0x8A;
sfr TH1         =        0x8D;
sfr TL1         =        0x8B;

sfr CKCON        =        0x8E;                /********CPU运行*******/
sfr        P1                =        0x90;
sfr        DPC                =        0x93;                /********MOVX指令后,DPTR的变化模式        0:不变 1+1  2-1*******/
sfr PAGESEL        =        0x94;                /********必须是0x01*******/
sfr        D_PAGESEL        =        0x95;        /********必须是0x02*******/

sfr SCON0        =        0x98;                /********UART2控制接口,同8051*******/
sbit        TI0        =        SCON0^1;
sbit        RI0        =        SCON0^0;
sfr        SBUF0        =        0x99;                /********UART2收发数据接口*******/
sfr        SREL0H        =        0xBA;                /********设置波特率,当ADCON0x80*******/
sfr        SREL0L        =        0xAA;

sfr        SCON1        =        0x9B;                /********UART3控制接口*******/
sfr        SBUF1        =        0x9C;
sfr        SREL1H        =        0xBB;
sfr        SREL1L        =        0x9D;

sfr        IEN2        =        0x9A;                /********中断使能控制器SFR  .7~.1必须写0                .0 UART3中断使能控制位*******/
sfr        P2                =        0xA0;
sfr        IEN0        =        0xA8;                /********中断使能控制器0*******/
sbit        EA        =        IEN0^7;                /********中断总控制位*******/
sbit        ET2        =        IEN0^5;                /********定时器2中断控制位*******/
sbit        ES0        =        IEN0^4;                /********UART2*******/
sbit        ET1        =        IEN0^3;                /********T1*******/
sbit        EX1        =        IEN0^2;                /********外部中断1*******/
sbit        ET0        =        IEN0^1;                /********T0*******/
sbit        EX0        =        IEN0^0;                /********外部中断0*******/

sfr        IP0                =        0xA9;                                /********中断优先级控制器0*******/
sfr        P3                =        0xB0;
sfr        IEN1        =        0xB8;                                /********中断使能接受控制器******/
sbit        ES3R        =        IEN1^5;                        /*****UART5接受中断使能控制位****/
sbit        ES3T        =        IEN1^4;                        /*****UART5接受中断使能控制位****/
sbit        ES2R        =        IEN1^3;                        /*****UART4接受中断使能控制位****/
sbit        ES2T        =        IEN1^2;                        /*****UART4接受中断使能控制位****/
sbit        ECAN        =        IEN1^1;                        /********CAN中断使能控制位******/

sfr        IP1                =        0xB9;                                /********中断优先级控制器0*******/
sfr        IRCON2        =        0xBF;
sfr        IRCON         =        0xC0;
sbit        TF2        =        IRCON^6;                        /********T2中断触发标志*******/
sfr        T2CON        =        0xC8;                                /********T2控制寄存器********/
sbit        TR2        =        T2CON^0;                        /***********T2使能***********/
sfr        TRL2H        =        0xCB;
sfr        TRL2L        =        0xCA;
sfr        TH2         =        0xCD;
sfr        TL2         =        0xCC;

sfr        PSW                =        0xD0;
sbit        CY        =        PSW^7;
sbit        AC        =        PSW^6;
sbit        F0        =        PSW^5;
sbit        RS1        =        PSW^4;
sbit        RS0        =        PSW^3;
sbit        OV        =        PSW^2;
sbit        F1        =        PSW^1;
sbit        P        =        PSW^0;
sfr        ADCON        =        0xD8;
sfr        ACC                =        0xE0;
sfr        B                 =        0xF0;

/******硬件扩展定义*********/
/******DGUS变量存储器访问*********/
sfr        RAMMODE        =        0xF8;                                /******DGUS变量存储器访问接口控制寄存器*********/
sbit        APP_REQ        =        RAMMODE^7;
sbit        APP_EN        =        RAMMODE^6;
sbit        APP_RW        =        RAMMODE^5;
sbit        APP_ACK        =        RAMMODE^4;
sfr ADR_H        =        0xF1;
sfr ADR_M        =        0xF2;
sfr ADR_L        =        0xF3;
sfr ADR_INC        =        0xF4;
sfr DATA3        =        0xFA;
sfr DATA2        =        0xFB;
sfr DATA1        =        0xFC;
sfr DATA0        =        0xFD;


//UART4
sfr        SCON2T        =        0x96;                                        /******UART4发送控制********/
sfr        SCON2R        =        0x97;                                        /******UART4接收控制*********/
sfr        BODE2_DIV_H        =        0xD9;                                /******波特率设置********/
sfr        BODE2_DIV_L        =        0xE7;
sfr        SBUF2_TX        =        0x9E;                                /******UART4发送数据接口********/
sfr        SBUF2_RX        =        0x9F;                                /******UART4接收数据接口*********/

//UART5
sfr        SCON3T        =        0xA7;                                       
sfr        SCON3R        =        0xAB;
sfr        BODE3_DIV_H        =        0xAE;
sfr        BODE3_DIV_L        =        0xAF;
sfr        SBUF3_TX        =        0xAC;
sfr        SBUF3_RX        =        0xAD;

//CAN通信
sfr        CAN_CR        =        0x8F;
sfr        CAN_IR        =        0x91;
sfr        CAN_ET        =        0xE8;

//GPIO
sfr        P0MDOUT        =        0xB7;
sfr        P1MDOUT        =        0xBC;
sfr        P2MDOUT        =        0xBD;
sfr        P3MDOUT        =        0xBE;
sfr        MUX_SEL        =        0xC9;
sfr        PORTDRV        =        0xF9;                                /******输出驱动强度*********/

//MAC&DIV
sfr        MAC_MODE        =        0xE5;
sfr        DIV_MODE        =        0xE6;

//SFR扩展接口
sfr        EXADR        =        0xFE;
sfr        EXDATA        =        0xFF;





#endif
接口连接
超声波测距模块与STM32F103C8T6单片机结合起来,可以实现测距功能,并将结果显示在OLED屏幕上。 实现步骤如下: 连接硬件:将超声波测距模块的Trig引脚连接到STM32F103C8T6的一个GPIO引脚,将Echo引脚连接到另一个GPIO引脚。 同时,将OLED屏幕连接到STM32F103C8T6的I2C接口。 配置GPIO:在STM32F103C8T6上配置Trig和Echo引脚为输入输出模式,并设置相应的中断和触发方式。
系统实现与测试


超声波测距系统是利用超声波的反射原理来测量物体距离的一种非接触式传感器技术。它的工作原理大致分为以下几个步骤:
发射:系统会发送一个短促的超声脉冲波,通常由一个小型晶体发出,比如压电陶瓷或晶片。
接收:当声波遇到物体(如墙壁、地面或其他物体表面)时,会被反射回来。部分时间被用来测量声波从发射到接收到回波的时间。
计算:通过计算声波来回传播的总时间(考虑到声速),然后将这个时间除以声速的一半,可以得出两个物体之间的距离。因为声波速度在空气中大约是每秒343米,所以距离公式通常是:(距离 = \frac{声波往返时间}{2} \times 声速 )。
数据处理:测距系统通常会将测量结果转换为电子信号,然后进行滤波和补偿,以减小误差并处理非线性影响。
测试:测试超声波测距系统的准确性和稳定性至关重要。这包括静态测试(在固定环境条件下测量不同距离),动态测试(观察系统在运动中的性能),以及抗干扰测试(评估系统在噪声或反射物干扰下的表现)。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|迪文科技论坛 ( 京ICP备05033781号-1 )

GMT+8, 2024-11-23 00:33 , Processed in 0.120499 second(s), 24 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表