• STC 51单片机55——加速度计GY-29 ADXL345


    //实现与VB模拟鼠标通信,但是噪声很大
    //采用输出角度的方式,输出x与z的角度和y与z的角度
    //在VB中将屏幕水平与垂直等分1800份(角度*10得到的结果)
    //***************************************
    // GY-29 ADXL345 IIC测试程序
    // 使用单片机STC89C51
    // 晶振:11.0592M
    // 显示:串口,11.0592M 波特率9600
    //****************************************
    #include      
    #include      //Keil library  
    #include     //Keil library    
    #include 
    #define   uchar unsigned char
    #define   uint unsigned int    
    sbit      SCL=P1^0;      //IIC时钟引脚定义
    sbit       SDA=P1^1;      //IIC数据引脚定义


    #define    SlaveAddress   0xA6      //定义器件在IIC总线中的从地址,根据ALT  ADDRESS地址引脚不同修改
                                  //ALT  ADDRESS引脚接地时地址为0xA6,接电源时地址为0x3A
    typedef unsigned char  BYTE;
    typedef unsigned short WORD;

    BYTE BUF[8];                         //接收数据缓存区          
    uchar ge,shi,bai,qian,wan;           //显示变量
    int  dis_data;                       //变量

    void delay(unsigned int k);
    void Init_ADXL345(void);             //初始化ADXL345


    void conversion(unsigned char a,int temp_data);     //数据转成字符串

    void  Single_Write_ADXL345(uchar REG_Address,uchar REG_data);   //单个写入数据
    uchar Single_Read_ADXL345(uchar REG_Address);                   //单个读取内部寄存器数据
    void  Multiple_Read_ADXL345();                                  //连续的读取内部寄存器数据
    //------------------------------------
    void Delay5us();
    void Delay5ms();
    void ADXL345_Start();
    void ADXL345_Stop();
    void ADXL345_SendACK(bit ack);
    bit  ADXL345_RecvACK();
    void ADXL345_SendByte(BYTE dat);
    BYTE ADXL345_RecvByte();
    void ADXL345_ReadPage();
    void ADXL345_WritePage();

    void Init_serialport();
    void Send(unsigned char dat);
    //-----------------------------------

    //*********************************************************
    void conversion(unsigned char a,int temp_data)  
    {  
        Send(a);
        Send(':');
        Send(' ');
        if(temp_data<0)
        {
           Send('-');
           temp_data=-temp_data;
        }
        else
          Send('+');
        wan=temp_data/10000+0x30 ;
        temp_data=temp_data%10000;   //取余运算
        qian=temp_data/1000+0x30 ;
        temp_data=temp_data%1000;    //取余运算
        bai=temp_data/100+0x30   ;
        temp_data=temp_data%100;     //取余运算
        shi=temp_data/10+0x30    ;
        temp_data=temp_data%10;      //取余运算
        ge=temp_data+0x30;
        Send(wan);
        Send(qian);
        Send(bai);
        Send(shi);
        Send(ge);
        Send('\t');    
    }

    /*******************************/
    void delay(unsigned int k)    
    {                        
    unsigned int i,j;                
    for(i=0;i {            
    for(j=0;j<121;j++)            
    {;}}                        
    }
                                
    /**************************************
    延时5微秒(STC90C52RC@12M)
    不同的工作环境,需要调整此函数,注意时钟过快时需要修改
    当改用1T的MCU时,请调整此延时函数
    **************************************/
    void Delay5us()
    {
        _nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();
    }

    .....

    .....

    //******单字节写入*******************************************

    void Single_Write_ADXL345(uchar REG_Address,uchar REG_data)
    {
        ADXL345_Start();                  //起始信号
        ADXL345_SendByte(SlaveAddress);   //发送设备地址+写信号
        ADXL345_SendByte(REG_Address);    //内部寄存器地址,请参考中文pdf22页
        ADXL345_SendByte(REG_data);       //内部寄存器数据,请参考中文pdf22页
        ADXL345_Stop();                   //发送停止信号
    }

    //********单字节读取*****************************************
    uchar Single_Read_ADXL345(uchar REG_Address)
    {  uchar REG_data;
        ADXL345_Start();                          //起始信号
        ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
        ADXL345_SendByte(REG_Address);                   //发送存储单元地址,从0开始    
        ADXL345_Start();                          //起始信号
        ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
        REG_data=ADXL345_RecvByte();              //读出寄存器数据
        ADXL345_SendACK(1);   
        ADXL345_Stop();                           //停止信号
        return REG_data;
    }
    //*********************************************************
    //
    //连续读出ADXL345内部加速度数据,地址范围0x32~0x37
    //
    //*********************************************************
    void Multiple_read_ADXL345(void)
    {   uchar i;
        ADXL345_Start();                          //起始信号
        ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
        ADXL345_SendByte(0x32);                   //发送存储单元地址,从0x32开始    
        ADXL345_Start();                          //起始信号
        ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
         for (i=0; i<6; i++)                      //连续读取6个地址数据,存储中BUF
        {
            BUF[i] = ADXL345_RecvByte();          //BUF[0]存储0x32地址中的数据
            if (i == 5)
            {
               ADXL345_SendACK(1);                //最后一个数据需要回NOACK
            }
            else
            {
              ADXL345_SendACK(0);                //回应ACK
           }
       }
        ADXL345_Stop();                          //停止信号
        Delay5ms();
    }


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

    //初始化ADXL345,根据需要请参考pdf进行修改************************
    void Init_ADXL345()
    {
       Single_Write_ADXL345(0x31,0x00);   //测量范围,正负2g,10位模式
       Single_Write_ADXL345(0x2C,0x08);   //正常模式下(非低功耗,噪声减小)数据速率设定为25hz 参考pdf13页
       Single_Write_ADXL345(0x2D,0x08);   //选择电源模式   参考pdf24页
       Single_Write_ADXL345(0x2E,0x80);   //使能 DATA_READY 中断
       Single_Write_ADXL345(0x1E,0x00);   //X 偏移量 根据测试传感器的状态写入pdf29页
       Single_Write_ADXL345(0x1F,0x00);   //Y 偏移量 根据测试传感器的状态写入pdf29页
       Single_Write_ADXL345(0x20,0x05);   //Z 偏移量 根据测试传感器的状态写入pdf29页
    }

    void Init_serialport()
    {
       TMOD=0x20;  //定时器T1工作于方式2 ,八位自动重装
       SCON=0x50;  //SCON=0101 0000B,串口工作方式1,允许接收(REN=1)
       PCON=0x00;  //PCON=0000 0000B,波特率9600
       TH1=0xFD ;  //根据规定给定时器T1赋初值     使用串口时,用第八位做定时,当他溢出时,就自动重载高八位数据
       TL1=0xFD;  //根据规定给定时器T1赋初值      
       TR1=1;    //启动定时器T1   
       REN=1;    //允许接收
    }
    void Send(unsigned char dat)
    {  
       REN=0;    //不允许接收
       SBUF=dat;
       while(TI==0)         //等待发送完毕
          ;
        TI=0;
        REN=1;    //允许接收
    }
    //函数功能:接收一个字节数据
    /***************************************************/
     unsigned char Receive(void)
    {
      unsigned char dat;
      while(RI==0)  //只要接收中断标志位RI没有被置“1”
             ;      //等待,直至接收完毕(RI=1)
          RI=0;      //为了接收下一帧数据,需将RI清0
         dat=SBUF;  //将接收缓冲器中的数据存于dat
          return dat;
    }
    //*********************************************************
    //******主程序********
    //*********************************************************
    void main()
    {
      uchar devid,dat,i ;
      int x=0,y=0,z=0;
      int D_x[5],D_y[5],D_z[5];
      int sum_x=0,sum_y=0,sum_z=0;
      double angle_xz,angle_yz;
      delay(500);                       //上电延时
      Init_serialport();              //初始化串口        
      Init_ADXL345();                 //初始化ADXL345
      devid=Single_Read_ADXL345(0X00);//读出的数据为0XE5,表示正确,经过测试读出的数据就是0XE5
      for(i=0;i<5;i++)
      {
         D_x[i]=0;
         D_y[i]=0;
         D_z[i]=0;
      }
      i=0;
      while(1)                         //循环
      {
        //Init_ADXL345();            //初始化ADXL345

          Multiple_Read_ADXL345();       //连续读出数据,存储在BUF中
          x=(BUF[1]<<8)+BUF[0];  //合成数据   
          y=(BUF[3]<<8)+BUF[2];  //合成数据   
          z=(BUF[5]<<8)+BUF[4];  //合成数据
                      
        sum_x-=D_x[i];    //以下算法含义:取出传感当前值代替他前边的第3个数据,更新sum数据,重新求平均值
        sum_y-=D_y[i];
        sum_z-=D_z[i];
        D_x[i]=x;
        D_y[i]=y;
        D_z[i]=z;
        sum_x+=D_x[i];      
        sum_y+=D_y[i];
        sum_z+=D_z[i];
        x=sum_x/5;
        y=sum_y/5;
        z=sum_z/5;
        i++;
        if(i==5)
          i=0;
       angle_xz= atan2((float)z,(float)x) * (180.0 / 3.14159265); // angle in degrees
       angle_yz= atan2((float)z,(float)y) * (180.0 / 3.14159265);
       angle_xz*=10;            //使角度扩大10倍,方便显示
       angle_yz*=10;
       conversion('X',angle_xz);
       conversion('Y',angle_yz);
       dat=Receive();  
       //delay(10);  
      }
    }

    完整资料打包:

    STC51单片机55-加速度计GY-29ADXL345-单片机文档类资源-CSDN下载

  • 相关阅读:
    pdfjs-dist的进阶使用:手动触发pdf文件跳转到指定页码
    Blender之锁定摄像机到视图方位
    SA实战 ·《SpringCloud Alibaba实战》专栏开篇
    (附源码)计算机毕业设计ssm 基于java的仓库管理系统
    Go 常用标准库之 fmt 介绍与基本使用
    ​​​​MyBatis友人帐之基础入门
    HashMap使用/HashSet使用 && 数据库知识_ && 基础-增删改 && 基础-查询 && 基础-增删改 && 数据库约束 &&_聚合查询
    两个有序表的合并(三种方法)
    设计模式-开闭原则和迪米特法则
    CSS中如何设置单行或多行内容超出后,显示省略号
  • 原文地址:https://blog.csdn.net/fengyuzhe13/article/details/128184738