【STM32】IIC

超级常见的外设通信方式,一般叫做I方C。

大部分图片来源:正点原子HAL库课程

 专栏目录:记录自己的嵌入式学习之路-CSDN博客


目录

1    基本概念

1.1    总线结构

1.2    IIC协议

1.3    软件模拟IIC逻辑

2    AT24C02

2.1    设备地址与通信地址

2.2    读写操作模式

2.3    写时序

2.4    读时序

2.5    驱动步骤(例程中使用的是软件IIC)

2.6    SDA的GPIO使用开漏输出的原因

3    硬件IIC

3.1    概述

3.2    配置

3.3    注意事项

4    关于AT24C04、AT24C08、AT24C16


1    基本概念

IIC:Inter Integrated Circuit,集成电路总线,是一种同步、串行、半双工通信总线。

1.1    总线结构

  • 一般来说IIC总线接3个设备就差不多了。
  • IIC的时钟信号是由主机发出的。

1.2    IIC协议


  • 主机通过SDA传输数据时,数据在SCL为高电平时有效。
  • 在主机传输完毕一个字节的数据后,其需要释放SDA,使得从机可以通过拉低SDA来应答确认数据收到。

1.3    软件模拟IIC逻辑

由于初期ST官方说自己的IIC有问题,口碑没做上来,导致大家都使用软件IIC代替其内部的硬件IIC实现。但其实硬件IIC应该没啥大问题,详见:

关于STM32的I2C(IIC)问题的讨论 (stmicroelectronics.cn)




2    AT24C02

EEPROM是一种掉电后数据不丢失的储存器,常用来存储一些配置信息,在系统重新上电时就可以加载。AT24C02是一个2K bit的EEPROM存储器,使用IIC通信方式。

2.1    设备地址与通信地址

  • 通讯地址指定了操作的写和读;
  • 而设备地址不包括读写位;
  • 编程时需要发送出去的是通讯地址,不是设备地址;
  • 对于4K、8K、16K的存储芯片,由于IIC发送一个字节是8位,而4K是9位,因此需要在通讯地址处借1位进行数据发送,8K和16K也是以此类推。但是这样一来通讯地址的可用枚举就变少了,因为A0、A1、A2的位置被拿去做内存扩展了。最终的结果就是,IIC总线上可搭载的该类设备的数量会大打折扣,如16K的就只能搭载一个了。

2.2    读写操作模式

  • 写操作
    • AT24C02支持字节写模式和页写模式,其实也并不是什么字节写,实际上就是在IIC主机发送了数据地址信号后到发送停止信号前,最多可以写到页尾,仅此而已;
    • 其本质就是:收到每个数据字后,数据字地址的低三位(1K/2K)或四位(4K、8K、16K)在内部递增。较高的数据字地址位不递增,保留存储器页面行位置。当内部生成的字地址到达页面边界时,随后的字节被放置在同一页面的开头。如果超过八个(1K/2K)或十六个(4K、8K、16K)数据字传输到EEPROM,数据字地址将“翻转”,先前的数据将被覆盖。
    • 字节写模式就是一个地址一个数据进行写入;
    • 页写模式就是连续写入数据。只需要写一个地址,连续写入数据时地址会自增,但存在页的限制,超出一页时,超出数据覆盖原先写入的数据。但读会自动翻页。因此,若需要使用页写模式,就需要手动在写完一页后进行翻页。
  • 读操作
    • AT24C02支持当前地址读模式,随机地址读模式和顺序读模式;
    • 当前读模式是基于上一次读/写操作的最后位置继续读出数据;
    • 随机地址读模式是指定地址读出数据;
    • 顺序读模式是连续读出数据。

2.3    写时序

2.4    读时序

2.5    驱动步骤(例程中使用的是软件IIC)


2.6    SDA的GPIO使用开漏输出的原因


3    硬件IIC

(正点原子没讲硬件IIC,这个是参考野火的HAL库教程的)

STM32的I2C片上外设专门负责实现I2C通讯协议,只要配置好该外设,它就会自动根据协议要求产生通讯信号,收发数据并缓存起来,CPU只要检测该外设的状态和访问数据寄存器,就能完成数据收发。这种由硬件外设处理I2C协议的方式减轻了CPU的工作,且使软件设计更加简单。

3.1    概述

STM32F103具有2个I2C总线接口,能够工作于多主模式或从模式,支持标准(100kHz)和快速模式(400kHz)。I2C接口支持7位或10位寻址,7位从模式时支持双从地址寻址。内置了硬件CRC发生器/校验器。它们可以使用DMA操作并支持SMBus总线2.0版/PMBus总线。

  • 时钟
    • STM32F103的两个IIC接口外设都挂载在APB1时钟总线上;
    • 为了产生正确的时序,必须在I2C_CR2寄存器中设定该模块的输入时钟。输入时钟的频率必须至少是(但APB1一般都会满足吧):
      • 标准模式下为:2MHz;
      • 快速模式下为:4MHz;

