IIC协议
IIC也有叫I2C,是半双工的,不能同时收发,有SDA和CLK两条线,一条总线上可以挂载多个从设备,要求从设备地址不同。
IIC地址的确定
下面以BOSH的Gsensor的BMA253为例,来讲解IIC。
- 从BMA253的datasheet可知,通过IO接GND还是VDD可以得到不同的IIC地址,我实际是连接到GND,所以地址是0x18;
- 确定读写地址,主机在读从机设备数据时要发送读地址,写数据要发送写地址,有下图,地址是7bits地址码(7~6) + 1bit (0)读写位,BMA253 0代表写,1表示读; 确定写地址是:BMA253_WRITE 0x30,读地址:BMA253_READ 0x31;
IIC读写数据
IIC时序
具体IIC时序要求参考:https://blog.csdn.net/drivermonkey/article/details/7695547?utm_source=blogxgwz5
注意有4us和4.7us两个时间
参考代码
参考代码读取BMA253的chip id,在写BMA253的寄存器进行芯片初始化;
参考代码不介绍硬件的IO设置,比如设置IO输入输出等;
if (BMA253_RD_Reg(BMA2x2_CHIP_ID_ADDR) == 0xFA)
{
BMA253_WR_Reg(0x14, 0xb6); // BMA2x2_RST_ADDR
BMA253_WR_Reg(0x28, 0x03); // BMA2x2_SLOPE_THRES_ADDR
BMA253_WR_Reg(0x27, 0x00); //BMA2x2_SLOPE_DURN_ADDR
BMA253_WR_Reg(0x16, 0x07); //BMA2x2_INTR_ENABLE1_ADDR
BMA253_WR_Reg(0x19, 0x04); //BMA2x2_INTR1_PAD_SELECT_ADDR
BMA253_WR_Reg(0x0f, 0x03); //BMA2x2_RANGE_SELECT_ADDR
BMA253_WR_Reg(0x10, 0x0b); //BMA2x2_BW_SELECT_ADDR
bma253_suspend_mode();
}
读函数实现
下图是BMA253_RD_Reg的实现,使用IIC读取一个char,我使用的是MSP430,主频1MHz,一个机器周期就5us多,所以没有使用delay;
unsigned char BMA253_RD_Reg(unsigned char addr)
{
unsigned char temp = 0;
I2CStart();
I2CSendByte(BMA253_WRITE); // 假写
I2CReceiveACK();
I2CSendByte(addr); // 假写是为了传入的地址
I2CReceiveACK();
I2CStart();
I2CSendByte(BMA253_READ);
I2CReceiveACK();
temp = I2CReceiveByte();
I2CStop();
return temp;
}
写函数实现
参考代码写了BMA253多个寄存器,主要是为了初始化芯片,具体BMA253_WR_Reg实现如下:
void BMA253_WR_Reg(unsigned char addr, unsigned char val)
{
I2CStart();
I2CSendByte(BMA253_WRITE);
I2CReceiveACK();
I2CSendByte(addr);
I2CReceiveACK();
I2CSendByte(val);
I2CReceiveACK();
I2CStop();
}
实际注意
对于ACK需要做超时处理,防止从机故障没有回应,造成主机卡死;