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
是在傳送資料中,中斷函式中不做任何處理,等待傳送完成。
相關文章
- mysql master-slave複製錯誤[解決事例]MySqlAST
- 【MySql】複製出現Slave_SQL_Running: No 錯誤解決MySql
- mysql slave錯誤skipMySql
- Ocelot錯誤解決
- MySQL錯誤之mysql.slave_master_infoMySqlAST
- VIM 常用錯誤解決
- sqldeveloper for windows 錯誤解決SQLDeveloperWindows
- MySQL複製跳過錯誤--slave_skip_errors、sql_slave_skip_counter、slave_exec_modeMySqlError
- vsftpd 錯誤:530 and 500 錯誤解決方法FTP
- latex 錯誤以及解決方案
- ora-27504錯誤解決
- Datastore error in 'dirbdb'錯誤解決ASTError
- ORA-27054 錯誤解決
- mysql與php錯誤解決MySqlPHP
- mysql錯誤解決總結MySql
- PbootCMS 404 錯誤解決方法boot
- 【故障解決】OGG-00446 錯誤解決
- dbfread報錯ValueError錯誤解決方法Error
- 【故障解決】ORA-06502錯誤解決
- HTTP 錯誤 500.19- Internal Server Error 錯誤解決方法HTTPServerError
- dns錯誤怎麼辦 dns錯誤的解決辦法DNS
- HTTP代理錯誤怎麼解決?HTTP
- undefined reference to錯誤的解決方法Undefined
- SAXParseException的錯誤解決之二Exception
- PHP curl error 60 錯誤解決PHPError
- ORA-04091錯誤解決
- ORA-3136 錯誤解決 .
- [Windows] 解決 COM Surrogate 錯誤提示Windows
- AFNetworkingErrorDomain 錯誤解決方法ErrorAI
- [Flashback]ORA-38760錯誤解決
- EXP-00091錯誤解決
- virtualbox 錯誤解決記錄
- INS-40904 錯誤解決
- Mac下面svn錯誤資訊解決Mac
- PHP錯誤“Thisfilehasexpired”的解決方法PHP
- SAP錯誤提示解決辦法
- ClamAV無法更新錯誤解決
- clamd socket找不到錯誤解決