IIC的使用

news2024/11/27 2:37:21

借鉴于:蓝桥杯嵌入式快速通关篇,IIC通讯及EEPROM_穿上我的格子衫的博客-CSDN博客

                IIC原理超详细讲解---值得一看_Z小旋的博客-CSDN博客_iic

总线空闲:SDA  = 1,SCL = 1;
启动信号:SCL = 1,SDA 1 -> 0;
停止信号:SCL = 1,SDA 0 -> 1;

 

数据传输:SCL为1时,SDA必须保持稳定,即为0或1(停止时相反,所以在停止前要改变SDA都要先把SCL置为0);
         SCL为0时,才允许改变SDA状态;
         SCL在上升沿时写入数据,在下降沿时读出数据;
         
应答信号:为0时,是有效应答,为1时,是无效应答;
         传输到最后一个字节后,要发送一个无效应答,再发送停止信号;

不管什么信号,其线的变化都要严格与对应时序吻合(包括起始,变化过程,结果)

总线封锁:将SCL锁定为0即可;

多次数据通信,采用复启动信号,即写一个停止信号,再接上一个启动信号;

单片机为主机,24C02为从机;
SCL时钟由主机控制;

初始化时仅需要设置端口为最基本的推挽模式(因为仅需要gpio输出最基本的高低电平)
写时应答信号从机给出;
读时由主机给出;

24C02器件地址:前四位默认为1010,后四位的前三位为A0,A1,A2,均已接地,即为0,
              最后一位为读写保护位,写时为0(0xA0),读时为1(0xA1).

在这里插入图片描述

Start: IIC开始信号,表示开始传输。
DEVICE_ADDRESS:: 从设备地址,就是7位从机地址
R/W: W(write)为写,R(read)为读
ACK: 应答信号
WORD_ADDRESS : 从机中对应的寄存器地址 比方说访问 OLED中的 某个寄存器
DATA发送的数据
STOP: 停止信号。结束IIC

  1. 主机首先产生START信号
  2. 然后紧跟着发送一个从机地址,这个地址共有7位,紧接着的第8位是数据方 向位(R/W),0表示主机发送数据(写),1表示主机接收数据(读)
  3. 主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比较,若相同,则认为自己正在被主机寻址,根据R/T位将自己确定为发送器和接收器
  4. 这时候主机等待从机的应答信号(A)
  5. 当主机收到应答信号时,发送要访问从机的那个地址, 继续等待从机的应答信号
  6. 当主机收到应答信号时,发送N个字节的数据,继续等待从机的N次应答信号,
  7. 主机产生停止信号,结束传送过程。

具体表现为:

void i2c_write(u8 add ,u8 reg ,u8 data)

{ I2CStart();

I2CSendByte(add);

I2CWaitAck();

I2CSendByte(reg);

I2CWaitAck();

I2CSendByte(data);

I2CWaitAck();

I2CStop();

}

函数void i2c_write(u8 add ,u8 reg ,u8 data);
是iic通讯的写函数,第一个 add是设备的地址,如0xa0是EEPROM的地址,0x38 是扩展板上的三轴加速度计的通讯地址。
第二个形参是寄存器的地址,需要注意的是AT24C02的地址是从0x00~0xff,如果超出该地址值会出现错误。地址和写入或读取的数据的类型都是无符号字符型,其他类型的数据有可能出现错误。就是说,但个地址存入读出的值不会超过255,即存取的的数据范围是0 ~255

主机要从从机读数据时

  1. 主机首先产生START信号
  2. 然后紧跟着发送一个从机地址,注意此时该地址的第8位为0,表明是向从机写命令,
  3. 这时候主机等待从机的应答信号(ACK)
  4. 当主机收到应答信号时,发送要访问的地址,继续等待从机的应答信号,
  5. 当主机收到应答信号后,主机要改变通信模式(主机将由发送变为接收,从机将由接收变为发送)所以主机重新发送一个开始start信号,然后紧跟着发送一个从机地址,注意此时该地址的第8位为1,表明将主机设 置成接收模式开始读取数据,
  6. 这时候主机等待从机的应答信号,当主机收到应答信号时,就可以接收1个字节的数据,当接收完成后,主机发送非应答信号,表示不在接收数据
  7. 主机进而产生停止信号,结束传送过程。

u8 i2c_read(u8 add ,u8 reg){
    u8 data ;
    I2CStart();
    I2CSendByte(add);
    I2CWaitAck();
    
    I2CSendByte(reg);
    I2CWaitAck();
    I2CStart();
    I2CSendByte(add+1);
    I2CWaitAck();
    data =I2CReceiveByte();
    I2CWaitAck();

    I2CStop();
    return data;
    
    
}
    

