资讯详情

加速度传感器芯片MMA8451Q初步——倾角计算与校准值

通过测量飞思卡公司生产的一系列加速度传感器芯片XYZ可以检测三轴的加速度等一系列运动状态。 我用14位精度。。单片机型号为

通过读取获得X,Y,Z传感器与自然坐标轴的夹角按三角函数公式计算。 此外,初步测试功能。

I2C读写模块 MMA8451.c/MMA8451.h

MMA8451.h

#ifndef __MMA8451_H #define __MMA8451_H  extern unsigned char BUF[6];  void Init_MMA8451(); void Multiple_read_MMA8451(); unsigned char Single_Read_MMA8452(unsigned char REG_Address); void Single_Write_MMA8451(unsigned char REG_Address,unsigned char REG_data); #endif  

MMA8451.c

#include "MMA8451.h" #include "intrins.h" #include "config.h"  #define   uchar unsigned char #define   uint unsigned int  typedef unsigned char BYTE; typedef unsigned int WORD; typedef unsigned long int LWORD;   sbit   SCL=P1^1;      //IIC时钟引脚定义 根据自己的电路板连接 sbit    SDA=P1^0;      //IIC数据引脚定义  #define SlaveAddress   0x38  BYTE BUF[6]; //数据区    /************************************** 延时5微秒(STC90C52RC@12M) 工作环境不同,需要调整此函数,注意时钟过快时需要修改 当改用1T的MCU时,请调整此延迟函数 **************************************/ void Delay5us() {     _nop_();_nop_();_nop_();_nop_();     _nop_();_nop_();_nop_();_nop_();  _nop_();_nop_();_nop_();_nop_(); }  /************************************** 延时5毫秒(STC90C52RC@12M) 工作环境不同,该函数需要调整 当改用1T的MCU时,请调整此延迟函数 **************************************/ void Delay5ms() {     WORD n = 560;      while (n--); }  /************************************** 起始信号 **************************************/ void MMA8451_Start() {     SDA = 1;                    ///提高数据线     SCL = 1;                    //提高时钟线     Delay5us();                 //延时     SDA = 0;                    //产生下降边     Delay5us();                 //延时     SCL = 0;                    //拉低时钟线 }  /************************************** 停止信号 **************************************/ void MMA8451_Stop() {     SDA = 0;                    ///拉低数据线     SCL = 1;                    //提高时钟线     Delay5us();                 //延时     SDA = 1;                    //产生上升沿     Delay5us();                 //延时 }  /************************************** 发送响应信号 入口参数:ack (0:ACK 1:NAK) **************************************/ void MMA8451_SendACK(bit ack) {     SDA = ack;                  //写应答信号     SCL = 1;                    //提高时钟线     Delay5us();                 //延时     SCL = 0;                    //拉低时钟线     Delay5us();                 //延时 }  /************************************** 接收响应信号 **************************************/ bit MMA8451_RecvACK() {     SCL = 1;                    //提高时钟线     Delay5us();                 //延时     CY = SDA;                   //阅读响应信号     SCL = 0;                    //拉低时钟线     Delay5us();                 //延时      return CY; }  /************************************** 向IIC总线发送字节数据 **************************************/ void MMA8451_SendByte(BYTE dat) {     BYTE i;      for (i=0; i<8; i  )         //8位计数器     {         dat <<= 1;              ///移出数据的最高位         SDA = CY;               ///发送数据端口         SCL = 1;                //提高时钟线         Delay5us();             //延时         SCL = 0;                //拉低时钟线         Delay5us();             //延时     }     MMA8451_RecvACK(); }  /************************************** 从IIC总线接收字节数据 **************************************/ BYTE MMA8451_RecvByte() {     BYTE i;     BYTE dat = 0;      SDA = 1;                    //使内部上拉,准备读取数据,     for (i=0; i<8; i  )         //8位计数器     {         dat <<= 1;         SCL = 1;                //提高时钟线         Delay5us();             //延时         dat |= SDA;             //读数据                        SCL = 0;                //拉低时钟线         Delay5us();             //延时     }     return dat; }  //******单字节写入*******************************************  void Single_Write_MMA8451(uchar REG_Address,uchar REG_data)//2a 01 {     MMA8451_Start();                  ///开始信号     MMA8451_SendByte(SlaveAddress);   //发送设备地址 写信号     MMA8451_SendByte(REG_Address);    ///内部寄存器地址     MMA8451_SendByte(REG_data);       //内部寄存器数据     MMA8451_Stop();                   ///发送停止信号 }  //********单字节读取*****************************************  uchar Single_Read_MMA8452(uchar REG_Address) {  uchar REG_data;     MMA8451_Start();                          ///开始信号     MMA8451_SendByte(SlaveAddress);           //发送设备地址 写信号     MMA8451_SendByte(REG_Address);                   //发送存储单元地址,从0开始      MMA8451_Start();                          ///开始信号     MMA8451_SendByte(SlaveAddress 1);         //发送设备地址 读信号     REG_data=MMA8451_RecvByte();              ///读取寄存器数据  MMA845_SendACK(1);   
	MMA8451_Stop();                           //停止信号
    return REG_data; 
}

