

//实现与VB模拟鼠标通信,但是噪声很大
 //采用输出角度的方式,输出x与z的角度和y与z的角度
 //在VB中将屏幕水平与垂直等分1800份(角度*10得到的结果)
 //***************************************
 // GY-29 ADXL345 IIC测试程序
 // 使用单片机STC89C51
 // 晶振:11.0592M
 // 显示:串口,11.0592M 波特率9600
 //****************************************
 #include  <REG52.H>    
 #include  <math.h>    //Keil library  
 #include  <stdio.h>   //Keil library    
 #include  <INTRINS.H>
 #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<k;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);  
   }
 }



![[附源码]计算机毕业设计基于Springboot校园订餐管理系统](https://img-blog.csdnimg.cn/3e2351435fea4031a441e7c680d7fafe.png)














