#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;
}