使用LPC55S28的I2C從機接口,比如實現(xiàn) 24LC系列的從機EEPROM ??梢蕴峁┮韵虏僮鳎缱止?jié)寫入、頁面寫入、當前地址讀取、隨機讀取和順序讀取。接下來,使用Byte Write和Random Read作為示例來說明。首先明確需要判斷的狀態(tài),包括以下內容:數(shù)據(jù)和地址-- 用于確定接收到的地址或數(shù)據(jù)。起始位-- 用于判斷是否接收到起始位。讀寫-- 用于判斷是寫狀態(tài)還是讀狀態(tài)。
隨機讀取
如果從設備生成kI2C_SlaveAddressMatchEvent,則表示從設備檢測到主設備發(fā)送的啟動或重復啟動??梢栽诔绦蛑性O置一個變量,記錄它是啟動還是重復啟動,并根據(jù)傳輸情況合理設置該變量的值。假設從設備檢測到啟動,那么根據(jù)接受容量字節(jié)大小,接收到兩個字節(jié)或三個字節(jié),那么第一個字節(jié)是包含讀寫操作的設備的地址,第二個和第三個字(如果存在)是要操作的數(shù)據(jù)的地址。接下來,LPC5528將再次檢測啟動,即再次接收具有讀取操作的設備地址。LPC5528從相應的數(shù)據(jù)地址讀取數(shù)據(jù)并將其返回給主機。
字節(jié)寫
如果從設備生成kI2C_SlaveAddressMatchEvent,則表示從設備檢測到主設備發(fā)送的啟動或重復啟動。可以在程序中設置一個變量,記錄它是啟動還是重復啟動,并根據(jù)傳輸情況合理設置該變量的值。假設從設備檢測到啟動,那么根據(jù)接收容量大小,接收到兩個字節(jié)或三個字節(jié),那么第一個字節(jié)是包含讀寫操作的設備的地址,第二個和第三個字(如果存在)是要操作的數(shù)據(jù)的地址。緊隨其后的字節(jié)是數(shù)據(jù)。將此數(shù)據(jù)字節(jié)保存到上一步驟中獲得的地址中。
當主機設置STOP條件停止傳輸?shù)臅r候,從機端需要獲得一個提醒。可以參考例程"i2c_interrupt_b2b_transfer_slave.c" 實現(xiàn)基于I2C從機的例子。
I2C驅動的狀態(tài)機設置xfer->rxSize 和xfer->txSize 變量。
static void i2c_slave_callback(I2C_Type *base, volatile i2c_slave_transfer_t *xfer, void *userData)
{
switch (xfer->event)
{
/* Address match event */
case kI2C_SlaveAddressMatchEvent:
xfer->rxData = NULL;
xfer->rxSize = 0;
break;
/* Transmit request */
case kI2C_SlaveTransmitEvent:
/* Update information for transmit process */
xfer->txData = &g_slave_buff[2];
xfer->txSize = g_slave_buff[1];
break;
/* Setup the slave receive buffer */
case kI2C_SlaveReceiveEvent:
/* Update information for received process */
xfer->rxData = g_slave_buff;
xfer->rxSize = I2C_DATA_LENGTH;
break;
/* The master has sent a stop transition on the bus */
casekI2C_SlaveCompletionEvent:
g_SlaveCompletionFlag = true;
break;
default:
g_SlaveCompletionFlag = false;
break;
}
}
如果主機發(fā)送一定數(shù)據(jù)后,判斷分支casekI2C_SlaveCompletionEvent將會執(zhí)行,同時g_SlaveCompletionFlag 標志將會設置為 true。在SDK中,使用I2C_SlaveTransferNonBlocking 函數(shù),有判斷字節(jié)傳輸完成的動作。
/* Start accepting I2C transfers on the I2C slave peripheral */
reVal = I2C_SlaveTransferNonBlocking(EXAMPLE_I2C_SLAVE, &g_s_handle,
kI2C_SlaveAddressMatchEvent | kI2C_SlaveCompletionEvent);
if (reVal != kStatus_Success)
{
return -1;
}
/* Wait for transfer completed. */
while (!g_SlaveCompletionFlag)
{
}
g_SlaveCompletionFlag = false;
case k2IC_SlaveCompletionEvent 這個分支的進入不是根據(jù)主機發(fā)送的stop條件進入的,而是根據(jù)字節(jié)數(shù)進入的,譬如:如果主機發(fā)送256字節(jié),接收字節(jié)數(shù)定義為16,當?shù)?6個數(shù)據(jù)接收完成后,就會進入該分支。但是 I2C 從機端事先并不知道 I2C 主機發(fā)送的字節(jié)數(shù),所以無法判定停止。有什么辦法能判斷停止呢?
“API需要編寫代碼判斷在I2C STOP停止時達到完成狀態(tài),而不是通過rxData計數(shù)到0?!眳⒖际纠a只顯示raData計數(shù)減到了0。如果要在停止時達到完成狀態(tài),在 i2c 從機回調函數(shù)i2c_slave_callback中,需要添加case kI2C_SlaveDeselectedEvent。
static void i2c_slave_callback(I2C_Type*base, volatile i2c_slave_transfer_t *xfer, void *userData)
{
switch (xfer->event)
{
...
casekI2C_SlaveDeselectedEvent:
g_SlaveCompletionFlag = true;
// 用戶代碼
break;
...
}
}
在傳輸函數(shù)中,需要添加kI2C_SlaveDeselectedEvent:
/* 在 I2C 從機外設中, 啟動接收 I2C傳輸*/
reVal = I2C_SlaveTransferNonBlocking(EXAMPLE_I2C_SLAVE,&g_s_handle,kI2C_SlaveAddressMatchEvent | kI2C_SlaveCompletionEvent|kI2C_SlaveDeselectedEvent);
當 I2C主機發(fā)送 STOP,從機的STAT標志將會設置為1,函數(shù) I2C_SlaveTransferHandleIRQ將會觸發(fā) kI2C_SlaveDeselectedEvent。查看驅動代碼如下:
void I2C_SlaveTransferHandleIRQ(I2C_Type *base,i2c_slave_handle_t *handle)
{
uint32_t i2cStatus = base->STAT;
if (i2cStatus &I2C_STAT_SLVDESEL_MASK)
{
I2C_SlaveInvokeEvent(base, handle,kI2C_SlaveDeselectedEvent);
I2C_SlaveClearStatusFlags(base,I2C_STAT_SLVDESEL_MASK);
}
...
}
在 LPC55 參考手冊第 637頁面有相關描述。
審核編輯:湯梓紅。
-
接口
+關注
關注
33文章
8257瀏覽量
149954 -
EEPROM
+關注
關注
9文章
1002瀏覽量
81061 -
I2C
+關注
關注
28文章
1452瀏覽量
122253 -
狀態(tài)機
+關注
關注
2文章
489瀏覽量
27394 -
從機
+關注
關注
0文章
3瀏覽量
831
原文標題:使用 LPC55S28 I2C 從機功能,接收不定長的數(shù)據(jù)(通過字節(jié)數(shù)或者STOP條件判斷)
文章出處:【微信號:嵌入式 MCU,微信公眾號:嵌入式 MCU】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論