裸机IIC协议-模拟IO驱动

裸机IIC协议-模拟IO驱动

  • IIC协议
    • IIC地址的确定
    • IIC读写数据
      • IIC时序
      • 参考代码
      • 读函数实现
      • 写函数实现
  • 实际注意

IIC协议

IIC也有叫I2C,是半双工的,不能同时收发,有SDA和CLK两条线,一条总线上可以挂载多个从设备,要求从设备地址不同。

IIC地址的确定

下面以BOSH的Gsensor的BMA253为例,来讲解IIC。

  1. 从BMA253的datasheet可知,通过IO接GND还是VDD可以得到不同的IIC地址,我实际是连接到GND,所以地址是0x18
    裸机IIC协议-模拟IO驱动_第1张图片
  2. 确定读写地址,主机在读从机设备数据时要发送读地址,写数据要发送写地址,有下图,地址是7bits地址码(7~6) + 1bit (0)读写位,BMA253 0代表写,1表示读; 确定写地址是:BMA253_WRITE 0x30,读地址:BMA253_READ 0x31裸机IIC协议-模拟IO驱动_第2张图片

IIC读写数据

IIC时序

具体IIC时序要求参考:https://blog.csdn.net/drivermonkey/article/details/7695547?utm_source=blogxgwz5

注意有4us和4.7us两个时间
裸机IIC协议-模拟IO驱动_第3张图片

参考代码

参考代码读取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需要做超时处理,防止从机故障没有回应,造成主机卡死;

你可能感兴趣的:(总线协议)