I2C总线协议

2023-05-16

毕业设计中使用到了AT24C04器件,其是Ateml公司出品的,是一种低功耗CMOS串行EEPROM,其使用两线串行的总线和控制器进行通讯。其内部保存的数据在掉电的情况下可以有40年以上的有效期。其采用8 脚的DIP 封装,易于使用。简单来说,AT24C02是一款能在断电的情况下依然能够长时间存储数据的芯片。

可以使用I2C协议总线与AT24C04进行交互。

I2C

I2C总线协议概论

I2C总线是一种由数据线SDA和时钟SCL构成的按串行方式传输的数据总线。所有需要通信的设备都挂载在总线上,但就像计算机网络一样,只有知道正确的IP地址,数据的传输才能正常工作,所以被控电路都拥有唯一的地址。在数据的传输过程中,I2C总线上挂载的每一模块即可以作为主控器,也可以作为接收器,如果它发起通信则是主控器,否则为接收器。主控器发出的信号分为两部分,一部分为地址码,其用来选址,即告诉总线主控器需要和那个设备通信,和操作是读还是写,另一部分为控制量,其为具体的数据,由具体设备和应用程序决定。这样,控制电路虽然挂载在同一条总线上,但是他们之间身份明确,操作互不影响。

基本工作过程

写通讯过程:
1. 如果检测到当前的总线处于空闲状态,如果一个器件想作为一个主控器与其他设备通信,那么它就需要发送一个启动信号来掌握总线;
2. 在设备掌握总线后,成为主控器,那么它就需要发送一个地址字节,高7位地址为需要通信设备的地址,低一位为写控制位;
3. 总线中的一个设备如果检测到主控器发送的地址与自己的地址一致,其就是被控器,那么他就需要回复主控器应答信号(ACK),表示可以进行下一步操作;
4. 当主控收到被控器回复的ACK后就可以开始发送数据字节;
5. 当被控器成功接收了数据后需要向主控器发送一个ACK信号,来向表示主控器前一个字节接收完成,可以继续传送下一个字节数据,如果没有ACK命令,则说明数据接收不成功;
6.一旦主控器完成全部数据发送后,立刻发送停止信号,表示整个通讯过程结束并且释放总线,这样其他的设备可以再使用这条总线。

读通讯过程:
1. 如果检测到当前的总线处于空闲状态,如果一个器件想作为一个主控器与其他设备通信,那么它就需要发送一个启动信号来掌握总线;
2. 在设备掌握总线后,成为主控器,那么它就需要发送一个地址字节,高7位地址为需要通信设备的地址,低一位为读控制位;
3. 总线中的一个设备如果检测到主控器发送的地址与自己的地址一致,其就是被控器,那么他就需要回复主控器应答信号(ACK),并开始向主控器发送数据;
4. 当主控收到被控器回复的ACK后就可以开始读取数据字节,一旦读取到一个字节就需要向从设备发送一个ACK;
5. 当被控器成功接收了主控器发送一个ACK信号,则继续发送字节给主设备;
6.一旦主控器完成全部数据接收,不发送ACK,直接发送停止信号并且释放总线。

时序模拟

使用CC2530中I/O端口模拟I2C总线时,最重要是对I2C总线时序的模拟,就是在作为SDA数据线和SCL时钟线的引脚上,根据I2C总线协议的规定,设置引脚的电平高低以及保持时长。下面的内容介绍了I2C协议中的几个时序和状态。
1、总线空闲状态
当I2C总线的SDA数据线和SCL时钟线都被拉高时,此时表示总线处于空闲状态。在空闲状态下,总线上的各个器件都处于截止状态,即释放总线,电平的上拉是由SDA和SCL各自的上拉电阻完成的。
2、启动信号
总线处于空闲状态时,SDA和SCL都为高电平,这时数据线SDA上的电平由高变低,即发生负跳变,定义这个时序信号为I2C总线的启动的信号,用它来标示一个数据传输过程的的开始。这里需要注意的是启动信号是电平跳变的时序信号,而不是电平信号,其必须要有一个动态的过程,不然不能标示开始。主控器在向总线发送启动信号,I2C总线必须处于空闲状态,不然这个信号不会作为一个启动信号处理。启动信号时序如下图所示。
这里写图片描述

3、停止信号
总线处于工作状态时,时钟线SCL处于高电平,释放数据线SDA,即SDA由低电平变为高电平,即发生正跳变,总线的两根信号线都为高电平,标示总线恢复到空闲状态,这个动态的过程就称为I2C总线的停止信号,它表示了一次数据传输过程的完成。停止信号时序如下图所示。
这里写图片描述

