ADXL345代碼

#include "math.h" 
#include "stm32f4xx.h"


 /******************ADXL345寄存器命令定義**********************/
#define DEVICE_ID           0X00        //獲取器件ID,0XE5
#define THRESH_TAP          0X1D        //敲擊閥值
#define OFSX                0X1E	     //x軸調整偏移值
#define OFSY                0X1F
#define OFSZ                0X20
#define DUR                 0X21
#define Latent              0X22
#define Window              0X23
#define THRESH_ACK          0X24
#define THRESH_INACT        0X25
#define TIME_INACT          0X26
#define ACT_INACT_CTL       0X27
#define THRESH_FF           0X28
#define TIME_FF             0X29
#define TAP_AXES            0X2A
#define ACT_TAP_STATUS      0X2B
#define BW_RATE             0X2C
#define POWER_CTL           0X2D 
#define INT_ENABLE          0X2E
#define INT_MAP             0X2F
#define INT_SOURCE          0X30
#define DATA_FORMAT         0X31
#define DATA_X0             0X32
#define DATA_X1             0X33
#define DATA_Y0             0X34
#define DATA_Y1             0X35
#define DATA_Z0             0X36
#define DATA_Z1             0X37
#define FIFO_CTL            0X38
#define FIFO_STATUS         0X39 
#define I_M_DEVID      ((uint8_t)0xE5) //器件ID=0XE5 
/******************SPI管腳配置宏**********************/
#define ADXL345_SPIX                      SPI1
#define ADXL345_SPI_RCC                   RCC_APB2Periph_SPI1 
#define ADXL345_SPI_SCK_PIN               GPIO_Pin_3
#define ADXL345_SPI_SCK_GPIO_PORT         GPIOB
#define ADXL345_SPI_SCK_GPIO_RCC          RCC_AHB1Periph_GPIOB
#define ADXL345_SPI_SCK_SOURCE            GPIO_PinSource3
#define ADXL345_SPI_SCK_AF                GPIO_AF_SPI1 
#define ADXL345_SPI_MISO_PIN              GPIO_Pin_4
#define ADXL345_SPI_MISO_GPIO_PORT        GPIOB
#define ADXL345_SPI_MISO_GPIO_RCC         RCC_AHB1Periph_GPIOB
#define ADXL345_SPI_MISO_SOURCE           GPIO_PinSource4
#define ADXL345_SPI_MISO_AF               GPIO_AF_SPI1
#define ADXL345_SPI_MOSI_PIN              GPIO_Pin_5
#define ADXL345_SPI_MOSI_GPIO_PORT        GPIOB
#define ADXL345_SPI_MOSI_GPIO_RCC         RCC_AHB1Periph_GPIOB
#define ADXL345_SPI_MOSI_SOURCE           GPIO_PinSource5
#define ADXL345_SPI_MOSI_AF               GPIO_AF_SPI1 
#define ADXL345_SPI_CS_PIN                GPIO_Pin_15
#define ADXL345_SPI_CS_GPIO_PORT          GPIOA
#define ADXL345_SPI_CS_GPIO_RCC           RCC_AHB1Periph_GPIOA 

//#define ADXL345_CS_LOW()                  GPIO_ResetBits(ADXL345_SPI_CS_GPIO_PORT, ADXL345_SPI_CS_PIN)
//#define ADXL345_CS_HIGH()                 GPIO_SetBits( ADXL345_SPI_CS_GPIO_PORT, ADXL345_SPI_CS_PIN)

#define ADXL345_CS_LOW()  GPIO_WRITE_BIT(ADXL345_SPI_CS_GPIO_PORT, ADXL345_SPI_CS_PIN, 0)
#define ADXL345_CS_HIGH()  GPIO_WRITE_BIT(ADXL345_SPI_CS_GPIO_PORT, ADXL345_SPI_CS_PIN, 1)

#define ADXL345_AVER_TIME   2






