I2C协议应用(嵌入式学习)

news2024/11/15 14:07:48

I2C协议&应用

  • 0. 前言
  • 1. 概念
  • 2. 特点&工作原理
  • 3. 应用示例代码
    • 模板
    • HAL模板

0. 前言

I2C是Inter-Integrated Circuit的缩写,它是一种广泛使用的串行通信协议。它由飞利浦(现在是NXP Semiconductors)开发,并已成为各种电子设备中集成电路(IC)之间通信的标准。

I2C是一种由两根线组成的接口,分别是串行数据线(SDA)和串行时钟线(SCL)。多个设备可以连接到同一总线上,每个设备都有一个唯一的地址,用于与总线上特定设备进行通信。
在这里插入图片描述

I2C协议支持主设备和从设备。主设备发起通信并生成时钟信号,而从设备则响应主设备的命令或请求。主设备可以向从设备传输数据,也可以从从设备接收数据。

与SPI或UART等其他协议相比,I2C支持的通信速度相对较低,但实现起来简单,并且需要较少的引脚,适用于需要简化和限制连接数的应用。
在这里插入图片描述

I2C的一些常见用途包括微控制器与传感器、执行器、EEPROM、实时时钟、显示控制器等外围设备之间的通信。许多集成电路(IC)例如温度传感器、加速度计和数字电位器,都内置了I2C接口,便于集成到电子系统中。

总的来说,I2C是一种流行且多用途的串行通信协议,提供了一种方便的方式,用于在各种电子设备中连接和通信不同的集成电路。

1. 概念

在这里插入图片描述

I2C(Inter-Integrated Circuit)协议是一种串行通信协议,用于在集成电路之间进行数据传输和通信。以下是I2C协议的一些关键概念:

  1. 总线架构:I2C协议使用两根线构成的总线来连接多个设备。这两根线分别是串行数据线(SDA)和串行时钟线(SCL)。所有设备共享这两根线,并且每个设备都有一个唯一的地址。

  2. 主从结构:I2C通信中有一个主设备和一个或多个从设备。主设备负责控制通信的发起和时钟信号的生成,而从设备响应主设备的指令或请求。

  3. 起始和停止条件:I2C通信以起始条件和停止条件来标识数据传输的开始和结束。起始条件是SDA线从高电平切换到低电平,而SCL线保持高电平。停止条件是SDA线从低电平切换到高电平,而SCL线保持高电平。

  4. 数据传输:在I2C协议中,数据以字节为单位传输。每个字节都由8个位组成,其中最高位是起始位(Start Bit)或停止位(Stop Bit),而剩余的7个位是数据位。数据传输可以是主设备向从设备发送数据,或者从设备向主设备发送数据。

  5. 设备地址:每个从设备在总线上都有一个唯一的地址,用于主设备识别和选择与之通信的设备。设备地址的长度可以是7位或10位,具体取决于使用的I2C协议版本。

  6. 时钟同步:I2C协议使用时钟同步机制来确保通信的可靠性。主设备在SCL线上生成时钟信号,指示数据的传输速率。从设备根据主设备提供的时钟信号进行数据采样和发送。

  7. 数据确认:在每个字节的传输之后,接收设备需要向发送设备发送一个数据确认信号(ACK/NACK)。ACK表示数据接收成功,NACK表示数据接收失败或设备不可用。

I2C协议的灵活性和可靠性使其成为连接和通信集成电路之间的常用选择,广泛应用于各种电子设备和系统中。

2. 特点&工作原理

I2C(Inter-Integrated Circuit)是一种串行通信协议,用于在集成电路之间进行数据传输。它由飞利浦(Philips)公司开发,现在已经成为一种广泛使用的标准。I2C协议使用两根信号线,一根是时钟线(SCL,Serial Clock),另一根是数据线(SDA,Serial Data)。
在这里插入图片描述

