历史上的今天
返回首页

历史上的今天

今天是:2024年09月26日(星期四)

正在发生

2021年09月26日 | 使用STM8L的硬件I2C(二)硬件I2C的事件和检测

2021-09-26 来源:eefocus

1、STM8L STD库对I2C状态的定义

I2C有Master写、Master读、Slave写、Slave读4种模式。


直接寄存器编程当然可以,不过必须吃透Reference手册,而且代码不直观,不易理解。

STD标准库对这四种方式做了抽象,对通信的各阶段都定义了状态进行指示,从而使得

使用逻辑更直观易懂。


下面以Master读写为例进行介绍:


Master写流程:

Master写

Master读流程:

Master 接收

2.EV状态的定义

上述抽象出的各种状态(EV1-EV9),标准库中的实际定义宏如下:

其中EV1-EV4是Slave用,EV5-EV9是Master用。


状态名一览

I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED           : EV1

I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED              : EV1

I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED            : EV1

I2C_EVENT_SLAVE_BYTE_RECEIVED                         : EV2

(I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_GENCALL)    : EV2

I2C_EVENT_SLAVE_BYTE_TRANSMITTED                      : EV3

(I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_GENCALL) : EV3

I2C_EVENT_SLAVE_ACK_FAILURE                           : EV3_2

I2C_EVENT_SLAVE_STOP_DETECTED                         : EV4

I2C_EVENT_MASTER_MODE_SELECT                          : EV5

I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED            : EV6

I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED               : EV6

I2C_EVENT_MASTER_BYTE_RECEIVED                        : EV7

I2C_EVENT_MASTER_BYTE_TRANSMITTING                    : EV8

I2C_EVENT_MASTER_BYTE_TRANSMITTED                     : EV8_2

I2C_EVENT_MASTER_MODE_ADDRESS10                       : EV9


状态值的定义(stm8l15x_i2c.h)


typedef enum

{

  /* --EV5 */

  I2C_EVENT_MASTER_MODE_SELECT   = (uint16_t)0x0301,  /*!< BUSY, MSL and SB flag */

  /* --EV6 */

  I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED = (uint16_t)0x0782,  /*!< BUSY, MSL, ADDR, TXE and TRA flags */

  I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED= (uint16_t)0x0302,  /*!< BUSY, MSL and ADDR flags */

  /* --EV9 */

  I2C_EVENT_MASTER_MODE_ADDRESS10= (uint16_t)0x0308,  /*!< BUSY, MSL and ADD10 flags */

  /* --EV7 */

  I2C_EVENT_MASTER_BYTE_RECEIVED = (uint16_t)0x0340,  /*!< BUSY, MSL and RXNE flags */

  /* --EV8 */

  I2C_EVENT_MASTER_BYTE_TRANSMITTING = (uint16_t)0x0780,  /*!< TRA, BUSY, MSL, TXE flags */

  /* --EV8_2 */

  I2C_EVENT_MASTER_BYTE_TRANSMITTED  = (uint16_t)0x0784,  /*!< EV8_2: TRA, BUSY, MSL, TXE and BTF flags */

  /* --EV1  (all the events below are variants of EV1) */

  /* 1) Case of One Single Address managed by the slave */

  I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED= (uint16_t)0x0202,  /*!< BUSY and ADDR flags */

  I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED = (uint16_t)0x0682,  /*!< TRA, BUSY, TXE and ADDR flags */

  /* 2) Case of Dual address managed by the slave */

  I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED= (uint16_t)0x8200,  /*! DUALF and BUSY flags */

  I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED = (uint16_t)0x8680,  /*! DUALF, TRA, BUSY and TXE flags */

  /* 3) Case of General Call enabled for the slave */

  I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED  = (uint16_t)0x1200,  /*!< EV2: GENCALL and BUSY flags */

  /* --EV2 */

  I2C_EVENT_SLAVE_BYTE_RECEIVED  = (uint16_t)0x0240,  /*!< BUSY and RXNE flags */

  /* --EV4  */

  I2C_EVENT_SLAVE_STOP_DETECTED  = (uint16_t)0x0010,  /*!< STOPF flag */

  /* --EV3 */

  I2C_EVENT_SLAVE_BYTE_TRANSMITTED   = (uint16_t)0x0684,  /*!< TRA, BUSY, TXE and BTF flags */

  I2C_EVENT_SLAVE_BYTE_TRANSMITTING  = (uint16_t)0x0680,  /*!< TRA, BUSY and TXE flags */

  /* --EV3_2 */

  I2C_EVENT_SLAVE_ACK_FAILURE= (uint16_t)0x0004  /*!< AF flag */

} I2C_Event_TypeDef;


如果上述预定义的状不满足需求(一般情况下是足够的),可自定义其他状态值。

