MMA8452Q 三轴加速度传感器驱动
扫描二维码
随时随地手机看文章
之前使用的是ADXL362测量加速度,功耗特别低,使用的还可以,但是后来用于测量角度时误差特别大,最终更换为MMA8452Q ,这个芯片较便宜,测量设备静态的倾角,还是蛮好用的,我的使用中只需要测量Z轴的倾角。
/************************************************************************************************************* * 文件名: MMA8452Q.c * 功能: MMA8452Q驱动 * 作者: cp1300@139.com * 创建时间: 2018-04-09 * 最后修改时间: 2018-04-09 * 详细: MMA8452Q三轴加速度传感器 依赖SoftwareIIC *************************************************************************************************************/ #include "system.h" #include "MMA8452Q.h" #include "math.h" #include#include "SoftwareIIC.h" //调试宏开关 #define MMA8452Q_DBUG 1 #if MMA8452Q_DBUG #include "system.h" #define MMA8452Q_Debug(format,...) uart_printf(format,##__VA_ARGS__) #else #define MMA8452Q_Debug(format,...) / / #endif //MMA8452Q_DBUG #define PI 3.1415926535898 u8 MMA8452Q_ReadOneReg(MMA8452Q_HANDLE *pHandle,u8 RegAddr); //MMA8452Q读取一个寄存器 void MMA8452Q_ReadMultReg(MMA8452Q_HANDLE *pHandle,u8 RegAddr, u8 RegNum, u8 DataBuff[]); //MMA8452Q读取多个寄存器 void MMA8452Q_WriteOneReg(MMA8452Q_HANDLE *pHandle,u8 RegAddr,u8 data); //MMA8452Q写一个寄存器 /************************************************************************************************************************* *函数 : bool MMA8452Q_Init(MMA8452Q_HANDLE *pHandle, u8 SlaveAddr) *功能 : MMA8452Q初始化 *参数 : pHandle:句柄;SlaveAddr:芯片IIC地址 *返回 : TRUE:初始化成功;FALSE:初始化失败 *依赖 : 底层宏定义 *作者 : cp1300@139.com *时间 : 2018-04-09 *最后修改时间 : 2018-04-09 *说明 : *************************************************************************************************************************/ bool MMA8452Q_Init(MMA8452Q_HANDLE *pHandle, u8 SlaveAddr) { u8 temp; if(pHandle == NULL) return FALSE; pHandle->SlaveAddr = SlaveAddr; MMA8452Q_WriteOneReg(pHandle, 0x2A, 0x01); MMA8452Q_WriteOneReg(pHandle, 0x2B, 0x02); temp = MMA8452Q_ReadOneReg(pHandle, 0x0D); //读取器件ID if(temp != 0x2A) //ID不对 { uart_printf("初始化失败,ID错误:0x%02Xrn", temp); return FALSE; } uart_printf("ID:0x%02Xrn", temp); return TRUE; } /************************************************************************************************************************* *函数 : u8 MMA8452Q_ReadOneReg(MMA8452Q_HANDLE *pHandle,u8 RegAddr) *功能 : MMA8452Q读取一个寄存器 *参数 : pHandle:句柄;RegAddr:寄存器地址 *返回 : 读取的寄存器值 *依赖 : 底层宏定义 *作者 : cp1300@139.com *时间 : 2018-04-09 *最后修改时间 : 2018-04-09 *说明 : *************************************************************************************************************************/ u8 MMA8452Q_ReadOneReg(MMA8452Q_HANDLE *pHandle,u8 RegAddr) { u8 data; SIIC_Start(&pHandle->IIC_Handle); //产生IIC起始信号 if(SIIC_SendByte(&pHandle->IIC_Handle, pHandle->SlaveAddr) == FALSE) //发送设备地址+写信号 { DEBUG("没有收到ACKrn"); } SIIC_SendByte(&pHandle->IIC_Handle, RegAddr); //发送寄存器地址 SIIC_Start(&pHandle->IIC_Handle); //产生IIC起始信号 SIIC_SendByte(&pHandle->IIC_Handle, pHandle->SlaveAddr|BIT0); //发送设备地址+读信号 data = SIIC_ReadByte(&pHandle->IIC_Handle, TRUE); //SIIC读取一个字节 SIIC_Stop(&pHandle->IIC_Handle); //产生IIC停止信号 return data; } /************************************************************************************************************************* *函数 : void MMA8452Q_ReadMultReg(MMA8452Q_HANDLE *pHandle,u8 RegAddr, u8 RegNum, u8 DataBuff[]) *功能 : MMA8452Q读取多个寄存器 *参数 : pHandle:句柄;RegAddr:寄存器地址;RegNum:寄存器数量;DataBuff:返回结果缓冲区 *返回 : 无 *依赖 : 底层宏定义 *作者 : cp1300@139.com *时间 : 2018-04-09 *最后修改时间 : 2018-04-09 *说明 : *************************************************************************************************************************/ void MMA8452Q_ReadMultReg(MMA8452Q_HANDLE *pHandle,u8 RegAddr, u8 RegNum, u8 DataBuff[]) { u8 i; SIIC_Start(&pHandle->IIC_Handle); //产生IIC起始信号 SIIC_SendByte(&pHandle->IIC_Handle, pHandle->SlaveAddr); //发送设备地址+写信号 SIIC_SendByte(&pHandle->IIC_Handle, RegAddr); //发送寄存器地址 SIIC_Start(&pHandle->IIC_Handle); //产生IIC起始信号 SIIC_SendByte(&pHandle->IIC_Handle, pHandle->SlaveAddr|BIT0); //发送设备地址+读信号 for(i = 0;i < RegNum;i ++) { if(i == (RegNum-1)) //最后一字节不响应ACK { DataBuff[i] = SIIC_ReadByte(&pHandle->IIC_Handle, FALSE); //SIIC读取一个字节-NAK } else { DataBuff[i] = SIIC_ReadByte(&pHandle->IIC_Handle, TRUE); //SIIC读取一个字节-ACK } } SIIC_Stop(&pHandle->IIC_Handle); //产生IIC停止信号 } /************************************************************************************************************************* *函数 : void MMA8452Q_WriteOneReg(MMA8452Q_HANDLE *pHandle,u8 RegAddr,u8 data) *功能 : MMA8452Q写一个寄存器 *参数 : pHandle:句柄;RegAddr:寄存器地址;data:要写入的值 *返回 : 无 *依赖 : 底层宏定义 *作者 : cp1300@139.com *时间 : 2018-04-09 *最后修改时间 : 2018-04-09 *说明 : *************************************************************************************************************************/ void MMA8452Q_WriteOneReg(MMA8452Q_HANDLE *pHandle,u8 RegAddr,u8 data) { SIIC_Start(&pHandle->IIC_Handle); //产生IIC起始信号 SIIC_SendByte(&pHandle->IIC_Handle, pHandle->SlaveAddr); //发送设备地址+写信号 SIIC_SendByte(&pHandle->IIC_Handle, RegAddr); //发送寄存器地址 SIIC_SendByte(&pHandle->IIC_Handle, data); //发送要写入的数据 SIIC_Stop(&pHandle->IIC_Handle); //产生IIC停止信号 } /************************************************************************************************************************* *函数 : bool MMA8452Q_ReadAcceleration(MMA8452Q_HANDLE *pHandle, s16 *pXa,s16 *pYa, s16 *pZa) *功能 : MMA8452Q 读取三轴加速度 *参数 : pHandle:句柄;pXa:返回X轴加速度;pYa:返回Y轴加速度;pZa:返回Z轴加速度 *返回 : TRUE:成功;FALSE:失败 *依赖 : 底层宏定义 *作者 : cp1300@139.com *时间 : 2018-04-09 *最后修改时间 : 2018-04-09 *说明 : *************************************************************************************************************************/ bool MMA8452Q_ReadAcceleration(MMA8452Q_HANDLE *pHandle, s16 *pXa,s16 *pYa, s16 *pZa) { u8 buff[6]; s16 temp; temp = MMA8452Q_ReadOneReg(pHandle, 0x0D); //读取器件ID if(temp != 0x2A) //ID不对 { return FALSE; } MMA8452Q_ReadMultReg(pHandle, 1, 6, buff); //读取数据 temp = buff[0]; temp<>4; if(buff[0] & BIT7) //负数 { temp |= 0xF000; } *pXa = temp; //X轴 temp = buff[2]; temp<>4; if(buff[2] & BIT7) //负数 { temp |= 0xF000; } *pYa = temp; //Y轴 temp = buff[4]; temp<>4; if(buff[4] & BIT7) //负数 { temp |= 0xF000; } *pZa = temp; //Z轴 return TRUE; } /************************************************************************************************************************* *函数 : void ADXL362_CalAngle(s16 Xa,s16 Ya, s16 Za, float *pAngleX, float *pAngleY, float *pAngleZ) *功能 : ADXL362 通过加速度计算角度信息 *参数 : Xa:X轴加速度;Ya:Y轴加速度;Za:Z轴加速度,pAngleX:X方向倾角;pAngleY:Y方向倾角;pAngleZ:Z方向倾角 *返回 : 无 *依赖 : 底层宏定义 *作者 : cp1300@139.com *时间 : 2016-04-06 *最后修改时间 : 2018-03-13 *说明 : 需要进行浮点,反正切运算 *************************************************************************************************************************/ void MMA8452Q_CalAngle(s16 Xa,s16 Ya, s16 Za, float *pAngleX, float *pAngleY, float *pAngleZ) { double A; //X方向 A = (double)Ya*Ya+(double)Za*Za; A = sqrt(A); A = (double)Xa/A; A = atan(A); A = A*180/PI; if(Za<0) //将坐标转换为±180度 { if(A <0)A=-90-(A+90); else A=90+(90-A); } if(A <0) //将坐标转换为360度 { A=fabs(A); A = 180+180-A; } *pAngleX = A; //Y方向 A = (double)Xa*Xa+(double)Za*Za; A = sqrt(A); A = (double)Ya/A; A = atan(A); A = A*180/PI; if(Za<0)//将坐标转换为±180度 { if(A <0)A=-90-(A+90); else A=90+(90-A); } if(A <0) //将坐标转换为360度 { A=fabs(A); A = 180+180-A; } *pAngleY = A; //Z方向 A = (double)Xa*Xa+(double)Ya*Ya; A = sqrt(A); A = (double)A/abs(Za); A = atan(A); A = A*180/PI; uart_printf("XA:%dtYA:%dtZA:%dt",Xa,Ya,Za); /*if(Za<0)//将坐标转换为±180度 { if(A <0)A=-90-(A+90); else A=90+(90-A); } if(A <0) //将坐标转换为360度 { A=fabs(A); A = 180+180-A; }*/ *pAngleZ = A; } /************************************************************************************************************************* *函数 : bool MMA8452Q_GetZAxisAngle(MMA8452Q_HANDLE *pHandle,s16 AcceBuff[3], float *pAngleZ) *功能 : MMA8452Q 获取Z轴倾角 *参数 : pHandle:句柄;AcceBuff:3个轴的加速度;pAngleZ:Y方向倾角 *返回 : TRUE:成功;FALSE:失败 *依赖 : 底层宏定义 *作者 : cp1300@139.com *时间 : 2018-04-09 *最后修改时间 : 2018-04-09 *说明 : *************************************************************************************************************************/ bool MMA8452Q_GetZAxisAngle(MMA8452Q_HANDLE *pHandle,s16 AcceBuff[3], float *pAngleZ) { double fx,fy,fz; double A; s16 Xa,Ya,Za; if(MMA8452Q_ReadAcceleration(pHandle, &Xa, &Ya, &Za) == FALSE) return FALSE; //ADXL362 读取加速度数据 //uart_printf("Xa:%d tYa:%d tZa:%d rn",Xa,Ya,Za); AcceBuff[0] = Xa; //x轴加速度 AcceBuff[1] = Ya; //y轴加速度 AcceBuff[2] = Za; //z轴加速度 fx = Xa; fx *= 10.0/1024; fy = Ya; fy *= 10.0/1024; fz = Za; fz *= 10.0/1024; //uart_printf("fx:%.04ftfy:%.04ftfz:%.04ftrn",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("=======角度:%.04frn",*pAngleZ); return TRUE; }
/************************************************************************************************************* * 文件名: MMA8452Q.c * 功能: MMA8452Q驱动 * 作者: cp1300@139.com * 创建时间: 2018-04-09 * 最后修改时间: 2018-04-09 * 详细: MMA8452Q三轴加速度传感器 *************************************************************************************************************/ #ifndef _MMA8452Q_H_ #define _MMA8452Q_H_ #include "system.h" #include "SoftwareIIC.h" //MMA8452Q 句柄 typedef struct { SIIC_HANDLE IIC_Handle; u8 SlaveAddr; }MMA8452Q_HANDLE; bool MMA8452Q_Init(MMA8452Q_HANDLE *pHandle, u8 SlaveAddr); //MMA8452Q初始化 bool MMA8452Q_ReadAcceleration(MMA8452Q_HANDLE *pHandle, s16 *pXa,s16 *pYa, s16 *pZa); //MMA8452Q 读取三轴加速度 bool MMA8452Q_GetZAxisAngle(MMA8452Q_HANDLE *pHandle,s16 AcceBuff[3], float *pAngleZ); //MMA8452Q 获取Z轴角度信息 #endif /*_MMA8452Q_H_*/
//测试
g_SysFlag.ADXL362_Status = MMA8452Q_Init(&g_SysFlag.MMA8452Q_Handle, 0x1C<<1); if(g_SysFlag.ADXL362_Status == FALSE) { DEBUG("MMA8452Q初始化失败!rn"); }
if(MMA8452Q_GetZAxisAngle(&g_SysFlag.MMA8452Q_Handle, g_SysFlag.AcceBuff, &AngleZ) == FALSE) //ADXL362 获取角度信息 { //角度读取失败 AngleZ = 0; //读取失败,固定为0 }