这是一个非常操蛋的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实现.