以AT24C02为例子(与连接芯片的差别为寄存器地址改为了具体储存地址

24C02是一个2K Bit的串行EEPROM存储器(掉电不丢失),内部含有256个字节。在24C02里面有一个8字节的页写缓冲器。
在这里插入图片描述
A0,A1,A2:硬件地址引脚
WP:写保护引脚,接高电平只读,接地允许读和写
SCL和SDA:IIC总线

以看出对于不同大小的24Cxx,具有不同的从器件地址。由于24C02为2k容量,也就是说只需要参考图中第一行的内容:
在这里插入图片描述
芯片的寻址:
AT24C设备地址为如下,前四位固定为1010,A2~A0为由管脚电平。AT24CXX EEPROM Board模块中默认为接地。A2~A0为000,最后一位表示读写操作。所以AT24Cxx的读地址为0xA1,写地址为0xA0。

也就是说如果是
写24C02的时候从器件地址为10100000(0xA0);
读24C02的时候,从器件地址为10100001(0xA1)。

片内地址寻址:

芯片寻址可对内部256B中的任一个进行读/写操作,其寻址范围为00~FF,共256个寻址单位。

对应的修改 A2A1A0 三位数据即可
在这里插入图片描述

向AT24C02中写数据
在这里插入图片描述
操作时序:

  1. MCU先发送一个开始信号(START)启动总线
  2. 接着跟上首字节,发送器件写操作地址(DEVICE ADDRESS)+写数据(0xA0)
  3. 等待应答信号(ACK)
  4. 发送数据的存储地址。24C02一共有256个字节的存储空间,地址从0x00~0xFF,想把数据存储>在哪个位置,此刻写的就是哪个地址。
  5. 发送要存储的数据第一字节、第二字节、…注意在写数据的过程中,E2PROM每个字节都会>回应一个“应答位0”,老告诉我们写E2PROM数据成功,如果没有回应答位,说明写入不成功。
  6. 发送结束信号(STOP)停止总线

注意:
在写数据的过程中,每成功写入一个字节,E2PROM存储空间的地址就会自动加1,当加到0xFF后,再写一个字节,地址就会溢出又变成0x00。

写数据的时候需要注意,E2PROM是先写到缓冲区,然后再“搬运到”到掉电非易失区。所以这个过程需要一定的时间,AT24C02这个过程是不超过5ms!
所以,当我们在写多个字节时,写入一个字节之后,再写入下一个字节之前,必须延时5ms才可以



 

从AT24C02中读数据

读当前地址的数据
在这里插入图片描述
2、读随机地址的数据
在这里插入图片描述

  1. MCU先发送一个开始信号(START)启动总线
  2. 接着跟上首字节,发送器件写操作地址(DEVICE ADDRESS)+写数据(0xA0)
    注意:这里写操作是为了要把所要读的数据的存储地址先写进去,告诉E2PROM要读取哪个地址的数据。
  3. 发送要读取内存的地址(WORD ADDRESS),通知E2PROM读取要哪个地址的信息。
  4. 重新发送开始信号(START)
  5. 发送设备读操作地址(DEVICE ADDRESS)对E2PROM进行读操作 (0xA1)
  6. E2PROM会自动向主机发送数据,主机读取从器件发回的数据,在读一个字节后,MCU会回应一个应答信号(ACK)后,E2PROM会继续传输下一个地址的数据,MCU不断回应应答信号可以不断读取内存的数据
  7. 如果不想读了,告诉E2PROM不想要数据了,就发送一个“非应答位NAK(1)”。发送结束信号(STOP)停止总线

应答信号(ack

每当主机向从机发送完一个字节的数据,主机总是需要等待从机给出一个应答信号,以确认从机是否成功接收到了数据,

应答信号:主机SCL拉高,读取从机SDA的电平,为低电平表示产生应答

  • 应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;
  • 应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。

在这里插入图片描述

**每发送一个字节(8个bit)**在一个字节传输的8个时钟后的第九个时钟期间,接收器接收数据后必须回一个ACK应答信号给发送器,这样才能进行数据传输。

应答出现在每一次主机完成8个数据位传输后紧跟着的时钟周期,低电平0表示应答,1表示非应答,

//主机产生应答信号ACK
//1.先拉低SCL,再拉低SDA
//2.拉高SCL
//3.拉低SCL
## 标题
void I2C_Ack(void)
{
   IIC_SCL=0;   //先拉低SCL,使得SDA数据可以发生改变
   IIC_SDA=0;   
   delay_us(2);
   IIC_SCL=1;
   delay_us(5);
   IIC_SCL=0;
}


//主机不产生应答信号NACK
//1.先拉低SCL,再拉高SDA
//2.拉高SCL
//3.拉低SCL
void I2C_NAck(void)
{
   IIC_SCL=0;   //先拉低SCL,使得SDA数据可以发生改变
   IIC_SDA=1;   //拉高SDA,不产生应答信号
   delay_us(2);
   IIC_SCL=1;
   delay_us(5);
   IIC_SCL=0;
}

3、连续读数据
在这里插入图片描述
E2PROM支持连续写操作,操作和单个字节类似,先发送设备写操作地址(DEVICE ADDRESS),然后发送内存起始地址(WORD ADDRESS),MCU会回应一个应答信号(ACK)后,E2PROM会继续传输下一个地址的数据,MCU不断回应应答信号可以不断读取内存的数据。E2PROM的地址指针会自动递增,数据会依次保存在内存中。不应答发送结束信号后终止传输。

软件IIC和硬件IIC

IIC分为软件IIC和硬件IIC

软件IIC:软件IIC通信指的是用单片机的两个I/O端口模拟出来的IIC,用软件控制管脚状态以模拟I2C通信波形,软件模拟寄存器的工作方式。

硬件IIC:一块硬件电路,硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用的,硬件(固件)I2C是直接调用内部寄存器进行配置。

硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活。

代码需要注意的点(出现问题也可依次检查)

读取的操作结束后,都建议延迟几毫秒,实测如果不延迟数据极有可能会出错,延迟操作可以加到函数末尾,也可在函数调用后。

调用函数之前,要先使用i2c.c文件中已有的函数i2c_init()来初始化iic要使用到的时钟,引脚等。

读写函数并不能直接存取超过范围的数,如果存入的数不在0到255之间,肯定会出错,地址也一样,要注意范围。

在读取iic的值时,需要再进行一次I2CStart(),不然读取的值也可能会出错!
在这里插入图片描述

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

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

相关文章

【王道计算机网络笔记】物理层-通信基础

文章目录物理层接口特性典型的数据通信模型数据通信相关术语三种通信方式(交互方式)串行传输&并行传输(数据传输方式)同步传输&异步传输码元速率带宽失真失真的一种现象——码间串扰奈氏准则(奈奎斯特定理&…

矩阵股份上市首日跌破发行价:振幅达10%,王冠为实际控制人

11月22日,矩阵纵横设计股份有限公司(下称“矩阵股份”,SZ:301365)在深圳证券交易所创业板上市。本次上市,矩阵股份的发行价为34.72元/股,发行数量为3000万股,募资总额约为10.42亿元,…

SpringBoot SpringBoot 开发实用篇 5 整合第三方技术 5.15 SpringBoot 整合 task

SpringBoot 【黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇5 整合第三方技术5.15 SpringBoot 整合 task5.15.1 SpringBoot 整合 …

对zygote的理解

一、 zygote的作用 启动SystemServer SystemServer需要用于zygote准备好的一些系统资源,比如常用类、注册的JNI函数、主题资源、共享库等等,直接从zygote那继承过来,SystemServer就不用重新再加载一遍,这样对性能有很大的提升。 …

CRM系统中联系人管理的十大好处

联系人管理通常是你的CRM策略中的一个关键部分。它是存储和组织联系人数据以便于访问的做法。简而言之,就是管理联系人数据的过程。如今联系人管理已内置到 CRM 系统中。因此,我们可以考虑利用系统软件将以下优点应用于联系人管理中。 1、更好、更持久的…

Matplotlib用法使用、Matplotlib绘图作图画图

一、Matplotlib Matplotlib:专门用于开发2D或3D图表,以渐进、交互式方式实现数据可视化 可视化是在整个数据挖掘的关键辅助工具,可以清晰的理解数据,从而调整我们的分析方法 能将数据进行可视化,更直观的呈现使数据…

希望所有计算机学生能看到这篇c语言教程

大部分程序员走入编程世界第一个学习的语言就是C语言。 作为一门古老的编程语言,c语言拥有48年的发展历程。 为什么要学习 C语言? C语言是学习计算机程序设计语言的入门语言。C语言是一门偏底层的语言,学好它,可以让你更好的了…

E - Fire! (双向bfs)

UVA-11624-Fire! 题意:在n*m的网格内,有一个人和n堆火,人可以往上下左右四个方向走,同时所有的火也会想四周蔓延,问你人可不可以在火包围他之前逃离这个n*m的范围。 思路:问人可不可以逃离这个范围&#xf…

m基于VDLL的矢量型GPS信号跟踪算法matlab仿真

目录 1.算法概述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法概述 载波跟踪环是传统独立式GPS接收机最脆弱的环节,针对弱信号环境下其比伪码跟踪环路更容易失锁的问题,给出一种基于矢量频率锁定环(vector-frequency lo…

集成学习-Boosting

Boosting 采用串行的方式训练,各基分类器之间有依赖。根据当前模型损失函数的负梯度训练新的弱分类器,将训练好的弱分类器以累加的形式结合到现有模型中。 过程中会不断减小损失函数,使模型偏差不断降低,方差不会降低。因为各弱分…

《CTFshow - Web入门》02. Web 11~20

Web 11~20web11知识点题解web12知识点题解web13知识点题解web14知识点题解web15知识点题解web16知识点题解web17知识点题解web18知识点题解web19知识点题解web20知识点题解web11 知识点 dns检查查询:http://dbcha.com/,输入域名,获取flag。…

MySQL数据库期末考试试题及参考答案(07)

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl 一、 填空题 如果不想提交当前事务,可以使用_____语句回滚事务。每个事务都是完整不可分割的最小单元是事务的_____性。MySQL中,显式开启事务的语句…

屏幕视频捕获组件-ByteScout Screen Capturing SDK

使用 ByteScout Screen Capturing SDK,您可以轻松地将屏幕视频捕获功能添加到您的应用程序中。输出带有音频、鼠标移动和点击的高质量桌面屏幕视频录制。 主要优势 只需几行代码即可在您的应用中启用屏幕视频捕获和屏幕录制功能;无需互联网连接即可离线…

Django day1

在windows下可以直接的创建django项目 但是需要把自动生成的templates和setting里面的DIRS里面字段删除(templates自动生成的可以删不删都行,我是看视频那个老师删了,但是setting DIRS里面的字段需要删,至于具体为啥我已经忘了&am…

TiDB数据库概述——PD

PD PD的架构与功能TSO的分配PD的调度原理label的作用 PD的架构 PD的个数一般是奇数个的。 PD的主要功能: 整个集群TiKV的元数据存储分配全局ID和事务ID生成全局时间戳TSO收集群信息进行调度提供label,支持高可用提供TiDB Dashboard 路由功能 用key…

vue3使用富文本编辑器wangEditor-v5(未使用composition api写法)

效果 安装 安装核心库和其vue组件库 yarn add wangeditor/editor yarn add wangeditor/editor-for-vuenext使用v-model封装富文本组件editor.vue <template><div class"editor-box"><Toolbar class"toolbar" :editor"editor" …

Flink是什么?场景?处理流的发展演变?

Flink是什么&#xff1f;Flink是什么&#xff1f;为什么选择Flink&#xff1f;什么场景需要处理流数据?处理流的发展演变Flink是什么&#xff1f; Apache Flink 是一个在无界和有界数据流上进行状态计算的框架和分布式处理引擎。Flink 能在所有常见集群环境中运行&#xff0c…

线性表的链式存储的基本

链表是线性表的链式存储方式&#xff0c;逻辑上相邻的数据在计算机内的存储位置不一定相邻&#xff0c;因此&#xff0c;我们需要为每一个元素设置有一个指针来指向与它逻辑相邻的元素。 为此&#xff0c;我们为每个元素设置一个结点&#xff0c;每个结点由数据域和指针域组成…

【3D目标检测】Monocular 3D Object Detection with Pseudo-LiDAR Point Cloud

目录概述整体流程伪点云vs点云2D-3D边界框的一致性约束概述 本文的输入数据仅仅是单目图像&#xff0c;在方法上是融合了伪点云&#xff08;Pseudo-LiDAR&#xff09;的深度信息表示方法与Frustum PointNets的检测方法。 乍一看文章和伪点云原论文Pseudo-LiDAR from Visual De…

Deep-SVDD 方法

两种情况 1. 数据集有正负样本&#xff0c;但正样本的量远远大于负样本为异常检测&#xff0c;即大量的正样本为正常&#xff0c;少数的负样本是异常的。 2. 数据集只有正样本&#xff0c;称为单分类&#xff0c;即只通过正样本训练模型&#xff0c;区分正样本和非正样本。 情…