以下是I2C协议的基本特点和工作原理:

  1. 主从结构:I2C协议使用主从结构,其中主设备(Master)负责发起通信和控制数据传输,从设备(Slave)则被动地响应主设备的命令或请求。

  2. 地址:每个I2C设备都有一个唯一的地址,用于在总线上进行识别和寻址。主设备通过发送设备地址来选择要与之通信的从设备。

  3. 传输模式:I2C协议支持两种传输模式:传输字节(Byte Transfer)和传输位(Bit Transfer)。在字节传输模式下,数据按字节传输,每个字节后跟一个应答位。在位传输模式下,数据以位为单位传输,速度更快,但复杂度也更高。

  4. 起始和停止条件:每次数据传输的开始和结束都由起始条件和停止条件来标识。起始条件是SCL线为高电平时,SDA线由高电平转为低电平;停止条件是SCL线为高电平时,SDA线由低电平转为高电平。

  5. 传输速率:I2C协议支持多种传输速率,如标准模式(100 kbps)、快速模式(400 kbps)和高速模式(3.4 Mbps)。具体的速率取决于总线的电气特性和设备的支持能力。

  6. 碰撞检测:I2C协议通过检测数据线上的电平来实现碰撞检测。如果两个设备同时尝试在同一时间传输数据,会导致数据线上电平的冲突,这时协议会检测到碰撞,并且通信将会停止。

I2C协议在许多应用中被广泛使用,如传感器、存储器、显示屏等。它提供了一种简单而灵活的方式来连接多个设备,并实现它们之间的数据交换。

3. 应用示例代码

模板

以下是一个简单的示例,可帮助你开始编写I2C通信的程序。请注意,此示例基于ARM Cortex-M微控制器,并使用Keil MDK-ARM开发环境。

#include <stm32f4xx.h>  // 替换为适合你的目标芯片的头文件

// 定义I2C设备地址
#define I2C_ADDRESS 0x50

// 初始化I2C总线
void I2C_Init(void)
{
    // 配置GPIO引脚为I2C模式
    // ...

    // 配置I2C外设
    // ...
}

// 启动I2C传输
void I2C_Start(void)
{
    // 生成起始条件(START)
    // ...
}

// 停止I2C传输
void I2C_Stop(void)
{
    // 生成停止条件(STOP)
    // ...
}

// 发送一个字节的数据
void I2C_SendByte(uint8_t data)
{
    // 发送数据
    // ...
}

// 从I2C接收一个字节的数据
uint8_t I2C_ReceiveByte(void)
{
    // 接收数据
    // ...
    // 返回接收到的数据
    return data;
}

int main(void)
{
    // 初始化I2C总线
    I2C_Init();

    while (1)
    {
        // 启动I2C传输
        I2C_Start();

        // 发送数据
        I2C_SendByte(I2C_ADDRESS);
        I2C_SendByte(0x01); // 发送要读取的寄存器地址

        // 重新启动I2C传输
        I2C_Start();

        // 发送数据
        I2C_SendByte(I2C_ADDRESS | 0x01); // I2C_ADDRESS + 读取位

        // 接收数据
        uint8_t receivedData = I2C_ReceiveByte();

        // 停止I2C传输
        I2C_Stop();

        // 处理接收到的数据
        // ...
    }
}

请注意,上述代码仅为示例,需要根据目标芯片和硬件配置进行适当修改。你需要根据你的具体情况配置正确的GPIO引脚和I2C外设寄存器。此外,I2C的初始化、起始条件、停止条件、发送数据和接收数据的具体实现取决于你所使用的芯片和I2C外设。因此,在编写完整的I2C代码之前,请参考芯片和外设的参考手册,以确保正确配置和操作I2C总线。

HAL模板

以下是用于在STM32微控制器上使用I2C协议进行数据传输。请确保你在KEIL5中创建了适当的STM32项目,并正确配置了I2C外设和相关引脚。

#include "stm32f4xx.h"

#define I2C_SCL_PIN     GPIO_PIN_6
#define I2C_SDA_PIN     GPIO_PIN_7
#define I2C_GPIO_PORT   GPIOB

#define I2C_SLAVE_ADDRESS   0xA0

I2C_HandleTypeDef I2C_Handle;

void I2C_Configuration(void)
{
  // 初始化I2C外设时钟
  __HAL_RCC_I2C1_CLK_ENABLE();
  
  // 初始化GPIO时钟
  __HAL_RCC_GPIOB_CLK_ENABLE();
  
  // 配置I2C引脚为复用功能
  GPIO_InitTypeDef GPIO_InitStruct;
  GPIO_InitStruct.Pin = I2C_SCL_PIN | I2C_SDA_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
  HAL_GPIO_Init(I2C_GPIO_PORT, &GPIO_InitStruct);
  
  // 配置I2C外设
  I2C_Handle.Instance = I2C1;
  I2C_Handle.Init.ClockSpeed = 100000;  // 设置I2C总线速度为100 kHz
  I2C_Handle.Init.DutyCycle = I2C_DUTYCYCLE_2;
  I2C_Handle.Init.OwnAddress1 = I2C_SLAVE_ADDRESS;
  I2C_Handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  I2C_Handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  I2C_Handle.Init.OwnAddress2 = 0;
  I2C_Handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  I2C_Handle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  HAL_I2C_Init(&I2C_Handle);
  
  // 使能I2C外设
  HAL_I2C_Enable(&I2C_Handle);
}

