在正点原子的STM32IIC实验例程中,从AT24Cxx芯片中某一位读取一个数据的操作如下:
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{
u8 temp=0;
IIC_Start();
if(EE_TYPE>AT24C16)
{
IIC_Send_Byte(0XA0);
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr>>8);
}else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr%256);
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(0XA1);
IIC_Wait_Ack();
temp=IIC_Read_Byte(0);
IIC_Stop();
return temp;
}

其中难以理解的部分是:
if(EE_TYPE>AT24C16)
{
IIC_Send_Byte(0XA0);
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr>>8);
}else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr%256);
IIC_Wait_Ack();
要理解这段程序需要结合AT24Cxx芯片的硬件结构。下面是百度文库中这种芯片的中文版参考手册地址。
https://wenku.baidu.com/view/05030b2fd15abe23492f4d7e.html
要对AT24Cxx芯片的某一位进行读写,首先要发送这一位的地址。对于不同容量型号AT24Cxx芯片的地址数据组成,下面这篇博客讲解的比较详细。
https://www.cnblogs.com/leo0621/p/8251897.html
从这篇文章中可以看出,对于型号为AT24C01~AT24C16的芯片,确定芯片中存储地址需要两个字节的地址信息,分别是一个字节(8位)的设备地址信息,和一个字节(8位)的数据地址信息。在设备地址信息中,高四位是固定的,为1010,最低位是用来表示是读还是写,第2,3,4位即A0,A1,A2是设备选用地址。
对AT24C01/02,A0,A1,A2作为片选位,从硬件上保证是拉高还是拉低,表示选择某一个2K芯片,由于三位用于选择,因此,最多可以配置8个2K芯片。
对AT24C04,A1,A2作为片选位,从硬件上保证拉高还是拉低,表示选择某一个4K芯片,由于两位用于选择,因此,最多可以配置4个4K芯片。而硬件上的A0位悬空,在编程时设备地址位的第二位作为页寻址位P0位。(关于页寻址的问题参考上两个资料,里面都有提到相关知识)
对AT24C08,A2位作为片选位,从硬件上保证拉高还是拉低,表示选择某一个8K芯片,由于一位用于选择,因此,最多可以配置2个8K芯片。而硬件上的A0,A1位悬空,在编程时设备地址位的第二位和第三位分别作为页寻址位P0位和P1位。
对AT24C16,无片选位,意味着只能配置1个16K芯片,硬件上A0,A1,A2全部悬空,编程时设备地址位的第二,三,四位分别作为页寻址位P0,P1和P2位。

需要注意的是,上面说的芯片的存储容量单位是bit,换成字节(byte)的话AT2402是256字节,AT24C04是512字节,依次类推。寻址的时候,是按照字节来寻址的,每个字节有一个地址。在操作的时候也是对每个字节进行操作。

用两个字节-设备地址和数据地址进行寻址,至多只能寻址211个地址,因为一共16位,设备地址的高四位始终不变,而设备地址的最低位用于表示读还是写操作,因此可用的只有11位,故而最多寻址211,也就是2K个字节,16K的bit。因此这种寻址方法,不管对哪种容量的芯片,最多的容量也即是16k,对AT24C02,最多8片,2x8=16k,对AT24C04,最多4片,4x4=16k,依次类推。
而要配置更大的容量,则需要增加一位数据位。这个时候设备地址只起到了标志读还是写的作用,第2,3,4位置为0。在读或者写数据的时候,首先发送设备地址位0XA0(写)或者是0XA1(读)。接着发送数据地址高八位,然后发送数据地址低八位。这种方法做多寻址216,即219bits,也就是512k。
当大于512k时,将设备地址的一位作为页寻址,在前面提到的博客中有详细讲解,这里就不赘述了。

