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

目录

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

对于IIC从机中断,例程中已封装好中断处理过程,用户调用app_i2c时,初始化中需要配置回调函数。

初始化的配置如下。

    struct i2c_slave_cb slave_user = {          //配置回调结构体
        .on_receive = i2c_on_slave_receive_user,
        .on_transmit = i2c_on_slave_transmit_user,
    };
    i2c_app_init(RxAdderss);                //IIC硬件模块的初始化及软件标志的初始化

    i2c_slave_cb_register(&slave_user);     //注册回调

默认回调函数如下。

static void i2c_on_slave_transmit_user(uint8_t *data, uint8_t *len)
{
    *len = sizeof(TxData);
    memcpy(data, TxData, sizeof(TxData));
}

static void i2c_on_slave_receive_user(uint8_t *data, uint8_t len)
{
    PRINT("I2C slave receiver callback: received (");
    for(int i = 0; i < len; i++) {
        PRINT(" %#x", data[i]);
    }
    PRINT(" )\n");
}

 

若需要串口打印日志,可以在工程预编译中增加宏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_length) {   //判断接下来需要接收多少字节,如果需要接收多个字节,就置自动回ACK
              //注意这里判断条件,在1.8的583EVT与之前的EVT不同,以这里的为准。
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"); }

 

posted @ 2023-02-01 17:33  JayWell  阅读(524)  评论(0编辑  收藏  举报