BMI055与其他imu不同的地方是他的加速度硬件单元和陀螺仪硬件单元是分开独立的(两个不同的CHIPID),他们使用两个不同的片选,地址空间重叠。
一般的imu如 mpu6050,mpu6500,mpu9250,imu160等等都是加速度硬件单元和陀螺仪硬件单元一体,一个片选,地址不重叠。
所以BMI055的编程稍微复杂点,需要两个spi,如果共用GPIO的话那就至少需要一个IO口模拟的spi(1硬件1模拟或者2个模拟)。
代码如下:
#include "imu.h"
void IMU_init(void)
{
u8 imu_data[12] = {0};
u16 imu_dat[6] = {0};
my_spi_io_init();
IMU_config(RANGE_2G,RANGE_2000);
while(1){//for test
IMU_Read(imu_data);
//acc
imu_dat[0] = (u16)imu_data[1]<<4 | imu_data[0]>>4;
imu_dat[1] = (u16)imu_data[3]<<4 | imu_data[2]>>4;
imu_dat[2] = (u16)imu_data[5]<<4 | imu_data[4]>>4;
//gyr
imu_dat[3] = imu_data[7]<<8 | imu_data[6];
imu_dat[4] = imu_data[9]<<8 | imu_data[8];
imu_dat[5] = imu_data[11]<<8 | imu_data[10];
asm("nop");
}
}
void IMU_Read(u8 *buf)
{
u8 i = 0;
u8 addr = 0x00;
addr |= 0x80;//read
//read acc data
SPI_CS_ACC = 0;
addr |= ACC_X_LSB_REG;
My_SPI_ReadWriteByte(addr);
for(i=0;i<6;i++){
*(buf+i) = My_SPI_ReadWriteByte(0);
asm("nop");
}
SPI_CS_ACC = 1;
//read gyr data
SPI_CS_GYR = 0;
addr |= GYR_X_LSB_REG;
My_SPI_ReadWriteByte(addr);
for(i=6; i<12; i++){
*(buf+i) = My_SPI_ReadWriteByte(0);
asm("nop");
}
SPI_CS_GYR = 1;
}
// for(i=0;i<6;i++){
// SPI_CS_ACC=0;
// addr |= (ACC_X_LSB_REG+i);
// RW_SPI(addr);
// acc[i] = RW_SPI(0);
// SPI_CS_ACC=1;
// }
u8 My_SPI_ReadWriteByte(u8 val)
{
u8 i;
for(i=0;i<8;i++){
SPI_CLK = 0;
asm("nop"); asm("nop"); asm("nop");
//write
if(val & 0x80)
SPI_DO = 1;
else
SPI_DO = 0;
val <<= 1;
SPI_CLK = 1;
asm("nop"); asm("nop"); asm("nop");
//read
if(SPI_DI)
val |= 1;
}
SPI_CLK = 0;
return val;
}
u8 IMU_config(u8 acc_range,u8 gyr_range)
{
u8 res = 0;
u8 reg = 0x00;//REG_CHIPID
reg |= 0x80;//read
//Check ACC CHIP_ID
SPI_CS_ACC=0;
My_SPI_ReadWriteByte(reg);
res = My_SPI_ReadWriteByte(0);
SPI_CS_ACC=1;
if(res != ACC_CHIP_ID){
res = 1;
}
//Check GYR CHIP_ID
SPI_CS_GYR=0;
My_SPI_ReadWriteByte(reg);
res = My_SPI_ReadWriteByte(0);
SPI_CS_GYR=1;
if(res != GYR_CHIP_ID){
res = 2;
}
//Config ACC RANGE
SPI_CS_ACC=0;
My_SPI_ReadWriteByte(IMU_CONFIG_REG);//write
My_SPI_ReadWriteByte(acc_range);
SPI_CS_ACC=1;
SPI_CS_ACC=0;
My_SPI_ReadWriteByte(reg | IMU_CONFIG_REG);
res = My_SPI_ReadWriteByte(0);//read reg
if(res != acc_range){//Write failed.
res = 3;
}
SPI_CS_ACC=1;
//Config GYR RANGE
SPI_CS_GYR=0;
My_SPI_ReadWriteByte(IMU_CONFIG_REG);//write
My_SPI_ReadWriteByte(gyr_range);
SPI_CS_GYR=1;
SPI_CS_GYR=0;
My_SPI_ReadWriteByte(reg | IMU_CONFIG_REG);
res = My_SPI_ReadWriteByte(0);//read reg
if(res != gyr_range){//Write failed.
res = 4;
}else{
res = 0;//ok
}
SPI_CS_GYR=1;
return res;
}
void my_spi_io_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE );//PORTB奀笘妏夔
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;//sck,miso
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_15);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //MOSI input
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//PA4: CS_ACC
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_4);
//PB12: CS_GYR
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_12);
}