// SPI2 :PB12(cs) ,PB13(clk) ,PB14(miso)  ,PB15(mosi)
void  ADXL345_SPI_Init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    SPI_InitTypeDef  SPI_InitStructure;
 
    RCC_AHB1PeriphClockCmd(ADXL345_SPI_SCK_GPIO_RCC|ADXL345_SPI_CS_GPIO_RCC, ENABLE);//使能GPIO時鐘
    RCC_APB2PeriphClockCmd(ADXL345_SPI_RCC, ENABLE);//使能SPI時鐘
 
    //sck miso mosi初始化設置
    GPIO_InitStructure.GPIO_Pin = ADXL345_SPI_SCK_PIN| ADXL345_SPI_MISO_PIN | ADXL345_SPI_MOSI_PIN ;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;   //複用功能
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推輓輸出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 
    GPIO_Init(ADXL345_SPI_SCK_GPIO_PORT, &GPIO_InitStructure); 
 
    GPIO_PinAFConfig(ADXL345_SPI_SCK_GPIO_PORT,  ADXL345_SPI_SCK_SOURCE,  ADXL345_SPI_SCK_AF);  //複用配置
    GPIO_PinAFConfig(ADXL345_SPI_MISO_GPIO_PORT, ADXL345_SPI_MISO_SOURCE, ADXL345_SPI_MISO_AF); //複用配置
    GPIO_PinAFConfig(ADXL345_SPI_MOSI_GPIO_PORT, ADXL345_SPI_MOSI_SOURCE, ADXL345_SPI_MOSI_AF); //複用配置
    
    //cs初始化設置
    GPIO_InitStructure.GPIO_Pin = ADXL345_SPI_CS_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通輸出
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推輓輸出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
    GPIO_Init(ADXL345_SPI_CS_GPIO_PORT, &GPIO_InitStructure);//初始化
    ADXL345_CS_HIGH();
 
    RCC_APB2PeriphResetCmd(ADXL345_SPI_RCC, ENABLE); //復位SPI
    RCC_APB2PeriphResetCmd(ADXL345_SPI_RCC, DISABLE); //停止復位SPI
    //spi配置
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //設置SPI單向或者雙向的數據模式:SPI設置爲雙線雙向全雙工
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                       //設置SPI工作模式:設置爲主SPI
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;                  //設置SPI的數據大小:SPI發送接收16位幀結構
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                         //串行同步時鐘的空閒狀態爲高電平
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                         //串行同步時鐘的第二個跳變沿(上升或下降)數據被採樣
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                            //NSS信號由硬件(NSS管腳)還是軟件(使用SSI位)管理:內部NSS信號有SSI位控制
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;  //定義波特率預分頻的值:波特率預分頻值 84M/psc
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;    //指定數據傳輸從MSB位還是LSB位開始:數據傳輸從MSB位開始
    SPI_InitStructure.SPI_CRCPolynomial = 7;    //CRC值計算的多項式
    SPI_Init(ADXL345_SPIX, &SPI_InitStructure);  //根據SPI_InitStruct中指定的參數初始化外設SPIx寄存器
 
    SPI_Cmd(ADXL345_SPIX, ENABLE); //使能SPI外設
}



