870|1

8

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

N32G430官方示例代码I2C_Master_Int中void I2C1_EV_IRQHandler(void)详解 [复制链接]

 
void I2C1_EV_IRQHandler(void)
{
    uint32_t last_event = 0;

    last_event = I2C_Last_Event_Get(I2C1);
    if ((last_event & I2C_ROLE_MASTER) == I2C_ROLE_MASTER) /* master mode */
    {
        switch (last_event)
        {
        case I2C_EVT_MASTER_MODE_FLAG: /* 0x00030001.EV5 Send addr */
            
            if(flag_trans_direct)     /* read */
            {
                Memset(rx_buf, 0, TEST_BUFFER_SIZE); /* clear recv buf, ready to recv data */
                I2C_7bit_Addr_Send(I2C1, I2C_SLAVE_ADDR, I2C_DIRECTION_RECV);
                rx_num = 0;
            }
            else /* write */
            {
                I2C_7bit_Addr_Send(I2C1, I2C_SLAVE_ADDR, I2C_DIRECTION_SEND);
                tx_num = 0;
            }
            break;

           /* MasterTransmitter	 */
        case I2C_EVT_MASTER_TXMODE_FLAG: /* 0x00070082. EV6 Send first data */
            Comm_Flag = C_READY;
            I2C_Data_Send(I2C1, tx_buf[tx_num++]);
            break;

        case I2C_EVT_MASTER_DATA_SENDING: /* 0x00070080. EV8 Sending data  */
            if (tx_num < TEST_BUFFER_SIZE)
            {
                I2C_Data_Send(I2C1, tx_buf[tx_num++]);
            }
            break;
            
        case I2C_EVT_MASTER_DATA_SENDED: /* 0x00070084.EV8_2 Send finish */
            if (tx_num == TEST_BUFFER_SIZE)
            {
                if (Comm_Flag == C_READY)
                {
                    Comm_Flag = C_STOP_BIT;
                    I2C_Generate_Stop_Enable(I2C1);
                    flag_master_send_finish = 1;
                }
            }
            break;
            
            /* MasterReceiver */
        case I2C_EVT_MASTER_RXMODE_FLAG: /* 0x00030002.EV6 */
            Comm_Flag = C_READY;
            if (TEST_BUFFER_SIZE == 1)
            {
                I2C_Acknowledg_Disable(I2C1);
                if (Comm_Flag == C_READY)
                {
                    Comm_Flag = C_STOP_BIT;
                    I2C_Generate_Stop_Enable(I2C1);
                }
            }
            else if (TEST_BUFFER_SIZE == 2)
            {
                I2C1->CTRL1 |= I2C_NACK_POS_NEXT; /* set ACKPOS */
                I2C_Acknowledg_Disable(I2C1);
            }
            break;

        case I2C_EVT_MASTER_DATA_RECVD_FLAG: /* 0x00030040. EV7.one byte recved  */
        case I2C_EVT_MASTER_DATA_RECVD_BSF_FLAG: /* 0x00030044. EV7.When the I2C communication rate is too high, BSF = 1 */
            
            rx_buf[rx_num++] = I2C_Data_Recv(I2C1);
            if (rx_num == (TEST_BUFFER_SIZE - 1))
            { 
                I2C_Acknowledg_Disable(I2C1);   /* Disable I2C1 acknowledgement. */
                if (Comm_Flag == C_READY)
                {
                    Comm_Flag = C_STOP_BIT;
                    I2C_Generate_Stop_Enable(I2C1); /* Send I2C1 STOP Condition. */
                }
            }
            else if (rx_num == TEST_BUFFER_SIZE)
            {
                flag_master_recv_finish = 1;
            }
            break;
        case 0x00030201: /* Arbitration lost */
        case 0x00030401: /* Acknowledge failure */
        case 0x00030501: /* Acknowledge failure and Bus error */
        case 0x00070000: /* TRF, BUSY, MSMODE flags */
            I2C_OFF(I2C1);
            I2C_ON(I2C1);
            break;

        default:
            log_info("I2C error status:0x%x\r\n", last_event);
            break;
        }
    }
}

