I2C
来源:互联网 发布:终端如何退出python 编辑:程序博客网 时间:2024/05/17 00:49
简介
I2C (Inter-Integrated Circuit) 总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。是微电子通信控制领域广泛采用的一种总线标准。它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高,传输距离短等特性。
- 7位或10位的地址空间
- 普通I2C总线速度为100kbit/s的标准模式和10kbit/s的低速模式,任意时钟频率
结构
两条接口线
- 串行数据线(SDA)
- 串行时钟线(SCL)
时序
主机信号时序: start + address-read/write + ACK + data + ACK + … + stop
主机信号时序: start + address-read + ACK + data + ACK + … + restart + adress-write + stop
I2C协议
总线协议分析
参考设计为使用串行数据线(SDA)和串行时钟线(SCL)、拥有7bit寻址空间的总线。
- 主机 - 产生时钟并发起与从机的通信
- 从机 - 接收时钟并响应主机的寻址
主机发送-从机接收
- 主机发送start信号,发送7bit从机地址和写控制位位(0)
- 从机响应start信号,匹配地址。如果匹配判断读/写标志位,从机发送ACK校验;如果地址不匹配,不发送ACK
- 主机发送1byte数据
- 从机接收数据,发送ACK校验;否则不发送ACK校验
- 重复3、4
- 主机发送stop信号,终止本次通信
主机接收-从机发送
- 主机发送start信号,发送7bit从机地址和写控制位(0)
- 从机相应start信号,匹配地址。如果匹配判断读写标志位,从机发送ACK校验;如果地址不匹配,不发送ACK
- 主机发送1byte数据
- 从机接收数据,并发送ACK校验;否则不发送ACK校验
- 重复3、4
- 主机发送restart信号,发送7bit从机地址和读控制位(1)
- 从机相应restart信号,并判断地址是否匹配。如果匹配判断读/写标志位,发送ACK校验信号。否则,不发送ACK校验
- 从机发送1byte数据
- 主机接收数据,并发送ACK校验
- 主机接收最后一位数据,发送NACK检验
- 主机发送stop信号,本次通信结束
#注:主机读取从机特定地址上的数据
I2C协议代码分析
开发环境
- 飞思卡尔FRDM-K64F开发板
- KDS3.2集成开发环境
- 飞思卡尔官方KSDK2.0开发库
- ubuntu16.04操作系统
代码实例
master主机
/* 产生start信号,发送地址数据,读/写操作 */result = I2C_MasterStart(I2C_MASTER, I2C_SLAVE_ADDR, kI2C_Write);/* 等待slave回复ACK信号 */while (I2C_MASTER->S & kI2C_ReceiveNakFlag);/* 发送数据 */result = I2C_MasterWriteBlocking(I2C_MASTER, masterTxBuffer, I2C_DATA_LEN);/* restart信号 */result = I2C_MasterRepeatedStart(I2C_MASTER, I2C_SLAVE_ADDR, kI2C_Read);/* 等待slave回复ACK信号 */while (I2C_MASTER->S & kI2C_ReceiveNakFlag);/* 读取数据 */I2C_MasterReadBlocking(I2C_MASTER, masterRxBuffer, 2 * sizeof(uint8_t));
slave从机
/* check stop flag */if (status & kI2C_StopDetectFlag) { I2C_SLAVE->S = kI2C_IntPendingFlag; I2C_SlaveClearStatusFlags(I2C_SLAVE, kI2C_StopDetectFlag); isStop = true; return ;}/* check start flag */if (status & kI2C_StartDetectFlag) { isStart = true; I2C_SLAVE->S = kI2C_IntPendingFlag; I2C_SlaveClearStatusFlags(I2C_SLAVE, kI2C_StartDetectFlag); if (!(status & kI2C_AddressMatchFlag)) { return; }}/* clear pending flag */I2C_SLAVE->S = kI2C_IntPendingFlag;/* check NAK */if (status & kI2C_ReceiveNakFlag) { /* nothing to do */ /* Receive mode */ I2C_SLAVE->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); I2C_SLAVE->D; PRINTF("NAK\r\n");}/* Slave address match */else if (status & kI2C_AddressMatchFlag) { if (status & kI2C_TransferDirectionFlag) { /* Slave transfer mode */ I2C_SLAVE->C1 |= I2C_C1_TX_MASK; isTransfer = true; } else { /* Slave recive mode */ I2C_SLAVE->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); I2C_SLAVE->D; isRecive = true; return; }}/* Transfer data */if (status & kI2C_TransferCompleteFlag) { /* Transmit data to master */ if (status & kI2C_TransferDirectionFlag) { I2C_SLAVE->D = slaveRxBuffer[1]; } else { /* Receive data from master */ slaveRxBuffer[receive_data_len] = I2C_SLAVE->D; receive_data_len++; }}
问题分析
I2C从机读取数据时,读取的第一字节数据总是为0x00。在KSDK2.0代码库中,I2C主机在读取数据之前,会先读取1byte的无效数据(Do dummy read),然后读取有效数据,KSDK库函数代码如下:
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize){ status_t result = kStatus_Success; volatile uint8_t dummy = 0; /* Add this to avoid build warning. */ dummy++; /* Wait until the data register is ready for transmit. */ while (!(base->S & kI2C_TransferCompleteFlag)) { } /* Clear the IICIF flag. */ base->S = kI2C_IntPendingFlag; /* Setup the I2C peripheral to receive data. */ base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); /* If rxSize equals 1, configure to send NAK. */ if (rxSize == 1) { /* Issue NACK on read. */ base->C1 |= I2C_C1_TXAK_MASK; } /* Do dummy read. */ dummy = base->D; while ((rxSize--)) { /* Wait until data transfer complete. */ while (!(base->S & kI2C_IntPendingFlag)) { } /* Clear the IICIF flag. */ base->S = kI2C_IntPendingFlag; /* Single byte use case. */ if (rxSize == 0) { /* Read the final byte. */ result = I2C_MasterStop(base); } if (rxSize == 1) { /* Issue NACK on read. */ base->C1 |= I2C_C1_TXAK_MASK; } /* Read from the data register. */ *rxBuff++ = base->D; } return result;}
0 0
- I2C
- I2C
- i2c
- I2C
- I2C
- i2c
- i2c
- I2C
- I2C
- I2c
- I2C
- I2C
- I2C
- I2C
- I2C
- i2c
- I2C
- i2c
- JS实现点击复选框变更DIV显示状态实例
- swift中UITextView的使用
- 让lua的gc替我们回收c的堆变量
- Til the Cows Come Home (Digkstra邻接矩阵裸模板)
- 枚举-生成元3.5Digit generator
- I2C
- Python练习实例16
- Objective-c - 构造方法(init方法)和init方法的重写
- SpringBoot Scala敏捷Web开发
- GOF23的一些总结(十五)
- 前端自学vs跟大神系统学?你看着办
- 聊天机器人学习笔记整理系列:POMDP-based Statistical Spoken Dialogue System: a Review
- I - Red and Black
- mongodb简单测试增删改查