当前位置: 首页 > article >正文

什么是IIC通信协议?

IIC(Inter-Integrated Circuit)通信协议,又称为I2C(Inter-Integrated Circuit 2)协议,是一种广泛使用的串行通信协议。它由飞利浦半导体公司(现NXP Semiconductors)开发,用于连接微控制器和其他设备,实现数据的串行传输。

IIC协议的基本原理

I2C协议使用两条线进行通信:数据线(SDA)和时钟线(SCL)。这两条线通过上拉电阻连接到电源,确保在空闲状态下保持高电平。I2C协议支持多主设备和多个从设备,通过每个设备的地址来区分通信目标。

IIC协议的关键特性

  1. 双向通信:I2C协议支持双向数据传输,即主设备可以发送数据给从设备,也可以从从设备接收数据。
  2. 多主模式:允许多个主设备连接到同一条总线上,通过仲裁机制来选择唯一的主设备进行通信。
  3. 多从模式:I2C总线可以连接多个从设备,每个从设备都有唯一的地址,主设备通过地址来选择要通信的从设备。
  4. 速率灵活:I2C总线的速率可以根据应用需求进行调整,常见的速率有100 kHz(标准模式)、400 kHz(快速模式)和3.4 MHz(高速模式)。
  5. 低成本:I2C总线只需要两根线进行通信,降低了硬件成本和复杂性。

IIC协议的应用场景

I2C协议被广泛应用于各种数字芯片间的通信,例如:

  • 传感器与微控制器之间的通信:如温度传感器、湿度传感器、加速度计等。
  • 存储器芯片:如EEPROM和RTC芯片,用于数据的读写和时钟管理。
  • 控制外设设备:如LED驱动器、LCD控制器、扩展IO芯片等。
  • 显示器控制器:如OLED显示屏、液晶显示模块等。
  • 工业自动化领域:如工业传感器、PLC等。

IIC协议的通信过程

I2C通信过程包括以下几个步骤:

  1. 起始信号:主设备发送一个起始信号,表示开始通信。
  2. 发送从设备地址:主设备发送从设备的地址和读/写位。
  3. 应答信号:从设备确认收到地址并发送应答信号。
  4. 数据传输:主设备和从设备之间进行数据的发送和接收。
  5. 停止信号:通信完成后,主设备发送停止信号,表示通信结束。

IIC协议的代码示例

以下是一个简单的I2C通信的代码示例,展示了如何使用STM32微控制器通过软件模拟I2C协议来读取AT24C02 EEPROM的数据。

#include "stm32f10x.h"
#include "delay.h"

#define I2C_SCL_PIN GPIO_Pin_6 // 定义SCL引脚
#define I2C_SDA_PIN GPIO_Pin_7 // 定义SDA引脚
#define I2C_SCL_PORT GPIOB // 定义SCL引脚所在的端口
#define I2C_SDA_PORT GPIOB // 定义SDA引脚所在的端口

// I2C延时函数
void I2C_Delay(void) {
    delay_us(5);
}

// I2C初始化函数
void I2C_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(I2C_SCL_PORT, &GPIO_InitStructure);
    
    // 释放总线
    I2C_SCL_PORT->BSRR = I2C_SCL_PIN;
    I2C_SDA_PORT->BSRR = I2C_SDA_PIN;
}

// I2C起始信号
void I2C_Start(void) {
    I2C_SDA_PORT->BSRR = I2C_SDA_PIN; // SDA高电平
    I2C_Delay();
    I2C_SCL_PORT->BSRR = I2C_SCL_PIN; // SCL高电平
    I2C_Delay();
    I2C_SDA_PORT->BRR = I2C_SDA_PIN; // SDA低电平,开始信号
    I2C_Delay();
    I2C_SCL_PORT->BRR = I2C_SCL_PIN; // SCL低电平
}

// I2C停止信号
void I2C_Stop(void) {
    I2C_SDA_PORT->BRR = I2C_SDA_PIN; // SDA低电平
    I2C_Delay();
    I2C_SCL_PORT->BSRR = I2C_SCL_PIN; // SCL高电平
    I2C_Delay();
    I2C_SDA_PORT->BSRR = I2C_SDA_PIN; // SDA高电平,停止信号
}

