【STM8】STM8S I2C Slave模式错误解决

it2023-06-15  65

文章目录

1.问题背景2.I2C Slave模式3.分析验证

1.问题背景

在STM8S平台使用I2C Slave模式,参考STM8S的标准库的Sample Code,但是只要Master Controller Read/Write多个Bytes时,就会存在中断一直被触发的问题。因为中断对应的I2C State Register没有被正确的清除,所以中断一直被触发导致I2C通信失败。

参考STM8S的标准库的Sample Code路径如下: STM8S_StdPeriph_Lib\Project\STM8S_StdPeriph_Examples\I2C\I2C_TwoBoards\I2C_DataExchange\Slave\

2.I2C Slave模式

下面是STM8S I2C Slave模式的参考代码,我这边验证目前没有遇到问题。

#define I2C_DATA_SIZE 8 #if ((I2C_DATA_SIZE > 0) && ((I2C_DATA_SIZE & (I2C_DATA_SIZE - 1)) != 0)) #error I2C_DATA_SIZE isnt a power of 2. #endif #define uint8_bits_def(x) union \ {\ unsigned char x; \ struct \ {\ unsigned char x##_Bit0:1, \ x##_Bit1:1, \ x##_Bit2:1, \ x##_Bit3:1, \ x##_Bit4:1, \ x##_Bit5:1, \ x##_Bit6:1, \ x##_Bit7:1; \ };\ } uint8_bits_def(tagI2C); uint8_t i2c_addr = 0; uint8_t i2c_data[I2C_DATA_SIZE] = {0x00}; void I2C_Slave_IRQHandler(void) { volatile I2C_Event_TypeDef Event = I2C_GetLastEvent(); /* Slave address matched with the address sent by master */ /* EV1: ADDR = 1, 顺序读SR1,SR3寄存器清除此标志位 */ if(Event == (I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED)) { tagI2C_Bit0 = 1; } /* Slave received the data byte from master */ /* EV2: RxNE = 1, 读DR寄存器清除此位 */ else if(Event == (I2C_EVENT_SLAVE_BYTE_RECEIVED)) { uint8_t ch = I2C_ReceiveData(); if(tagI2C_Bit0){ tagI2C_Bit0 = 0; i2c_addr = ch; }else{ i2c_data[i2c_addr++ & (I2C_DATA_SIZE - 1)] = ch; } } /* Slave received STOP byte from master */ /* EV4: STOPF = 1,读SR1寄存器后再写CR2清除 */ else if(Event == (I2C_EVENT_SLAVE_STOP_DETECTED)) { I2C_GetFlagStatus(I2C_FLAG_STOPDETECTION); I2C_GenerateSTOP(DISABLE); } /* SLAVE TRANSMITTER */ /* Data transmited from slave to master */ /* EV3: TxE = 1, 写DR寄存器清除DR */ else if((Event == (I2C_EVENT_SLAVE_BYTE_TRANSMITTED)) || (Event == (I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED))) { uint8_t ch = i2c_data[i2c_addr++ & (I2C_DATA_SIZE - 1)]; I2C_SendData(ch); } /* Acknowledge failure */ /* EV3-2: AF = 1, AF is cleared by writing '0' in AF bit of SR2 register */ else if(Event == (I2C_EVENT_SLAVE_ACK_FAILURE)) { I2C_ClearFlag(I2C_FLAG_ACKNOWLEDGEFAILURE); } } void I2C_Slave_Init(void) { I2C_DeInit(); /* Initialize I2C peripheral */ I2C_Init(400000, SLAVE_ADDRESS, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 16); /* Enable Error Interrupt*/ I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF), ENABLE); }

【备注】:I2C_Slave_IRQHandler是在stm8s_it.c文件中的INTERRUPT_HANDLER(I2C_IRQHandler, 19)中被调用的。

3.分析验证

为了方便验证问题,在I2C_Slave_IRQHandler函数中保存了所有的Event,如下:

+uint16_t event_rx_buf[50] = {0x00}; +uint16_t event_count = 0; void I2C_Slave_IRQHandler(void) { volatile I2C_Event_TypeDef Event = I2C_GetLastEvent(); + if(event_count < 50){ + event_rx_buf[event_count++] = Event; + } ... } Master端write 2个byte产生的Event,如下:

【备注】上面截图出现了3次0x240,因为是1个Register addr + 2个data,所以其实是write3个数据。

Master端read 2个byte产生的Event,如下:

【备注】0x680是在发送数据中,中断函数中不做任何处理,等待发送完成。

最新回复(0)