上一个帖子主要是看其中函数开始的时候last_event中的值是多少,现在已知里面的内容是两个状态寄存器值得集合

内容是
I2C_STS2-----I2C_STS1
xxxx xxxx --zzzz zzzz----last_event

接下来看第一个判断函数

if ((last_event & I2C_ROLE_MASTER) == I2C_ROLE_MASTER)

其中还有一个数据I2C_ROLE_MASTER对应的值

//官方实例例程的内容
#define I2C_ROLE_MASTER (((uint32_t)I2C_STS2_MSMODE)<<16) 
#define I2C_STS2_MSMODE    ((uint16_t)0x0001) /* Master/Slave */
//由此可以看出来I2C_ROLE_MASTER中的值为
//0000 0001 0000 0000 

这时候看(last_event & I2C_ROLE_MASTER)==I2C_ROLE_MASTER

这个语句的意思主要是看last_event的第九位,也就是I2C_STS2中的第一位是不是1

然后看手册中对状态寄存器2的内容

 

 

从上面的图可以看出来这个判断语句主要是判断目前是不是主模式

接下来就是对主模式中的其他状态继续观察

case I2C_EVT_MASTER_MODE_FLAG: /* 0x00030001.EV5 Send addr */

#define I2C_EVT_MASTER_MODE_FLAG (((uint32_t)I2C_STS1_STARTBF)\
                                |((((uint32_t)I2C_STS2_BUSY)|((uint32_t)I2C_STS2_MSMODE))<<16))

#define I2C_STS1_STARTBF  ((uint16_t)0x0001) /* Start Bit (Master mode) */
//----0000 0000 0000 0001
#define I2C_STS2_BUSY      ((uint16_t)0x0002) /* Bus Busy */
//----0000 0000 0000 0010
#define I2C_STS2_MSMODE    ((uint16_t)0x0001) /* Master/Slave */
//----0000 0000 0000 0001
//根据上面的内容计算得出 I2C_EVT_MASTER_MODE_FLAG的结果
//0000 0011 0000 0001
//分别对应-----主模式-----在总线上正在进行数据通信-----起始条件已发送
//如果成功就说明满足上面的内容

接下来的内容简洁续写

case I2C_EVT_MASTER_TXMODE_FLAG:
#define I2C_EVT_MASTER_TXMODE_FLAG (((uint32_t)I2C_STS1_ADDRF)|((uint32_t)I2C_STS1_TXDATE)\
                                  |((((uint32_t)I2C_STS2_BUSY)|((uint32_t)I2C_STS2_MSMODE)\																																																 
                                  |((uint32_t)I2C_STS2_TRF))<<16))
主模式---在总线上正在进行数据通讯---数据发送模式---地址发送完成---数据寄存器空
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case I2C_EVT_MASTER_DATA_SENDING: 
#define I2C_EVT_MASTER_DATA_SENDING (((uint32_t)I2C_STS1_TXDATE)\
                                  |((((uint32_t)I2C_STS2_BUSY)|((uint32_t)I2C_STS2_MSMODE)\
                                  |((uint32_t)I2C_STS2_TRF))<<16))
主模式---在总线上正在进行数据通讯---数据发送模式---数据寄存器空
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case I2C_EVT_MASTER_DATA_SENDED:
#define I2C_EVT_MASTER_DATA_SENDED (((uint32_t)I2C_STS1_BSF)|((uint32_t)I2C_STS1_TXDATE)\
                                  |((((uint32_t)I2C_STS2_BUSY)|((uint32_t)I2C_STS2_MSMODE)\
                                  |((uint32_t)I2C_STS2_TRF))<<16)) 
主模式---在总线上正在进行数据通讯---数据发送模式---数据寄存器空---字节传输结束
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case I2C_EVT_MASTER_RXMODE_FLAG:
#define I2C_EVT_MASTER_RXMODE_FLAG (((uint32_t)I2C_STS1_ADDRF)\
                                  |((((uint32_t)I2C_STS2_BUSY)|((uint32_t)I2C_STS2_MSMODE))<<16))
