一、简介
由飞利浦主导开发的片间互联协议。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 > 7);
data = 0;i--) {
scl(1);
pin_sta = HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin);
data += pin_sta
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 GPIOB
HAL_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