看下这种写法:
- void I2C1_IRQHandler(void)
- {
- if (i2c_ctrl[1].enable == 0)
- goto error;
-
- if (I2C1->TOCTL & I2C_TOCTL_TOIF_Msk)
- {
- goto error;
- }
- else if (I2C1->CTL & I2C_CON_I2C_STS)
- {
- uint32_t status = I2C1->STATUS;
- if (i2c_ctrl[1].rw) // read phase
- {
- if ((status == 0x08) || (status == 0x10))
- {
- I2C1->DAT = (i2c_ctrl[1].chip_addr << 1) + 1;
- I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS);
- }
- else if (status == 0x40)
- {
- if (i2c_ctrl[1].read_len > 1)
- {
- // host reply ack
- I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS | I2C_CON_ACK);
- }
- else if (i2c_ctrl[1].read_len == 1)
- {
- // host reply nack
- I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS);
- }
- else
- {
- goto error;
- }
- }
- else if (status == 0x50)
- {
- if (i2c_ctrl[1].read_prt < i2c_ctrl[1].read_len)
- i2c_ctrl[1].read[i2c_ctrl[1].read_prt++] = I2C1->DAT;
- if (i2c_ctrl[1].read_prt < i2c_ctrl[1].read_len - 1)
- {
- // host reply ack
- I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS | I2C_CON_ACK);
- }
- else
- {
- // host reply nack
- I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS);
- }
- }
- else if (status == 0x58)
- {
- if (i2c_ctrl[1].read_prt < i2c_ctrl[1].read_len)
- i2c_ctrl[1].read[i2c_ctrl[1].read_prt++] = I2C1->DAT;
-
- i2c_ctrl[1].read = NULL;
-
- if (i2c_ctrl[1].write != NULL)
- {
- i2c_ctrl[1].rw = 0;
- I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS | I2C_CON_START);
- }
- else
- {
- I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS | I2C_CON_STOP);
- I2C1->TOCTL = 0;
- if (m45x_i2c_callback[1] != NULL &&
- i2c_ctrl[1].callback_enable)
- {
- i2c_ctrl[1].enable = 0;
- i2c_ctrl[1].callback_enable = 0;
- m45x_i2c_callback[1](m45x_i2c_param[1],
- i2c_ctrl[1].read_prt,
- i2c_ctrl[1].write_prt);
- }
- }
- }
- else
- {
- goto error;
- }
- }
- else // write phase
- {
- if ((status == 0x08) || (status == 0x10)) // start send finish
- {
- I2C1->DAT = i2c_ctrl[1].chip_addr << 1;
- I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS);
- }
- else if ((status == 0x18) || (status == 0x28)) // addr/data send finish and ACK received
- {
- if (i2c_ctrl[1].write_prt < i2c_ctrl[1].write_len)
- {
- I2C1->DAT = i2c_ctrl[1].write[i2c_ctrl[1].write_prt++];
- I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS);
- }
- else
- {
- i2c_ctrl[1].write = NULL;
- if (i2c_ctrl[1].read != NULL)
- {
- i2c_ctrl[1].rw = 1;
- I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS | I2C_CON_START);
- }
- else
- {
- I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS | I2C_CON_STOP);
- I2C1->TOCTL = 0;
- if (m45x_i2c_callback[1] != NULL &&
- i2c_ctrl[1].callback_enable)
- {
- i2c_ctrl[1].enable = 0;
- i2c_ctrl[1].callback_enable = 0;
- m45x_i2c_callback[1](m45x_i2c_param[1],
- i2c_ctrl[1].read_prt,
- i2c_ctrl[1].write_prt);
- }
- }
- }
- }
- else
- {
- goto error;
- }
- }
- }
- return;
- error:
- I2C1->TOCTL = I2C_TOCTL_TOIF_Msk;
- I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS | I2C_CON_STOP);
-
- i2c_ctrl[1].enable = 0;
- if (m45x_i2c_callback[1] != NULL && i2c_ctrl[1].callback_enable)
- {
- i2c_ctrl[1].callback_enable = 0;
- m45x_i2c_callback[1](m45x_i2c_param[1], -1, -1);
- }
- }
类似linux的驱动,通过msg将单次需传输的信息全部交友驱动层,驱动通过中断不断访问IIC,直到操作完成,回调高层。
这是最高效的。
|