//*********************************************************
//
//连续读出MMA8451内部加速度数据,地址范围0x01~0x06	
//
//*********************************************************
void Multiple_read_MMA8451()//Multiple_Read_MMA8451();
{   uchar i;
    MMA8451_Start();                          //起始信号
    MMA8451_SendByte(SlaveAddress);           //发送设备地址+写信号
    MMA8451_SendByte(0x01);                   //发送存储单元地址,从0x01开始	
    MMA8451_Start();                          //起始信号
    MMA8451_SendByte(SlaveAddress+1);         //发送设备地址+读信号
	 for (i=0; i<6; i++)                      //连续读取6个地址数据,存储中BUF
    {
        BUF[i] = MMA8451_RecvByte();          //BUF[0]存储0x32地址中的数据
        if (i == 5)
        {
           MMA8451_SendACK(1);                //最后一个数据需要回NOACK
        }
        else
        {
          MMA8451_SendACK(0);                //回应ACK
       }
   }
    MMA8451_Stop();                          //停止信号
    Delay5ms();
}


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

//初始化MMA8451,根据需要请参考pdf进行修改************************
void Init_MMA8451()
{
   Single_Write_MMA8451(0x2a,0x01);   //
   Single_Write_MMA8451(0x2b,0x02);   //

}

V1:获取倾角 计算atan值 main.c


/*********************************************
P10 数据口 P11时钟口
P0,P2,接数码管

倾角寄存器0x01-0x06
读取数据为重力加速度在传感器坐标轴上分量
通过计算过程转换为自然XYZ坐标轴夹角tan值
当tan值在极值(无穷大)一侧时,改用cot值计算
***********************************************/

#include "config.h"
//#include "MPU6050.h"
#include "MMA8451.h"
#include "display.h"
#include <math.h>

void	delay_ms(u8 ms);


int xa,ya,za;

//*********************************************************************
//****************角度计算*********************************************
//*********************************************************************
           
int MMA8451_Get_Angle(long x,long y,long z,u8 dir); 
void MMA8451_Add_Angle2(int x,int y,int z);
void MMA8451_Get_Angle3(int x,int y,int z);