主模式---在总线上正在进行数据通讯---地址发送完成
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case I2C_EVT_MASTER_DATA_RECVD_FLAG:
#define I2C_EVT_MASTER_DATA_RECVD_FLAG (((uint32_t)I2C_STS1_RXDATNE)\
                                  |((((uint32_t)I2C_STS2_BUSY)|((uint32_t)I2C_STS2_MSMODE))<<16))
主模式---在总线上正在进行数据通讯---数据寄存器非空
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

case I2C_EVT_MASTER_DATA_RECVD_BSF_FLAG:
#define I2C_EVT_MASTER_DATA_RECVD_BSF_FLAG (((uint32_t)I2C_STS1_RXDATNE)|((uint32_t)I2C_STS1_BSF)\
                                  |((((uint32_t)I2C_STS2_BUSY)|((uint32_t)I2C_STS2_MSMODE))<<16))
主模式---在总线上正在进行数据通讯---数据寄存器非空---字节传输结束
case 0x00030201: /* Arbitration lost */
case 0x00030401: /* Acknowledge failure */
case 0x00030501: /* Acknowledge failure and Bus error */
case 0x00070000: /* TRF, BUSY, MSMODE flags */

判断条件看完了,接下来看里面的内容

case I2C_EVT_MASTER_MODE_FLAG: /* 0x00030001.EV5 Send addr */
            
            if(flag_trans_direct)     /* read */
            {
                Memset(rx_buf, 0, TEST_BUFFER_SIZE); /* clear recv buf, ready to recv data */
                I2C_7bit_Addr_Send(I2C1, I2C_SLAVE_ADDR, I2C_DIRECTION_RECV);
                rx_num = 0;
            }
            else /* write */
            {
                I2C_7bit_Addr_Send(I2C1, I2C_SLAVE_ADDR, I2C_DIRECTION_SEND);
                tx_num = 0;
            }
            break;

           /* MasterTransmitter	 */

首先看if(flag_trans_direct)
里面的flag_trans_direct这个是读写标志
如果为1就说明要进行读操作,如果为0就进行写操作

首先如果为1进行读操作

  Memset(rx_buf, 0, TEST_BUFFER_SIZE); /* clear recv buf, ready to recv data */
  I2C_7bit_Addr_Send(I2C1, I2C_SLAVE_ADDR, I2C_DIRECTION_RECV);
  rx_num = 0;

先看第一句

Memset(rx_buf, 0, TEST_BUFFER_SIZE);
先看原型
void Memset(void* s, uint8_t c, uint32_t count)
{
    char* xs = (char*)s;

    while (count--) /* clear 17byte buffer */
    {
        *xs++ = c;
    }

    return;
}
再看三个输入参数rx_buf、0、TEST_BUFFER_SIZE
rx_buf是官方定义的一个读缓存取,读到的数据存储在rx_buf中,大小为TEST_BUFFER_SIZE  
TEST_BUFFER_SIZE---官方内容---#define TEST_BUFFER_SIZE  100
所以Memset(rx_buf, 0, TEST_BUFFER_SIZE);的含义就是清空读缓存区

然后

       I2C_7bit_Addr_Send(I2C1, I2C_SLAVE_ADDR, I2C_DIRECTION_RECV);
函数原型
void I2C_7bit_Addr_Send(I2C_Module* I2Cx, uint8_t address, uint8_t mode)
{
    /* Test on the direction to set/reset the read/write bit */
    if (mode == I2C_DIRECTION_RECV)
    {
        /* Set the address bit0 for read */
        address |= I2C_ADDR0_SET;
    }
    else
    {
        /* Reset the address bit0 for write */
        address &= I2C_ADDR0_RESET;
    }
    /* Send the address */
    I2Cx->DAT = address;
}
第一个参数为I2C1的寄存器结构体
第二个参数为结构体的地址
第三个参数为传输方向,这里是从目标方向读取数据
所以以上的函数为
向 I2C1 发送一个读取方向的 I2C 7 位地址,并且成功设置了 address 参数的第 0 位为 1,以标识读取方向。