可以看出,上述状态的值本质上还是寄存器的状态组合。

比如,I2C_EVENT_MASTER_MODE_SELECT,也就是EV5,其代表的含义为Master控制选中,

其实就是BUSY, MSL 以及 SB 三个标志位被设定的情况。

即:总线忙+Master模式选中+Start生成,代表Master已经控制总线并已发出Start,通讯就绪。


3、STM8L 硬件I2C的使用模式

STM8L中,使用I2C有3种基本的模式,即:


Polling mode(轮询)

Interrupt mode(中断)

DMA mode(DMA)

Polling要通过不停的检查寄存器的值来判断当前通信所处状态,读写代码是阻塞执行的,代码最简单。

中断模式是通过中断触发做动作,代码发出读写开始的指令后,后续无需阻塞执行,代码最复杂。

DMA是走DMA通道传输数据,别途再说明。


4、STM8L标准库所提供的各种I2C状态判断和用法区别

大家使用库的I2C函数判断状态时,总会被多个看起来功能类似却又不太一样的函数困扰。

不清楚应该使用哪一种,在什么样的场合下使用。

STD标准库提供了3种主要的状态监测方式,并分别围绕3个函数进行:


基本状态监测 Basic state monitoring (Using I2C_CheckEvent() function)

高级状态监测 Advanced state monitoring (Using the function I2C_GetLastEvent())

基于标志的状态监测 Flag-based state monitoring (Using the function I2C_GetFlagStatus())

这三种其实没有本质不同,下层都是判断寄存器的值组合。简单的说,


基本状态监测:I2C_CheckEvent()用于判断I2C是否正处于某种状态(EV)。

高级状态监测:I2C_GetLastEvent()返回当前SR1/SR3的组合值(错误除外),由用户自己判断当前是何种状态

标志的状态监测:I2C_GetFlagStatus()用于单独判断单独某个寄存器的位状态

从使用类型上来说,基本状态监测适用于Polling模式,即在不停的轮询当前状态,等待所需的I2C状态并做后续处理。高级状态监测更适合中断下使用,通过事件中断、缓冲中断等判断I2C当前状态,灵活度是最好的(同时更繁琐)。基于标志的状态监测一般用来判断简单状态,如总线忙,或者用于调试。

其实标准库只是对寄存器编程的一层薄封装,无论那种方式,其内在依然是相关寄存器值的检查。


4.1 Basic state monitoring 基本状态监测


它的核心是使用I2C_CheckEvent()函数做出和预期状态是否一致的判断。

I2C_CheckEvent函数将状态寄存器(SR1、SR2和SR3)内容与给定事件进行比较(可以是一个或多个Flag的组合)。如果当前状态包含被检查的标志,则返回SUCCESS,如果当前状态中缺少一个或多个标志,则返回ERROR。


何时使用:


此功能适用于大多数应用程序以及初始化操作

适用于需要定义自己事件的用户

限制:

如果发生错误(即除了监视的标志外,还设置了错误标志), 尽管通信可能已经失败,

但I2C_CheckEvent函数依然可能会返回SUCCESS。

在这种情况下,建议使用错误中断来监视错误,在中断处理中对错误进行判断


对于错误管理,建议使用以下功能:


使用I2C_ITConfig()函数配置并启用错误中断(I2C_IT_ERR)。

实现I2Cx_IRQHandler()函数,作为I2C中断入口函数(x为1,STM8L只有I2C1)

使用I2C_GetFlagStatus()函数或I2C_GetITStatus()函数确定发生了什么错误

使用I2C_ClearFlag()函数或I2C_ClearITPendingBit()函数来清中断

使用I2C_softwarerestcmd()函数或I2C_GenerateStop()函数()返回到正确的通信状态

4.2 Advance Monitoring 高级状态监测

i2c_GetLastEvent()函数返回一个Uint16,其中保存了SR1&SR3状态寄存器的值(SR3为高8位,SR1为低8位)。


何时使用:


和基本监测一样可以适应大多数的场合,而且能避免i2c_GetFlagStatus()函数的局限性(见下)。


可以比较预定义事件或者是用户定义的自定义值。


当需要同时监视多个标志时。不过与i2c_CheckEvent()函数相反i2c_GetLastEvent()函数可以用户自行判断所需事件。


限制:

用户(有时)需要定义自己的事件。如果只检查通信标志,而忽略错误标志,则错误管理和上述简单模式相同。


4.3 Flag-based state monitoring 基于标志的状态监测

何时使用:


用于特定的程序或者调试阶段

适合一次只检查一种Flag的情况(多数的I2C状态需要同时判断多个Flag)

限制:


有些I2C寄存器,如SR1和SR2读取后会被硬件自动清除,因此读取1次Flag可能会让其他位被清除。


检查由多个Flag组合判断事件时,必须读取多次

推荐阅读

史海拾趣

固驰(GUERTE)公司的发展小趣事

在快速发展的同时,固驰电子始终不忘履行社会责任。公司积极参与公益事业,关注环境保护和可持续发展。通过采用环保材料和节能技术,固驰电子努力降低生产过程中的能耗和排放,为构建绿色、低碳的生态环境贡献力量。此外,公司还注重员工培训和职业发展,为员工提供良好的工作环境和晋升机会,实现了企业与员工的共同成长。

申风(everanalog)公司的发展小趣事

随着技术实力的不断提升和产品线的日益丰富,申风(everanalog)公司开始积极拓展市场。公司凭借优质的产品和服务,逐渐在国内市场上树立了良好的品牌形象。同时,公司也积极开展国际合作,与国际知名企业建立了战略合作关系,共同推动集成电路产业的发展。这些合作不仅为公司带来了更多的商业机会,也提升了公司在国际市场上的竞争力。

品赞(G-Switch)公司的发展小趣事
电路结构相对简单,易于实现和维护。
Crystal Semiconductor Corp公司的发展小趣事

Crystal Semiconductor Corp成立之初,面临着资金短缺、技术难题和市场竞争的多重压力。然而,公司的创始人凭借对半导体技术的深刻理解和敏锐的市场洞察力,成功吸引了一批志同道合的工程师和投资者。他们共同攻克了技术难关,推出了首款具有竞争力的晶体管产品,迅速在市场上占据了一席之地。

Changzhou Galaxy Century Microelectronics Co.,Ltd公司的发展小趣事

银河微电自成立之初,便专注于半导体分立器件的研发与生产。面对国内外市场的激烈竞争,公司坚持自主创新,不断投入研发力量,终于在某关键技术上取得了重大突破。这一技术突破不仅提高了产品的性能,还降低了生产成本,使得银河微电的产品在市场上更具竞争力。凭借这一技术优势,银河微电逐渐在行业中树立起了自己的地位。

DESOUTTER公司的发展小趣事

Desoutter公司一直注重技术创新和产品升级。公司拥有一支专业的研发团队,不断投入资源进行新产品的研发和现有产品的改进。例如,公司成功开发了一系列新型气动螺丝起子、气动钻和气动冲击扳手等,这些产品不仅提高了工作效率,还降低了劳动强度。同时,Desoutter公司还利用先进的电脑辅助技术,实现了产品设计和生产的自动化,进一步提升了产品的质量和性能。

问答坊 | AI 解惑

IC名词解释

1、什么是MRAM?MARM(Magnetic Random Access Memory) 是一种非挥发性的磁性随机存储器。它拥有静态随机存储器(SRAM)的高速读取写入能力,以及动态随机存储器(DRAM)的高集成度,而且基本上可以无限次地重复写入。 2、光刻:IC生产的主要工艺手段 ...…

查看全部问答>

MAX7128开发板电路图

MAX7128开发板电路图…

查看全部问答>

一种多功能开关电源的设计

本帖最后由 paulhyde 于 2014-9-15 03:30 编辑 资料 可以 参考 一下  …

查看全部问答>

电源怎么做啊

本帖最后由 paulhyde 于 2014-9-15 09:21 编辑 今年的电源到底能是什么题目呢! 很闹心啊!  …

查看全部问答>

请教在PXA270中添加一个中断服务程序的方法!!!

我需要在BSP中加一个中断,中断引脚是GPIO36 BSP是WINCE42下的,也就是静态申请中断的那种 我的步骤: 1、在OALINTR.H中我加了#define SYSINTR_WIFI  (SYSINTR_FIRMWARE+19) 2、cfwBvd1.c中我分别在OEMInterruptEnable、OEMInterrup ...…

查看全部问答>

大家好,做嵌入那个版本更比较好?

大家好,做嵌入那个版本更好? 我用的redhat9.0,但是有些开发工具编译不过去.比较头痛! 大家都用什么操作系统?那个比较稳定?…

查看全部问答>

问个ARM中数据存储的问题

ARM中有符号数和无符号数怎么区分的?都是补码表示吗? 比方说MOV R1  #0x80000000 R1里面保存的是补码的话:是负数最小 要是无符号的话编译器怎么知道? 要是我做加法的话处理器怎么知道是有符号数还是无符号数加法啊?…

查看全部问答>

tcpmp支持图片浏览吗

tcpmp支持图片浏览吗,如果不支持,可以用什么插件代替?…

查看全部问答>

你们 用哪个 ARM-linux交叉编译器编译Linux

内核用Linux-2.4.27及补丁 compiler: cross-3.0/3.2/3.4 出现的错误如下 3.0: .... hub.c: 317: internal compiler error . flow.c .... 3.2: ... arm-linux-ld : internal error earmelf_linux.c ... 3.4: make dep 时提示: cc1: er ...…

查看全部问答>