SC7A20 ±2G/±4G/±8G/±16G三轴微机械数字加速度计
一直没找到简单好用的SC7A20驱动库,索性自己写了一个,采用IIC接口读取数据,需要注意网上查到的芯片地址都不对,应该是0x18,可以看我下面用逻辑分板仪抓取到的数据据包,只有0X18才反回ACK.
另一点是芯片输出是2进制补码形式,负数需要转换成原码.
软件 IDE
PlatformIO
硬件连接
EPS23主控
IIC SDA-----21
IIC SCK-----22
测试数据
量程±2g,12bit精度,无外力仅重力时1g=1023个测量值,1=1mg
#ifndef _SC7A20_H
#define _SC7A20_H
#include "Wire.h"
#include "Arduino.h"
#define SC7A20_I2C_ADDR 0x18
//Reg Table
#define WHO_AM_I_REG 0x0F
#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define ADDR_STATUS_REG 0x27
#define OUT_X_L_REG 0x28
#define OUT_X_H_REG 0x29
#define OUT_Y_L_REG 0x2A
#define OUT_Y_H_REG 0x2B
#define OUT_Z_L_REG 0x2C
#define OUT_Z_H_REG 0x2D
// For CHIP_ID_REG
#define CHIP_ID 0x11
class SC7A20_Class
{
public:
int accel_X;
int accel_Y;
int accel_Z;
bool begin( uint8_t address=SC7A20_I2C_ADDR, TwoWire &wirePort=Wire);
void measure(void);
private:
uint8_t _address;
TwoWire *_i2cPort;
void IIC_Write_Byte(uint8_t reg,uint8_t data);
void IIC_Read_Byte(uint8_t reg,uint8_t* buf,int lenght);
bool IsExist();
int16_t _12bitComplement(uint8_t msb,uint8_t lsb);
};
#endif
#include "SC7A20.h"
bool SC7A20_Class::begin( uint8_t address, TwoWire &wirePort)
{
_address = address;
_i2cPort = &wirePort;
_i2cPort->begin();
if(!IsExist())
return false;
IIC_Write_Byte(CTRL_REG1,0x27); //正常模式 10HZ
return true;
}
void SC7A20_Class::IIC_Write_Byte(uint8_t reg,uint8_t data)
{
_i2cPort->beginTransmission(_address);
_i2cPort->write(reg);
_i2cPort->write(data);
_i2cPort->endTransmission();
}
void SC7A20_Class::IIC_Read_Byte(uint8_t reg,uint8_t* buf,int lenght)
{
uint8_t i=0;
_i2cPort->beginTransmission(_address);
reg |= 0x80; //turn auto-increment bit on
_i2cPort->write(reg);
_i2cPort->endTransmission(false);
_i2cPort->requestFrom(_address, lenght);
while (_i2cPort->available() && i<lenght)
{
*buf= _i2cPort->read();
buf++;
i++;
}
}
bool SC7A20_Class::IsExist()
{
uint8_t config;
IIC_Read_Byte(WHO_AM_I_REG,&config,1);
if (config == CHIP_ID)
return true;
else
return false;
}
int16_t SC7A20_Class::_12bitComplement(uint8_t msb,uint8_t lsb)
{
int16_t temp;
temp=msb<<8|lsb;
temp=temp>>4; //只有高12位有效
temp=temp & 0x0fff;
if(temp&0x0800) //负数 补码==>原码
{
temp=temp&0x07ff; //屏弊最高位
temp=~temp;
temp=temp+1;
temp=temp&0x07ff;
temp=-temp; //还原最高位
}
return temp;
}
void SC7A20_Class::measure(void)
{
uint8_t buff[6];
IIC_Read_Byte(0x28,buff,6);
accel_X=_12bitComplement(buff[1],buff[0]);
accel_Y=_12bitComplement(buff[3],buff[2]);
accel_Z=_12bitComplement(buff[5],buff[4]);
}
#include <Arduino.h>
#include "SC7A20.h"
SC7A20_Class SC7A20;
void setup()
{
Serial.begin(9600);
if(!SC7A20.begin())
{
while (1);
}
}
void loop()
{
SC7A20.measure();
Serial.printf("X:%d Y:%d Z:%d\r\n",SC7A20.accel_X,SC7A20.accel_Y,SC7A20.accel_Z);
delay(1000);
}