在这里我发现这个函数对于读操作还是写操作进行了两次判断,先在外面进行了一次读写判断,然后在I2C_7bit_Addr_Send中又进行了一次读写操作

然后进行tx_num = 0;将数据传输量置为0,去除地址发送的字节数

继续进行

case I2C_EVT_MASTER_TXMODE_FLAG: /* 0x00070082. EV6 Send first data */
            Comm_Flag = C_READY;
            I2C_Data_Send(I2C1, tx_buf[tx_num++]);
            break;
先通过 Comm_Flag = C_READY;表示为通信已准备就绪,可以开始传输数据
然后通过I2C_Data_Send(I2C1, tx_buf[tx_num++]);将数据传输
原型为
void I2C_Data_Send(I2C_Module* I2Cx, uint8_t data)
{
    /* Write in the DAT register the data to be sent */
    I2Cx->DAT = data;
}

接下来判断数据传输

case I2C_EVT_MASTER_DATA_SENDING: /* 0x00070080. EV8 Sending data  */
            if (tx_num < TEST_BUFFER_SIZE)
            {
                I2C_Data_Send(I2C1, tx_buf[tx_num++]);
            }
            break;

然后判断数据传输量是否等于一次数据,如果等于代表这个数据帧传输结束,将各项标志位改变,并添加停止位

case I2C_EVT_MASTER_DATA_SENDED: /* 0x00070084.EV8_2 Send finish */
            if (tx_num == TEST_BUFFER_SIZE)
            {
                if (Comm_Flag == C_READY)
                {
                    Comm_Flag = C_STOP_BIT;
                    I2C_Generate_Stop_Enable(I2C1);
                    flag_master_send_finish = 1;
                }
            }
            break;

接下来

case I2C_EVT_MASTER_RXMODE_FLAG: /* 0x00030002.EV6 */
            Comm_Flag = C_READY;
            if (TEST_BUFFER_SIZE == 1)
            {
                I2C_Acknowledg_Disable(I2C1);
                if (Comm_Flag == C_READY)
                {
                    Comm_Flag = C_STOP_BIT;
                    I2C_Generate_Stop_Enable(I2C1);
                }
            }
            else if (TEST_BUFFER_SIZE == 2)
            {
                I2C1->CTRL1 |= I2C_NACK_POS_NEXT; /* set ACKPOS */
                I2C_Acknowledg_Disable(I2C1);
            }
            break;
这段代码还没有想明白,明明TEST_BUFFER_SIZE的默认值都是100,怎么会跟1和2进行判断?
想不明白

继续

case I2C_EVT_MASTER_DATA_RECVD_FLAG: /* 0x00030040. EV7.one byte recved  */
        case I2C_EVT_MASTER_DATA_RECVD_BSF_FLAG: /* 0x00030044. EV7.When the I2C communication rate is too high, BSF = 1 */
            
            rx_buf[rx_num++] = I2C_Data_Recv(I2C1);
            if (rx_num == (TEST_BUFFER_SIZE - 1))
            { 
                I2C_Acknowledg_Disable(I2C1);   /* Disable I2C1 acknowledgement. */
                if (Comm_Flag == C_READY)
                {
                    Comm_Flag = C_STOP_BIT;
                    I2C_Generate_Stop_Enable(I2C1); /* Send I2C1 STOP Condition. */
                }
            }
            else if (rx_num == TEST_BUFFER_SIZE)
            {
                flag_master_recv_finish = 1;
            }
            break;

代码能够正确地接收和处理主机接收模式下的数据,并在达到指定字节数时生成停止条件,以确保数据接收的正确性和完整性。

剩下的都是判断是否为传输错误

最新回复

代码能够正确地接收和处理主机接收模式下的数据,并在达到指定字节数时生成停止条件,这就可以   详情 回复 发表于 2023-12-30 22:49
点赞 关注
 
 

回复
举报

6850

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

代码能够正确地接收和处理主机接收模式下的数据,并在达到指定字节数时生成停止条件,这就可以

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表