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;
代码能够正确地接收和处理主机接收模式下的数据,并在达到指定字节数时生成停止条件,以确保数据接收的正确性和完整性。
剩下的都是判断是否为传输错误
|