BMA250凭借其超小的封装,低功耗越来越多的产品在这个芯片作为辅助,比如GPS定位时防止静止时定位信息漂移,可以借助其判断物体是静止还是运动。还有实现计步功能、角度测试等………………
经过几天对BMA250资料的搜集和测试,先做以下小的总结:
1、 其测量可以测试±2g、±4g、±8g、±16g。因为芯片内部集成了AD转换,转换精度是10位的,所以当我们接受数据时可以先分析其数值接受的范围是0-1023。在这里要了解一个名词就是LSB(最小有效位,为数字输出方式)在芯片手册里我们会发现:
通过配置寄存器g-range地址是0x0f选择加速度的范围。程序中我们选择了±2g,即配置寄存器为0x03。当我们接受到数值以后将接受的数值*3.9就是当前某个轴的加速度。这里在回忆一下高中学习的知识,物体静止时有1g的重力加速度。三轴加速度也是一样,查看芯片手册里面有一个芯片的摆放以及各个方向的重力加速度,这个可以作为测试用。
2、 分别读取X、Y、Z三轴的数值,看手册会发现其寄存器是0x02、0x03、0x04、0x05、0x06、0x07,其中xyz的MSB分别在0x03、0x05、0x07,LSB中是0x02、0x04、0x06,所以在读取寄存器的值的时候合并时是16位的数据,但是低六位是没有的所以要右移六位去掉无效数据,剩下的十位数据就是我们要的结果。收集到收据以后我们就可以进行数据的处理。本程序因为只测试是运动还是静止没有必要分析是哪个方位运动所以讲正负加速度都处理成加速度没有方向。这里我们通过一个加速度的信号幅度向量SVM(Support Vector Machine)来做一个总的处理。程序是:(我们定义的是无符号整形,因为做简单处理)
SVM=(u16)(sqrt(temp_x*temp_x+temp_y*temp_y+temp_z*temp_z));
3、 该芯片有SPI和IIC两种通信方式,我们采用的是IIC通信方式,这里主要就是通过手册我们查找其地址,看手册我们发现当SDO接GNG或者float时,芯片地址是0x18(即写地址是0x30读地址是0x31),当SDO接VDDIO时芯片地址是0x19(即写地址是0x32读地址是0x33)。
4、 芯片的配置还有就是器传输的带宽我们可以参考器手册:程序中选择了7.81HZ。
5、 如果没有使用中断我们通过配置寄存器0x09将其设置为0x00。
附录程序:
#include"bma250.h"
u16AccelX;
u16AccelY;
u16AccelZ;
externu16 SVM;
//写寄存器函数
staticvoid bma250_write_reg(u8 addr,u8 val)
{
I2C_Start();
I2C_Send_Byte(slaveaddress) ; //发送写器件指令
I2C_Wait_Ack();
I2C_Send_Byte(addr); //发送寄存器地址
I2C_Wait_Ack();
I2C_Send_Byte(val); //发送值
I2C_Wait_Ack();
I2C_Stop(); //产生一个停止条件
}
//传感器初始化
voidbma250_init()
{
bma250_write_reg(0x0F,0x03); //加速度范围为+-2g
bma250_write_reg(0x10,0x08); //传输带宽为7.81HZ,64MS
bma250_write_reg(0x09,0x00); //无中断
}
//读寄存器函数
u8bma250_read_reg(u8 addr)
{
u8 temp=0;
I2C_Start();
I2C_Send_Byte(slaveaddress); //发送写器件指令
temp=I2C_Wait_Ack();
I2C_Send_Byte(addr); //发送寄存器地址
temp=I2C_Wait_Ack();
I2C_Start(); //重新启动
I2C_Send_Byte(regaddress); //发送读器件指令
temp=I2C_Wait_Ack();
temp=I2C_Read_Byte(0); //读取一个字节,不继续再读,发送NAK
I2C_Stop(); //产生一个停止条件
return temp;
}
//读取数据函数
u16bma250_read_data(void)
{
u8 buf[6];
float temp_x,temp_y,temp_z;
u8 i;
I2C_Start();
I2C_Send_Byte(slaveaddress); //发送写器件指令
I2C_Wait_Ack();
I2C_Send_Byte(0x02); //发送寄存器地址(数据缓存的起始地址为0X32)
I2C_Wait_Ack();
I2C_Start(); //重新启动
I2C_Send_Byte(regaddress); //发送读器件指令
I2C_Wait_Ack();
for(i=0;i<6;i++)
{
if(i==5)
buf[i]=I2C_Read_Byte(0);//读取一个字节,不继续再读,发送NACK
else
buf[i]=I2C_Read_Byte(1); //读取一个字节,继续读,发送ACK
}
I2C_Stop(); //产生一个停止条件
AccelX = buf[1] << 8;
AccelX |= buf[0];
AccelX >>=6;
if(AccelX>512)
{
AccelX <<=6;
AccelX=~AccelX;
AccelX=AccelX+1;
AccelX >>=6;
}
temp_x=(float)AccelX*3.9; //计算数据和显示
AccelY = buf[3] << 8;
AccelY |= buf[2];
AccelY >>=6;
if(AccelY>512)
{
AccelY <<=6;
AccelY=~AccelY;
AccelY=AccelY+1;
AccelY >>=6;
}
temp_y=(float)AccelY*3.9; //计算数据和显示
AccelZ = buf[5] << 8;
AccelZ |= buf[4];
AccelZ >>=6;
if(AccelZ>512)
{
AccelZ <<=6;
AccelZ=~AccelZ;
AccelZ=AccelZ+1;
AccelZ >>=6;
}
temp_z=(float)AccelZ*3.9; //计算数据和显示
SVM=(u16)(sqrt(temp_x*temp_x+temp_y*temp_y+temp_z*temp_z));
return SVM;
}
#ifndef_BMA250_H
#define_BMA250_H
#define slaveaddress 0x30 //看BMA250手册当SDO接GND或者float是地址是//0x18(即写地址是0x30,读地址是0x31)当SDO接VDDIO时
//地址是0x19(即写地址是0x32,读地址是0x33)
#defineregaddress 0X31 //read
#defineDEVICE_ID 0X00
//传感器初始化
voidbma250_init();
//读寄存器函数
u8bma250_read_reg(u8 addr);
//读取数据函数
u16bma250_read_data(void);
#endif