15. STM32-I²C 介绍

介绍

I²C(Inter-Integrated Circuit)中文是内部整合电路,属於串列通讯汇流排。最早是由Philips开发,为了使嵌入式系统、手机等等可以连接低速周边装置而发展的,适用於短距离通讯。

I²C只需要两条线即可完成通讯,分别是SDA与SCL因此非常的节省空间。大多应用於小型元件,最常看到的应该是EEPROM这一类的元件。

那I²C与SPI差别在哪呢?

I²C SPI
半/全双工 半双工 全双工
传输速度 较低 较高
所需脚位 2 4 or 3
通讯 允许多个Master 1 Master n Slave
资料传输方式 8bit→8bit 1 bit逐位交换

I²C汇流排架构

使用时允许多个Master进行通讯,将各设备SCL与SDA连结即可。每一设备皆由属於自己的地址,不管是任何设备SDA与SCL都属於Open Drain 的IO脚,同时并接(Wired-And)在两条线路上,皆需要加入上拉电阻。当导通时是低电位不导通时为浮接,所以利用电阻将电位拉高。
https://ithelp.ithome.com.tw/upload/images/20220319/20146325OD2gqO4fyV.png
Wired-And指的是:

→Wired : 直接将设备对应的线接在一起

→And : 也就是大家熟知的And逻辑闸

a b output
0 0 0
0 1 0
1 0 0
1 1 1

也就是说只有当输入都为High的时候才会输出High,任一个为Low即为Low。代表着在汇流排当中只要有一个晶片为Low那就会是Low,而晶片可以轻易地控制Bus输出Low,但要输出High实则连其他晶片也必须同时输出High。


I²C Protocol

https://ithelp.ithome.com.tw/upload/images/20220319/20146325Sm651XEd1g.png
可以看到上图是一个I²C传送资料的过程,先说明一下什麽是SDA与SCL:

SDA : 资料线,所以的资料交换都是在SDA上完成
SCL : 时钟线,由Master输出用

I²C的传输包括了四个部分:最开头的Start信号,接下来会接上设备的I²C地址与传送的资料,最後会接上一个Stop信号。

  1. 先从起始信号与结束信号来看:
    https://ithelp.ithome.com.tw/upload/images/20220319/20146325Gmhm8jZnDl.png

如何开始通讯?可以看到上方一刚开始由SDA与SCL皆处於High的情况,接着SDA向下拉由1变为0,这时SCL一样保持为High,这个动作就可以当作一个开始信号。

SDA = 1;
Delay();
SCL = 1;
Delay();
SDA = 0;
Delay();
SCL = 0;
Delay();

如何结束通讯? 首先由SDA先降为Low而SCL处在High,接着再将SDA拉回High则代表结束通讯。

SDA = 0;
Delay();
SCL = 1;
Delay();
SDA = 1;
Delay();
  1. 资料传输过程 :

在I²C当中交换资料时,是以8bit加上1bit的ACK为一组,每一次交换都是将MSB先传送。无论是I²C的设备地址还是後续要交换的资料都需要按照这个模式去做传送。

ACK与NACK说明

上方提到每一组资料会在後方接上一个ACK bit,而这个bit会由接收端产生。其中又分为ACK与NACK,ACK为Low而NACK为High。在这过程并非发送端一定时Master,也有可能是由Slave在传送,而由Master产生ACK或NACK。

那是不是任何时候都能去透过SDA做资料交换呢?

当然是不行,可以看看下方这张图片说明资料有效性。只有在SCL为Low时才可以去做资料的交换,这时候表示SDA处在混乱的阶段。相反的当SCL为High时则无法去变更SDA,表示SDA处於稳定状态。
https://ithelp.ithome.com.tw/upload/images/20220319/20146325XfAsAjtWmS.png
3. I²C地址说明 :

地址分为7bit与10bit两种地址,大多设备还是使用7bit作为地址长度。而如何区分究竟是7还是10bit则可以看到下图,假设是10bit前方5个bit则为11110而後续接上2bit设备地址并且接上r/w(r:1 / w: 0)後等待ACK,接着才会接收剩余的7bit。
https://ithelp.ithome.com.tw/upload/images/20220319/20146325ZsoGsesVi5.png


.IOC档设定

  1. 左侧Connectivity选单当中可以选择I2C1-I2C3这边以I2C示范。点选後可以看到上方可以设置I2C的模式选择I2C开启。
  • SMBus-Alert-Mode
  • SMBus-two-wire-interface

SMBus另外有支援Alert Signal可以在收到Alert时询问是哪个Slace所发出的,再去对该设备进行後续处理。

https://ithelp.ithome.com.tw/upload/images/20220319/20146325wmmodGgj2C.png
2. GPIO脚位 : I2C1的SCL连接为PB6 SDA为PB7
https://ithelp.ithome.com.tw/upload/images/20220319/20146325euxOzMgzFh.png
3. 详细设置
https://ithelp.ithome.com.tw/upload/images/20220319/20146325sB30lvnKoN.png


函数说明

同样的有分为轮询与中断方式

Master

  • 传送轮询方式
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,uint16_t Size, uint32_t Timeout)
  • 接收轮询方式
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,uint16_t Size, uint32_t Timeout);
  • 传送 中断方式
HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,uint16_t Size);
  • 接收 中断方式
HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,uint16_t Size);

Slave

  • 传送轮询方式
HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,uint32_t Timeout);
  • 接收轮询方式
HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,uint32_t Timeout);
  • 传送 中断方式
HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);
  • 接收 中断方式
HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);

中断回调函式-Master

  • 传送中断回调函式
__weak void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(hi2c);

  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_I2C_MasterTxCpltCallback could be implemented in the user file
   */
}
  • 接收中断回调函式
__weak void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(hi2c);

  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_I2C_MasterRxCpltCallback could be implemented in the user file
   */
}

中断回调函式-Slave

  • 传送中断回调函式
__weak void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(hi2c);

  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_I2C_SlaveTxCpltCallback could be implemented in the user file
   */
}
  • 接收中断回调函式
__weak void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(hi2c);

  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_I2C_SlaveRxCpltCallback could be implemented in the user file
   */
}

<<:  Python & Celery 学习笔记_重试策略 (retry)

>>:  Python & Celery 学习笔记_任务链结

Day25 - 加入简单的动画

今天想偷个懒,先为App加入一点动画, 主要是从欢迎页到登入页的过度动画。 Navigation t...

Day14:堆积排序(Heap Sort)

堆积(Heap) 堆积,是一种树状结构,用於实现「优先伫列(Priority queue)」。Pri...

资安学习路上-渗透测试实务3

漏洞利用 利用侦测到的现有漏洞取得初始控制权 上图取自台科大资安社课教材 1. Exploit-db...

[Day15]ISO 27001 标准:内稽管审

是菜稽还是老稽,大部份可以看他们稽核的顺序来辨别, 有一阵子观察五年以上的资深前辈,会从内稽、管审开...

Day 05 - Scanners

本篇重点 Scanners介绍 当日成交金额排行 当日成交量排行 当日涨(跌)金额排行 最高/最低价...