使用LPC55S28的I2C从机接口,比如实现 24LC系列的从机EEPROM 。可以提供以下操作,如字节写入、页面写入、当前地址读取、随机读取和顺序读取。接下来,使用Byte Write和Random Read作为示例来说明。首先明确需要判断的状态,包括以下内容:数据和地址-- 用于确定接收到的地址或数据。起始位-- 用于判断是否接收到起始位。读写-- 用于判断是写状态还是读状态。
随机读取
如果从设备生成kI2C_SlaveAddressMatchEvent,则表示从设备检测到主设备发送的启动或重复启动。可以在程序中设置一个变量,记录它是启动还是重复启动,并根据传输情况合理设置该变量的值。假设从设备检测到启动,那么根据接受容量字节大小,接收到两个字节或三个字节,那么第一个字节是包含读写操作的设备的地址,第二个和第三个字(如果存在)是要操作的数据的地址。接下来,LPC5528将再次检测启动,即再次接收具有读取操作的设备地址。LPC5528从相应的数据地址读取数据并将其返回给主机。
字节写
如果从设备生成kI2C_SlaveAddressMatchEvent,则表示从设备检测到主设备发送的启动或重复启动。可以在程序中设置一个变量,记录它是启动还是重复启动,并根据传输情况合理设置该变量的值。假设从设备检测到启动,那么根据接收容量大小,接收到两个字节或三个字节,那么第一个字节是包含读写操作的设备的地址,第二个和第三个字(如果存在)是要操作的数据的地址。紧随其后的字节是数据。将此数据字节保存到上一步骤中获得的地址中。
当主机设置STOP条件停止传输的时候,从机端需要获得一个提醒。可以参考例程"i2c_interrupt_b2b_transfer_slave.c" 实现基于I2C从机的例子。
I2C驱动的状态机设置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;
}
}
如果主机发送一定数据后,判断分支casekI2C_SlaveCompletionEvent将会执行,同时g_SlaveCompletionFlag 标志将会设置为 true。在SDK中,使用I2C_SlaveTransferNonBlocking 函数,有判断字节传输完成的动作。
/* 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 这个分支的进入不是根据主机发送的stop条件进入的,而是根据字节数进入的,譬如:如果主机发送256字节,接收字节数定义为16,当第16个数据接收完成后,就会进入该分支。但是 I2C 从机端事先并不知道 I2C 主机发送的字节数,所以无法判定停止。有什么办法能判断停止呢?
“API需要编写代码判断在I2C STOP停止时达到完成状态,而不是通过rxData计数到0。”参考示例代码只显示raData计数减到了0。如果要在停止时达到完成状态,在 i2c 从机回调函数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;
...
}
}
在传输函数中,需要添加kI2C_SlaveDeselectedEvent:
/* 在 I2C 从机外设中, 启动接收 I2C传输*/
reVal = I2C_SlaveTransferNonBlocking(EXAMPLE_I2C_SLAVE,&g_s_handle,kI2C_SlaveAddressMatchEvent | kI2C_SlaveCompletionEvent|kI2C_SlaveDeselectedEvent);
当 I2C主机发送 STOP,从机的STAT标志将会设置为1,函数 I2C_SlaveTransferHandleIRQ将会触发 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文章
8434浏览量
150685 -
EEPROM
+关注
关注
9文章
1008浏览量
81299 -
I2C
+关注
关注
28文章
1473浏览量
122970 -
状态机
+关注
关注
2文章
490浏览量
27450 -
从机
+关注
关注
0文章
3浏览量
849
原文标题:使用 LPC55S28 I2C 从机功能,接收不定长的数据(通过字节数或者STOP条件判断)
文章出处:【微信号:嵌入式 MCU,微信公众号:嵌入式 MCU】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论