【STM32】IIC

news/2024/10/21 6:28:30/

超级常见的外设通信方式,一般叫做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位数据地址也发过去,发完就可以开始发数据了。


http://www.ppmy.cn/news/1519479.html

相关文章

【python 第七篇章】类

在Python中,类(Class)是一种用于定义对象(Object)的蓝图或模板。通过类,我们可以创建具有相同属性和方法的对象。Python的类提供了面向对象编程(OOP)的所有基本功能:封装…

SpringBatch4升级SpringBatch5踩坑指南

SpringBatch5使用JDK17作为基线版本&#xff0c;若项目未升级&#xff0c;亦无需升级springbatch。 报错1:JobParameter类型问题 报错内容&#xff1a; java.util.Map.Entry<java.lang.String,org.springframework.batch.core.JobParameter<?>>无法转换为java.u…

RabbitMQ 常见问题与故障排查

目录 前言 常见错误与解决方案 1. 连接失败 2. 队列阻塞 3. 消息丢失 4. 消费者不消费 5. 资源耗尽 日志分析 1. 配置 RabbitMQ 日志 2.日志文件位置 3. 日志分析工具 4. 分析日志文件 5. 常见日志问题及解决方案 Docker中日志分析 1. 查看 RabbitMQ 日志 2. 获…

elasticsearch安装在服务器并进行向量检索

服务器安装elasticsearch 安装Elasticsearch的步骤通常包括以下几个阶段&#xff1a; 导入Elasticsearch公钥。 创建Elasticsearch仓库。 安装Elasticsearch。 启动Elasticsearch服务。 配置Elasticsearch开机自启。 以下是针对基于Debian/Ubuntu系统的安装示例&#xf…

OpenCV绘图函数(6)绘制椭圆函数ellipse()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 画出一个简单的或粗的椭圆弧或者填充一个椭圆扇形。 函数 cv::ellipse 使用更多的参数可以画出椭圆轮廓、填充的椭圆、椭圆弧或填充的椭圆扇形。…

SQL慢查询优化方式

目录 一、SQL语句优化 1.避免使用 SELECT * &#xff0c;而是具体字段 2.避免使用 % 开头的 LIKE 的查询 3.避免使用子查询&#xff0c;使用JOIN 4.使用EXISTS代替IN 5.使用LIMIT 1优化查询 6.使用批量插入、优化INSERT操作 7.其他方式 二、SQL索引优化 1.在查询条件…

python:浅谈yolov10对比yolov5的方便之处

文章目录 前言一、环境配置二、数据标注三、配置文件四、训练数据五、数据预测总结 前言 ‌YOLOv10‌是YOLO系列的最新版本&#xff0c;旨在提高推理速度并减少计算开销。它是实时目标检测领域中的一项重要进展&#xff0c;通过移除非最大值抑制(NMS)并采用双重标签分配、空间…

Cesium 台湾省白膜数据渲染

Cesium 台湾省白膜数据渲染 效果图