超声波传感器测距报警器

硬件设备:

HC-SR04超声波测距模块;

LCD;

蜂鸣器;

QMC5883L电子罗盘模块;

步进机(可无)。

部分有关代码:

position.c(QMC5883L电子罗盘模块)

#include "lcd.h"
extern uchar BUF[8];    //数据缓存

//延时5us
void Delay_5us()
{
	uchar a,b;
	for(b=1;b>0;b--)
		for(a=1;a>0;a--);

}

//起始信号
void QMC5883_Start()
{
    SDA = 1;  
    SCL = 1; 
    Delay_5us();     
    SDA = 0;    
    Delay_5us();       
    SCL = 0;      
}

//停止信号
void QMC5883_Stop()
{
    SDA = 0;                  
    SCL = 1;                  
    Delay_5us();                
    SDA = 1;                  
    Delay_5us();              
}

//发送应答信号
//入口参数:ack (0:ACK 1:NAK)
void QMC5883_SendACK(bit ack)
{
    SDA = ack;                
    SCL = 1;                  
    Delay_5us();              
    SCL = 0;                   
    Delay_5us();              
}

//接收应答信号
bit QMC5883_RecvACK()
{
    SCL = 1;                  
    Delay_5us();            
    CY = SDA;                 
    SCL = 0;                  
    Delay_5us();               
    return CY;
}

//向IIC总线发送一个字节数据
void QMC5883_SendByte(uchar dat)
{
    uchar i;

    for (i=0; i<8; i++)         
    {
        dat <<= 1;        //移出数据的最高位
        SDA = CY;         //送数据口
        SCL = 1;          //拉高时钟线
        Delay_5us();      //延时
        SCL = 0;          //拉低时钟线
        Delay_5us();      //延时
    }
    QMC5883_RecvACK();
}

//从IIC总线接收一个字节数据
uchar QMC5883_RecvByte()
{
    uchar i;
    uchar dat = 0;

    SDA = 1;           //使能内部上拉,准备读取数据,
    for (i=0; i<8; i++)//8位计数器
    {
        dat <<= 1;
        SCL = 1;       //拉高时钟线
        Delay_5us();   //延时
        dat |= SDA;    //读数据               
        SCL = 0;       //拉低时钟线
        Delay_5us();   //延时
    }
    return dat;
}

//写入单字节数据
void Single_Write_QMC5883(uchar REG_Address,uchar REG_data)
{
    QMC5883_Start();                //起始信号
    QMC5883_SendByte(Slave_Address);//发送设备地址+写信号
    QMC5883_SendByte(REG_Address);  //内部寄存器地址,请参考中文pdf 
    QMC5883_SendByte(REG_data);     //内部寄存器数据,请参考中文pdf
    QMC5883_Stop();//发送停止信号
}

//连续读出QMC5883内部角度数据,地址范围0x00~0x05
void Multiple_Read_QMC5883(void)
{   
    uchar i;
    QMC5883_Start();                //起始信号
    QMC5883_SendByte(Slave_Address);//发送设备地址+写信号
    QMC5883_SendByte(0x00);         //发送存储单元地址,从0x00开始	
    QMC5883_Start();                //起始信号
    QMC5883_SendByte(Slave_Address+1);//发送设备地址+读信号
	 for (i=0; i<6; i++)            //连续读取6个地址数据,存储中BUF
   {
        BUF[i] = QMC5883_RecvByte();//BUF[0]存储数据
        if (i == 5)
        {
           QMC5883_SendACK(1);     //最后一个数据需要回非应答NOACK
        }
        else
        {
          QMC5883_SendACK(0);     //应答ACK
       }
   }
    QMC5883_Stop();              //停止信号
    Lcd1602_Delay1ms(5);
}

//初始化QMC5883
void Init_QMC5883()
{

	Single_Write_QMC5883(0x09,0x0d);//控制寄存器配置
	Single_Write_QMC5883(0x0b,0x01);//设置清除时间寄存器
	Single_Write_QMC5883(0x20,0x40);
	Single_Write_QMC5883(0x21,0x01);
}

main.c(HC-SR04超声波测距模块+蜂鸣器频率报警)

#include <reg52.h>
#include <intrins.h>	
#include "lcd.h"
#include "math.h"
#include "stdio.h"

typedef uint u16;	  //对数据类型进行声明定义
typedef uchar u8;

sbit Trig = P1^4;
sbit Echo = P1^5;

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

uchar showP1[]="Distance:";
uchar showP2[]="-Offset:";
uchar code ASCII[15] = {'0','1','2','3','4','5','6','7','8','9','.','-','M','S',' '};//定义字符

static uchar DisNum = 0;                       //显示用指针				  
uint  time=0;
unsigned long S=0;
bit      flag =0;
uchar disbuff[4]={ 0,0,0,0,};
unsigned long sss=0;

uchar first=0,second=0,third=0,fourth=0,wan=0; //显示变量             
uchar BUF[8]=0;                                //数据缓冲区

int X=0,Y=0;
double Angle_XY=0;

//蜂鸣器
void delay(u16 i)
{
	while(i--);	
}
		
void ring(long ss)
{
	uchar j=0;
	while(1)
	{
		
		if(ss<=200)            //距离小于2m时报警
		{
			beep=~beep;
			delay(5*ss);       //不同频率响应

		}
		j++;
		if(j==50)
		{
				break;
		}
	}
}