// I2C发送一个字节
void I2C_SendByte(uint8_t byte) {
    uint8_t i;
    for (i = 0; i < 8; i++) {
        I2C_SDA_PORT->BRR = I2C_SDA_PIN; // SDA低电平
        if (byte & 0x80) {
            I2C_SDA_PORT->BSRR = I2C_SDA_PIN; // SDA高电平
        }
        I2C_Delay();
        I2C_SCL_PORT->BSRR = I2C_SCL_PIN; // SCL高电平
        I2C_Delay();
        I2C_SCL_PORT->BRR = I2C_SCL_PIN; // SCL低电平
        byte <<= 1;
    }
    I2C_SDA_PORT->BSRR = I2C_SDA_PIN; // SDA释放,准备接收应答
    I2C_Delay();
    I2C_SCL_PORT->BSRR = I2C_SCL_PIN; // SCL高电平
    I2C_Delay();
    I2C_SCL_PORT->BRR = I2C_SCL_PIN; // SCL低电平
}

// I2C读取一个字节
uint8_t I2C_ReadByte() {
    uint8_t i, byte = 0;
    I2C_SDA_PORT->ODR &= ~I2C_SDA_PIN; // SDA输入模式
    for (i = 0; i < 8; i++) {
        byte <<= 1;
        I2C_SCL_PORT->BSRR = I2C_SCL_PIN; // SCL高电平
        I2C_Delay();
        if (I2C_SDA_PORT->IDR & I2C_SDA_PIN) {
            byte |= 0x01;
        }
        I2C_SCL_PORT->BRR = I2C_SCL_PIN; // SCL低电平
        I2C_Delay();
    }
    return byte;
}

// 从AT24C02读取一个字节数据
uint8_t AT24C02_ReadByte(uint16_t addr) {
    uint8_t data;
    I2C_Start();
    I2C_SendByte(0xA0 << 1); // 发送设备地址和写命令
    I2C_WaitAck();
    I2C_SendByte(addr >> 8); // 发送高地址字节
    I2C_WaitAck();
    I2C_SendByte(addr & 0xFF); // 发送低地址字节
    I2C_WaitAck();
    I2C_Start();
    I2C_SendByte(0xA1 << 1); // 发送设备地址和读命令
    I2C_WaitAck();
    data = I2C_ReadByte();
    I2C_Stop();
    return data;
}

int main(void) {
    I2C_Init();
    uint8_t data = AT24C02_ReadByte(0x00); // 从地址0x00读取数据
    // ... 其他操作
    while (1) {
        // ... 主循环
    }
}

以上代码展示了如何初始化I2C接口,发送起始和停止信号,以及如何发送和接收数据。在实际应用中,可能需要根据具体的硬件连接和设备地址进行适当的调整。通过理解和掌握I2C协议的原理和编程方法,可以实现微控制器与其他设备的高效通信。

✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进

❤欢迎关注我的知乎:对error视而不见

代码获取、问题探讨及文章转载可私信。

☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。

🍎获取更多嵌入式资料可点击链接进群领取,谢谢支持!👇

点击领取更多详细资料


http://www.kler.cn/news/327095.html

相关文章:

  • JAVA姓氏头像情侣头像家庭头像签名头像谐音顽埂头像设计小程序头像大全系统小程序源码
  • sentinel2 L2A处理基线04.00 反射率计算方法
  • 【MySQL】视图和触发器
  • 使用代理爬取数据需要筛选合适的ip吗
  • C++11 多线程编程-小白零基础到手撕线程池
  • 【VUE】案例:商场会员管理系统
  • find()和findIndex()方法
  • 微信小程序——音乐播放器
  • 【有啥问啥】二分图(Bipartite Graph)算法原理详解
  • SpringMVC源码-AbstractUrlHandlerMapping处理器映射器将实现Controller接口的方式定义的路径存储进去
  • 健康生活,从日常细节开始
  • NVLM多模态 LLM 在图像和语言任务中的表现优于 GPT-4o
  • Oracle数据恢复—异常断电导致Oracle数据库报错的数据恢复案例
  • 第167天:应急响应-日志自动提取分析项目_ELK_Logkit_LogonTracer_Anolog等
  • Mysql高级篇(下)——日志
  • Microsoft Edge 五个好用的插件
  • MySQL存储过程循环操作
  • LVGL 笔记
  • SpringBoot3+Swagger3(最新版springdoc-openapi教程)
  • 组合优化与凸优化 学习笔记5 对偶拉格朗日函数
  • 21 vue3之发布npm插件(hook自定义指令)
  • 国产RISC-V案例分享,基于全志T113-i异构多核平台!
  • 【刷题6】一维前缀和、二维前缀和
  • 学习VTK的目的和方法
  • 速盾:cdn加速什么好?
  • 【Linux探索学习】第二弹——Linux的基础指令(中)——夯实基础第二篇
  • 25考研咨询周开启,西安电子科技大学是否改考408??
  • HarmonyOS Next系列之水波纹动画特效实现(十三)
  • ClickHouse入库时间与实际相差8小时问题
  • 升级FreeBSD13.2到14.1-RELEASE