SC7A20 三轴加速度传感器 驱动
时间:2022-10-30 21:00:00
使用时,您需要找到正确的文档。以前的文档是错误的,导致读取的数据计算角度不成功。发现高通滤波器需要关闭。由于高通滤波器寄存器中的滤波阈值没有文档描述,我可以直接关闭它。代码与硬件平台无关,需要底层IIC接口支持,软件IIC或HC32的硬件IIC可以查阅我的其他博客;
连续读取时,寄存器地址最高位置1;
/************************************************************************************************************* * 文件名: SC7A20.c * 功能: SC7A20 支持三轴加速度传感器 * 作者: cp1300@139.com * 创建时间: 2022-07-01 * 最后修改时间: 2022-07-01 * 详细: https://www.doc88.com/p-80659792307153.html?r=1 * 若要一次读写多个寄存器,需将寄存器地址的最高位置1,也就是寄存器地址|0x80 *************************************************************************************************************/ #include "system.h" #include "SC7A20.h" #include "math.h" #include #define SC7A20_REG_WHO_AM_I 0x0F #define SC7A20_REG_CTRL_1 0x20 #define SC7A20_REG_CTRL_2 0x21 #define SC7A20_REG_CTRL_3 0x22 #define SC7A20_REG_CTRL_4 0x23 #define SC7A20_REG_X_L 0x28 #define SC7A20_REG_X_H 0x29 #define SC7A20_REG_Y_L 0x2A #define SC7A20_REG_Y_H 0x2B #define SC7A20_REG_Z_L 0x2C #define SC7A20_REG_Z_H 0x2D #define SC7A20_REG_STATUS 0x27 /************************************************************************************************************************* *函数 : bool SC7A20_Init(SC7A20_HANDLE *pHandle, u8 SlaveAddr, bool (*IIC_ReadReg)(u8 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum), bool (*IIC_WriteReg)(u16 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum)) *功能 : SC7A20初始化 *参数 : pHandle:句柄;SlaveAddr:芯片IIC写地址;IIC_ReadReg:IIC读取接口;IIC_WriteReg:IIC写入接口; *返回 : TRUE:初始化成功;FALSE:初始化失败 *依赖 : 底层宏定义 *作者 : cp1300@139.com *时间 : 2022-07-01 *最后,修改时间 : 2022-07-01 *说明 : *************************************************************************************************************************/ bool SC7A20_Init(SC7A20_HANDLE *pHandle, u8 SlaveAddr, bool (*IIC_ReadReg)(u8 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum), bool (*IIC_WriteReg)(u16 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum)) { u16 i,j; u8 tempreg; u8 buff[16]; if(pHandle == NULL) { ERROR_S("无效的句柄\r\n"); SYS_DelayMS(5000); return FALSE; } pHandle->SlaveAddr = SlaveAddr; //记录地址 pHandle->IIC_ReadReg = IIC_ReadReg; //IIC接口 pHandle->IIC_WriteReg = IIC_WriteReg; //IIC接口 tempreg = 0; Delay_MS(50); for (i = 0; i < 10; i ) { buff[0] = buff[1] = 0; if (pHandle->IIC_ReadReg(pHandle->SlaveAddr, SC7A20_REG_WHO_AM_I, buff, 1) == FALSE) { INFO_S("Sensor通讯失败\r\n"); } else if(buff[0] == 0x11) { break; } else { INFO_S("无效的id0xX\r\n", buff[0]); } SYS_DelayMS(100); } tempreg = 0x47; pHandle->IIC_WriteReg(pHandle->SlaveAddr, SC7A20_REG_CTRL_1, &tempreg, 1);//50Hz 正常模式xyz使能 tempreg = 0x00; pHandle->IIC_WriteReg(pHandle->SlaveAddr, SC7A20_REG_CTRL_2, &tempreg, 1)//关闭滤波器,手册上没有滤波器截止频率设置说明,静态状态下的重力加速度无法测量 tempreg = 0x00; pHandle->IIC_WriteReg(pHandle->SlaveAddr, SC7A20_REG_CTRL_3, &tempreg, 1); //关闭中断 tempreg = 0x88; pHandle->IIC_WriteReg(pHandle->SlaveAddr, SC7A20_REG_CTRL_4, &tempreg, 1); //读取后更新,小端模式,2,g 正常模式,高精度模式 if (i < 10) return TRUE; return FALSE; } s16 SC7A20_12bitComplement(uint8_t msb, uint8_t lsb) { s16 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; } /************************************************************************************************************************* *函数 : bool SC7A20_ReadAcceleration(SC7A20_HANDLE* pHandle, s16* pXa, s16* pYa, s16* pZa) *功能 : SC7A20读取加速度值 *参数 : pHandle:句柄;pXa,pYa,pZa 三轴加速度值 *返回 : TRUE:成功;FALSE:失败 *依赖 : 底层宏定义 *作者 : cp1300@139.com *时间 : 2022-07-01 *最后,修改时间 : 2022-07-01 *说明 : *************************************************************************************************************************/ bool SC7A20_ReadAcceleration(SC7A20_HANDLE* pHandle, s16* pXa, s16* pYa, s16* pZa) { u8 buff[6]; u8 i; s16 temp; memset(buff, 0, 6); if (pHandle->IIC_ReadReg(pHandle->SlaveAddr, SC7A20_REG_X_L|BIT7, buff, 6) == FALSE) { return FALSE; } else { pHandle->IIC_ReadReg(pHandle->SlaveAddr, 0x27, &i, 1); /*for (i = 0; i < 6; i ) { uart_printf("X ",buff[i]); } uart_printf("r\n");*/ //X轴 *pXa = buff[1]; *pXa <<= 8; *pXa |= buff[0]; *pXa >>= 4; //取12bit精度 //Y轴 *pYa = buff[3]; *pYa <<= 8; *pYa |= buff[2]; *pYa >>= 4; //取12bit精度 //Z轴 *pZa = buff[5]; *pZa <<= 8; *pZ |= buff[4];
*pZa >>= 4; //取12bit精度
return TRUE;
}
}
#define PI 3.1415926535898
/*************************************************************************************************************************
*函数 : bool SC7A20_GetZAxisAngle(SC7A20_HANDLE* pHandle, s16 AcceBuff[3], float* pAngleZ)
*功能 : SC7A20 获取Z轴倾角
*参数 : pHandle:句柄;AcceBuff:3个轴的加速度;pAngleZ:Z方向倾角
*返回 : TRUE:成功;FALSE:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2022-07-02
*最后修改时间 : 2022-07-02
*说明 :
*************************************************************************************************************************/
bool SC7A20_GetZAxisAngle(SC7A20_HANDLE* pHandle, s16 AcceBuff[3], float* pAngleZ)
{
double fx, fy, fz;
double A;
s16 Xa, Ya, Za;
if (SC7A20_ReadAcceleration(pHandle, &Xa, &Ya, &Za) == FALSE) return FALSE; //ADXL362 读取加速度数据
//uart_printf("Xa:%d \tYa:%d \tZa:%d \r\n",Xa,Ya,Za);
AcceBuff[0] = Xa; //x轴加速度
AcceBuff[1] = Ya; //y轴加速度
AcceBuff[2] = Za; //z轴加速度
fx = Xa;
fx *= 2.0 / 4096;
fy = Ya;
fy *= 2.0 / 4096;
fz = Za;
fz *= 2.0 / 4096;
//uart_printf("fx:%.04f\tfy:%.04f\tfz:%.04f\t\r\n",fx,fy,fz);
//Z方向
A = fx * fx + fy * fy;
A = sqrt(A);
A = (double)A / fz;
A = atan(A);
A = A * 180 / PI;
*pAngleZ = A;
uart_printf("=======角度:%.04f\r\n",*pAngleZ);
return TRUE;
}
/*************************************************************************************************************
* 文件名: SC7A20.h
* 功能: SC7A20 三轴加速度传感器支持
* 作者: cp1300@139.com
* 创建时间: 2022-07-01
* 最后修改时间: 2022-07-01
* 详细:
*************************************************************************************************************/
#ifndef _SC7A20_H_
#define _SC7A20_H_
#include "system.h"
//SC7A20 句柄
typedef struct
{
bool (*IIC_ReadReg)(u8 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum); //IIC读取寄存器接口
bool (*IIC_WriteReg)(u16 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum); //IIC写入寄存器接口
u8 SlaveAddr;
u8 ModeConfigData; //记录模式配置值
}SC7A20_HANDLE;
//SC7A20初始化
bool SC7A20_Init(SC7A20_HANDLE *pHandle, u8 SlaveAddr,
bool (*IIC_ReadReg)(u8 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum),
bool (*IIC_WriteReg)(u16 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum));
bool SC7A20_ReadAcceleration(SC7A20_HANDLE* pHandle, s16* pXa, s16* pYa, s16* pZa);//SC7A20读取加速度值
bool SC7A20_GetZAxisAngle(SC7A20_HANDLE* pHandle, s16 AcceBuff[3], float* pAngleZ);//SC7A20 获取Z轴倾角
#endif /*_SC7A20_H_*/
测试代码
/*************************************************************************************************************
* 文件名: SC7A20_Test.c
* 功能: SC7A20测试
* 作者: cp1300@139.com
* 创建时间: 2022-07-01
* 最后修改时间: 2022-07-01
* 详细:
*************************************************************************************************************/
#include "system.h"
#include "hc32f46x_system.h"
#include "test.h"
#include "SoftwareIIC.h"
#include "board.h"
#include "SC7A20.h"
static SC7A20_HANDLE sg_Temp_SC7A20_Handle;
//读取寄存器接口
static bool SC7A20_IIC_ReadReg(u8 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum)
{
if (IIC_MasterReadReg(SC7A20_IIC_CH, SlaveAddr, RegAddr, TRUE, pDataBuff, ByteNum) != IIC_OK) return FALSE;
else return TRUE;
}
//写寄存器接口
static bool SC7A20_IIC_WriteReg(u16 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum)
{
if (IIC_MasterWriteReg(SC7A20_IIC_CH, SlaveAddr, RegAddr, TRUE, pDataBuff, ByteNum) != IIC_OK) return FALSE;
else return TRUE;
}
//SC7A20测试
void SC7A20_Test(void)
{
u8 buff[7];
s16 acc[3];
float zAngle;
SC7A20_IO_Init();
IIC_Init(SC7A20_IIC_CH, 300, 100);//硬件IIC初始化
//SC7A20初始化
SC7A20_Init(&sg_Temp_SC7A20_Handle, SC7A20_ADDR, SC7A20_IIC_ReadReg, SC7A20_IIC_WriteReg);
while (1)
{
if (FALSE == SC7A20_GetZAxisAngle(&sg_Temp_SC7A20_Handle, acc, &zAngle))//SC7A20读取加速度值
{
INFO_S("加速度数据读取失败\r\n");
}
else
{
INFO_S("Z:%f\r\n", zAngle);
}
SYS_DelayMS(500);
}
}