有了上面的知识之后,我们再来看这段代码,首先看这个if的判断条件:
if(EE_TYPE>AT24C16)
这是用来判断要进行读写的芯片的容量,因为容量决定了设备地址和数据地址的分配方法。如果容量大于16K,则设备地址只起到了一个标志读写操作的作用,有两位数据地址表示要读写的字节的地址。故而首先发送0XA0,然后发送要写入的地址的高八位。这里是通过将16位地址数据右移8位实现的这个操作。即如下代码:
IIC_Send_Byte(0XA0);
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr>>8);
在后面再将低八位,也即是ReadAddr%256发送给芯片在,这就完成了对要读取的字节的位置的寻址。
而当芯片的容量小于16k的时候,设备地址中可能用于页寻址的位。来分析这一句:
IIC_Send_Byte(0XA0+((ReadAddr/256)<<1))
假如是AT24C02,则设备地址中无页寻址的位,则ReadAddr的高八位均为0,则((ReadAddr/256)<<1)也为0,因此最后就是发送0XA0。
假如是AT24C04,则设备地址中有一位页寻址的位,假如是1,则(ReadAddr/256)为0X01,再左移一位为0x02,则最终发送的位0XA2。正好对应P0位为1。依次类推。
其实ReadAddr/256,也就是ReadAddr的高八位(但是高8位的第4位到第8位一定为0)即为设备地址的第2,3,4位的值,因此,将ReadAddr/256然后再左移一位加到0XA0中,对应的就是目标字节的设备地址。ReadAddr的低八位就是数据目标字节的数据地址。这样就能理解这段代码的含义了。

还有一个问题是,为什么是从AT24Cxx中读取数据,却最先发送0XA0,这是写数据的信号。之后才再启动一次IIC通信,然后再发送读取信号。直接发送0XA1和地址进行读取不行吗?
这个问题就要涉及到读写操作的时序问题了。其实在读取的时候最先的一个0XA0是伪写操作,这个伪写操作是为了修改存储器内部的工作指针。具体的可以看这篇博文中的随机写的内容。
https://www.cnblogs.com/dengxiaojun/p/4279446.html

菜鸡初学STM32,难免有很多的错误,请各位批评指正!

STM32 IIC实验中关于AT24Cxx的读写相关推荐

  1. 45 STM32 IIC主机、从机通信实例(ma51t12b触摸按键芯片)

    45.1引言 最近在研究触摸按键板的通信,按键板主要用到的通信协议为IIC,事实上IIC的例子有很多,但大都都是模拟IIC的主机(引用某网友的评论),从机这边的内容还是比较少. 早在两三年前就跟着原子 ...

  2. 关于iic协议和对AT24C02进行读写数据的理解和代码解读

    关于iic协议和对AT24C02进行读写数据的理解和代码解读 认识IIC协议 IIC协议软件模拟方法 管脚初始化 时序 AT24C02 简介 存储大小计算 工作方式 流程(代码) 认识IIC协议 本文 ...

  3. STM32笔记(十二)---SPI读写FLASH

    SPI读写FLASH 文章目录 SPI读写FLASH 一.SPI协议简介 1.1 SPI 物理层 1.2 协议层 1.2.1 SPI 基本通讯过程 1.2.2 通讯的起始和停止信号 1.2.3 数据有 ...

  4. linux i2c dev.h freq,STM32F103ZET(基于秉火开发板)+Cubemx(F1 V1.60库)+IIC+AT24C02(修复官方例程读写死机bug)...

    首先说明下开发条件: 1.开发板:秉火霸道,STM32F103ZET 2.软件:Cubemx V4.23(F1 V1.60库) 3.硬件:AT24C02 256KByte 问题描述:Cubemx生成I ...

  5. NB-IOT实验练习2——STM32基础实验

    STM32基础实验 上一节介绍了江苏学蠡信息科技有限公司的无线传感器网络实验平台关于NB-IOT实验所需要的各项硬件以及所需要的软件组成部分,这一章,主要是使用STM32F103单片机的基础实验进行介 ...

  6. STM32 LWIP实验第一章节--了解以太网

    STM32 LWIP实验第一章节--了解以太网 心有猛虎,无所畏惧! 一.了解以太网流程: 借鉴: https://www.xitongtiandi.net/wenzhang/xp/23235.htm ...

  7. STM32利用FATFS文件系统给SD卡读写数据

    STM32利用FATFS文件系统给SD卡读写数据 注:FATFS文件系统官方网址(内含各种函数具体功能及参数配置): FATFS文件系统官方网址 1. 所需.c和.h文件 FATFS中的文件的作用如下 ...

  8. STM32 在SRAM中调试代码

    本文所有内容转自他人内容,非本人原创,仅做资料收集.原文地址 https://www.cnblogs.com/firege/p/5806141.html 全套200集视频教程和1000页PDF教程请到 ...

  9. python中io.textio_Python文件读写概述(IO操作、文件读写、stringiobytesio、序列化),python,的,小,总结,StringIOBytesIO...

    IO操作 在进行文件的读写之前,需要说明几点.首先,运行的程序和读取的数据都会在内存中缓存. 进入到 程序或数据 内存 其次,用python程序进行文件的读写,需要创建一个小工具–文件流,用来处理数据 ...

  10. Lesson 12.1 深度学习建模实验中数据集生成函数的创建与使用

    Lesson 12.1 深度学习建模实验中数据集生成函数的创建与使用   为了方便后续练习的展开,我们尝试自己创建一个数据生成器,用于自主生成一些符合某些条件.具备某些特性的数据集.相比于传统的机器学 ...