// ===================== 主函数 =====================
void main(void)
{
	int x,y,z;
	//所有I/O口全设为准双向,弱上拉模式
	P0M0=0xff;	P0M1=0xff;
	P1M0=0xff;	P1M1=0xff;
	P2M0=0xff;	P2M1=0xff;
	P3M0=0xff;	P3M1=0xff;
	P4M0=0xff;	P4M1=0xff;
	P5M0=0xff;	P5M1=0xff;
	P6M0=0xff;	P6M1=0xff;
	P7M0=0xff;	P7M1=0xff;

//P1=0x00;

   P1M0=0xfc;	P1M1=0xfc;	//时钟口1.1 数据口1.0 11111100 11111100

	P0 = 0xFF;

   P0M0=0x00;	P0M1=0x00;	   //数码管数据通道 00000000 00000000 常规

	P2 = 0xFF;

   P2M0=0x00;	P2M1=0x00;	  //数码管位选通道 00000000 00000000 常规

	
	 initLedDisplay();


	 delay_ms(100);
	Init_MMA8451();	//初始化MPU-6050
	delay_ms(100);

	EA = 1;	//允许总中断
	
	

	while(1)
	{

		//	 Init_MMA8451();	
		//	delay_ms(100);
			
			delay_ms(100);
			Multiple_read_MMA8451();
			
			x=(unsigned int)BUF[0]<<8|BUF[1];
		    y=(unsigned int)BUF[2]<<8|BUF[3];
			z=(unsigned int)BUF[4]<<8|BUF[5];

			//hexstr[7]=(BUF[0]&0xf0)>>4;
			//hexstr[6]=(BUF[0]&0x0f);
			//hexstr[5]=16;
			//hexstr[4]=(BUF[2]&0xf0)>>4;
			//hexstr[3]=(BUF[2]&0x0f);
			//hexstr[2]=18;
			//hexstr[1]=(BUF[4]&0xf0)>>4;
			//hexstr[0]=(BUF[4]&0x0f);
			//hexstr[1]=(BUF[5]&0xf0)>>4;
			//hexstr[0]=(BUF[5]&0x0f);

		//	x=(char)BUF[0];
		 //   y=(char)BUF[2];
		//	z=(char)BUF[4];
			
			xa=MMA8451_Get_Angle(x,y,z,1);
			ya=MMA8451_Get_Angle(x,y,z,2);
		    za=MMA8451_Get_Angle(x,y,z,0);

			hexstr[7]=ya/1000;
		//	if(ya<0)
		//	  hexstr[7]=16,ya=-ya;
		//	else 
		//		hexstr[7]=17;

			
			hexstr[6]=(ya%1000)/100;
			hexstr[5]=(ya%100)/10;
			hexstr[4]=ya%10;

			hexstr[3]=xa/1000;
		//	if(za<0)
		//	  hexstr[3]=16,za=-za;
		//	else
		//		hexstr[3]=17;
				
			hexstr[2]=(xa%1000)/100;
			hexstr[1]=(xa%100)/10;
			hexstr[0]=xa%10;
			

			showLedDisplay();
			  delay_ms(3000);
	}
}


int abs_round(double v){
 return (int)(v>=0?(v+0.5):(v-0.5));
}

void MMA8451_Get_Angle3(int x,int y,int z)
{
        double temp,xd,yd,zd;
		        

		temp = sqrt((double)(x*x+y*y+z*z));

		yd = y/temp;

		if(yd<=0.707 && yd>=-0.707){
		 yd = asin(yd);
		 ya = yd*180/3.1416+0.5;
		}else{
		 yd = acos(yd);
		 ya = yd*180/3.1416-0.5;
		 ya=90-ya;
		}

		zd = z/temp;

		if(zd<=0.707 && zd>=-0.707){
		 zd = asin(zd);
		 za = zd*180/3.1416+0.5;
		}else{
		 zd = acos(zd);
		 za = zd*180/3.1416-0.5;
		 za=90-za;
		}
		
        xd = x/temp;

		if(xd<=0.707 && xd>=-0.707){
		 xd = asin(xd);
		 xa = xd*180/3.1416+0.5;
		}else{
		 xd = acos(xd);
		 xa = xd*180/3.1416-0.5;
		 xa=90-xa;
		}
}


