IIC

smallcracker 2021-02-26 00:00:00
Categories: Tags:

IIC

一、IIC介绍

I2C(Inter-Integrated Circuit)总线是80年代PHILIPS公司开发的两线式串行总线,如今已经成为芯片间低速串行通信的事实标准,被广泛使用在消费、控制类电子设备场合。这里的两个关键词两线和低速:
两线意味着结构简单,低速意味着好实现,做电路的都知道速度越慢电路实现起来就越容易,而且协议方式也很优雅。所以这是一个简单、优雅、好实现、应用又广泛的电路协议。

二、TM4C123GH6PM的I2C模块的特征

内部集成电路(I2C)总线通过一个两线设计(串行数据线 SDA 和串行时钟线 SCL)来提供双向数据传输,并且与外部 I2C 器件诸如串行存储器(RAM 和 ROM),网络设备,LCD,音频发生器等联系。I2C 总线也可用于产品开发和制造的系统测试和诊断的目的。TM4C123GH6PM 微控制器提供与其他 I2C 总线上的设备交互(发送和接收)的能力。TM4C123GH6PM 控制器的 I2C 模块具有以下特点:

  1. 当使用那些API操作I2C主机模块时,用户必须首先调用 I2CMasterInitExpClk()函数,这个函数可以设置总线速率、使能主机模块。
  2. 首先设置从机地址 I2CMasterSlaveAddrSet(),这个函数还可以用于设置定义是发送(向从机写)还是接收(从从机读)。
  3. 然后如果当前总线是一个多主机主线的话,我们这个主机要先调用l I2CMasterBusBusy()函数。这个函数可以确定这个主线忙不忙。
  4. 最后,如果是想发送数据,就调用I2CMasterDataPut()函数,可以将要传送的数据存入I2C主机数据寄存器中。I2CMasterControl()控制I2C主机的状态(也就是发送一个指令),这样的指令就能操纵总线,发送开始序列,发送从机地址和方向。剩余部分的传送可以通过轮询或者中断的方法来进行。下面是指令的内容
    IIC_CMD

    关于轮询模式和中断模式的介绍

    • For the single send and receive cases, the polling method involves looping on the return fromI2CMasterBusy(). Once that function indicates that the I2C master is no longer busy, the bus transaction has been completed and can be checked for errors using I2CMasterErr(). If there are no errors, then the data has been sent or is ready to be read using I2CMasterDataGet().
    • For the burst send and receive cases, the polling method also involves calling the I2CMasterControl() function for each byte transmitted or received (using either the I2C_MASTER_CMD_BURST_SEND_CONT or I2C_MASTER_CMD_BURST_RECEIVE_CONT commands), and for the last byte sent or received (using either the I2C_MASTER_CMD_BURST_SEND_FINISH or I2C_MASTER_CMD_BURST_RECEIVE_FINISH commands). If any error is detected during the burst transfer, the I2CMasterControl() function should be called using the appropriate stop command (I2C_MASTER_CMD_BURST_SEND_ERROR_STOP or I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP).
    • For the interrupt-driven transaction, the user must register an interrupt handler for the I2C devices and enable the I2C master interrupt; the interrupt occurs when the master is no longer busy.

    具体功能需结合数据手册的相应位查看
    I2C_MASTER_CMD_BURST_SEND_START
    起始信号+从机地址+应答+从机寄存器+应答
    I2C_MASTER_CMD_BURST_SEND_CONT
    数据+应答
    I2C_MASTER_CMD_BURST_SEND_FINISH
    I2C_MASTER_CMD_BURST_SEND_STOP
    停止信号
    I2C_MASTER_CMD_BURST_RECEIVE_START
    起始信号+从机地址+应答+从机寄存器+应答
    I2C_MASTER_CMD_BURST_RECEIVE_CONT
    接收数据+应答
    I2C_MASTER_CMD_BURST_RECEIVE_FINISH
    停止信号
    注意
    I2C_MASTER_CMD_SINGLE_SEND
    起始信号+从机地址+应答+数据+应答
    与I2C_MASTER_CMD_BURST_SEND_CONT区别:多了起始信号+从机地址+应答
    I2C_MASTER_CMD_SINGLE_RECEIVE
    起始信号+从机地址+应答+接收数据+应答
    同上!

    2.从机模式

    当使用I2C从机模式时,用户需要调用I2CSlaveInit()函数。这个函数可以使能I2C从机模块,初始化从机地址。然后,根据操作的不同,用户可以调用I2CSlaveDataPut()或者I2CSlaveDataGet()来完成传输。或者可以通过中断来完成传输操作。中断用I2CIntRegister()来注册

    五、驱动包含在 driverlib/i2c.c 和 driverlib/i2c.h 里

    六、例程

    这里先给出一个loopback的程序(无需连接外置I2C设备,自发自收)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    uint32_t pui32DataTx[NUM_I2C_DATA];
    uint32_t pui32DataRx[NUM_I2C_DATA];
    uint32_t ui32Index;
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    GPIOPinConfigure(GPIO_PB2_I2C0SCL);
    GPIOPinConfigure(GPIO_PB3_I2C0SDA);
    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
    I2CLoopbackEnable(I2C0_BASE);
    I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);
    I2CSlaveEnable(I2C0_BASE);
    I2CSlaveInit(I2C0_BASE, SLAVE_ADDRESS);
    I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, false);
    pui32DataTx[0] = 'I';
    pui32DataTx[1] = '2';
    pui32DataTx[2] = 'C';
    for(ui32Index = 0; ui32Index < NUM_I2C_DATA; ui32Index++){
    pui32DataRx[ui32Index] = 0;
    }
    for(ui32Index = 0; ui32Index < NUM_I2C_DATA; ui32Index++){
    I2CMasterDataPut(I2C0_BASE, pui32DataTx[ui32Index]);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_RREQ)){}
    pui32DataRx[ui32Index] = I2CSlaveDataGet(I2C0_BASE);
    while(I2CMasterBusy(I2C0_BASE)){}
    }
    for(ui32Index = 0; ui32Index < NUM_I2C_DATA; ui32Index++){
    pui32DataRx[ui32Index] = 0;
    }
    I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, true);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
    while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_TREQ)){}
    for(ui32Index = 0; ui32Index < NUM_I2C_DATA; ui32Index++){
    I2CSlaveDataPut(I2C0_BASE, pui32DataTx[ui32Index]);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
    while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_TREQ)){}
    pui32DataRx[ui32Index] = I2CMasterDataGet(I2C0_BASE);
    }

reference

简单优雅的总线协议——I2C
TM4C123Gx单片机之—-I2C接口笔记
TM4C123G 硬件I2C