STM8S I2C Slave模式錯誤解決
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
是在傳送資料中,中斷函式中不做任何處理,等待傳送完成。
相關文章
- Ocelot錯誤解決
- MySQL複製跳過錯誤--slave_skip_errors、sql_slave_skip_counter、slave_exec_modeMySqlError
- 解決 Python UnicodeEncodeError 錯誤PythonUnicodeError
- dbfread報錯ValueError錯誤解決方法Error
- PbootCMS 404 錯誤解決方法boot
- Linux下錯誤解決方案Linux
- latex 錯誤以及解決方案
- HTTP 錯誤 500.19- Internal Server Error 錯誤解決方法HTTPServerError
- steam磁碟寫入錯誤怎麼解決 steam磁碟寫入錯誤解決方法大全
- undefined reference to錯誤的解決方法Undefined
- Cocopods的升級錯誤解決
- ORA-12005 錯誤的解決
- SAXParseException的錯誤解決之二Exception
- ORA-28000錯誤解決方案
- dedecms提示500錯誤解決方法
- PHP curl error 60 錯誤解決PHPError
- linux解決“XXX is not in the sudoers file”錯誤Linux
- 解決java.lang.NoSuchMethodError錯誤JavaError
- HTTP代理錯誤怎麼解決?HTTP
- TCP網路除錯助手提示錯誤:“1035:未知錯誤” 解決方案TCP除錯
- 解決MySQL server has gone away錯誤的解決方案MySqlServerGo
- Go:錯誤 could not launch process: EOF 解決Go
- 畢設之錯誤解決辦法
- 解決 ngrok 的 Domain 錯誤問題AI
- 錯誤解決:Attempting to use uninitialized value VariableZed
- Ubuntu Cannot allocate memory 錯誤解決方案Ubuntu
- Qt報Multiple definition錯誤的解決QT
- Excel匯入null錯誤解決方式ExcelNull
- 代理508限制錯誤怎麼解決?
- Hadoop常見錯誤及解決方案Hadoop
- Idea編譯錯誤解決辦法Idea編譯
- 錯誤720寬頻連線解決辦法 寬頻連線錯誤程式碼720怎麼解決
- 解決ubuntu系統“XXX is not in the sudoers file”錯誤Ubuntu
- ubuntu下import matplotlib錯誤解決辦法UbuntuImport
- HTTP 錯誤 500.21 - Internal Server Error 解決方案HTTPServerError
- SyntaxError: EOL while scanning string literal錯誤解決ErrorWhile
- 解決 eslint 的 Parsing error: Unexpected token 錯誤EsLintError
- Mac上搭建chromedriver的錯誤解決方法MacChrome