I2C主控器规范文档

需积分: 17 4 下载量 23 浏览量 更新于2024-07-20 收藏 207KB PDF 举报
"I2C主控制器规范" I2C(Inter-Integrated Circuit)是一种由Philips(现NXP Semiconductors)开发的两线式串行总线,用于在微控制器和其他电子设备之间进行低速通信。这个规范,"I2C-MasterCore Specification",是由Richard Herveille编写的,详细阐述了如何设计和实现一个I2C主控制器。以下是该文档的一些关键知识点: 1. **I2C总线协议**:I2C协议定义了两个主设备和多个从设备之间的通信方式。主设备发起传输,从设备响应。数据在总线上以时钟同步的方式传输,通过两条线——SCL(时钟)和SDA(数据)。 2. **主控制器功能**:I2C-MasterCore是主设备的硬件实现,负责生成时钟信号、控制数据传输的方向以及处理从设备的响应。它支持多种操作,如启动、停止、读写数据、地址从设备等。 3. **编程示例**:文档中的"Programming Examples"部分提供了如何与I2C-MasterCore交互的实际代码片段,这对于理解和调试I2C通信至关重要。 4. **核心更新历史**:文档的修订历史展示了设计的演进过程,包括添加BUSY位(状态寄存器)、支持ASIC的I2C IO更改、对FPGA IO的注释,以及数据总线宽度从n位扩展到8位等改进。 5. **状态寄存器**:BUSY位的添加表明主控制器当前是否正在进行I2C通信,这对于软件控制和错误检测非常有用。 6. **ASIC和FPGA支持**:I2C-MasterCore的设计考虑了ASIC和FPGA两种不同的硬件平台,这意味着它可以被集成到不同类型的集成电路设计中。 7. **多主设备能力**:版本0.8中增加了对多主设备环境的支持,这是I2C协议的一个重要特性,允许多个主设备共享总线,并通过仲裁机制决定谁可以控制传输。 8. **时序图**:新的时序图提供了更清晰的视觉表示,帮助理解数据在不同I2C操作中的传输方式,例如开始条件、停止条件、应答和非应答等。 9. **预分频器寄存器公式**:在版本0.7中,预分频器寄存器的计算公式有所变化,这可能涉及到调整I2C总线的传输速度。 10. **地址编码**:例如,文档在版本0.9中修正了示例1中的地址从0x5C更改为0xAC,确保了正确通信。 "I2C-MasterCore Specification"是一个深入的技术文档,详细描述了I2C主控制器的实现细节,对于设计和使用I2C接口的工程师来说,这是一个宝贵的参考资料。

#include "i2c.h"#define I2C_SPEED 100000 // I2C总线速度,单位为Hzvoid i2c_init(void){ GPIO_InitTypeDef GPIO_InitStruct; I2C_InitTypeDef I2C_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能GPIOB时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); // 使能I2C1时钟 // 配置GPIOB6和GPIOB7为复用推挽输出 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStruct); // 配置I2C1为标准模式,时钟速度为100kHz I2C_InitStruct.I2C_Mode = I2C_Mode_I2C; I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStruct.I2C_OwnAddress1 = 0x00; I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStruct.I2C_ClockSpeed = I2C_SPEED; I2C_Init(I2C1, &I2C_InitStruct); I2C_Cmd(I2C1, ENABLE); // 使能I2C1}void i2c_write(uint8_t addr, uint8_t *data, uint16_t len){ uint32_t timeout = 0; while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) { if (++timeout > 0x10000) return; } I2C_GenerateSTART(I2C1, ENABLE); timeout = 0; while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) { if (++timeout > 0x10000) return; } I2C_Send7bitAddress(I2C1, addr << 1, I2C_Direction_Transmitter); timeout = 0; while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if (++timeout > 0x10000) return; } while (len--) { I2C_SendData(I2C1, *data++); timeout = 0; while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { if (++timeout > 0x10000) return; } } I2C_GenerateSTOP(I2C1, ENABLE);}void i2c_read(uint8_t addr, uint8_t *data, uint16_t len){ uint32_t timeout = 0; while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) { if (++timeout > 0x10000) return; } I2C_GenerateSTART(I2C1, ENABLE); timeout = 0; while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) { if (++timeout > 0x10000) return; } I2C_Send7bitAddress(I2C1, addr << 1, I2C_Direction_Receiver); timeout = 0; while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) { if (++timeout > 0x10000) return; } while (len--) { if (len == 0) I2C_AcknowledgeConfig(I2C1, DISABLE); timeout = 0; while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) { if (++timeout > 0x10000) return; } *data++ = I2C_ReceiveData(I2C1); } I2C_AcknowledgeConfig(I2C1, ENABLE); I2C_GenerateSTOP(I2C1, ENABLE);}

2023-05-30 上传