找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4314|回复: 4
收起左侧

stc15F2K60s2单片机超声波测距+角度测量ADXL345+LCD602

[复制链接]
ID:219033 发表于 2017-7-12 10:11 | 显示全部楼层 |阅读模式
/**********************头文件*************************/
#include <reg52.h>
#include <math.h>
#include <intrins.h>
#include <lcd.h>                   //1602显示
#include <ADXL345.h>          //测量角度
#include <HCSR04.h>


/*************************主函数***************************/
void main(void)
{
        delay_ms(5);       //上电延时
        UART_init();           //串口初始化
        ADXL345_init();           // ADXL345的初始化
        LcdInit();                   // LCD的初始化;       
        ID=Read_Data_Reg(0x00);        //  读出机器ID值,DEVID寄存器保存0xE5的固定器件ID代码
        while(1)
        {
                                                                         
                Read_Data();                                                //读出X Y Z 轴加速度值                                                                                         
                transform();                                                  //数据重建过程
                calculate_angle(XX,YY,ZZ);                        //计算x和y轴相对于水平面的倾角
                calculate();                                                  //   ASCII码计算
                display_LCD();                                                //   显示

                get_temp_data();                                          //获取超声波测距距离 单位CM
                dispaly_data();                                                //显示超声波数据
        }       
}



#include <reg52.h>
#include <intrins.h>
#include <lcd.h>
#include <HCSR04.h>
/*----------------------------
                超声波测距模块
-----------------------------*/
uchar serial[4];
uchar cnt,sum,temp;
uint temp_data = 0;
bit flag1;
uchar Average_flag = 0;
uint sum_data = 0;
uint Average_data = 0;
/*----------------------------
UART 中断服务程序
-----------------------------*/
void serial_serve() interrupt 4         //串口中断4号
{  
    EA=0;//       
    RI=0;
    temp=SBUF;//读第一个字节,如果是0XFF的话,说明是启使码对了
    switch(cnt)
        {          
          case 0:serial[0]=temp;
          if(serial[0]==0xff)
          {
                  cnt=1;
                  flag1=0;
               
          }
          else
          cnt=0; break;
          case 1:serial[1]=temp;cnt=2;break;
          case 2:serial[2]=temp;cnt=3;break;
          case 3:serial[3]=temp;cnt=0;flag1=1;break;
    }
    EA=1;
}

void UART_init()
{
        SCON = 0x50;                //8位数据,可变波特率
        AUXR |= 0x40;                //定时器1时钟为Fosc,即1T
        AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
        TMOD &= 0x0F;                //设定定时器1为16位自动重装方式
        TL1 = 0xE0;                        //设定定时初值
        TH1 = 0xFE;                        //设定定时初值
        ET1 = 0;                        //禁止定时器1中断
        TR1 = 1;                        //启动定时器1
        EA = 1;                            //开总中断
        ES = 1;                                //开串口中断
        cnt=0;
}
void dispaly_data()
{
                LcdWriteCom(0x80+0x40);
                 LcdWriteData('H');
                LcdWriteData('=');
                LcdWriteData('0'+Average_data/1000);
                LcdWriteData('0'+Average_data/100%10);
                LcdWriteData('0'+Average_data/10%10);
                LcdWriteData('.');      
                LcdWriteData('0'+Average_data%10);
                LcdWriteData('c');
                LcdWriteData('m');
}

void get_temp_data(void)
{
     if(flag1==1)
          {    //进行校验,如果校验正确,则采集数据  
                  sum=serial[0]+serial[1]+serial[2];
                  if(sum==serial[3])
                  {  //将两个字节合并成一个16位的int
                  temp_data= serial[1] ;
                  temp_data<<=8;
             temp_data= temp_data|serial[2] ;
         // temp_data/=10;//毫米单位转换成厘米单位
                         Average_flag++;
                         sum_data=sum_data+temp_data;                //累加
                         if(Average_flag == 16)
                         {
                                 Average_data=sum_data/16+20;
                                Average_flag = 0;
                                sum_data = 0;
                                temp = 0;
                         }

                  }
          }
}

