最近做一个项目用ADXL345芯片测量加速度,然后进行速度和位移的求解,加速度芯片是从网上买的模块,用的模拟I2C通信,程序是按照原子哥的代码写的,可是不知道为啥,当模块平放在桌子上时,读取Z轴的加速度,总会出现一些波动较大的点,完全超过芯片手册上写的零飘,求用过模拟I2C的大神们指点下,谢谢了!
[mw_shl_code=c,true]void I2C_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = I2C_SCL|I2C_SDA;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
//I2C_SCL_H;
//I2C_SDA_H;
}
void I2C_SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin =I2C_SDA;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
void I2C_SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructureA;
GPIO_InitStructureA.GPIO_Pin =I2C_SDA;
GPIO_InitStructureA.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIO_I2C, &GPIO_InitStructureA);
}
void I2C_START(void)
{
I2C_SDA_OUT();
I2C_SCL_H;
I2C_SDA_H;
delay_us(4); //6
I2C_SDA_L;
delay_us(4); //6
I2C_SCL_L;
}
void I2C_STOP(void)
{
I2C_SDA_OUT();
I2C_SCL_L;
I2C_SDA_L;
delay_us(4);
I2C_SCL_H;
delay_us(4); //6
I2C_SDA_H;
delay_us(4); //6
}
void I2C_ACK(void)
{
I2C_SCL_L;
I2C_SDA_OUT();
I2C_SDA_L;
delay_us(2); //2
I2C_SCL_H;
delay_us(2); //5
I2C_SCL_L;
}
void I2C_NACK(void)
{
I2C_SCL_L;
I2C_SDA_OUT();
I2C_SDA_H;
delay_us(2); //2
I2C_SCL_H;
delay_us(2); //5
I2C_SCL_L;
}
u8 I2C_Wait_ACK(void)
{
u8 temp=0;
I2C_SDA_IN();
I2C_SDA_H;
delay_us(1); //1
I2C_SCL_H;
delay_us(1); //1
while(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA))
{
temp++;
if(temp>250)
{
I2C_STOP();
return 1; //返回值1 接收应答失败
}
}
I2C_SCL_L;
return 0;
}
void I2C_Send_BYTE(u8 txd)
{
u8 i=0;
I2C_SDA_OUT();
I2C_SCL_L;//拉低时钟初始
for(i=0;i<8;i++)
{
if((txd&0x80)>0)
I2C_SDA_H;
else
I2C_SDA_L;
txd<<=1;
delay_us(2);
I2C_SCL_H;
delay_us(2); //2
I2C_SCL_L;
delay_us(2); //2
}
}
u8 I2C_Read_BYTE(u8 ack)
{
u8 i=0;
u8 receive;
I2C_SDA_IN();
for(i=0;i<8;i++)
{
I2C_SCL_L;
delay_us(2); //5
I2C_SCL_H;
receive<<=1;
if(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA))
receive++;
delay_us(1); //5
}
if(ack==0)
I2C_NACK();
else
I2C_ACK();
return receive;
}[/mw_shl_code]
上面是I2C的代码
[mw_shl_code=c,true]u8 ADXL345_ReadOneByte(u8 addr)
{
u8 temp=0;
I2C_START();
I2C_Send_BYTE(0xA6);
I2C_Wait_ACK();
I2C_Send_BYTE(addr);
I2C_Wait_ACK();
I2C_START();
I2C_Send_BYTE(0xA7);
I2C_Wait_ACK();
temp = I2C_Read_BYTE(0);
I2C_STOP();
return temp;
}
void ADXL345_WriteOneByte(u8 addr,u8 data)
{
I2C_START();
I2C_Send_BYTE(0xA6);
if(I2C_Wait_ACK()==0)
{
I2C_Send_BYTE(addr);
if(I2C_Wait_ACK()==0)
I2C_Send_BYTE(data);
}
I2C_STOP();
delay_ms(10);
}
u8 ADXL345_init(void)
{
if(ADXL345_ReadOneByte(0x00)==0xE5)
{
ADXL345_WriteOneByte(0x2D,0x00); //设置芯片为待机模式
ADXL345_WriteOneByte(0x2C,0x0D); //带宽1600hz 输出速率3200hz
ADXL345_WriteOneByte(0x31,0x29); //低电平中断输出,10位全分辨率,输出数据右对齐,4g量程
ADXL345_WriteOneByte(0x2E,0x00); //中断不使能
ADXL345_WriteOneByte(0x1E,0x00); //X,Y,Z偏移
ADXL345_WriteOneByte(0x1F,0x00);
ADXL345_WriteOneByte(0x20,0x00);
ADXL345_WriteOneByte(0x2D,0x08); //测量模式
return 0;
}
return 1;
}
void ADXL345_Read_XYZ(short *x,short *y,short *z)
{
u8 BUF[2];
u8 i;
I2C_START();
I2C_Send_BYTE(0xA6); //发送写器件指令
I2C_Wait_ACK();
I2C_Send_BYTE(0x36); //发送寄存器地址(数据缓存的起始地址为0X32)
I2C_Wait_ACK();
//delay_us(2);
I2C_START(); //重新启动
I2C_Send_BYTE(0xA7); //发送读器件指令
I2C_Wait_ACK();
for(i=0;i<2;i++)
{
if(i==1)
BUF = I2C_Read_BYTE(0);
else
BUF = I2C_Read_BYTE(1);
}
I2C_STOP();
//*x=(short)(((u16)BUF[1]<<8)+BUF[0]);
//*y=(short)(((u16)BUF[3]<<8)+BUF[2]);
*z=(short)(((u16)BUF[1]<<8)+BUF[0]);
}[/mw_shl_code]
求各位帮帮忙了非常感谢! |