首页 > 其他分享 >硬件IIC主从机中断代码注释解析

硬件IIC主从机中断代码注释解析

时间:2023-02-01 17:46:50浏览次数:61  
标签:解析 slave IIC DBG event RB I2C 主从 i2c

目录

硬件IIC的主从中断在582的最新EVT中已支持。

例程中已封装好中断处理过程,用户调用app_i2c时,初始化中需要配置回调函数即可。若需要串口打印日志,可以在工程预编译中增加宏CONFIG_I2C_DEBUG。

接下来以注释的方式解析一下中断服务函数中做了哪些处理。

__INTERRUPT
__HIGH_CODE
void I2C_IRQHandler(void)
{
    uint32_t event = I2C_GetLastEvent();
     print_i2c_irq_sta(event);

    /* I2C Master */
    if (event & (RB_I2C_MSL << 16)) {       //判断为主机模式
        if (event & RB_I2C_SB) {            //判断主机模式已发送起始信号
            /* Start condition sent, send address */
            I2C_SendData(i2c_slave_addr_rw);    //写从地址到数据寄存器后,SB位会自动清除
            I2C_DBG("Master selected, send address\n");
        }

        /* I2C Master transmitter */
        if (event & (RB_I2C_TRA << 16)) {   //判断是主机的发送模式
            I2C_DBG("Master transmitter:\n");
            /* Slave receiver acked address or sent bit */
            if (event & (RB_I2C_ADDR | RB_I2C_BTF | RB_I2C_TxE | (RB_I2C_TRA << 16))) {
                /* if there is data to send, send it, otherwise stop */
                if (i2c_master_buffer_index < i2c_master_buffer_length) {       //判断待发送数据还没发完
                    I2C_SendData(i2c_master_buffer[i2c_master_buffer_index++]);
                    I2C_DBG("  send (%#x)\n", 
                            i2c_master_buffer[i2c_master_buffer_index - 1]);
                } else {
                    if (i2c_send_stop) {    //判断数据发完了,如果允许产生停止位则产生停止位
                        i2c_state = I2C_READY;
                        I2C_GenerateSTOP(ENABLE);   //产生停止位
                        I2C_DBG("  send STOP\n");
                    } else {
                        i2c_in_repstart = true;     //置标志表示即将重起始
                        /* we're gonna send the START, don't enable the interrupt. */
                        I2C_ITConfig(I2C_IT_BUF, DISABLE);
                        I2C_ITConfig(I2C_IT_EVT, DISABLE);
                        I2C_ITConfig(I2C_IT_ERR, DISABLE);
                        I2C_GenerateSTART(ENABLE);
                        i2c_state = I2C_READY;
                        I2C_DBG("  restart\n");
                    }
                }
            }

            /* Address or data sent, nack received */
            if (event & RB_I2C_AF) {        //地址/数据发送后应答失败
                I2C_ClearFlag(I2C_FLAG_AF);     //清标志

                i2c_error = I2C_MT_NACK;    //置主机发送接收错误标志
                i2c_state = I2C_READY;      //发送停止信号停止帧传输
                I2C_GenerateSTOP(ENABLE);   //产生停止信号
                I2C_DBG("  NACK received, sent stop\n");
            }
        } else {                //判断是主机的接收模式
        /* I2C Master reveiver */
            I2C_DBG("Master receiver:\n");

            /* address sent, ack received */
            if(event & RB_I2C_ADDR) {       //主机成功设置了从机的地址
                /* ack if more bytes are expected, otherwise nack */
                if (i2c_master_buffer_index + 1 < i2c_master_buffer_length) {   //判断接下来需要接收多少字节,如果需要接收多个字节,就置自动回ACK
                    I2C_AcknowledgeConfig(ENABLE);
                    I2C_DBG("  address sent\n");
                    I2C_DBG("  ACK next\n");
                } else {    //判断接下来只接收一个字节,关闭自动回ACK即自动回NACK
                    //XXX: Should not delay too match before NACK 
                    I2C_AcknowledgeConfig(DISABLE);
                    is_nack_sent = true;    //置标志,数据接收时做具体处理
                    I2C_DBG("  address sent\n");
                    I2C_DBG("  NACK next\n");
                }
            }

            /* data reveived */
            if (event & (RB_I2C_RxNE)) {        //接收数据寄存器内非空,即收到数据
                /* put byte into buffer */ 
                i2c_master_buffer[i2c_master_buffer_index++] = I2C_ReceiveData();   //接收数据到buffer中

                if (i2c_master_buffer_index < i2c_master_buffer_length) {   //判断接下来是否为期望接收的最后一个字节
                    I2C_AcknowledgeConfig(ENABLE);      //接下来不是最后一个字节,接收应答设置为自动回ACK
                    I2C_DBG("  ACK next\n");
                } else {
                    //XXX: Should not delay too match before NACK 
                    I2C_AcknowledgeConfig(DISABLE);     //连续读倒数最后一个字节前将接收应答ACK关闭,即最后一个字节后自动回NACK
                    I2C_DBG("  NACK next\n");

                    if (is_nack_sent) {             //如果已设置最后一个字节前置了接收应答NACK
                        is_nack_sent = false;       //清标志
                        if (i2c_send_stop) {
                            I2C_GenerateSTOP(ENABLE);
                            i2c_state = I2C_READY;
                            I2C_DBG("  send STOP\n");
                        } else {
                            i2c_in_repstart = true; //写完了从机内的目标寄存器,发重起始信号
                            /* we're gonna send the START, don't enable the interrupt. */
                            I2C_ITConfig(I2C_IT_BUF, DISABLE);
                            I2C_ITConfig(I2C_IT_EVT, DISABLE);
                            I2C_ITConfig(I2C_IT_ERR, DISABLE);
                            I2C_GenerateSTART(ENABLE);
                            i2c_state = I2C_READY;
                            I2C_DBG("  restart\n");
                        }
                    } else {
                        is_nack_sent = true;        //没有要求
                    }
                }

                I2C_DBG("  received data (%#x)\n", 
                        i2c_master_buffer[i2c_master_buffer_index - 1]);
            }

            /* nack received */
            if (event & RB_I2C_AF) {                //主机接收模式最后一个字节后为NACK
                I2C_ClearFlag(I2C_FLAG_AF);
                /* put final byte into buffer */
                i2c_master_buffer[i2c_master_buffer_index++] = I2C_ReceiveData();       //收下最后一个字节的数据

                if (i2c_send_stop) {            //判断读完之后是停止信号还是重起始信号
                    i2c_state = I2C_READY;
                    I2C_GenerateSTOP(ENABLE);
                    I2C_DBG("  NACK received, send STOP\n");
                } else {
                    i2c_in_repstart = true;     //读完后不停止,会产生重起始信号以衔接后续操作
                    /* we're gonna send the START, don't enable the interrupt. */
                    I2C_ITConfig(I2C_IT_BUF, DISABLE);
                    I2C_ITConfig(I2C_IT_EVT, DISABLE);
                    I2C_ITConfig(I2C_IT_ERR, DISABLE);
                    I2C_GenerateSTART(ENABLE);
                    i2c_state = I2C_READY;
                    I2C_DBG("  restart\n");
                }
            }
        }

    } else {        //判断为从机模式
    /* I2C slave */
        /* addressed, returned ack */
        if (event & RB_I2C_ADDR) {      //地址匹配,接下来判断方向

            if (event & ((RB_I2C_TRA << 16) | RB_I2C_TxE)) {    //判断从机发送方向匹配或者发送方向寄存器空,那么接下来需要发送数据      //发送方向寄存器空需要判断吗?
                I2C_DBG("Slave transmitter address matched\n");
                
                i2c_state = I2C_STX;
                i2c_slave_txbuffer_index = 0;
                i2c_slave_txbuffer_length = 0;

                if (slave_cb && slave_cb->on_transmit) {        //如果注册了回调,就按照回调函数,将数据拷贝到i2c_slave_txbuffer中
                    slave_cb->on_transmit(i2c_slave_txbuffer, &i2c_slave_txbuffer_length);
                }
            } else {                //判断从机接收方向地址匹配,那么接下来需要接收数据
                I2C_DBG("Slave reveiver address matched\n");

                i2c_state = I2C_SRX;
                i2c_slave_rxbuffer_index = 0;
            }
        }

        if (event & (RB_I2C_TRA << 16)) {       //从机发送
            /* Slave transmintter */
            I2C_AcknowledgeConfig(ENABLE);      //预设自动回复ACK
            I2C_DBG("Slave transmitter:\n");

            if (event & RB_I2C_AF) {        //收到了NACK,发送失败
                /* Nack received */
                I2C_ClearFlag(I2C_FLAG_AF);     //清除应答失败标志
                I2C_AcknowledgeConfig(ENABLE);  //预设自动回复ACK
                I2C_DBG("  Nack received\n");

                /* leave slave receiver state */
                i2c_state = I2C_READY;
                /* clear status */
                event = 0;
            }

            if(event & (RB_I2C_BTF | RB_I2C_TxE)) {     //字节发送结束或者发送方向寄存器空
                /* copy data to output register */

                I2C_SendData(i2c_slave_txbuffer[i2c_slave_txbuffer_index++]);   //逐字节发送数据

                /* if there is more to send, ack, otherwise nack */
                if (i2c_slave_txbuffer_index < i2c_slave_txbuffer_length) {
                    I2C_AcknowledgeConfig(ENABLE);      //预设自动回复ACK
                }else{
                    I2C_AcknowledgeConfig(DISABLE);     //预设自动回复NACK
                }
                I2C_DBG("  send (%#x)\n", 
                        i2c_slave_txbuffer[i2c_slave_txbuffer_index - 1]);
            }
        } else {                    //从机接收
            /* Slave receiver */
            I2C_DBG("Slave receiver:\n");

            if (event & RB_I2C_RxNE) {      //判断非空即收到了数据
                /* if there is still room in the rx buffer */
                //判断还有没有缓存空间,如果仍有空间就接收数据并回ACK,没有更多空间了就回NACK
                if (i2c_slave_rxbuffer_index < I2C_BUFFER_LENGTH) {
                    /* put byte in buffer and ack */
                    i2c_slave_rxbuffer[i2c_slave_rxbuffer_index++] = I2C_ReceiveData();
                    I2C_AcknowledgeConfig(ENABLE);
                    I2C_DBG("  received (%#x)\n", 
                            i2c_slave_rxbuffer[i2c_slave_rxbuffer_index - 1]);
                } else {
                    // otherwise nack
                    I2C_AcknowledgeConfig(DISABLE);
                }
            }

            if (event & RB_I2C_STOPF) {     //从机接收模式下收到停止位,清标志,清数组下标索引
                /* ack future responses and leave slave receiver state */

                R16_I2C_CTRL1 |= RB_I2C_PE; //clear flag

                I2C_DBG("  reveive stop\n");

                /* callback to user defined callback */
                if (slave_cb && slave_cb->on_receive) {
                    slave_cb->on_receive(i2c_slave_rxbuffer, i2c_slave_rxbuffer_index);
                }
                /* since we submit rx buffer , we can reset it */
                i2c_slave_rxbuffer_index = 0;
            }

            if (event & RB_I2C_AF) {        //如果接收模式中接收到了NACK,清标志,预设自动回复ACK
                I2C_ClearFlag(I2C_FLAG_AF);

                /* ack future responses */
                I2C_AcknowledgeConfig(ENABLE);
            }
        }
    }

    if(event & RB_I2C_BERR){            //总线错误
        I2C_ClearFlag(RB_I2C_BERR);
        I2C_GenerateSTOP(ENABLE);

        i2c_error = I2C_BUS_ERROR;
        I2C_DBG("RB_I2C_BERR\n");
    }

    if(event & RB_I2C_ARLO){            //仲裁丢失错误
        I2C_ClearFlag(RB_I2C_ARLO);
        
        i2c_error = I2C_ARB_LOST;
        I2C_DBG("RB_I2C_ARLO\n");
    }

    I2C_DBG("\n");
}

 