3.2    配置

由于正点原子和野火都没讲硬件IIC的配置,因此此处的配置步骤是我通过网络上的CubeMX教程总结来的(没错,就连正点原子的CubeMX教程都是用模拟IIC的)。

  • CubeMX方式
    • 根据需要控制的IIC外部原件连接的GPIO其对应的IIC外设进行使能,例如正点原子F103板子上的AT24C02接在PB6、PB7上,因此是I2C1:
    • 配置IIC的设置,对于AT24C02,除了速率外基本不需要变:
    • 在高速模式下,有一个Fast Mode Duty,是用来调节高速模式下的占空比的,据野火教程说两个选项没太大差别,一般使用可以随便选;
  • HAL库函数手动编写方式
    • 初始化IIC:HAL_I2C_Init
    • 初始化时钟和GPIO:HAL_I2C_MspInit
  • 在需要的位置使用HAL_I2C_Mem_Read或者HAL_I2C_Mem_Write进行读写。这两个函数直接可以一次性指定目标从机地址、寄存器地址、要写入寄存器的数据等,超级方便:
      • hi2c:IIC句柄;
      • DevAddress:从机通讯读地址(注意是通讯地址,不是设备地址,分读写地址不同那个);
      • MemAddress:操作的从机寄存器地址;
      • MemAddSize:从机寄存器数据宽度;
      • pData:准备写入的数据的地址或指针;
      • Size:准备写入的数据的字节数;
      • Timeout:超时时间;
      • pData:返回的数据将要写入的缓存地址或指针(一般为变量地址或数组地址);
      • 其余与上一个类似;
  • 除了上述两个函数外,还有两个函数可以实现IIC通信:HAL_I2C_Master_Receive和HAL_I2C_Master_Transmit。这两个只能同时发送从机地址和数据,适合写入和读取那种从机内无需寄存器地址就能读到数据的从机,如传感器之类的。
    • 有博主提出使用HAL_I2C_Mem_Write等于先使用HAL_I2C_Master_Transmit传输第一个寄存器地址,再用HAL_I2C_Master_Transmit传输写入第一个寄存器的数据。我没有试验过,不知道对不对。

3.3    注意事项

  • 在使用HAL_I2C_Mem_Write的过程中,需要注意AT24C02一页只有8个字节的数据,所以一次Write的长度最多是8,要在循环写32次才能写完整片。循环过程记住要改变MemAddress(每次+8);
  • 在Write的循环中,请务必务必在每次Write后delay一段时间,具体的时间可根据EEPROM手册上说的时间设置,最好设置大一点;
  • 在读写过程中设置的超时时间也应设置大一点;
  • 不过在HAL_I2C_Mem_Read过程中就不需要分页,直接能读256个字节;

4    关于AT24C04、AT24C08、AT24C16

前面提到,这几个性高的通讯地址中有一定的位数是寄存器地址的借位:

由于其数据地址的借位,在发送通讯地址的时候,要结合数据地址对通讯地址进行处理。这篇文章讲得很好:

AT24C04、AT24C08、AT24C16系列EEPROM芯片单片机读写驱动程序-CSDN博客

这里截取一下其对写入的处理:

其中,第一个IIC_WriteByte,实际上是将设备地址DEV_ADDR和写地址WRITE_CMD(即0)或操作组成通讯的写地址;其次,对数据地址进行右移8位,并与0x07进行与运算,实际上就是取出数据地址中高8位的低3位,即通讯地址中的P2、P1、P0(若有的话对应位就是1,所以用或运算很安全)。然后还对取出的低三位进行了左移1位运算,再与通讯地址做与运算,这是因为通讯地址的最低位是读/写设置位。

第二个IIC_WriteByte就是将剩下的8位数据地址也发过去,发完就可以开始发数据了。

  • 15
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32IIC通信是通过SDA和SCL两个引脚进行的。在进行读取数据时,可以使用IIC_Read_Data函数来读取数据。该函数通过拉高SCK电平,并在每个时钟脉冲中读取一个bit的数据,最后返回读取到的数据。\[1\] 要检测IIC设备是否存在,可以使用ee_CheckDevice函数。该函数发送设备地址,并读取设备是否返回应答信号来判断设备是否存在。返回值为0表示设备存在,返回1表示未探测到IIC设备。\[2\] 在读取数据时,可以使用i2c_ReadByte函数。该函数通过拉高SCL引脚,并在每个时钟脉冲中读取一个bit的数据,最后将数据取出,完成一次8bit数据的读取。\[3\] #### 引用[.reference_title] - *1* [STM32----IIC详解](https://blog.csdn.net/qq_45604814/article/details/116099878)[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* *3* [STM32IIC详细解析](https://blog.csdn.net/qq_43940175/article/details/123437156)[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 ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值