MMA8452Q 三軸加速度傳感器驅(qū)動(dòng)
之前使用的是ADXL362測(cè)量加速度,功耗特別低,使用的還可以,但是后來用于測(cè)量角度時(shí)誤差特別大,最終更換為MMA8452Q ,這個(gè)芯片較便宜,測(cè)量設(shè)備靜態(tài)的傾角,還是蠻好用的,我的使用中只需要測(cè)量Z軸的傾角。
/************************************************************************************************************* ?*?文件名: MMA8452Q.c ?*?功能: MMA8452Q驅(qū)動(dòng) ?*?作者: cp1300@139.com ?*?創(chuàng)建時(shí)間: 2018-04-09 ?*?最后修改時(shí)間: 2018-04-09 ?*?詳細(xì): MMA8452Q三軸加速度傳感器 依賴SoftwareIIC *************************************************************************************************************/ #include?"system.h" #include?"MMA8452Q.h" #include?"math.h" #include#include?"SoftwareIIC.h" //調(diào)試宏開關(guān) #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讀取一個(gè)寄存器 void?MMA8452Q_ReadMultReg(MMA8452Q_HANDLE?*pHandle,u8?RegAddr,?u8?RegNum,?u8?DataBuff[]); //MMA8452Q讀取多個(gè)寄存器 void?MMA8452Q_WriteOneReg(MMA8452Q_HANDLE?*pHandle,u8?RegAddr,u8?data); //MMA8452Q寫一個(gè)寄存器 /************************************************************************************************************************* *函數(shù)???????? : bool?MMA8452Q_Init(MMA8452Q_HANDLE?*pHandle,?u8?SlaveAddr) *功能???????? : MMA8452Q初始化 *參數(shù)???????? : pHandle:句柄;SlaveAddr:芯片IIC地址 *返回???????? : TRUE:初始化成功;FALSE:初始化失敗 *依賴 :? 底層宏定義 *作者??????? : cp1300@139.com *時(shí)間????? : 2018-04-09 *最后修改時(shí)間 : 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不對(duì) { uart_printf("初始化失敗,ID錯(cuò)誤:0x%02Xrn",?temp); return?FALSE; } uart_printf("ID:0x%02Xrn",?temp); return?TRUE; } /************************************************************************************************************************* *函數(shù)???????? : u8?MMA8452Q_ReadOneReg(MMA8452Q_HANDLE?*pHandle,u8?RegAddr) *功能???????? : MMA8452Q讀取一個(gè)寄存器 *參數(shù)???????? : pHandle:句柄;RegAddr:寄存器地址 *返回???????? : 讀取的寄存器值 *依賴 :? 底層宏定義 *作者??????? : cp1300@139.com *時(shí)間????? : 2018-04-09 *最后修改時(shí)間 : 2018-04-09 *說明???????? : *************************************************************************************************************************/ u8?MMA8452Q_ReadOneReg(MMA8452Q_HANDLE?*pHandle,u8?RegAddr) { u8?data; SIIC_Start(&pHandle->IIC_Handle); //產(chǎn)生IIC起始信號(hào) if(SIIC_SendByte(&pHandle->IIC_Handle,?pHandle->SlaveAddr)?==?FALSE) //發(fā)送設(shè)備地址+寫信號(hào) { DEBUG("沒有收到ACKrn"); } SIIC_SendByte(&pHandle->IIC_Handle,?RegAddr); //發(fā)送寄存器地址 SIIC_Start(&pHandle->IIC_Handle); //產(chǎn)生IIC起始信號(hào) SIIC_SendByte(&pHandle->IIC_Handle,?pHandle->SlaveAddr|BIT0); //發(fā)送設(shè)備地址+讀信號(hào) data?=?SIIC_ReadByte(&pHandle->IIC_Handle,?TRUE); //SIIC讀取一個(gè)字節(jié) SIIC_Stop(&pHandle->IIC_Handle); //產(chǎn)生IIC停止信號(hào) return?data; } /************************************************************************************************************************* *函數(shù)???????? : void?MMA8452Q_ReadMultReg(MMA8452Q_HANDLE?*pHandle,u8?RegAddr,?u8?RegNum,?u8?DataBuff[]) *功能???????? : MMA8452Q讀取多個(gè)寄存器 *參數(shù)???????? : pHandle:句柄;RegAddr:寄存器地址;RegNum:寄存器數(shù)量;DataBuff:返回結(jié)果緩沖區(qū) *返回???????? : 無 *依賴 :? 底層宏定義 *作者??????? : cp1300@139.com *時(shí)間????? : 2018-04-09 *最后修改時(shí)間 : 2018-04-09 *說明???????? : *************************************************************************************************************************/ void?MMA8452Q_ReadMultReg(MMA8452Q_HANDLE?*pHandle,u8?RegAddr,?u8?RegNum,?u8?DataBuff[]) { u8?i; SIIC_Start(&pHandle->IIC_Handle); //產(chǎn)生IIC起始信號(hào) SIIC_SendByte(&pHandle->IIC_Handle,?pHandle->SlaveAddr); //發(fā)送設(shè)備地址+寫信號(hào) SIIC_SendByte(&pHandle->IIC_Handle,?RegAddr); //發(fā)送寄存器地址 SIIC_Start(&pHandle->IIC_Handle); //產(chǎn)生IIC起始信號(hào) SIIC_SendByte(&pHandle->IIC_Handle,?pHandle->SlaveAddr|BIT0); //發(fā)送設(shè)備地址+讀信號(hào) for(i?=?0;i?<?RegNum;i?++) { if(i?==?(RegNum-1)) //最后一字節(jié)不響應(yīng)ACK { DataBuff[i]?=?SIIC_ReadByte(&pHandle->IIC_Handle,?FALSE); //SIIC讀取一個(gè)字節(jié)-NAK } else { DataBuff[i]?=?SIIC_ReadByte(&pHandle->IIC_Handle,?TRUE); //SIIC讀取一個(gè)字節(jié)-ACK } } SIIC_Stop(&pHandle->IIC_Handle); //產(chǎn)生IIC停止信號(hào) } /************************************************************************************************************************* *函數(shù)???????? : void?MMA8452Q_WriteOneReg(MMA8452Q_HANDLE?*pHandle,u8?RegAddr,u8?data) *功能???????? : MMA8452Q寫一個(gè)寄存器 *參數(shù)???????? : pHandle:句柄;RegAddr:寄存器地址;data:要寫入的值 *返回???????? : 無 *依賴 :? 底層宏定義 *作者??????? : cp1300@139.com *時(shí)間????? : 2018-04-09 *最后修改時(shí)間 : 2018-04-09 *說明???????? : *************************************************************************************************************************/ void?MMA8452Q_WriteOneReg(MMA8452Q_HANDLE?*pHandle,u8?RegAddr,u8?data) { SIIC_Start(&pHandle->IIC_Handle); //產(chǎn)生IIC起始信號(hào) SIIC_SendByte(&pHandle->IIC_Handle,?pHandle->SlaveAddr); //發(fā)送設(shè)備地址+寫信號(hào) SIIC_SendByte(&pHandle->IIC_Handle,?RegAddr); //發(fā)送寄存器地址 SIIC_SendByte(&pHandle->IIC_Handle,?data); //發(fā)送要寫入的數(shù)據(jù) SIIC_Stop(&pHandle->IIC_Handle); //產(chǎn)生IIC停止信號(hào) } /************************************************************************************************************************* *函數(shù)???????? : bool?MMA8452Q_ReadAcceleration(MMA8452Q_HANDLE?*pHandle,?s16?*pXa,s16?*pYa,?s16?*pZa) *功能???????? : MMA8452Q?讀取三軸加速度 *參數(shù)???????? : pHandle:句柄;pXa:返回X軸加速度;pYa:返回Y軸加速度;pZa:返回Z軸加速度 *返回???????? : TRUE:成功;FALSE:失敗 *依賴 :? 底層宏定義 *作者??????? : cp1300@139.com *時(shí)間????? : 2018-04-09 *最后修改時(shí)間 : 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不對(duì) { return?FALSE; } MMA8452Q_ReadMultReg(pHandle,?1,?6,?buff); //讀取數(shù)據(jù) temp?=?buff[0]; temp<>4; if(buff[0]?&?BIT7) //負(fù)數(shù) { temp?|=?0xF000; } *pXa?=?temp; //X軸 temp?=?buff[2]; temp<>4; if(buff[2]?&?BIT7) //負(fù)數(shù) { temp?|=?0xF000; } *pYa?=?temp; //Y軸 temp?=?buff[4]; temp<>4; if(buff[4]?&?BIT7) //負(fù)數(shù) { temp?|=?0xF000; } *pZa?=?temp; //Z軸 return?TRUE; } /************************************************************************************************************************* *函數(shù)???????? : void?ADXL362_CalAngle(s16?Xa,s16?Ya,?s16?Za,?float?*pAngleX,?float?*pAngleY,?float?*pAngleZ) *功能???????? : ADXL362?通過加速度計(jì)算角度信息 *參數(shù)???????? : Xa:X軸加速度;Ya:Y軸加速度;Za:Z軸加速度,pAngleX:X方向傾角;pAngleY:Y方向傾角;pAngleZ:Z方向傾角 *返回???????? : 無 *依賴 :? 底層宏定義 *作者??????? : cp1300@139.com *時(shí)間????? : 2016-04-06 *最后修改時(shí)間 : 2018-03-13 *說明???????? : 需要進(jìn)行浮點(diǎn),反正切運(yùn)算 *************************************************************************************************************************/ 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) //將坐標(biāo)轉(zhuǎn)換為±180度 { if(A?<0)A=-90-(A+90); else?A=90+(90-A); } if(A?<0) //將坐標(biāo)轉(zhuǎn)換為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)//將坐標(biāo)轉(zhuǎn)換為±180度 { if(A?<0)A=-90-(A+90); else?A=90+(90-A); } if(A?<0) //將坐標(biāo)轉(zhuǎn)換為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)//將坐標(biāo)轉(zhuǎn)換為±180度 { if(A?<0)A=-90-(A+90); else?A=90+(90-A); } if(A?<0) //將坐標(biāo)轉(zhuǎn)換為360度 { A=fabs(A); A?=?180+180-A; }*/ *pAngleZ?=?A; } /************************************************************************************************************************* *函數(shù)???????? : bool?MMA8452Q_GetZAxisAngle(MMA8452Q_HANDLE?*pHandle,s16?AcceBuff[3],?float?*pAngleZ) *功能???????? : MMA8452Q?獲取Z軸傾角 *參數(shù)???????? : pHandle:句柄;AcceBuff:3個(gè)軸的加速度;pAngleZ:Y方向傾角 *返回???????? : TRUE:成功;FALSE:失敗 *依賴 :? 底層宏定義 *作者??????? : cp1300@139.com *時(shí)間????? : 2018-04-09 *最后修改時(shí)間 : 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?讀取加速度數(shù)據(jù) //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驅(qū)動(dòng) ?*?作者: cp1300@139.com ?*?創(chuàng)建時(shí)間: 2018-04-09 ?*?最后修改時(shí)間: 2018-04-09 ?*?詳細(xì): 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_*/
//測(cè)試
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 }