4、数据位传输
I2C总线上数据按位串行传输,每位数据的传输都受SCL时钟线电平的控制。在数据传输时,SCL时钟线必须为高电平,此时SDA上的电平必须保持稳定,不能改变,那么这一位数据才是有效的。数据发送是一连串的0和1,如果要对SDA的电平做改变,那么必须使SCL处于低电平状态,此时才能改变SDA上的电平。在发送完一个字节数据后,需要释放数据线。数据传输是边沿触发的。数据传输时序如下图所示。
这里写图片描述
5、应答信号
主控器成功发送一个字节数据后,就需要在第九个SCL释放数据线,即拉高数据线,等待被控器发送一个应答信号。如果数据线被拉低,说明被控器反馈了一个有效应答位ACK,说明被控器已经成功接收数据;如果数据线没有变化,还是高电平,那么为非应答位(NACK),说明接收器接收数据失败。如果是读操作,也就是接收方是主控器,在完成最后一个字节接收后,主控器需要向被控器发送一个NACK信号,来通知被控器结束发送和释放SDA,然后主控器发送结束信号,完成此次操作过程。ACK和NACK如下图所示。
这里写图片描述
由于CC2530的I/O端口具有方向性,所以在模拟I2C总线时序时,需要时时刻刻地根据是输出还是输入设置端口的方向寄存器,根据需要设置0还是1。延时的准确性对时序模拟的正确性起到很大的决定作用,在模拟的过程中使用了NOP指令来作为延时的最小时间单位。

Coding

i2c.h

#ifndef I2C_H
#define I2C_H


#include "ioCC2530.h"
#include "util.h"

#define SCL P1_0
#define SDA P2_0


void SCL_0();
void SCL_1();
void SDA_0();
void SDA_1();
void start();
void stop();
uint8 getAck();
void putAck(uint8 ack);
void init_i2c();
void i2c_writeByte(uint8 value);
uint8 i2c_readByte();
uint8 i2c_sendBytes(uint8 addr, uint8 data_addr, uint8 *value, uint8 len);
uint8 i2c_getBytes(uint8 addr, uint8 data_addr, uint8 *buffer, uint8 len);




#endif

i2c.c


#include "i2c.h"



void SCL_0()
{
    P1DIR |= 0x01;
    SCL = 0;
}

void SCL_1()
{
    P1DIR |= 0x01;
    SCL = 1;
}

void SDA_0()
{
    P2DIR |= 0x01;
    SDA = 0;
}

void SDA_1()
{
    P2DIR |= 0x01;
    SDA = 1;
}

uint8 readSDA()
{
    //P2DIR &= 0xfe;
    return SDA;
}

void start()
{
    SDA_1();
    delay_us(5);
    SCL_1();
    delay_us(5);
    SDA_0();
    delay_us(5);
    SCL_0();
}

void stop()
{
    SDA_0();
    delay_us(5);
    SCL_1();
    delay_us(5);
    SDA_1();
    delay_us(5);
    SCL_0();
}

uint8 getAck()
{
    uint8 ack;
    int i = 0;
    P2DIR &= 0xfe;
    SDA_1();
    SCL_1();
    delay_us(12);
    while((SDA == 1) && (i < 200))
    {
        i++;
    }
    ack = readSDA();
    SCL_0();
    delay_us(12);
    return ack;
}

void putAck(uint8 ack)
{
    if (ack) {
        SDA_1();
    } else {
        SDA_0();
    }
    SCL_1();
    delay_us(12);
    SCL_0();
    delay_us(12);

}


void init_i2c()
{
    SCL_1();
    delay_us(5);
    SDA_1();
    delay_us(12);

}

void i2c_writeByte(uint8 value)
{
    uint8 i;
    for (i = 0; i < 8; ++i)
    {
        /* code */
        if (value & 0x80)
        {
            /* code */
            SDA_1();
        } else {
            SDA_0();
        }

        value <<= 1;
        delay_us(5);
        SCL_1();
        delay_us(5);
        SCL_0();
    }
}

uint8 i2c_readByte()
{
    uint8 i;
    uint8 temp;
    SDA_1();
    for (i = 0; i < 8; ++i)
    {
        /* code */
        temp <<= 1;
        SCL_1();
        temp |= readSDA();
        SCL_0();
        delay_us(5);
    }
    return temp;
}