void I2C_WriteByte(uint8_t address, uint8_t data)
{
  // 等待I2C总线空闲
  while (HAL_I2C_GetState(&I2C_Handle) != HAL_I2C_STATE_READY);
  
  // 发送起始条件
  HAL_I2C_Master_Transmit(&I2C_Handle, address, &data, 1, HAL_MAX_DELAY);
  
  // 等待数据传输完成
  while (HAL_I2C_GetState(&I2C_Handle) != HAL_I2C_STATE_READY);
  
  // 发送停止条件
  HAL_I2C_Stop(&I2C_Handle);
}

以上示例代码演示了如何配置I2C外设和GPIO引脚,并使用HAL库函数进行数据传输。你可以根据自己的需求进行修改和扩展。记得在主函数中调用I2C_Configuration()进行初始化,并调用I2C_WriteByte()发送数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/684187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无迹卡尔曼滤波在目标跟踪中的作用(一)

在前一节中&#xff0c;我们介绍了扩展卡尔曼滤波算法EKF在目标跟踪中的应用&#xff0c;其原理是 将非线性函数局部线性化&#xff0c;舍弃高阶泰勒项&#xff0c;只保留一次项 &#xff0c;这就不可避免地会影响结果的准确性&#xff0c;除此以外&#xff0c;实际中要计算雅各…

软件测试面试试卷,答对90%直接入职大厂

一&#xff0e;填空 1、 系统测试使用&#xff08; C &#xff09;技术, 主要测试被测应用的高级互操作性需求, 而无需考虑被测试应用的内部结构。 A、 单元测试 B、 集成测试 C、 黑盒测试 D、白盒测试 2、单元测试主要的测试技术不包括&#xff08;B &…

Linux 如何刷新 DNS 缓存

Linux 如何刷新 DNS 缓存 全文&#xff1a;如何刷新 DNS 缓存 (macOS, Linux, Windows) Unix Linux Windows 如何刷新 DNS 缓存 (macOS, FreeBSD, RHEL, CentOS, Debian, Ubuntu, Windows) 请访问原文链接&#xff1a;https://sysin.org/blog/how-to-flush-dns-cache/&#…

Elasticsearch:install

ElasticSearch Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。 Elasticsearch结合Kibana、Logstash、Beats&#xff0c;也就是elastic stack(ELK)。被广泛应用在日志分析、实时监控&#xff08;CPU、Memory、Program&#xff09;等领域。 elasticsearch是…

【Linux 驱动篇(一)】字符设备驱动开发

文章目录 一、字符设备驱动简介二、字符设备驱动开发步骤1. 驱动模块的加载和卸载2. 字符设备注册与注销3. 实现设备的具体操作函数3.1 能够对 chrtest 进行打开和关闭操作3.2 对 chrtest 进行读写操作 4. 添加 LICENSE 和作者信息 三、Linux 设备号1. 设备号的组成 一、字符设…

网工内推 | 2023应届生专场,上市公司招网工,CCNP以上认证优先

01 浙江宇视科技有限公司 招聘岗位&#xff1a;IT网络工程师 职责描述&#xff1a; 1、负责公司内部核心网络建设&#xff0c;进行网络架构的规划、设计、调整、性能优化&#xff1b; 2、负责公司网络环境的管理&#xff0c;配置&#xff0c;监控、排错&#xff0c;维护&#…

津津乐道设计模式 - 适配器模式详解(家里电器电源标准不统一的问题都解决了)

&#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Micro麦可乐的博客 &#x1f425;《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程&#xff0c;入门到实战 &#x1f33a;《RabbitMQ》…

Servlet 相关内容

1. Servlet 1.1 Servlet概述 Servlet 是 SUN 公司提供的一套规范&#xff0c;名称就叫 Servlet 规范&#xff0c;它也是 JavaEE 规范之一&#xff0c;可以通过API来学习。目前在Oracle官网中的最新版本是JavaEE8&#xff0c;该网址中介绍了JavaEE8的一些新特性。当然&#xff…

