[APM32F0]

APM32F003 I2C从机传输不定长度数据

[复制链接]
6665|2
手机看帖
扫描二维码
随时随地手机跟帖
defaultname|  楼主 | 2023-2-28 11:26 | 显示全部楼层 |阅读模式
本帖最后由 defaultname 于 2023-2-28 11:25 编辑

项目遇到一个需求,需要I2C主机读取从机数据时,可以分段传输,每次长度不一。使用F003的I2C从机例程`I2C\I2C_TwoBoards\I2C_TwoBoards_Slave`作以下修改:
#define DATA_BUF_SIZE       (9)
uint8_t dataBufPt = 0;
uint8_t dataBuf[DATA_BUF_SIZE] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
void I2CIsr(void)
{
    //...
    /** STS1_TXBEF = 1 and STS3_RWMF = 1 */
    if(I2C_ReadStatusFlag(I2C_FLAG_TXBE |I2C_FLAG_RWMF) == SET)
    {
        if (dataBufPt >= DATA_BUF_SIZE)
            dataBufPt = 0;
        I2C_TxData(dataBuf[dataBufPt++]);
    }
    //...
}

测试主机读取两次数据的时序如下:
5130f7f124974053da3e0551b13e33c_1677549446342_0.png
7816aa323ed12d32ae88793463565b4_1677549454989_0.png
可以看到出问题了,第一次读取三个字节01, 02, 03,第二次读取到05, 06, 07,中间跳过了1个字节的数据,丢掉了04
调试代码发现,从机每次发送数据之后,都会进入I2C_FLAG_TXBE中断,所以实际上发送3个字节,中断会进入4次


但由于需求是每次传输的数据是不定长的,这次读3个字节,下次就可能读4个、2个……没办法通过字节长度来判断传输结束,所以得从I2C的停止位入手,所以在中断里添加以下代码:
/** Stop condition is detected */
if(I2C_ReadStatusFlag(I2C_FLAG_STOP) == SET)
{
    I2C->CTRL2 = I2C->CTRL2;
    //判断到停止位,手动把数据指针减1
    if (dataBufPt == 0)
        dataBufPt = DATA_BUF_SIZE - 1;
    else
        dataBufPt--;
}

运行之后现象依旧,进一步调试发现I2C_FLAG_STOP中断根本不会进入


于是转变思路,从主机的NAK非应答信号入手,判断本次传输结束:
image_1677551269506_0.png


根据手册,作出以下修改:
void I2CInit(void)
{
    //...
    /** Enable buffer and event interrupt */
    i2cConfig.interrupt = I2C_INT_BUFFER | I2C_INT_EVENT | I2C_INT_ERROR;
    //...
}
void I2CIsr(void)
{
    //...
    /** STS1_TXBEF = 1 and STS3_RWMF = 1 */
    if(I2C_ReadStatusFlag(I2C_FLAG_TXBE |I2C_FLAG_RWMF) == SET)
    {
        if (dataBufPt >= DATA_BUF_SIZE)
            dataBufPt = 0;
        I2C_TxData(dataBuf[dataBufPt++]);
    }

    if (I2C_ReadStatusFlag(I2C_FLAG_ACKERR) == SET)
    {
        I2C_ClearStatusFlag(I2C_FLAG_ACKERR);
        if (dataBufPt == 0)
            dataBufPt = DATA_BUF_SIZE - 1;
        else
            dataBufPt--;
    }
          //...
}

最后测试成功:

b3982a77b54c35ce5fe1165fe46c9d9_1677551555235_0.png


主机改为每次读取两个字节时,测试时序也正确:
71d1bf89e7f4ff47b2c6b6c0e2fb9e6_1677551567998_0.png a952cadfada5a8f1ea3322abb1fd11d_1677551577414_0.png


问题解决。



使用特权

评论回复
零erer| | 2023-2-28 11:30 | 显示全部楼层
学习一手

使用特权

评论回复
Fanexs168| | 2023-2-28 13:51 | 显示全部楼层
点赞点赞

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

1

帖子

0

粉丝