uint8 i2c_sendBytes(uint8 addr, uint8 data_addr,uint8 *value, uint8 len)
{
    addr &= 0xfe;
    start();
    i2c_writeByte(addr);
    if (getAck())
    {
        /* code */
        stop();
        return 1;
    }

    i2c_writeByte(data_addr);
    if (getAck())
    {
        stop();
        return 1;
    }

    for (int i = 0; i < len; ++i)
    {
        /* code */
        i2c_writeByte(*value++);
        if (getAck())
        {
            /* code */
            stop();
            return 1;
        }
    }

    stop();
    return 0;

}


uint8 i2c_getBytes(uint8 addr, uint8 data_addr, uint8 *buffer, uint8 len)
{
    addr &= 0xfe;
    start();
    i2c_writeByte(addr);
    if (getAck()) {
        stop();
        return 1;
    }

    i2c_writeByte(data_addr);
    if (getAck()) {
        stop();
        return 1;
    }
    start();
    addr |= 0x01;
    i2c_writeByte(addr);
    if (getAck()) {
        stop();
        return 1;
    }
    for (int i = 0; i < len; ++i)
    {
        /* code */
        *buffer++ = i2c_readByte();
        putAck(0);
    }
    putAck(1);

    stop();
    return 0;




}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

I2C总线协议 的相关文章

  • I2C总线和触摸屏驱动移植实战-linux驱动开发第9部分-朱有鹏-专题视频课程

    I2C总线和触摸屏驱动移植实战 linux驱动开发第9部分 9306人已学习 课程介绍 本课程是linux驱动开发的第9个课程 xff0c 主要内容是linux的I2C子系统以及电容触摸屏驱动的移植 学习本课程的核心点在于I2C子系统 xf
  • I2C slave address

    1 同一 I2C bus device 之 I2C slaver address 不可一样 2 检查 这些 devices 是否可以变更 I2C slaver address hardware pin control or software
  • I2C总线基础知识及操作详解

    I2C总线是一种简单的双向两线式同步串行总线 xff0c 最初由Philips公司开发 xff0c 后又经过几次发展和完善 xff0c 目前已被业界厂商广泛采用 xff0c 成为最常用的板级通信总线之一 xff0c 大量应用于处理器与外围设
  • I2C驱动体系结构一:驱动软件概念与对应硬件的关系

    一 概念 xff1a 1 设备 xff1a struct device xff1a 该数据结构是对物理设备的软件抽象 xff0c 比如I2C slave xff08 对应i2c client xff09 和I2C 适配器 xff08 对应i
  • I2C—读写EEPROM

    1 I2C协议简介 I2C通讯协议 Inter xff0d IntegratedCircuit 是由Phiilps公司开发的 xff0c 由于它引脚少 xff0c 硬件实现简单 xff0c 可扩展性强 xff0c 不需要USART CAN等
  • 什么是I2C通信

    ARM体系 I2C通信 一 什么是I2C 1 I2C总线是由Philips公司开发的一种简单 双向二线制同步串行总线 它只需要两根线即可在连接于总线上的设备之间传送信息 2 主设备用于启动总线传送数据 xff0c 并产生时钟以开放传送的设备
  • Linux控制I2C/SMBus设备

    平台 xff1a 树莓派 bcm2835 Raspberry Pi 3 Model B Rev 1 2 I2C是Philips开发的一种两线通信协议 xff0c 常用于一些对速度要求不高的小型器件上 SMBus是系统管理总线 xff0c 基
  • I2C调试工具

    1 I2C调试工具 i2c tools工具是开源I2C调试工具 xff0c 具有获取I2C总线挂载的设备列表及设备地址 xff0c 可对指定设备指定寄存器进行读写的功能 ubuntu安装 xff1a apt get install libi
  • 海思文件系统缺少文件himm 、i2c_read 、i2c_write 、ssp_read 、ssp_write

    原因 xff1a 海思根文件默认没有把himm i2c read i2c write ssp read ssp write工具集成在bin里 xff0c 但是在sdk中 解决办法 xff1a cd osdrv tools board reg
  • CAN总线协议:标准CAN和扩展CAN

    CAN通讯协议是一个载波侦听 基于报文优先级碰撞检测和仲裁 xff08 CSMA CD 43 AMP xff09 的多路访问协议 CSMA的意思是总线上的每一个节点在企图发送报文前 xff0c 必须要监听总线 xff0c 当总线处于空闲时
  • 串口通信协议 UART+I2C+SPI

    UART 异步 串行 全双工 I2C SPI 不同通信协议比较 UART UART协议详解 UART通信 xff0c 接收与发送 xff08 详细版 xff0c 附代码 xff09 UART串行通信详解 待整理 UART是Universal
  • 【总线】I2C 通信协议

    目录 I2C 总线协议概述 参数总结 I2C 的工作原理 寻址 读 写位 数据帧 I2C数据传输的步骤 具有多个从机的单个主机 具有多个从机的多个主机 I2C的优缺点 优点 缺点 文章参考 I2C 总线协议概述 I2C 总线广泛应用在 OL
  • 外设驱动库开发笔记22:ADXL345三轴数字加速度计驱动

    移动设备的广泛应用增加对移动过程中各种参数的检测需求 ADXL345三轴数字加速度计可以用来检测加速度 进而测量倾斜角度等 在这一篇中 我们将讨论ADXL345三轴数字加速度计驱动程序的设计与实现 1 功能概述 ADXL345是一款小而薄的
  • 快速对比UART、SPI、I2C通信的区别与应用

    参考 带你快速对比SPI UART I2C通信的区别与应用 作者 一口Linux 网址 https mp weixin qq com s 4 RSM2jk2W6nTboO1W8HCw 电子设备之间的通信就像人类之间的交流 双方都需要说相同的
  • Linux:从用户空间实例化:eeprom new_device

    环境 x86 Ubuntu 14 04 我想获得类似的东西 i2c0 eeprom eeprom 50 compatible at 24c32 reg lt 0x50 gt 但因为在 x86 中没有可用的设备树 所以我遵循i2c insta
  • 为什么我只收到第一个地址字节? (I2C协议)

    期望从机确认并返回数据 但它没有 这是我的协议 这是我的数据表 数据表提到 从机将通过首先发送 MSB 字节来应答 Byte0 和 byte1 包含 预测值 所有字节均由主机确认 Edit 源库 另外仅供参考 我使用的是 Arduino F
  • docker 容器内的 I2C

    我正在尝试在 docker 容器内的树莓派上使用 i2c 引脚 我使用 RUN 安装所有模块 但是当我使用 CMD 运行我的 python 程序时 我收到一条错误消息 Trackback most recent call last file
  • STM32F207 I2C 测试失败

    我正在使用 STM32F207 微控制器在 STM3220G EVAL 板上学习嵌入式开发 我尝试通过连接同一芯片上的两个 I2C2 和 I2C3 模块并发送 接收字符来测试 I2C 接口 这是我当前编写的代码 使用 mdk arm 5 i
  • MCP23017 I2C 设备驱动程序探测函数未调用

    我正在使用以下 I2C GPIO设备驱动 https github com torvalds linux blob master drivers gpio gpio mcp23s08 c访问 MCP23017 GPIO 使用 insmod
  • 为什么 i2c_smbus 函数不可用? (I2C——嵌入式Linux)

    有很多参考使用i2c smbus 开发嵌入式 Linux 软件时在 I2C 总线上进行通信的函数 什么时候i2c smbus函数如i2c smbus read word data在软件项目中引用了 ARM8 处理器错误 例如 i2c smb