void MMA8451_Add_Angle2(int x,int y,int z)
{
        double temp,xd,yd,zd;
		        

		temp = sqrt((double)(x*x+y*y+z*z));
		

	   	zd = asin(z/temp)*180/3.1416; //与自然Z轴的角度
        xd = asin(x/temp)*180/3.1416; //与自然X轴的角度
		yd = asin(y/temp)*180/3.1416; //与自然Y轴的角度

	   	za += (int)(zd+0.5);
		ya += (int)(yd+0.5);
		xa += (int)(xd+0.5);
        
}

 
int MMA8451_Get_Angle(long x,long y,long z,u8 dir)
{
        double temp;
        double res=0;
        switch(dir)
        {
                case 0://与自然Z轴的角度
						temp = sqrt((double)(x*x+y*y));
						if(temp<abs(z))
						{ 
                        	temp=temp/z;
							res=atan(temp);
						}
						else
						{
							temp= z/temp;
						    res=atan(temp);
							if(res>=0)
							  res = 1.5708 - res;
							else
							  res = - 1.5708 - res;
						}
                        res=atan(temp);
                        break;
                case 1://与自然X轴的角度

						temp = sqrt((double)(y*y+z*z));
						if(temp>=abs(x))
						{ 
                        	temp=x/temp;
							res=atan(temp);
						}
						else
						{
							temp= temp/x;
						    res=atan(temp);
							if(res>=0)
							  res = 1.5708 - res;
							else
							  res = - 1.5708 - res;
						}
                        
                        break;
                case 2://与自然Y轴的角度

						temp = sqrt((double)(x*x+z*z));
						if(temp>=abs(y))
						{ 
                        	temp=y/temp;
							res=atan(temp);
						}
						else
						{
							temp= temp/y;
						    res=atan(temp);
							if(res>=0)
							  res = 1.5708 - res;
							else
							  res = - 1.5708 - res;
						}

                        break;
        }
	//	if(res<0) 
		res = 1.5708+res;

        return res*1800/3.1416;//把弧度转换成角度
}


void  delay_ms(u8 ms)
{
     u16 i;
	 do
	 {
	 	i = MAIN_Fosc / 13000;
		while(--i)	;   //13T per loop
     }while(--ms);
}

V2:加上偏差校正,可抵消因机械误差引起的14度以内的微小角度偏移。

main.c


/*********************************************
P10 数据口 P11时钟口
P0,P2,接数码管
 P30 P31 P32 P33接触点开关

P30 清零校准寄存器重新计算校正值
P31 获取当下倾角值
P32 清零校准计算器
P33 将最近一次计算的校正值写到校准寄存器
***********************************************/
#include "config.h"
//#include "MPU6050.h"

#include "MMA8451.h"
#include "display.h"

#include <math.h>

int MMA8451_Get_Angle(long x,long y,long z,u8 dir);

void displayAngle();

/* ============================================= */



void	delay_ms(u8 ms);

unsigned char hexstr_cp[8];

int xa,ya,za;
      


