#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);//方位
}
}