随机推荐

  • JS判断日期范围(日期范围应在一个月之内)

    本文转自 xff1a 点击打开链接 之前的一个项目的日期选择功能由单个日期 xff0c 修改为日期范围 xff0c 用到了日期范围的判断 xff0c 使用JS实现 xff0c 希望对需要的人有所帮助 代码如下 xff1a var start
  • python视频教程大全集下载啦

    本文转自 xff1a 点击打开链接 python3英文视频教程 全87集 http pan baidu com s 1dDnGBvV python从入门到精通视频 xff08 全60集 xff09 链接 xff1a http pan bai
  • 如何关闭ubuntu alt快捷键

    本文转自 xff1a 点击打开链接 有时候发现ubuntu的alt快捷键真是太烦人了 xff0c 动不动就能把搜索框呼唤出来 xff0c 尤其是我在ubuntu上装了win7虚拟机 xff0c 喜欢用qq的alt 43 s发送消息 xff0
  • ubuntu安装原生迅雷,让下载成为简单

    今天想到电影天堂下点电影 xff0c 发现TM全都是迅雷链接 xff0c 旋风链接什么的 无奈自带的BT下载器速度又慢 xff0c 又满足不了日常的一些文件下载 于是乎google了下 xff0c 哎呀 xff0c 有个mldonkey的电
  • Android 采用fastboot刷system.img boot.img recovery.img’

    手机正常启动后 xff0c 命令行模式下输入 adb reboot bootloader 该命令会自动进入fastboot模式 接着 xff1a fastboot devices 查看是否有设备 erase 擦除的意思 xff0c 你懂得
  • Executors.newSingleThreadExecutor的一些坑

    还是直接上源码吧 public static ExecutorService newSingleThreadExecutor return new FinalizableDelegatedExecutorService new Thread
  • 学习AOP之透过Spring的Ioc理解Advisor

    本文转自 xff1a 点击打开链接 花了几天时间来学习Spring xff0c 突然明白一个问题 xff0c 就是看书不能让人理解Spring xff0c 一方面要结合使用场景 xff0c 另一方面要阅读源代码 xff0c 这种方式理解起来
  • 计算广告资料汇总

    papers 计算广告论文 学习资料 业界分享 王喆Paper Collection of Real Time Bidding Weinan Zhang计算广告干货整理 雪伦 在线课程 Introduction to Computation
  • 编辑器之神-vim的使用技巧

    vim VS emacs vim被誉为编辑器之神 xff0c 而emacs被誉为神之编辑器 中国文化博大精深 xff0c 他们究竟有什么区别呢 xff1f 作为emacs小白的我来说不想在这里献丑 xff0c 直接贴上一篇博客 xff0c
  • Linux离线环境安装bzip2

    1 下载离线安装包 bzip2 1 0 6 13 el7 x86 64 rpm http mirror centos org centos 7 os x86 64 Packages bzip2 1 0 6 13 el7 x86 64 rpm
  • Vivado使用与注意事项

    作者 QQ群 xff1a 852283276 微信 xff1a arm80x86 微信公众号 xff1a 青儿创客基地 B站 xff1a 主页 https space bilibili com 208826118 DRC INBB 3 Bl
  • Android Beam 详细实现步骤

    前言 最近没怎么写东西了 xff0c 主要是在了解Beam这个东东 找到一些高手写的文章 xff0c 奈何水平有限看的云里雾里的 没办法 xff0c 只好去复习官方文档 正文 xff1a 先摘取一部分官方文档 xff1a Beaming N
  • Qt中UTF-8转Unicode

    include lt QtCore QCoreApplication gt include lt QDebug gt include lt iostream gt include lt QTextCodec gt int main int
  • Qt中unicode转utf-8

    最经在研究AT指令接受短信 xff0c 短信是unicode编码 xff0c 接受后需要根据系统的编码方案进行相关的转码 比如接受到了一串字符4F60597D xff0c 它是 你好 的unicode编码 xff0c 一个unicode编码
  • 移植qt5.3.1到arm

    最近刚入手一款开发板 比较低端 刚毕业工作还没一个月 穷屌丝一个 在学校以前都是用的是Friendly Arm的6410 使用的qt版本是使用的最多的4 7 0版本 入手的板子是4 7 4 qt5出来也有好长的时间了 其中提供了很多的特性
  • Linux下生产者与消费者的线程实现

    代码见 现代操作系统 第3版 为了显示效果 xff0c 添加了printf 函数来显示运行效果 1 include lt stdio h gt 2 include lt pthread h gt 3 define MAX 20 4 pthr
  • 基于TCP协议的视频传输

    这个程序是为了大二上学期一个设计作业 xff0c 写的太水 xff0c 之前也发过 xff0c 那个不是最新版 xff0c 这个找到了可能是最新版的 xff0c 昨晚调试了下 xff0c 没用 xff0c 是一个itcol的函数操作无效 x
  • 使用nginx作为websocket的proxy server

    WebSocket WebSocket协议为创建客户端和服务器端需要实时双向通讯的webapp提供了一个选择 其为HTML5的一部分 WebSocket相较于原来开发这类app的方法来说 其能使开发更加地简单 大部分现在的浏览器都支持Web
  • 前后端分离开发部署模式

    身体出了点小毛病 xff0c 这周基本在家养病 xff0c 转文章一篇 xff0c 以激励学习 在开始讨论这个话题之前我们先来认识一下传统的开发模式 一 传统开发模式 相信很多做过Web开发童鞋应该都会经历这样一种开发模式 xff0c 利用
  • I2C总线协议

    毕业设计中使用到了AT24C04器件 xff0c 其是Ateml公司出品的 xff0c 是一种低功耗CMOS串行EEPROM xff0c 其使用两线串行的总线和控制器进行通讯 其内部保存的数据在掉电的情况下可以有40年以上的有效期 其采用8