// ===================== 主函数 =====================
void main(void)
{
	unsigned char reg;
	unsigned int ux,uy,uz;
	int sx,sy,sz;
	//所有I/O口全设为准双向,弱上拉模式
	P0M0=0xff;	P0M1=0xff;
	P1M0=0xff;	P1M1=0xff;
	P2M0=0xff;	P2M1=0xff;
	P3M0=0xff;	P3M1=0xff;
	P4M0=0xff;	P4M1=0xff;
	P5M0=0xff;	P5M1=0xff;
	P6M0=0xff;	P6M1=0xff;
	P7M0=0xff;	P7M1=0xff;

//P1=0x00;

   P1M0=0xfc;	P1M1=0xfc;	//时钟口1.1 数据口1.0 11111100 11111100

	P0 = 0xFF;

   P0M0=0x00;	P0M1=0x00;	   //数码管数据通道 00000000 00000000 常规

	P2 = 0xFF;

   P2M0=0x00;	P2M1=0x00;	  //数码管位选通道 00000000 00000000 常规
   
   P2 = 0xFF;

   P3M0=0x00;	P3M1=0x00;
	
	 initLedDisplay();


	 delay_ms(100);
	Init_MMA8451();	//初始化MPU-6050
	delay_ms(100);

	EA = 1;	//允许总中断
	
	

	while(1)
	{

		//	 Init_MMA8451();	
		//	delay_ms(100);
			
			
			if(!P30){
			  delay_ms(10);
			  if(!P30){
			   while(!P30);

			   showdot = 0;

			   delay_ms(100);

			   reg = Single_Read_MMA8452(0x2A); 
			   reg &= 0xFE; 
			   Single_Write_MMA8451(0x2A, reg); 

				delay_ms(100);

			   Single_Write_MMA8451(0x2F,0x00);
			   Single_Write_MMA8451(0x30,0x00);
			   Single_Write_MMA8451(0x31,0x00);

			   delay_ms(100);

			   reg = Single_Read_MMA8452(0x2A); 
			   reg |= 0x01; 
			   Single_Write_MMA8451(0x2A, reg);

			   delay_ms(100);

			   Multiple_read_MMA8451();

			   /*
				hexstr[7]=(BUF[0]&0xf0)>>4;
				hexstr[6]=(BUF[0]&0x0f);
				hexstr[5]=(BUF[1]&0xf0)>>4;
				hexstr[4]=(BUF[1]&0x0f);
				hexstr[3]=(BUF[2]&0xf0)>>4;
				hexstr[2]=(BUF[2]&0x0f);
				hexstr[1]=(BUF[3]&0xf0)>>4;
				hexstr[0]=(BUF[3]&0x0f);
			   */
			   	
				displayAngle();
				showLedDisplay();

				hexstr_cp[0]=hexstr[0];
				hexstr_cp[1]=hexstr[1];
				hexstr_cp[2]=hexstr[2];
				hexstr_cp[3]=hexstr[3];
				hexstr_cp[4]=hexstr[4];
				hexstr_cp[5]=hexstr[5];
				hexstr_cp[6]=hexstr[6];
				hexstr_cp[7]=hexstr[7];
			   
			   ux=((unsigned int)BUF[0]<<8)|BUF[1];
			   uy=((unsigned int)BUF[2]<<8)|BUF[3];
			   uz=((unsigned int)BUF[4]<<8)|BUF[5];
			   
				/*
			   if(BUF[0]>0x7f){
				   ux=(~ux+1)>>2;
				   sx=ux/8;
			   }else{
				   sx=((~ux+1)>>2)/8;
			   }


			   if(BUF[2]>0x7f){
				   uy=(~uy+1)>>2;
				   sy=uy/8;
			   }else{
				   sy=((~uy+1)>>2)/8;
			   }

			   if(BUF[4]>0x7f){
				   uz=(~uz+1)>>2;
				   sz=(4069+uz)/8;
			   }else{
				   sz=(int)(4069-(uz>>2))/8;
				   if(sz<0){
					sz+=256;
				   }
			   }
			   */

			   if(BUF[0]>0x7f){				   
				   ux=(~ux+1)>>2;
				   sx=ux/8;
			   }else{
				   sx=~(ux>>2)+1;
				   sx=sx/8;
			   }

			   if(BUF[2]>0x7f){
				   uz=(~uz+1)>>2;
				   sz=uz/8;
			   }else{
				   sz=~(uz>>2)+1;
				   sz=sz/8;
			   }

			   if(BUF[4]>0x7f){
				   uy=(~uy+1)>>2;
				   sy=(4069+uy)/8;
			   }else{
			   	   sy=~(uy>>2)+1;
				   sy=(4069+sy)/8;				   
			   }	

			  /*
			   delay_ms(100);

			   reg = Single_Read_MMA8452(0x2A); 
			   reg &= 0xFE; 
			   Single_Write_MMA8451(0x2A, reg); 

				delay_ms(100);

			   Single_Write_MMA8451(0x2F,(char)sx);
			   Single_Write_MMA8451(0x30,(char)sy);
			   Single_Write_MMA8451(0x31,(char)sz);

			   delay_ms(100);

			   reg = Single_Read_MMA8452(0x2A); 
			   reg |= 0x01; 
			   Single_Write_MMA8451(0x2A, reg);

			   delay_ms(100);
			    reg = Single_Read_MMA8452(0x2F);

				hexstr[7]=(reg&0xf0)>>4;
				hexstr[6]=(reg&0x0f);
				hexstr[5]=0;
				reg = Single_Read_MMA8452(0x30);
				
				hexstr[4]=(reg&0xf0)>>4;
				hexstr[3]=(reg&0x0f);
				hexstr[2]=18;
				reg = Single_Read_MMA8452(0x31);

				hexstr[1]=(reg&0xf0)>>4;
				hexstr[0]=(reg&0x0f);
				showLedDisplay();
				*/
			   delay_ms(3000);

			  }
			}
			
			 if(!P31){
			  delay_ms(10);
			  if(!P31){
			   while(!P31);
				 delay_ms(100);
				   Multiple_read_MMA8451();
				   /*
					hexstr[7]=(BUF[2]&0xf0)>>4;
					hexstr[6]=(BUF[2]&0x0f);
					hexstr[5]=(BUF[3]&0xf0)>>4;
					hexstr[4]=(BUF[3]&0x0f);
					hexstr[3]=(BUF[4]&0xf0)>>4;
					hexstr[2]=(BUF[4]&0x0f);
					hexstr[1]=(BUF[5]&0xf0)>>4;
					hexstr[0]=(BUF[5]&0x0f);
				   	*/

					displayAngle();
					showLedDisplay();
					  delay_ms(3000);

				  

			  }
			}
			
			if(!P32){
			  delay_ms(10);
			  if(!P32){
			   while(!P32);

				showdot = 0;

			   delay_ms(100);

			   reg = Single_Read_MMA8452(0x2A); 
			   reg &= 0xFE; 
			   Single_Write_MMA8451(0x2A, reg); 

				delay_ms(100);

			   Single_Write_MMA8451(0x2F,0x00);
			   Single_Write_MMA8451(0x30,0x00);
			   Single_Write_MMA8451(0x31,0x00);

			   delay_ms(100);

			   reg = Single_Read_MMA8452(0x2A); 
			   reg |= 0x01; 
			   Single_Write_MMA8451(0x2A, reg);
				/*
				delay_ms(100);
				
			    reg = Single_Read_MMA8452(0x2F);

				hexstr[7]=(reg&0xf0)>>4;
				hexstr[6]=(reg&0x0f);
				hexstr[5]=0;
				reg = Single_Read_MMA8452(0x30);
				
				hexstr[4]=(reg&0xf0)>>4;
				hexstr[3]=(reg&0x0f);
				hexstr[2]=16;
				reg = Single_Read_MMA8452(0x31);

				hexstr[1]=(reg&0xf0)>>4;
				hexstr[0]=(reg&0x0f);
				*/

				hexstr[0]=0;
				hexstr[1]=0;
				hexstr[2]=0;
				hexstr[3]=0;
				hexstr[4]=0;
				hexstr[5]=0;
				hexstr[6]=0;
				hexstr[7]=0;
				showLedDisplay();
			   delay_ms(3000);

			   }
			}

	   if(!P33){
			  delay_ms(10);
			  if(!P33){
			   while(!P33);

				showdot = 1;

			   delay_ms(100);

			   reg = Single_Read_MMA8452(0x2A); 
			   reg &= 0xFE; 
			   Single_Write_MMA8451(0x2A, reg); 

				delay_ms(100);

			   Single_Write_MMA8451(0x2F,0x00);
			   Single_Write_MMA8451(0x30,0x00);
			   Single_Write_MMA8451(0x31,0x00);

			  

				delay_ms(100);

			   Single_Write_MMA8451(0x2F,(char)sx);
			   Single_Write_MMA8451(0x30,(char)sy);
			   Single_Write_MMA8451(0x31,(char)sz);

			   delay_ms(100);

			   reg = Single_Read_MMA8452(0x2A); 
			   reg |= 0x01; 
			   Single_Write_MMA8451(0x2A, reg);

			   /*
			   delay_ms(100);
			    reg = Single_Read_MMA8452(0x2F);

				hexstr[7]=(reg&0xf0)>>4;
				hexstr[6]=(reg&0x0f);
				hexstr[5]=0;
				reg = Single_Read_MMA8452(0x30);
				
				hexstr[4]=(reg&0xf0)>>4;
				hexstr[3]=(reg&0x0f);
				hexstr[2]=17;
				reg = Single_Read_MMA8452(0x31);

				hexstr[1]=(reg&0xf0)>>4;
				hexstr[0]=(reg&0x0f);

				*/

				hexstr[0]=hexstr_cp[0];
				hexstr[1]=hexstr_cp[1];
				hexstr[2]=hexstr_cp[2];
				hexstr[3]=hexstr_cp[3];
				hexstr[4]=hexstr_cp[4];
				hexstr[5]=hexstr_cp[5];
				hexstr[6]=hexstr_cp[6];
				hexstr[7]=hexstr_cp[7];

				showLedDisplay();
			   delay_ms(3000);



			}
		}
			
	}
}