void Count(void)
{
	 time=TH0*256+TL0;
	 TH0=0;
	 TL0=0;
	
	 S=(time*1.7)/100;                //算出来是CM
	 if((S>=700)||flag==1)            //超出测量范围显示“-”
	 {	 
			flag=0;
			DisplayOneChar(9, 0, ASCII[11]);
			DisplayOneChar(10, 0, ASCII[10]);//显示点
			DisplayOneChar(11, 0, ASCII[11]);
			DisplayOneChar(12, 0, ASCII[11]);
			DisplayOneChar(13, 0, ASCII[12]);//显示M
	 }
	 else
	 {
			disbuff[0]=S%1000/100;
			disbuff[1]=S%1000%100/10;
			disbuff[2]=S%1000%10 %10;
			DisplayOneChar(9, 0, ASCII[disbuff[0]]);
			DisplayOneChar(10, 0, ASCII[10]);//显示点
			DisplayOneChar(11, 0, ASCII[disbuff[1]]);
			DisplayOneChar(12, 0, ASCII[disbuff[2]]);
			DisplayOneChar(13, 0, ASCII[12]);//显示M
	 }
	 	if(S<=200)
		{
			  DisplayOneChar(14, 0, ASCII[13]);	
		}else{
				DisplayOneChar(14, 0, ASCII[14]);
		}
}

void zd0() interrupt 1//T0中断用来计数器溢出,超过测距范围
{
   flag=1;//中断溢出标志
}

void  StartModule()//启动模块
{
	  Trig=1;//启动一次模块
	//通过nop指令的填充(nop指令一个字节),使指令按字对齐,从而减少取指令时的内存访问次数。产生一定的延迟。i/o传输时,等待缓冲区清空,总线恢复。
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_();
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_();
	  Trig=0;
}



void delayms(uint ms)
{
	unsigned char i=100,j;
	for(;ms;ms--)
	{
		while(--i)
		{
			j=10;
			while(--j);
		}
	}
}



//显示在LCD的数据取位
void Conversion(uint temp_data)  
{  
    wan=temp_data/10000+0x30;
    temp_data=temp_data%10000;//取余运算
		fourth=temp_data/1000+0x30;
    temp_data=temp_data%1000;//取余运算
    third=temp_data/100+0x30;
    temp_data=temp_data%100;//取余运算
    second=temp_data/10+0x30;
    temp_data=temp_data%10;//取余运算
    first=temp_data+0x30; 	
}

void Position()
{

		Multiple_Read_QMC5883();//连续读取三轴角度数据,存储在BUF中 
		//显示XY轴
		X=BUF[1] << 8 | BUF[0];//Combine MSB and LSB of X Data output register  最高有效位
		Y=BUF[3] << 8 | BUF[2];//Combine MSB and LSB of Y Data output register
		
		if(X>0x7fff)X-=0xffff;	  
		if(Y>0x7fff)Y-=0xffff; 
		

		Angle_XY= atan2((double)Y,(double)X) * (180 / 3.14159265) + 180;//计算XY平面角度
		Angle_XY*=10;
		Conversion(Angle_XY);//计算XY平面角度数据和显示
//第一位D前,R后,第二位L左,R右;偏移30~60显示DL;120~150:DR;210~240:RR;300~330:RL;其余区间显示为空
		if(Angle_XY>=300&&Angle_XY<600)//DRLR-postion
		{
				DisplayOneChar(0,1,'D');
				DisplayOneChar(1,1,'L');
		}
		else if(Angle_XY>=1200&&Angle_XY<1500)
		{
				DisplayOneChar(0,1,'D');		
				DisplayOneChar(1,1,'R');
		}
		else if(Angle_XY>=2100&&Angle_XY<2400)
		{
				DisplayOneChar(0,1,'R');		
				DisplayOneChar(1,1,'R');
		}else if(Angle_XY>=3000&&Angle_XY<3300)
		{
				DisplayOneChar(0,1,'R');		
				DisplayOneChar(1,1,'L');
		}else{
				DisplayOneChar(0,1,' ');
				DisplayOneChar(1,1,' ');
		}

	    //显示偏移量
		DisplayOneChar(10,1,fourth); 
		DisplayOneChar(11,1,third); 
		DisplayOneChar(12,1,second); 
		DisplayOneChar(13,1,'.'); 
		DisplayOneChar(14,1,first); 
}


void main(void)
{

	 TMOD=0x01;               //设T0为方式1,GATE=1;
	 TH0=0;
	 TL0=0;          
	 ET0=1;                   //允许T0中断
	 EA=1;                    //开启总中断	
	
  Lcd1602_Delay1ms(200);
	LcdInit();
	Init_QMC5883();
	Lcd1602_Delay1ms(300);
	LcdShowStr(0,0,showP1);
	LcdShowStr(2,1,showP2);
	while(1)
	{
		 StartModule();
	   while(!Echo);         //当RX为零时等待
	   TR0=1;//开启计数
	   while(Echo);          //当RX为1计数并等待
	   TR0=0;//关闭
		 Count();            //计算
		 sss=S;
		 ring(sss);
		 if(sss!=S)
		 {
				ring(S);     //报警
				
		 }
		 Position();
		 delayms(2);         //方位
	}
			
}

整体模拟测试接线:

原计划是进阶设计汽车盲区报警器,由于存在缺陷,海绵体会吸收超声波信号(*——*)。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值