STM32 IIC实验中关于AT24Cxx的读写

在正点原子的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,难免有很多的错误,请各位批评指正!

  • 15
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
在使用HAL库进行STM32IIC读写AT24C02时,你可以参考以下步骤: 1. 首先,你需要在你的工程包含AT24CXX.c文件,并在代码引用该文件。该文件定义了一些常量和函数,用于初始化AT24CXX芯片、写入数据和取数据等操作。 2. 在AT24CXX.c文件,你可以看到定义了一些常量,如AT24C02的地址为255。这些常量可以根据你所使用的芯片型号进行修改。 3. 在AT24CXX.c文件,还定义了一些函数,如AT24CXX_Init()用于初始化AT24CXX芯片,AT24CXX_Write()用于写入数据,AT24CXX_Read()用于取数据,AT24CXX_Check()用于检查AT24CXX芯片是否正常工作。你可以根据需要调用这些函数来实现对AT24C02的读写操作。 4. 在配置STM32的引脚时,你需要将IIC的引脚与AT24C02芯片的引脚相连接。具体的引脚配置可以参考AT24CXX.c文件的注释。 5. 在配置串口时,你可以选择使用串口进行数据查看,以便调试和验证读写操作的结果。 6. 最后,根据你的需求选择适当的时钟频率,生成Keil工程代码。 综上所述,你可以使用HAL库的函数和AT24CXX.c文件定义的函数来实现对AT24C02芯片的读写操作。 #### 引用[.reference_title] - *1* *3* [STM32 (基于HAL库) 硬件IIC读写任意AT24CXX芯片](https://blog.csdn.net/weixin_56565733/article/details/124401443)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [STM32系列(HAL库)——F103C8T6通过IIC/I2C方式读写AT24C02—(EEPROM 存储模块)](https://blog.csdn.net/lwb450921/article/details/124394615)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值