void displayAngle(){

		   int x,y,z;

			x=(unsigned int)BUF[0]<<8|BUF[1];
		    y=(unsigned int)BUF[2]<<8|BUF[3];
			z=(unsigned int)BUF[4]<<8|BUF[5];
			
  			xa=MMA8451_Get_Angle(x,y,z,1);
			ya=MMA8451_Get_Angle(x,y,z,2);
		    za=MMA8451_Get_Angle(x,y,z,0);

			//hexstr[7]=ya/1000;
			if(ya<0)
			  hexstr[7]=16,ya=-ya;
			else 
				hexstr[7]=17;

			
			hexstr[6]=(ya%1000)/100;
			hexstr[5]=(ya%100)/10;
			hexstr[4]=ya%10;

			//hexstr[3]=xa/1000;
			if(xa<0)
			  hexstr[3]=16,xa=-xa;
			else
				hexstr[3]=17;
				
			hexstr[2]=(xa%1000)/100;
			hexstr[1]=(xa%100)/10;
			hexstr[0]=xa%10;

			/*
			  	//hexstr[3]=za/1000;
			if(za<0)
			  hexstr[3]=16,za=-za;
			else
				hexstr[3]=17;
				
			hexstr[2]=(za%1000)/100;
			hexstr[1]=(za%100)/10;
			hexstr[0]=za%10;

			*/

			
}