#include"lcd.h"

/*******************************************************************************
* 函 数 名         : Lcd1602_Delay1ms
* 函数功能                   : 延时函数,延时1ms
* 输    入         : c
* 输    出         : 无
* 说    名         : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/

void Lcd1602_Delay1ms(uint c)   //误差 0us
{
    uchar i,j;
        for (; c>0; c--)
        {
                _nop_();
                _nop_();
                _nop_();
                i = 11;
                j = 190;
                do
                {
                        while (--j);
                } while (--i);
        }
           
}

/*******************************************************************************
* 函 数 名         : LcdWriteCom
* 函数功能                   : 向LCD写入一个字节的命令
* 输    入         : com
* 输    出         : 无
*******************************************************************************/
#ifndef         LCD1602_4PINS         //当没有定义这个LCD1602_4PINS时
void LcdWriteCom(uchar com)          //写入命令
{
        LCD1602_E = 0;     //使能
        LCD1602_RS = 0;           //选择发送命令
        LCD1602_RW = 0;           //选择写入
       
        LCD1602_DATAPINS = com;     //放入命令
        Lcd1602_Delay1ms(1);                //等待数据稳定

        LCD1602_E = 1;                  //写入时序
        Lcd1602_Delay1ms(5);          //保持时间
        LCD1602_E = 0;
}
#else
void LcdWriteCom(uchar com)          //写入命令
{
        LCD1602_E = 0;         //使能清零
        LCD1602_RS = 0;         //选择写入命令
        LCD1602_RW = 0;         //选择写入

        LCD1602_DATAPINS = com;        //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
        Lcd1602_Delay1ms(1);

        LCD1602_E = 1;         //写入时序
        Lcd1602_Delay1ms(5);
        LCD1602_E = 0;

//        Lcd1602_Delay1ms(1);
        LCD1602_DATAPINS = com << 4; //发送低四位
        Lcd1602_Delay1ms(1);

        LCD1602_E = 1;         //写入时序
        Lcd1602_Delay1ms(5);
        LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名         : LcdWriteData
* 函数功能                   : 向LCD写入一个字节的数据
* 输    入         : dat
* 输    出         : 无
*******************************************************************************/                  
#ifndef         LCD1602_4PINS                  
void LcdWriteData(uchar dat)                        //写入数据
{
        LCD1602_E = 0;        //使能清零
        LCD1602_RS = 1;        //选择输入数据
        LCD1602_RW = 0;        //选择写入

        LCD1602_DATAPINS = dat; //写入数据
        Lcd1602_Delay1ms(1);

        LCD1602_E = 1;   //写入时序
        Lcd1602_Delay1ms(5);   //保持时间
        LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat)                        //写入数据
{
        LCD1602_E = 0;          //使能清零
        LCD1602_RS = 1;          //选择写入数据
        LCD1602_RW = 0;          //选择写入

        LCD1602_DATAPINS = dat;        //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
        Lcd1602_Delay1ms(1);

        LCD1602_E = 1;          //写入时序
        Lcd1602_Delay1ms(5);
        LCD1602_E = 0;

        LCD1602_DATAPINS = dat << 4; //写入低四位
        Lcd1602_Delay1ms(1);

        LCD1602_E = 1;          //写入时序
        Lcd1602_Delay1ms(5);
        LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名       : LcdInit()
* 函数功能                 : 初始化LCD屏
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/                  
#ifndef                LCD1602_4PINS
void LcdInit()                                                  //LCD初始化子程序
{
        LcdWriteCom(0x38);  //开显示
        LcdWriteCom(0x0c);  //开显示不显示光标
        LcdWriteCom(0x06);  //写一个指针加1
        LcdWriteCom(0x01);  //清屏
        LcdWriteCom(0x80);  //设置数据指针起点
}
#else
void LcdInit()                                                  //LCD初始化子程序
{
        LcdWriteCom(0x32);         //将8位总线转为4位总线
        LcdWriteCom(0x28);         //在四位线下的初始化
        LcdWriteCom(0x0c);  //开显示不显示光标
        LcdWriteCom(0x06);  //写一个指针加1
        LcdWriteCom(0x01);  //清屏
        LcdWriteCom(0x80);  //设置数据指针起点
}
#endif

/**********************头文件*************************/
#include <reg52.h>
#include <math.h>
#include <intrins.h>
#include <lcd.h>
#include <ADXL345.h>

/***********************宏定义***********************/
#define uchar unsigned char
#define uint unsigned int





/***********************函数声明**********************/
//void write_comd(uchar);
//void write_data_LCD(uchar);

/***********************全局变量**********************/
uint Data_X_2[2];           //  读出的数据储存 X Y Z
uint Data_Y_2[2];
uint Data_Z_2[2];
int Data_X,Data_Y,Data_Z;   //  数值转换后的值
float XX,YY,ZZ;                //  3轴的重力加速度分量
uchar ID;
float roll,pitch;
uchar dis1[16] = {"X+00.00  Y+00.00"};



/********************************************************************
*                                                                                                                                        *
*  函数名:        Delayms()                                                                                                *
*  功能描述:产生延迟                                                                                                *
*  形参:ms  延迟的时间,单位ms                                                                                *
*  返回值:无                                                                                                                *
*  局部变量:i                                                                                                                *
*  全局变量:无                                                                                                                *
*  函数调用: 无                                                                                                        *
*                                                                                                                                        *
********************************************************************/
void delay_ms(uchar ms)
{
        uchar i;
        while(ms--)
        {
                for(i = 0; i< 250; i++)
                {
                        _nop_();
                        _nop_();     //空执行消耗CPU时间达到等待的效果
                        _nop_();
                        _nop_();
                }
        }
}

/********************************************************************
*                                                                                                                                        *
*  函数名:        Write_Data(uchar Data_write)                                                        *
*  功能描述:写指令到寄存器                                                                                    *
*  形参:Data_write  要写的数据  8位                                                                *
*  返回值:无                                                                                                                *
*  局部变量:i                                                                                                                *
*  全局变量:无                                                                                                                *
*  函数调用: _nop_();                                                                                            *
*                                                                                                                                        *
********************************************************************/
/*************************写数据函数*******************/
void Write_Data(uchar Adress_Reg,uchar Data_write)
{
        uchar i=0;
        Adress_Reg=(Adress_Reg & 0x7f);                        //  置最高位位0  写状态
        Adress_Reg=(Adress_Reg & 0xbf);                   //         置第二高位0  单字节读写
        CS=0;
        _nop_();
        SCLK=1;
        _nop_();
        for(i=0;i<8;i++)                                  //  8位串行输出  寄存器地址值
        {
                SCLK=0;
                _nop_();
                SDI=(bit)(Adress_Reg & 0x80);
                _nop_();
                _nop_();
                _nop_();
                SCLK=1;
                _nop_();
                _nop_();
                Adress_Reg<<=1;
               
        }
        for(i=0;i<8;i++)                                //  8位串行输出          指令值
        {
                SCLK=0;
                _nop_();
                SDI=(bit)(Data_write & 0x80);
                _nop_();
                _nop_();
                _nop_();
                SCLK=1;
                _nop_();
                _nop_();
                Data_write<<=1;
               
        }
        _nop_();
        _nop_();
        SCLK=1;
        _nop_();
        _nop_();
        SDI=1;
        CS=1;
}
                               
/********************************************************************
*                                                                                                                                        *
*  函数名:         Read_Data_Reg(uchar Adress_Reg)                                            *
*  功能描述:往寄存器读数据                                                                                    *
*  形参:Adress_Reg   寄存器地址                                                                        *
*  返回值:        Data_Read   读取的数据                                                                        *
*  局部变量:i  Data_Read   读取的数据                                                                 *
*  全局变量:无                                                                                                                *
*  函数调用: _nop_();                                                                                            *
*                                                                                                                                        *
********************************************************************/
uchar Read_Data_Reg(uchar Adress_Reg)
{
        uchar i=0;
        uchar Data_Read;
        Adress_Reg=(Adress_Reg|0x80);                 //          置最高位为1, 读状态
        Adress_Reg=(Adress_Reg&0xbf);                 //          置第二高位位0, 单字节读写
        CS=0;
        _nop_();
        _nop_();
        SCLK=1;
        _nop_();
        _nop_();
        for(i=0;i<8;i++)                                         //  8位串行输出  寄存器地址值
        {
                SCLK=0;
                _nop_();
                SDI=(bit)(Adress_Reg & 0x80);
                _nop_();
                _nop_();
                _nop_();
                SCLK=1;
                _nop_();
                _nop_();
                Adress_Reg<<=1;
               
        }
        for(i=0;i<8;i++)                                   //  8位串行读入  数据(8位)  
        {
                SCLK=0;
                Data_Read<<=1;
                _nop_();
                Data_Read|=(uchar)SDI;
                _nop_();
                _nop_();
                SCLK=1;
                _nop_();
                _nop_();
        }

        for(i=0;i<8;i++)                                    //  产生8个脉冲  (手册要求,目的不知道)
        {
                SCLK=0;
                _nop_();
                _nop_();
                SCLK=1;
                _nop_();
                _nop_();
        }
        _nop_();
        _nop_();
        SCLK=1;
        _nop_();
        CS=1;
        return Data_Read;
}
/********************************************************************
*                                                                                                                                        *
*  函数名:        Read_Data()                                                                                        *
*  功能描述:读出6字节X Y Z 轴各两字节的数据                                                    *
*  形参:        无                                                                                                                *
*  返回值:        无                                                                                                                *
*  局部变量:无                                                                                                                *
*  全局变量:Data_X_2[2] Data_Y_2[2] Data_Z_2[2]    存放读出值      *
*  函数调用:Read_Data_Reg(__);delay_ms(__);                                            *
*                                                                                                                                        *
********************************************************************/
void  Read_Data()
{

                /*DATAX0是X轴加速度的低字节寄存器,DATAX1是高字节寄存器*/
               
                Data_X_2[0]=Read_Data_Reg(0x32);           //  读出X轴低位
                Data_X_2[1]=Read_Data_Reg(0x33);           //  读出X轴高位
                delay_ms(10);
                Data_Y_2[0]=Read_Data_Reg(0x34);           //  读出Y轴低位
                Data_Y_2[1]=Read_Data_Reg(0x35);           //  读出Y轴高位
                delay_ms(10);
                Data_Z_2[0]=Read_Data_Reg(0x36);           //  读出Z轴低位
                Data_Z_2[1]=Read_Data_Reg(0x37);           //  读出Z轴高位

}

/********************************************************************
*                                                                                                                                        *
*  函数名:         ADXL345_init()                                                                                *
*  功能描述:ADXL345 初始化  对寄存器写指令                                                    *
*  形参:        无                                                                                                                *
*  返回值:        无                                                                                                                *
*  局部变量:无                                                                                                                *
*  全局变量:无                                                                                                                *
*  函数调用:        Write_Data_Reg(__,__);                                                                *
*                                                                                                                                        *
********************************************************************/
void ADXL345_init()
{
        Write_Data(0x31,0x4f);                  //测量范围为正负16g 13位模式 3线SPI  中断低有效  禁用自测力 左对齐(MSB)模式
        delay_ms(10);
        Write_Data(0x2C,0x08);                  //速率设定为25HZ,带宽12.5HZ
        delay_ms(10);
        Write_Data(0x2D,0x08);                  //选择电源模式
        delay_ms(10);
        Write_Data(0x2E,0x80);                  //使能 DATA_READY 中断
        delay_ms(10);
        Write_Data(0x2f,0x00);                  //中断功能设定,不使用中断
        delay_ms(10);

        /*Write_Data(0x1E,0x00);                  //X 偏移量 根据测试传感器的
        delay_ms(10);
           Write_Data(0x1F,0x00);                  //Y 偏移量 根据测试传感器的
        delay_ms(10);
           Write_Data(0x20,0x00);                  //Z 偏移量 根据测试传感器的
        delay_ms(10);

        Write_Data(0x21,0x00);                  //敲击延时0:禁用; (1.25ms/LSB)
        delay_ms(10);
        Write_Data(0x22,0x00);                  //检测第一次敲击后的延时0:禁用; (1.25ms/LSB)
        delay_ms(10);
        Write_Data(0x23,0x00);                  //敲击窗口0:禁用; (1.25ms/LSB)
        delay_ms(10);

        Write_Data(0x24,0x00);                  //保存检测活动阀值; (62.5mg/LSB)
        delay_ms(10);
        Write_Data(0x25,0x00);                  //保存检测静止阀值; (62.5mg/LSB)                                                          
        delay_ms(10);
        Write_Data(0x26,0x2b);                  //检测活动时间阀值; (1s/LSB)
        delay_ms(10);


        Write_Data(0x27,0x00);                  // 活动  静止检测禁止
        delay_ms(10);
        Write_Data(0x28,0x09);                  //保存检测活动阀值; (62.5mg/LSB)
        delay_ms(10);
        Write_Data(0x29,0xff);                  //保存检测静止阀值; (62.5mg/LSB)
        delay_ms(10);
        Write_Data(0x2a,0x80);                  
        delay_ms(10);*/
}

/********************************************************************
*                                                                                                                                        *
*  函数名:         transform(void)                                                                                *
*  功能描述:数值整合和转换        ,并转换为加速度  放大1000倍                        *
*  形参:        无                                                                                                                *
*  返回值:        无                                                                                                                *
*  局部变量:无                                                                                                                *
*  全局变量:Data_X=0,Data_Y=0,Data_Z   整合后的X Y Z 轴值                        *
*  函数调用:无                                                                                                                *
*                                                                                                                                        *
********************************************************************/

/*从数据寄存器中获取加速度数据后,用户必须对数据进行重建*/
/***************************数值转换***********************/
void transform(void)
{
        (int)Data_X=(Data_X_2[0])+(Data_X_2[1]<<8);
        (int)Data_Y=(Data_Y_2[0])+(Data_Y_2[1]<<8);        
        (int)Data_Z=(Data_Z_2[0])+(Data_Z_2[1]<<8);
       

        if(Data_X&0x2000)
        {                                                                   //  若位负数  转换为补码
                Data_X=(~Data_X)+1;
                Data_X=Data_X*3.90625;                           //  乘比例因素
                Data_X=-Data_X;
        }
        else
        {
                Data_X=Data_X*3.90625;
        }
        if(Data_Y&0x2000)
        {                                                                //  若位负数  转换为补码
                Data_Y=(~Data_Y)+1;
                Data_Y=Data_Y*3.90625;                        //  乘比例因素
                Data_Y=-Data_Y;
        }
        else
        {
                Data_Y=Data_Y*3.90625;
        }
        if(Data_Z&0x2000)
        {                                                                  //  若位负数  转换为补码
                Data_Z=(~Data_Z)+1;
                Data_Z=Data_Z*3.90625;                          //  乘比例因素
                Data_Z=-Data_Z;
        }
        else
        {
                Data_Z=Data_Z*3.90625;
        }
        /*if(Data_X<0)
        {                                                                  
                Data_X=-Data_X;
                Data_X=(float)Data_X*3.9;//Data_X单位为1000倍的g,即mg
        }
        else
        {
                Data_X=(float)Data_X*3.9;
        }
        if(Data_Y<0)
        {
                Data_Y=-Data_Y;
                Data_Y=(float)Data_Y*3.9;
        }
        else
        {
                Data_Y=(float)Data_Y*3.9;
        }
        if(Data_Z<0)
        {                                                                  
                Data_Z=-Data_Z;
                Data_Z=(float)Data_Z*3.9;
        }
        else
        {
                Data_Z=(float)Data_Z*3.9;
        }*/
       
        /*扩大1000倍后结果*/
       
        /*检测轴始终检测到的是正加速度*/
        XX=Data_X;                           //  X轴重力加速度分量
        YY=Data_Y;                           //  Y轴重力加速度分量
        ZZ=Data_Z;                           //  Z轴重力加速度分量

}


/********************************************************************
*                                                                                                                                        *
*  函数名:        calculate_angle(float V_x,float V_y,float V_z)                        *
*  功能描述:计算横滚角和俯仰角                                                                            *
*  形参:G_x  G_x  G_z        X Y Z轴的加速度值                                                        *
*  返回值:无                                                                                                                *
*  局部变量:无                                                                                                    *
*  全局变量:roll  pitch  横滚角和俯仰角                                                        *
*  函数调用:atan2(_,_);                                                              *
*                                                                                                                                        *
********************************************************************/

/*********计算角度函数***************/
void calculate_angle(float G_x,float G_y,float G_z)
{

        roll=-(float)(((atan2(G_z,G_x)*180)/3.1415926535)-90);//弧度转成角度
    pitch=-(float)(((atan2(G_z,G_y)*180)/3.1415926535)-90);
        roll=roll*100;
        pitch=pitch*100;
}






/*******************计算函数********************/
void calculate()
{
        //uchar flag_X,flag_Y;
        if(roll<0)
        {
                roll=-roll;
                dis1[1]='-';//flag_X=45;
        }
        else
        {
                dis1[1]='+';
        }
        if(pitch<0)
        {
                pitch=-pitch;
                dis1[10]='-';//flag_Y=45;
        }
        else
        {
                dis1[10]='+';
        }

        dis1[0]='X';
        //dis1[1]=flag_X;
        dis1[2]=(int)roll%10000/1000+48;
        dis1[3]=(int)roll%10000%1000/100+48;
        dis1[4]='.';
        dis1[5]=(int)roll%10000%1000%100/10+48;
        dis1[6]=(int)roll%10000%1000%100%10+48;

        dis1[9]='Y';
        //dis1[10]=flag_Y;
        dis1[11]=(int)pitch%10000/1000+48;
        dis1[12]=(int)pitch%1000/100+48;
        dis1[13]='.';
        dis1[14]=(int)pitch%1000%100/10+48;
        dis1[15]=(int)pitch%1000%100%10+48;

}

void display_LCD()
{       
       
        uint i;

        LcdWriteCom(0x80);//初始化数据指针,写在第一行
       
        for(i=0;i<16;i++)
                {
                        LcdWriteData(dis1[i]);
                        ADXL345_delay(1);
                }

}
/*******************延时函数********************/
void ADXL345_delay(uint k)
{
        uint j,i;
        for(j=k;j>0;j--)
                for(i=100;i>0;i--);
}



回复

使用道具 举报

ID:288884 发表于 2018-5-19 14:19 | 显示全部楼层
大神,有几个头文件没有
回复

使用道具 举报

ID:359325 发表于 2018-6-26 14:34 | 显示全部楼层
仿真文件有没有
回复

使用道具 举报

ID:361216 发表于 2018-7-5 13:16 | 显示全部楼层
不错不错,学习了,正在研究怎么把ADXL345  数据上传PC
回复

使用道具 举报

ID:393702 发表于 2018-9-4 21:00 | 显示全部楼层
lhqsbz 发表于 2018-7-5 13:16
不错不错,学习了,正在研究怎么把ADXL345  数据上传PC

请问楼主,您说的这个问题可由研究?请赐教!
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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