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

MMA845xQ系列是飞思卡公司出品的一系列加速度传感器芯片,通过测量XYZ三轴的加速度可以检测倾角,自由落体,翻转,脉冲,振动等一系列运动状态。
我用的是14位精度的MMA8451Q。单片机型号为STC8A8K64

通过读取倾角寄存器获得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();              //读出寄存器数据
	MMA8451_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 

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=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 

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=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例程。可以根据自己的外设环境改变配置。

你可能感兴趣的:(玩单片机)