int MMA8451_Get_Angle(long x,long y,long z,u8 dir)
{
        double temp;
        double res=0;
        switch(dir)
        {
                case 0://与自然Z轴的角度
						temp = sqrt((double)(x*x+y*y));
						if(temp<abs(z))
						{ 
                        	temp=temp/z;
							res=atan(temp);
						}
						else
						{
							temp= z/temp;
						    res=atan(temp);
							if(res>=0)
							  res = 1.5708 - res;
							else
							  res = - 1.5708 - res;
						}
                        res=atan(temp);
                        break;
                case 1://与自然X轴的角度

						temp = sqrt((double)(y*y+z*z));
						if(temp>=abs(x))
						{ 
                        	temp=x/temp;
							res=atan(temp);
						}
						else
						{
							temp= temp/x;
						    res=atan(temp);
							if(res>=0)
							  res = 1.5708 - res;
							else
							  res = - 1.5708 - res;
						}
                        
                        break;
                case 2://与自然Y轴的角度

						temp = sqrt((double)(x*x+z*z));
						if(temp>=abs(y))
						{ 
                        	temp=y/temp;
							res=atan(temp);
						}
						else
						{
							temp= temp/y;
						    res=atan(temp);
							if(res>=0)
							  res = 1.5708 - res;
							else
							  res = - 1.5708 - res;
						}

                        break;
        }
	//	if(res<0) 
		//res = 1.5708+res;

        return res*1800/3.1416;//把弧度转换成角度
}


void  delay_ms(u8 ms)
{
     u16 i;
	 do
	 {
	 	i = MAIN_Fosc / 13000;
		while(--i)	;   //13T per loop
     }while(--ms);
}


PS:display.c是数码管显示模块,config.h来自STC例程。可以根据自己的外设环境改变配置。

标签: m系列倾角传感器加速度倾斜度角度传感器芯片1207系列加速度传感器基于微加速度传感器的倾角传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台