接上一篇:STM32CubeIDE HAL庫操作IIC (一)配置篇
目錄
一、IIC協議操作MPU9250寄存器函數
#define MPU9250Addr 0xd0
/*****************************************************************************
* 功 能:寫一個字節數據到 MPU9250 寄存器
* 參 數:reg: 寄存器地址
* data: 要寫入的數據
* 返回值:0成功 1失敗
*****************************************************************************/
uint8_t MPU9250_WriteByte(uint8_t reg,uint8_t data)
{
if(HALIIC_WriteByteToSlave(MPU9250Addr,reg,data))
return 1;
else
return 0;
}
/*****************************************************************************
* 功 能:從指定MPU6050寄存器讀取一個字節數據
* 參 數:reg: 寄存器地址
* buf: 讀取數據存放的地址
* 返回值:1失敗 0成功
*****************************************************************************/
uint8_t MPU9250_ReadByte(uint8_t reg,uint8_t *buf)
{
if(HALIIC_ReadByteFromSlave(MPU9250Addr,reg,buf))
return 1;
else
return 0;
}
/*****************************************************************************
* 功 能:從指定寄存器寫入指定長度數據
* 參 數:reg:寄存器地址
* len:寫入數據長度
* buf: 寫入數據存放的地址
* 返回值:0成功 1失敗
*****************************************************************************/
uint8_t MPU9250_WriteMultBytes(uint8_t reg,uint8_t len,uint8_t *buf)
{
if(HALIIC_WriteMultByteToSlave(MPU9250Addr,reg,len,buf))
return 1;
else
return 0;
}
/*****************************************************************************
* 功 能:從指定寄存器讀取指定長度數據
* 參 數:reg:寄存器地址
* len:讀取數據長度
* buf: 讀取數據存放的地址
* 返回值:0成功 0失敗
*****************************************************************************/
uint8_t MPU9250_ReadMultBytes(uint8_t reg,uint8_t len,uint8_t *buf)
{
if(HALIIC_ReadMultByteFromSlave(MPU9250Addr,reg,len,buf))
return 1;
else
return 0;
}
二、MPU9250的操作(舉例)
1、設置寄存器方法
#define MPU9250_RA_PWR_MGMT_1 0x6B
MPU9250_WriteByte(MPU6050_RA_PWR_MGMT_1, 0x80); //復位MPU9250
2、讀取寄存器方法
讀單個字節
#define MPU9250_RA_WHO_AM_I 0x75
uint8_t buf;
MPU9250_ReadByte(MPU9250_RA_WHO_AM_I, &buf);//讀取器件ID
讀多個字節
/******************************************************************************
* 功 能:讀取加速度的原始數據
* 參 數:*accData 原始數據的指針
* 返回值:無
*******************************************************************************/
void MPU9250_AccRead(int16_t *accData)
{
uint8_t buf[6];
MPU9250_ReadMultBytes(MPU6050_RA_ACCEL_XOUT_H,6,buf);
accData[0] = (int16_t)((buf[0] << 8) | buf[1]);
accData[1] = (int16_t)((buf[2] << 8) | buf[3]);
accData[2] = (int16_t)((buf[4] << 8) | buf[5]);
}
三、MPU9250簡單數據讀取流程
1、初始化
#define MPU9250_RA_INT_ENABLE 0x38
#define MPU9250_RA_PWR_MGMT_1 0x6B
#define MPU9250_RA_GYRO_CONFIG 0x1B
#define MPU9250_RA_ACCEL_CONFIG 0x1C
#define MPU9250_RA_CONFIG 0x1A
#define MPU9250_RA_SMPLRT_DIV 0x19
#define MPU9250_RA_INT_PIN_CFG 0x37
//設置低通濾波
#define MPU9250_DLPF_BW_256 0x00
#define MPU9250_DLPF_BW_188 0x01
#define MPU9250_DLPF_BW_98 0x02
#define MPU9250_DLPF_BW_42 0x03
#define MPU9250_DLPF_BW_20 0x04
#define MPU9250_DLPF_BW_10 0x05
#define MPU9250_DLPF_BW_5 0x06
void MPU9250_Init(void)
{
MPU9250_Check(); //通過讀取ID,檢查MPU9250是否連接
MPU9250_WriteByte(MPU9250_RA_PWR_MGMT_1, 0x80); //復位MPU9250
HAL_Delay(100);
MPU9250_WriteByte(MPU9250_RA_PWR_MGMT_1, 0x00); //喚醒MPU9250,並選擇陀螺儀x軸PLL爲時鐘源 (MPU9250_RA_PWR_MGMT_1, 0x01)
MPU9250_WriteByte(MPU9250_RA_INT_ENABLE, 0x00); //禁止中斷
MPU9250_WriteByte(MPU9250_RA_GYRO_CONFIG, 0x18); //陀螺儀滿量程+-2000度/秒 (最低分辨率 = 2^15/2000 = 16.4LSB/度/秒
MPU9250_WriteByte(MPU9250_RA_ACCEL_CONFIG, 0x08); //加速度滿量程+-4g (最低分辨率 = 2^15/4g = 8196LSB/g )
MPU9250_WriteByte(MPU9250_RA_CONFIG, MPU6050_DLPF_BW_20);//設置陀螺的輸出爲1kHZ,DLPF=20Hz
MPU9250_WriteByte(MPU9250_RA_SMPLRT_DIV, 0x00); //採樣分頻 (採樣頻率 = 陀螺儀輸出頻率 / (1+DIV),採樣頻率1000hz)
MPU9250_WriteByte(MPU9250_RA_INT_PIN_CFG, 0x02); //MPU 可直接訪問MPU9250輔助I2C
}
2、讀取各傳感器數據函數
#define MPU9250_RA_ACCEL_XOUT_H 0x3B
#define MPU9250_RA_TEMP_OUT_H 0x41
#define MPU9250_RA_GYRO_XOUT_H 0x43
//MPU9250內部封裝了一個AK8963磁力計,地址和ID如下:
#define AK8963_ADDR 0X0C //AK8963的I2C地址
#define AK8963_ID 0X48 //AK8963的器件ID
//AK8963的內部寄存器
#define MAG_WIA 0x00 //AK8963的器件ID寄存器地址
#define MAG_XOUT_L 0X03
/******************************************************************************
* 功 能:讀取加速度的原始數據
* 參 數:*accData 原始數據的指針
* 返回值:無
*******************************************************************************/
void MPU9250_AccRead(int16_t *accData)
{
uint8_t buf[6];
MPU9250_ReadMultBytes(MPU9250_RA_ACCEL_XOUT_H,6,buf);
accData[0] = (int16_t)((buf[0] << 8) | buf[1]);
accData[1] = (int16_t)((buf[2] << 8) | buf[3]);
accData[2] = (int16_t)((buf[4] << 8) | buf[5]);
}
/******************************************************************************
* 功 能:讀取陀螺儀的原始數據
* 參 數:*gyroData 原始數據的指針
* 返回值:無
*******************************************************************************/
void MPU9250_GyroRead(int16_t *gyroData)
{
uint8_t buf[6];
MPU9250_ReadMultBytes(MPU9250_RA_GYRO_XOUT_H, 6, buf);
gyroData[0] = (int16_t)((buf[0] << 8) | buf[1]) ;
gyroData[1] = (int16_t)((buf[2] << 8) | buf[3]) ;
gyroData[2] = (int16_t)((buf[4] << 8) | buf[5]) ;
}
/******************************************************************************
* 功 能:讀取磁力計的原始數據
* 參 數:*magData原始數據的指針
* 返回值:無
*******************************************************************************/
void MPU9250_MagRead(int16_t *magData)
{
uint8_t buf[6];
HALIIC_WriteByteToSlave(MPU9250Addr,0x37,0x02);//turn on Bypass Mode
HAL_Delay(10);
HALIIC_WriteByteToSlave(AK8963_MAG_ADDRESS,0x0A,0x11);
HAL_Delay(10);
HALIIC_ReadMultByteFromSlave(AK8963_MAG_ADDRESS,MAG_XOUT_L, 6, buf);
magData[0] = (int16_t)((buf[1] << 8) | buf[0]) ;
magData[1] = (int16_t)((buf[3] << 8) | buf[2]) ;
magData[2] = (int16_t)((buf[5] << 8) | buf[4]) ;
}
/******************************************************************************
* 功 能:溫度值讀取
* 參 數:*tempdata 溫度數據的指針
* 返回值:無
*******************************************************************************/
void MPU9250_TempRead(float *tempdata)
{
uint8_t buf[2];
short data;
MPU9250_ReadMultBytes(MPU9250_RA_TEMP_OUT_H, 2, buf);
data = (int16_t)((buf[0] << 8) | buf[1]) ;
*tempdata = 21f + ((float)data/333.87f);
}
3、使用
int16_t acc[3],gyy[3],mag[3];
MPU9250_AccRead(acc);
MPU9250_GyroRead(gyy);
MPU9250_MagRead(mag);
ANO_DT_Send_Senser(acc[0],acc[1],acc[2],gyy[0],gyy[1],gyy[2],mag[0],mag[1],mag[2],0);
注:ANO_DT_Send_Senser函數是適用於匿名電子的V6版本上位機的發送協議,可以用來看波形顯示
#define BYTE0(dwTemp) ( *( (char *)(&dwTemp) ) )
#define BYTE1(dwTemp) ( *( (char *)(&dwTemp) + 1) )
#define BYTE2(dwTemp) ( *( (char *)(&dwTemp) + 2) )
#define BYTE3(dwTemp) ( *( (char *)(&dwTemp) + 3) )
uint8_t data_to_send[50]; //發送數據緩存
void ANO_DT_Send_Senser(int16_t a_x,int16_t a_y,int16_t a_z,int16_t g_x,int16_t g_y,int16_t g_z,int16_t m_x,int16_t m_y,int16_t m_z,s32 bar)
{
uint8_t _cnt=0,sum = 0,i;
vs16 _temp;
data_to_send[_cnt++]=0xAA;
data_to_send[_cnt++]=0x05;
data_to_send[_cnt++]=0xAF;
data_to_send[_cnt++]=0x02;
data_to_send[_cnt++]=0;
_temp = a_x;
data_to_send[_cnt++]=BYTE1(_temp);
data_to_send[_cnt++]=BYTE0(_temp);
_temp = a_y;
data_to_send[_cnt++]=BYTE1(_temp);
data_to_send[_cnt++]=BYTE0(_temp);
_temp = a_z;
data_to_send[_cnt++]=BYTE1(_temp);
data_to_send[_cnt++]=BYTE0(_temp);
_temp = g_x;
data_to_send[_cnt++]=BYTE1(_temp);
data_to_send[_cnt++]=BYTE0(_temp);
_temp = g_y;
data_to_send[_cnt++]=BYTE1(_temp);
data_to_send[_cnt++]=BYTE0(_temp);
_temp = g_z;
data_to_send[_cnt++]=BYTE1(_temp);
data_to_send[_cnt++]=BYTE0(_temp);
_temp = m_x;
data_to_send[_cnt++]=BYTE1(_temp);
data_to_send[_cnt++]=BYTE0(_temp);
_temp = m_y;
data_to_send[_cnt++]=BYTE1(_temp);
data_to_send[_cnt++]=BYTE0(_temp);
_temp = m_z;
data_to_send[_cnt++]=BYTE1(_temp);
data_to_send[_cnt++]=BYTE0(_temp);
data_to_send[4] = _cnt-5;
for(i=0;i<_cnt;i++)
sum += data_to_send[i];
data_to_send[_cnt++] = sum;
usart_send(data_to_send, _cnt);
}
參考文獻: