zoukankan      html  css  js  c++  java
  • STM32-I2C_CheckEvent-标志位自动清除理解

    STM32里I2C_CheckEvent函数我们应该是相当熟悉了,在每次发送数据后我们都需要检验相应的EVx(x = 0,1,2,,,)事件是否有发送。

    函数定义如下:

     1 ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
     2 {
     3   uint32_t lastevent = 0;
     4   uint32_t flag1 = 0, flag2 = 0;
     5   ErrorStatus status = ERROR;
     6 
     7   /* Check the parameters */
     8   assert_param(IS_I2C_ALL_PERIPH(I2Cx));
     9   assert_param(IS_I2C_EVENT(I2C_EVENT));
    10 
    11   /* Read the I2Cx status register */
    12   flag1 = I2Cx->SR1;
    13   flag2 = I2Cx->SR2;
    14   flag2 = flag2 << 16;
    15 
    16   /* Get the last event value from I2C status register */
    17   lastevent = (flag1 | flag2) & FLAG_Mask;
    18 
    19   /* Check whether the last event contains the I2C_EVENT */
    20   if ((lastevent & I2C_EVENT) == I2C_EVENT)
    21   {
    22     /* SUCCESS: last event is equal to I2C_EVENT */
    23     status = SUCCESS;
    24   }
    25   else
    26   {
    27     /* ERROR: last event is different from I2C_EVENT */
    28     status = ERROR;
    29   }
    30   /* Return status */
    31   return status;
    32 }

    该函数第一个参数是输入需要检查的I2Cx(x = 1,2,3,4,5)外设,第二个参数是检查的事件,如下所示:

    I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED :       EV1
    I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED :         EV1
    I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED :     EV1
    I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED :       EV1
    I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED :         EV1
    I2C_EVENT_SLAVE_BYTE_RECEIVED :                 EV2
    (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_DUALF) :       EV2
    (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_GENCALL) :       EV2
    I2C_EVENT_SLAVE_BYTE_TRANSMITTED :               EV3
    (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_DUALF) :     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

    本文就举里面常用的一些事件为例,来分析该函数为什么能够自动清除标志位。包含EV5,EV6,EV8以及EV7事件。

    在使用I2C发送数据时我们会用到EV5,EV6,EV8事件,事件名称及定义如下:

    /*I2C_EVENT_MASTER_MODE_SELECT                          : EV5*/
    #define  I2C_EVENT_MASTER_MODE_SELECT                      ((uint32_t)0x00030001)  /* BUSY, MSL and SB flag */
    
    /*I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED            : EV6 */
    #define  I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED        ((uint32_t)0x00070082)  /* BUSY, MSL, ADDR and TRA flags */
    /*I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED               : EV6*/
    #define  I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED           ((uint32_t)0x00030002)  /* BUSY, MSL and ADDR flags */
    
    
    /*I2C_EVENT_MASTER_BYTE_TRANSMITTING                    : EV8*/
    #define I2C_EVENT_MASTER_BYTE_TRANSMITTING                 ((uint32_t)0x00070080) /* TRA, BUSY, MSL, TXE flags */
    /*I2C_EVENT_MASTER_BYTE_TRANSMITTED                     : EV8_2*/
    #define  I2C_EVENT_MASTER_BYTE_TRANSMITTED                 ((uint32_t)0x00070084)  /* TRA, BUSY, MSL, TXE and BTF flags */
    • 根据I2C_CheckEvent函数的定义,事件的高16位为I2C外设的SR2寄存器,低16位为I2C外设的SR1寄存器。
    • 先来看看 I2C_EVENT_MASTER_MODE_SELECT,宏定义为,0x00030001,对应的SR1和SR2寄存器如下所示:

    其中MSL为1表为主模式,BUSY为1表总线忙碌,

    这两位一般都是在产生STOP信号的时候置0,其他时候都为1。

    看看SB位如何清零,

    我们在Check_Event函数里面读取了SR1寄存器,我们在发送了起始信号之后就需要发送设备地址进行访问,在I2C_Send7bitAddress函数里面我们访问了数据寄存器SD,于是在下一次检测标志位之前SB被清除。

    • 再来看看两个EV6事件 I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED 和 I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED,这两者的区别就是一个用于发送模式,另一个用于接受模式,发送模式为0x00070082,

     

    TRA数据单元一般产生STOP信号后清除,至于ADDR位,在I2C_CheckEvent函数里面,我们是顺序地读取了SR1和SR2寄存器,于是ADDR位被清除。对于TxE位,我们下一步能会进行数据发送操作,也就是使用I2C_SendData函数访问DR数据寄存器,于是TxE也被清除。

    • 还有一个EV8事件 I2C_EVENT_MASTER_BYTE_TRANSMITTED, 定义为0x00070084,

     

    此处只讨论BTF位的清除,

    也是访问SR1寄存器和对数据寄存器的读或写可以清除该位,因此BTF位也被清除。

    至于I2C_CheckEvent里面其他事件所设计的位清除,我就不一一举例了,可以按照这个思路,参考STM32F10x-中文参考手册自己一步步的查看。

    I2C_ChencEvent比I2C_GetFlagStatus函数好的一点就是它检测了与事件相关的所有寄存器位,而后者只检测提供的标志位。

  • 相关阅读:
    20165103 第四周查漏补缺
    20165103 2017-2018-2 《Java程序设计》第3周学习总结
    20165103 2017-2018-2 《Java程序设计》第2周学习总结
    20165103 2017-2018-2 《Java程序设计》第1周学习总结
    MySQL事务一致性理解
    mysql的事务四个特性以及 事务的四个隔离级别
    序列化和反序列化的简单理解
    内存溢出和内存泄漏的区别,产生原因以及解决方案
    oracle入门学习之oracle数据库结构
    Java微服务(Spring-boot+MyBatis+Maven)入门教程
  • 原文地址:https://www.cnblogs.com/jackis-tang/p/11224512.html
Copyright © 2011-2022 走看看