【C语言初阶】带你轻松玩转所有常用操作符(2) ——赋值操作符,单目操作符

君兮_的个人主页 勤时当勉励 岁月不待人 C/C 游戏开发 Hello,这里是君兮_&#xff0c;今天给大家带来的是有关操作符的第二部分内容&#xff0c;废话不多说&#xff0c;咱们直接开始吧&#xff01; 在正式开始之前&#xff0c;我们还是借助一张思维导图帮助大致简单回忆一下有…

Docker-compose的使用

目录 Docker-compose 简介 docker-compose的安装 docker-compose.yaml文件说明 compose的常用命令 总结 Docker-compose 简介 Docker-compose 是用于定义和运行多容器的 Docker 应用程序的工具。可以使用YAML文件来配置应用程序的服务。&#xff08;通俗讲是可以通过yml文…

LeetCode108-将有序数组转换为二叉搜索树

题目来源 108. 将有序数组转换为二叉搜索树 - 力扣&#xff08;LeetCode&#xff09; 题目 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵高度平衡 二叉搜索树。 高度平衡二叉树是一棵满足「每个节点的左右两个子树的高度差的…

智慧地下采矿,“像素游戏”智能呈现

在这个像素世界里&#xff0c;我们需要一个智能地下采矿可视化综合管理平台&#xff0c;来帮助我们管理和监控地下采矿全流程。 图扑软件依托自主研发的 HT for Web 产品&#xff0c;结合三维定制化渲染、动态模拟、物理碰撞、5G、物联网、云计算及大数据等先进技术&#xff0c…

从零开始理解Linux中断架构(8)---执行上下文之CPU上下文

1 CPU上下文的来由 CPU上下文是切换任务到CPU时需要保存和恢复的CPU寄存器。ARM64需要保存的寄存器如下图所示 X19-X29作为CPU上下文的依据是什么? 实际上这里使用了一个隐含的事实:Linux所有的任务切换都是在内核中__switch_to函数中进行的,当前任务通过__…

KubeSphere 社区双周报 | OpenFunction 发布 v1.1.1 | 2023.6.9-6.22

KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过 commit 的贡献者&#xff0c;并对近期重要的 PR 进行解析&#xff0c;同时还包含了线上/线下活动和布道推广等一系列社区动态。 本次双周报涵盖时间为&#xff1a;2023.6.9-6.22。 …

Elisp之定时器run-with-timer、run-with-idle-timer、run-at-time 区别(二十二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

libevent(11)libevent中的循环和退出函数

一、libevent基本原理介绍 一个 event_base 对象相当于一个 Reactor 实例&#xff08;不了解Reactor的读者可自行查询相关文章&#xff09;。libevent默认情况下是单线程的&#xff0c;每个线程有且只有一个event_base&#xff0c;对应一个struct event_base结构体以及附于其上…

由于找不到msvcp120.dll无法继续执行代码怎么办?

msvcp120.dll是微软软件包的一部分。它是一个库文件&#xff0c;可用于支持软件运行时&#xff0c;msvcp120.dll的作用是提供计算机程序所需的标准库&#xff0c;msvcp120.dll还负责管理堆内存、线程和异常处理函数等。在使用windows编写的应用程序中&#xff0c;通常需要使用此…

android 如何分析应用的内存(八)——malloc debug

android 如何分析应用的内存&#xff08;八&#xff09; 接上文&#xff0c;介绍六大板块中的第三个————malloc调试和libc回调 上一篇文章中&#xff0c;仅仅是在分配和释放的时候&#xff0c;拦截对应的操作。而不能进一步的去检查内存问题。比如&#xff1a;释放之后再…

深入理解Android Jetpack Compose的Box

Box是一个提供了一种快速、简便的方式来对其子元素进行层叠布局的布局组件。 一、什么是Box? 二、如何使用Box? 三、Box中的contentAlignment属性 四、使用Modifier在Box内进行更复杂的布局 一、什么是Box? 在Compose中&#xff0c;Box是一个简单的布局组件&#xff0c…

如何写出高效、准确的会议记录?

在企业或组织中&#xff0c;会议是一种常见的沟通和决策方式。作为参会人员之一&#xff0c;撰写一份高效、准确的会议记录显得尤为重要。会议记录不仅记录了会议的主题、议题和讨论结果&#xff0c;还能帮助参与者回顾会议过程、梳理思路、明确职责&#xff0c;同时也为后续工…