最新文章

  1. 华为路由器静态路由配置
  2. java的知识点34——任务定时调度(多线程)
  3. 计算机二级题目小汽车大客车,浙江省计算机二级办公软件Excel练习题.xls
  4. VMware虚拟机:桥接、NAT、Host-only(仅主机)上网方式的区别
  5. python爬虫中for循环无法每一段输出_1024程序员节送你一套爬虫玩玩
  6. ImportError: No module named ‘pandas.io.data‘
  7. attempt to write a readonly database 错误
  8. 2021计算机科学调剂,2021北京科技大学计算机科学与技术专业接收调剂研究生的通知...
  9. 一步一步在virtual box4.1.6中安装基于rhel5.5x86_64的oracle 10g R2双节点RAC
  10. idea springmvc项目搭建_IntelliJ IDEA基于SpringBoot如何搭建SSM开发环境
  11. 谷歌被墙,如何给谷歌浏览器添加迅雷下载插件
  12. 万兆网络传输速度测试_Intel万兆网卡的真实测试万兆速度的方法
  13. Win10 使用 Virtual Box 安装 Ubuntu 虚拟机
  14. 记录下IDEA导入web项目遇到的web facet问题
  15. Spring Boot的启动流程
  16. 双系统基础上装三系统教程
  17. 第十一周学习周报(20180514-20180520)
  18. C# 将PPT转为OFD、DPT、DPS、ODP、POTX、UOP
  19. 一个SAPer的网络日志-连载二-说说MM的倒爷们
  20. 写给零基础的前端算法入门指南,acmer带女友刷80+【递归与回溯篇】|牛气冲天新年征文

热门文章

  1. html表白代码大全_100条代码,拿去“表白”
  2. 安卓端黑名单拦截电话
  3. html模仿登陆页面,登陆注册页面html代码(仿知乎)
  4. Android 程序员计算器 开发记录-Git版本控制初步接触
  5. 保研复习——信号与系统1:信号与系统(绪论)
  6. 《机器视觉算法与应用》第3章 机器视觉算法之几何基元的分割和拟合——学习笔记
  7. SSCOM下载及无法打开问题解决
  8. 英伟达驱动怎么设置显示帧数?
  9. IDEA 如果修改工作区的主题 也就是黑色背景和白色背景
  10. seay代码审计mysql插件报错_Seay源代码审计系统的配置和安装