stm32 ADXL345传感器

加速度灵敏度轴
沿敏感轴加速时相应输出电压增长
1web

寄存器映射
1svg

寄存器定义
0x31—DATA_FORMAT
1ui

SELF_TEST位:设置为1,自测力应用至传感器,形成输出数据转换。值为0时,禁用自测力
SPI位:值为1,设置器件为3线式SPI模式,值为0,则设置为4线式SPI模式
INT_INVERT位:值为0,设置中断至高电平有效,值为1,则设置至低电平有效
FULL_RES位:设置为1,该器件为全分辨率模式,输出分辨率随着范围位设置的g范围,以4 mg/LSB的比例因子而增长。 FULL_RES位设置为0时,该器件为10位模式,范围位决定最大g范围和比例因子
对齐位:设置为1,选择左对齐(MSB)模式,设置为0,选择右对齐模式,并带有符号扩展功能
范围位:设置g范围
1spa

0x2C—BW_RATE
1code

LOW_POWER位:设置为0,选择正常操做,设置为1,选择低功率操做,而此时噪声有所增长
速率位:选择器件带宽和输出数据速率。默认值为0x0A,转换为100Hz的输出数据速率xml

0x2D—POWER_CTL
1blog

连接位:活动和静止功能的连接位设置为1,延迟活动功能开始,直到检测到静止。检测到活动后,静止检测开始,活动检测中止。该位串行连接活动和静止功能。此位设置为0时,静止功能和活动功能同时进行
AUTO_SLEEP位:设置连接位, AUTO_SLEEP位设置为1,自动休眠功能使能
测量位:测量位设置为0,将器件置于待机模式,设置为1,置于测量模式
休眠位:休眠位设置为0,将器件置于普通工做模式,设置为1,置于休眠模式
唤醒位:控制休眠模式下的读取频率
1get

0x2E—INT_ENABLE
1string

设置位值为1,使能相应功能,生成中断,设置为0时,阻止这些功能产生中断it

寄存器0x1E、0x1F、0x20 — OFSX、OFSY、OFSZ。提供用户设置偏移调整

寄存器0x32至0x37 — DATAX0、DATAX一、DATAY0、DATAY一、DATAZ0和DATAZ1。保存各轴的输出数据

举例

#define DEVICE_ID 0X00 //器件ID
#define THRESH_TAP 0X1D
#define OFSX 0X1E
#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 ADXL_READ 0X3B //读指令
#define ADXL_WRITE 0X3A //写指令

typedef enum
{
    X, //与x轴的角度
    Y, //与y轴的角度
    Z  //与z轴的角度
}DIR_t;

void ADXL345_write(u8 addr, u8 data)
{
    I2C_start();
    I2C_send_byte(ADXL_WRITE);
    I2C_wait_ack();
    I2C_send_byte(addr);
    I2C_wait_ack();
    I2C_send_byte(data);
    I2C_wait_ack();
    I2C_stop();  

    delay_ms(10);
}

u8 ADXL345_read(u8 addr)
{
    u8 d = 0;

    I2C_start();    
    I2C_send_byte(ADXL_WRITE);
    I2C_wait_ack();
    I2C_send_byte(addr);
    I2C_wait_ack();
    I2C_start();    
    I2C_send_byte(ADXL_READ);
    I2C_wait_ack();
    d = I2C_recv_byte();
    I2C_ack(1);
    I2C_stop();

    return d;   
}

void ADXL345_init()
{
    u8 d;

    I2C_init();

    d = ADXL345_read(DEVICE_ID);

    printf("ADXL345_read %d\n", d);

    if(d == 0xE5)
    {
        ADXL345_write(DATA_FORMAT, 0x2B); //中断低电平有效,13位全分辨率模式,16g量程
        ADXL345_write(POWER_CTL, 0x28); //连接使能,测量模式
        ADXL345_write(INT_ENABLE, 0x00); //不使用中断
        ADXL345_write(OFSX, 0x00);
        ADXL345_write(OFSY, 0x00);
        ADXL345_write(OFSZ, 0x00);
    }   
}

void ADXL345_read_XYZ(short *x, short *y, short *z)
{
    u8 i = 0;
    u16 buf[6] = {0};

    I2C_start();    
    I2C_send_byte(ADXL_WRITE);
    I2C_wait_ack();
    I2C_send_byte(0x32); //数据首地址
    I2C_wait_ack();
    I2C_start();    
    I2C_send_byte(ADXL_READ);
    I2C_wait_ack();

    for(i = 0; i < 6; i++) //总共6个
    {
        buf[i] = I2C_recv_byte();
// printf("I2C_recv_byte [%d] %d\r\n", i, buf[i]);
        if(i == 5)
        {
            I2C_ack(1);
        }
        else
        {
            I2C_ack(0);
        }
    }

    I2C_stop();

    *x = (short)((buf[1]<<8) + buf[0]);         
    *y = (short)((buf[3]<<8) + buf[2]);         
    *z = (short)((buf[5]<<8) + buf[4]);
}

void ADXL345_read_times(short *x, short *y, short *z, u8 times)
{
    u8 i = 0;
    short tx, ty, tz;

    *x = *y = *z = 0;

    for(i = 0; i < times; i++) //读取times次
    {
        ADXL345_read_XYZ(&tx, &ty, &tz);

        *x += tx;
        *y += ty;
        *z += tz;       

        delay_ms(5);
    }

    *x /= times; //求平均
    *y /= times;
    *z /= times;    
}

short ADXL345_get_result(float x, float y, float z, u8 dir) //计算角度
{
    float t;
    float res;

    switch(dir)
    {
        case X:
            t = x / sqrt(y*y + z*z);
            res = atan(t); //求出弧度
            break;
        case Y:
            t = y / sqrt(x*x + z*z);
            res = atan(t);
            break;
        case Z:
            t = sqrt(x*x + y*y) / z;
            res = atan(t);
            break;
        default:
            break;
    }

    return (res * 180 / 3.14); //求出角度
}

void ADXL345_main()
{
    short x, y, z;
    short rx, ry, rz;

    ADXL345_read_times(&x, &y, &z, 10); //读出x,y,z方向加速度值
    printf("x %d\n", x);
    printf("y %d\n", y);
    printf("z %d\n", z);

    rx = ADXL345_get_result(x, y, z, X);
    ry = ADXL345_get_result(x, y, z, Y);
    rz = ADXL345_get_result(x, y, z, Z);
    printf("rx %d\n", rx);
    printf("ry %d\n", ry);
    printf("rz %d\n", rz);
}