//讀單字節
u8 ADXL345_read_byte(u16 add)
{
    ADXL345_CS_LOW() ;
    while(SPI_I2S_GetFlagStatus(ADXL345_SPIX, SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(ADXL345_SPIX, (add | 0x0080) << 8 );
    while(SPI_I2S_GetFlagStatus(ADXL345_SPIX, SPI_I2S_FLAG_RXNE) == RESET);
    ADXL345_CS_HIGH();
    return SPI_I2S_ReceiveData(ADXL345_SPIX) & 0x00ff;
}
//寫單字節
void ADXL345_write_byte(u16 add, u16 val)
{
    ADXL345_CS_LOW();
    while (SPI_I2S_GetFlagStatus(ADXL345_SPIX, SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(ADXL345_SPIX, add << 8 | val);
    while (SPI_I2S_GetFlagStatus( ADXL345_SPIX, SPI_I2S_FLAG_RXNE) == RESET);
    SPI_I2S_ReceiveData(ADXL345_SPIX);
    ADXL345_CS_HIGH();
}
//初始化ADXL345.
//返回值:0,初始化成功;其他值,初始化失敗.
u8  ADXL345_Init(void)
{
    ADXL345_SPI_Init();
    DelayTicks(500);
    if( ADXL345_read_byte( DEVICE_ID ) == I_M_DEVID )
    {
        ADXL345_write_byte(DATA_FORMAT, 0X0b);  //BIT6:SPI4線模式(默認);BIT5:中斷電平0/1(高/低有效);BIT0-1:量程=16g
        ADXL345_write_byte(POWER_CTL,   0x08);  //BIT3=0/1:(測量模式/待機模式);BIT2=0/1:(工作/休眠);
        ADXL345_write_byte(BW_RATE,     0x0e);  //低4位:輸出數據速率=1600(此速率下,SPI速率要設置>=2M) ;BIT4=0/1(低功耗/正常)
        ADXL345_write_byte(INT_ENABLE,  0x00);  //中斷功能設置:不使能
        ADXL345_write_byte(INT_MAP,     0x00);  //設置中斷映射到INT1引腳還是INT2引腳
        ADXL345_write_byte(FIFO_CTL,    0x00);
        
        ADXL345_write_byte(OFSX, 0x00);   //XYZ偏移調整
        ADXL345_write_byte(OFSY, 0x00);
        ADXL345_write_byte(OFSZ, 0x00);
 
        
        return 0;
    }
    else
    {
        ADXL_ASSERT; 
        return 1;
    }
}


//讀取三個方向的加速度
void ADXL345_RD_XYZ(short *x, short *y, short *z)
{
    u8 BUF[6];
 
    BUF[0] = ADXL345_read_byte(0x32);
    BUF[1] = ADXL345_read_byte(0x33);
 
    BUF[2] = ADXL345_read_byte(0x34);
    BUF[3] = ADXL345_read_byte(0x35);
 
    BUF[4] = ADXL345_read_byte(0x36);
    BUF[5] = ADXL345_read_byte(0x37);
 
    *x = ((u16)BUF[1] << 8) + BUF[0];
    *y = ((u16)BUF[3] << 8) + BUF[2];
    *z = ((u16)BUF[5] << 8) + BUF[4];
 
}

//讀取ADXL的平均值
//x,y,z:讀取10次後取平均值
void ADXL345_RD_Avval(short *x,short *y,short *z)
{
	short tx=0,ty=0,tz=0;	   
	u8 i;  
	for(i=0;i<10;i++)
	{
		ADXL345_RD_XYZ(x,y,z);
		DelayTicks(10);
		tx+=(short)*x;
		ty+=(short)*y;
		tz+=(short)*z;	   
	}
	*x=tx/10;
	*y=ty/10;
	*z=tz/10;
} 

//自動校準
//xval,yval,zval:x,y,z軸的校準值
void ADXL345_AUTO_Adjust(short *xval,short *yval,short *zval)
{
	short tx,ty,tz;
	u8 i;
	short offx=0,offy=0,offz=0;
	ADXL345_write_byte(POWER_CTL,0x00);	   	//先進入休眠模式.
	DelayTicks(100);
	ADXL345_write_byte(DATA_FORMAT,0X2B);	//低電平中斷輸出,13位全分辨率,輸出數據右對齊,16g量程 
	ADXL345_write_byte(BW_RATE,0x0A);		//數據輸出速度爲100Hz
	ADXL345_write_byte(POWER_CTL,0x28);	   	//鏈接使能,測量模式
	ADXL345_write_byte(INT_ENABLE,0x00);	//不使用中斷		 

	ADXL345_write_byte(OFSX,0x00);
	ADXL345_write_byte(OFSY,0x00);
	ADXL345_write_byte(OFSZ,0x00);
	DelayTicks(12);
	for(i=0;i<ADXL345_AVER_TIME;i++)
	{
		ADXL345_RD_Avval(&tx,&ty,&tz);
		offx+=tx;
		offy+=ty;
		offz+=tz;
	}	 		
	offx/=ADXL345_AVER_TIME;
	offy/=ADXL345_AVER_TIME;
	offz/=ADXL345_AVER_TIME;
	*xval=-offx/4;
	*yval=-offy/4;
	*zval=-(offz-256)/4;	  
 	ADXL345_write_byte(OFSX,*xval);
	ADXL345_write_byte(OFSY,*yval);
	ADXL345_write_byte(OFSZ,*zval);	
} 

//讀取ADXL345的數據times次,再取平均
//x,y,z:讀到的數據
//times:讀取多少次
void ADXL345_Read_Average(short *x,short *y,short *z)
{
	u8 i;
	short tx,ty,tz;
	*x=0;
	*y=0;
	*z=0;
	
	for(i=0;i<ADXL345_AVER_TIME;i++)//連續讀取times次
	{
		ADXL345_RD_XYZ(&tx,&ty,&tz);
		*x+=tx;
		*y+=ty;
		*z+=tz;
		DelayTicks(5);
	}
	*x/=ADXL345_AVER_TIME;
	*y/=ADXL345_AVER_TIME;
	*z/=ADXL345_AVER_TIME;	
}


//得到角度
//x,y,z:x,y,z方向的重力加速度分量(不需要單位,直接數值即可)
//dir:要獲得的角度.0,與Z軸的角度;1,與X軸的角度;2,與Y軸的角度.
//返回值:角度值.單位0.1°.

short ADXL345_Get_Angle(float x,float y,float z,u8 dir)
{
	float temp;
 	float res=0;
	switch(dir)
	{
		case 0://與自然Z軸的角度
 			temp=sqrt((x*x+y*y))/z;
 			res=atan(temp);
 			break;
		case 1://與自然X軸的角度
 			temp=x/sqrt((y*y+z*z));
 			res=atan(temp);
 			break;
 		case 2://與自然Y軸的角度
 			temp=y/sqrt((x*x+z*z));
 			res=atan(temp);
 			break;
 	}
	return res*1800/3.14;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章