一、简介

由飞利浦主导开发的片间互联协议。iic通信使用三线(sda scl以及gnd,不包括电源线),极大程度上减少了对ic的io口的占用。同时iic支持多主机以及多从机,方便了程序的设计。

二、协议层简介

在iic总线上scl的电平决定了整条iic总线的有效性。
当scl出于高电平时,主机与从机可以侦测sda数据的变化,sda上的数据有效。当scl出于低电平时sda线无效,目标准备读取下一位数据。
在iic总线上,一共有四种状态:起始,0/应答,1/非应答,结束 在scl线处于高电平的状态下,这四种状态对应的sda的状态分别是: 起始: sda产生下降沿 0/ack: sda处于低电平 1/nack:sda处于高电平 结束: sda产生上升沿 同时,在iic总线启动后以及一轮通信结束后,需要将scl置1,便于其他设备快速发起以及响应iic请求。而在通信中,scl要在读取前与读取后及时置0,便于目标设备读取下一位数据。

iic帧格式
首先是起始信号,通知各设备开始传输。随后是1byte的目标设备的地址(准确的说,是7位地址加上一个读写控制位)。然后由目标设备给出ack。在主机收到ack后,可进行对应数据的读取。在数据传输部分,根据iic协议规定,每次只允许连续传输1byte,也即随后需要有一方及时给出ack,否则将超时终止传输(包括nack)。所有数据传输完毕后,主机设置结束信号。
在一次通信中,如果需要转变读写状态,需要主机重新发送起始信号、目标地址与读写状态。

三、参考实现:

基于stm32f103c6t6 HAL编写
iic.c

#include "iic.h"//private functions void sda(uint8_t sta) {    HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, sta ? GPIO_PIN_SET : GPIO_PIN_RESET);    for (int i = 0;i < 100;i++);//delay}void scl(uint8_t sta) {    HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, sta ? GPIO_PIN_SET : GPIO_PIN_RESET);    for (int i = 0;i < 100;i++);}void signal(uint8_t sig) {    sda(sig);    scl(0);    scl(1);    scl(0);}//public functionsHAL_StatusTypeDef iic_st(void) {    sda(1);//startup    scl(1);    sda(0);    scl(0);    return HAL_OK;}HAL_StatusTypeDef iic_ed(void) {    scl(0);//end    sda(0);    scl(1);    sda(1);    return HAL_OK;}HAL_StatusTypeDef iic_tx(uint8_t data) {    for (int i = 0;i > 7);        data <= 0;i--) {        scl(1);        pin_sta = HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin);        data += pin_sta<<i;        scl(0);    }    *pdata = data;    return HAL_OK;}HAL_StatusTypeDef iic_wait_ack(void) {    uint8_t t = 0xff;        scl(0);    sda(1);    scl(1);    while (t--) {        if (HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin) == GPIO_PIN_RESET) {            scl(0);            return HAL_OK;        }    }    iic_ed();    return HAL_TIMEOUT;}HAL_StatusTypeDef iic_send_ack(uint8_t ack) {    signal(ack);    return HAL_OK;}

iic.h

#ifndef __IIC_H__#define __IIC_H__#include "stm32f1xx_hal.h"#define SDA_Pin GPIO_PIN_8#define SDA_GPIO_Port GPIOB#define SCL_Pin GPIO_PIN_9#define SCL_GPIO_Port GPIOBHAL_StatusTypeDef iic_st(void);HAL_StatusTypeDef iic_ed(void);HAL_StatusTypeDef iic_tx(uint8_t data);HAL_StatusTypeDef iic_rx(uint8_t* data);HAL_StatusTypeDef iic_wait_ack(void);HAL_StatusTypeDef iic_send_ack(uint8_t ack) ;#endif