标签:解析,slave,IIC,DBG,event,RB,I2C,主从,i2c
From: https://www.cnblogs.com/JayWellsBlog/p/16917961.html

相关文章

  • 第三方软件测试机构解析:加盖CMA、CNAS章的软件测试报告才有效
    一、CMA认证是什么?CMA认证是由省级以上人民政府计量行政部门对检测机构的检测能力及可靠性进行的一种全面的认证及评价,认证对象是所有对社会出具公正数据的产品质......
  • Java并发编程——CompletableFuture源码解析
    前言JDK8为我们带来了CompletableFuture这个有意思的新类,它提供比Future更灵活更强大的回调功能,借助CompletableFuture我们可以更方便的编排异步任务。 由于Com......
  • 随堂笔记3-spring之底层架构核心概念解析
    1.BeanDefinition:bean定义,有一些特定属性描述bean,比如bean类型-class,scope作用域,lazyInit是否懒加载2.beanDefinitionReader:beanDefinition读取器,比如AnnotationBeanDe......
  • 亿佰特SX1280的lora模块关于WIFI干扰优势解析
    SX1280的LORA模式在关于WIFI干扰的情况下相交于传统调制方式具有极大的优势。与用于共存的传统调制技术相比,LoRa物理层的使用为我们提供了一些潜在的额外性能好处,并对带内和......
  • 配置dataguard broker(19C)并主从切换
    环境:OS:CentOS7Oracle:19.3.0.0拓扑结构:一主一从角色         ip             实例id主库         19......
  • 面试题-Redis的主从同步是如何实现的
    Redis的主从同步是如何实现的Redis的主从复制可以根据是否是全量,分为全量同步和增量同步(也叫全量复制和部分复制)。全量复制一般用于初次复制的场景部分复制则用于处理......
  • Redis主从同步分析
    一、Redis主从同步原理1.1Redis主从同步的过程配置好slave服务器连接的master后,slave会建立和master的连接,然后发送sync命令。无论是第一次同步建立的连接还是连接断开后的......
  • xml解析_Jsoup_根据选择器查询、根据Xpath查询
    xml解析_Jsoup_根据选择器查询快捷查询方式:selector:选择器使用的方法:Elements select(String cssQuery)语法:参考Selector类中定义的语法......
  • 669~670 xml的Jsoup快速入门 AND xml解析Jsoup对象
    Jsoup:jsoup是一款Java的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOMCSS以及类似于jQuery的操作方法来取出和操作数据但是用来......
  • Redis主从复制
    Redis主从复一、概念主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master/Leader),后者称为从节点(Slave/Follower),​​数据的复制是单向的,只......