这是一个非常操蛋的BUG,在之前的程序会发现,就是i2cdetect不能连续执行两次,如果使用不正常的I2C访问时许会导致器件死锁。现在实现一个功能,有Read Only寄存器,也有普通寄存器。
主要逻辑代码是这样的。
const uint8_t BufferIndex_RO[0xFF] = { 0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }; __IO uint8_t BufferState = 0; __IO uint8_t BufferIndex = 0; __IO uint8_t RxBuffer[0xFF]={ 0x67,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }; __IO uint8_t BufferTmp = 0; void I2C2_EV_IRQHandler(void) { /* Check ADDR flag value in ISR register */ if(LL_I2C_IsActiveFlag_ADDR(I2C2)) { /* Verify the Address Match with the OWN Slave address */ if(LL_I2C_GetAddressMatchCode(I2C2) == SLAVE_OWN_ADDRESS) { /* Verify the transfer direction, a read direction, Slave enters transmitter mode */ if(LL_I2C_GetTransferDirection(I2C2) == LL_I2C_DIRECTION_READ) { /* Clear ADDR flag value in ISR register */ LL_I2C_ClearFlag_ADDR(I2C2); /* Enable Transmit Interrupt */ LL_I2C_EnableIT_TX(I2C2); } else { BufferState = I2C_SLAVE_START_WRITE_FIRST; /* Clear ADDR flag value in ISR register */ LL_I2C_ClearFlag_ADDR(I2C2); LL_I2C_EnableIT_RX(I2C2); } } else { /* Clear ADDR flag value in ISR register */ LL_I2C_ClearFlag_ADDR(I2C2); /* Call Error function */ Error_Callback(); } } /* Check NACK flag value in ISR register */ else if(LL_I2C_IsActiveFlag_NACK(I2C2)) { /* End of Transfer */ LL_I2C_ClearFlag_NACK(I2C2); } /* Check TXIS flag value in ISR register */ else if(LL_I2C_IsActiveFlag_TXIS(I2C2)) { /* Call function Slave Ready to Transmit Callback */ //Slave_Ready_To_Transmit_Callback(); LL_I2C_TransmitData8(I2C2, RxBuffer[BufferIndex++]); BufferState = I2C_SLAVE_INIT; } /* Check TXIS flag value in ISR register */ else if(LL_I2C_IsActiveFlag_RXNE(I2C2)) { if(BufferState == I2C_SLAVE_START_WRITE_FIRST){ BufferIndex = LL_I2C_ReceiveData8(I2C2); BufferState = I2C_SLAVE_START_WRITE_DATA; }else if(BufferState == I2C_SLAVE_START_WRITE_DATA){ if(BufferIndex_RO[BufferIndex] == 0xFF){ /* If not 0xFF,it is read only. */ RxBuffer[BufferIndex] = LL_I2C_ReceiveData8(I2C2); }else{ BufferTmp = LL_I2C_ReceiveData8(I2C2); } BufferState = I2C_SLAVE_INIT; }else{ BufferTmp = LL_I2C_ReceiveData8(I2C2); BufferState = I2C_SLAVE_INIT; } } /* Check STOP flag value in ISR register */ else if(LL_I2C_IsActiveFlag_STOP(I2C2)) { /* Clear STOP flag value in ISR register */ LL_I2C_ClearFlag_STOP(I2C2); /* Check TXE flag value in ISR register */ if(!LL_I2C_IsActiveFlag_TXE(I2C2)) { /* Flush the TXDR register */ LL_I2C_ClearFlag_TXE(I2C2); } } /* Check TXE flag value in ISR register */ else if(!LL_I2C_IsActiveFlag_TXE(I2C2)) { /* Do nothing */ /* This Flag will be set by hardware when the TXDR register is empty */ /* If needed, use LL_I2C_ClearFlag_TXE() interface to flush the TXDR register */ } else { /* Call Error function */ Error_Callback(); } }
简单说下,BufferIndex_RO就说明哪些是RO寄存器,RxBuffer就算寄存器内容。
如果利用这个,STM32不断ADC采集DMA到这个数组,然后上面RPI这么访问,岂不是可以做一个外部ADC芯片?
程序放出来记录下。
I2C从机通信寄存器读写
非常感谢博主 去年开始学stm8 还是直接用寄存器在写 最近stm8资源不够 想改成stm32 首先就要用到iic从机 用hal库搞了两三天都没弄好 各种问题 直到看了这篇文章 如获至宝啊 用博主的例程一次就成功了 LL库也便于理解 棒!
@wang 其实HAL库不错的,只不过有些看起来很常用(比如I2C从机)就很难通过HAL实现.