[技术问答]

求助:AC7801X芯片I2C通信DMA方式从机最后一个字节发送NACK

[复制链接]
686|18
手机看帖
扫描二维码
随时随地手机跟帖
fanchenxinok|  楼主 | 2021-2-22 10:47 | 显示全部楼层 |阅读模式

芯片用的Autochip的AC78013 MCU,现在MCU配置为从机模式,主机是安卓系统的。MCU和安卓系统I2C通信。我从机端参考代码是:ac7801xSampleCode20200729\ac7801xSampleCode20200729\i2c\SampleCode\5 I2C_Slave_DMA\I2C_Slave\User下的i2c.c。目前主机和从机通信是没问题的 主机发送的命令我从机都能收到。


在 Slave DMA 接收模式下, 地址匹配后,然后每当接收到一字节数据
产生的 BND 标志都将触发 DMA 将数据搬运到内存。 DMA 会根据设定的传输长度自动在最后一字节
回 NACK。

怎么样设置使得最后一个字节也发送ACK呢?

使用特权

评论回复

相关帖子

GrootBrain| | 2021-2-22 13:37 | 显示全部楼层
1613972069.png
最后一个字节接收完成后,是发送NACK的。
您这是什么应用,最后一个字节接收成功后需要发送ACK的吗?

使用特权

评论回复
fanchenxinok|  楼主 | 2021-2-22 17:13 | 显示全部楼层
GrootBrain 发表于 2021-2-22 13:37
最后一个字节接收完成后,是发送NACK的。
您这是什么应用,最后一个字节接收成功后需要发送ACK的吗?

是这样的,master端发送命令,slave接收,slave接收成功数据都是对的,但是master端的写函数却返回NACK的错误码,master端接口是android的。我怀疑是最后一个字节回复了NACK,master端才出现这个错误。也不能确定是不是这个问题,大神有啥高见?

使用特权

评论回复
GrootBrain| | 2021-2-23 09:51 | 显示全部楼层
I2C从机使用DMA接受N个字节,是一个很明确的动作,N个字节接收完成后,就不需要接受了,所以应答位为NACK。
这里看来有两种解决办法:
1. 改andriod, 让andriod识别发送N个字节后的应答位为NACK也是正确的;
2. 该MCU。改用中断或轮询方式接收,没接收一个字节,都返回ACK.

使用特权

评论回复
GrootBrain| | 2021-2-24 20:15 | 显示全部楼层
想到一个新的方法。
目前DMA是接收所有字节,接收最后一个字节返回NACK;
可以将DMA传输完成中断改为传输完成一半产生中断,将接收字节数改为2倍,接收到一半的时候产生中断,然后停止接收。这样就会返回ACK.

使用特权

评论回复
评论
fanchenxinok 2021-3-2 13:47 回复TA
现在我采样的策略是slave端多接收一个字节,主机就不会接收到最后一个字节的NACK了。slave端做超时处理。 
fanchenxinok|  楼主 | 2021-3-2 13:46 | 显示全部楼层
本帖最后由 fanchenxinok 于 2021-3-2 16:37 编辑
GrootBrain 发表于 2021-2-24 20:15
想到一个新的方法。
目前DMA是接收所有字节,接收最后一个字节返回NACK;
可以将DMA传输完成中断改为传输完 ...

实验了这个方法,I2C_SlaveReceiveDMA接口的DMA初始化了半中断使能,接收数据长度翻倍, 但是没有接收一半的callback来。
void I2C_SlaveReceiveDMA(I2C_Type *I2Cx, DMA_ChannelType *DMAx, uint8_t *rxBuffer, uint16_t length, DeviceCallback_Type callback)
{
    DMA_ConfigType dmaConfig;

    DEVICE_ASSERT(I2C_INSTANCE_MAX > I2C_INDEX(I2Cx));
    DEVICE_ASSERT(IS_DMA_PERIPH(DMAx));
    DEVICE_ASSERT(IS_DMA_TRANSFER_NUM(length));

    dmaConfig.memStartAddr = (uint32_t)rxBuffer;
    dmaConfig.memEndAddr = (uint32_t)rxBuffer + length;
    dmaConfig.periphStartAddr = (uint32_t)(&(I2Cx->DATA));
    dmaConfig.periphSelect = (I2C0 == I2Cx) ? DMA_PEPIRH_I2C0_RX : DMA_PEPIRH_I2C1_RX;
    dmaConfig.MEM2MEM = DISABLE;
    dmaConfig.memSize = DMA_MEM_SIZE_8BIT;
    dmaConfig.periphSize = DMA_PERIPH_SIZE_32BIT;
    dmaConfig.memIncrement = ENABLE;
    dmaConfig.periphIncrement = DISABLE;
    dmaConfig.direction = DMA_READ_FROM_PERIPH;
    dmaConfig.transferNum = length;
    dmaConfig.memByteMode = DMA_MEM_BYTE_MODE_1TIME;
    dmaConfig.circular = DISABLE;
    dmaConfig.channelPriority = DMA_PRIORITY_VERY_HIGH;
    dmaConfig.errorInterruptEn = ENABLE;
    dmaConfig.halfFinishInterruptEn = ENABLE;
    dmaConfig.finishInterruptEn = DISABLE;
    dmaConfig.channelEn = ENABLE;
    dmaConfig.callBack = callback;
    DMA_Init(DMAx, &dmaConfig);
}


使用特权

评论回复
fanchenxinok|  楼主 | 2021-3-3 10:48 | 显示全部楼层
本帖最后由 fanchenxinok 于 2021-3-3 10:49 编辑
GrootBrain 发表于 2021-2-24 20:15
想到一个新的方法。
目前DMA是接收所有字节,接收最后一个字节返回NACK;
可以将DMA传输完成中断改为传输完 ...

hi GrootBrain
为啥使能DMA半中断,I2C啥都收不到了呢, callback也不来了?

使用特权

评论回复
单片小菜| | 2021-3-3 13:03 | 显示全部楼层
感谢楼主耐心细致的分享,不错的。

使用特权

评论回复
fanchenxinok|  楼主 | 2021-3-3 15:06 | 显示全部楼层
GrootBrain 发表于 2021-2-23 09:51
I2C从机使用DMA接受N个字节,是一个很明确的动作,N个字节接收完成后,就不需要接受了,所以应答位为NACK。 ...

I2C Slave轮询用啥接口?看i2c驱动中只有master轮询的接口

使用特权

评论回复
czq2317| | 2021-3-3 15:26 | 显示全部楼层
fanchenxinok 发表于 2021-3-3 10:48
hi GrootBrain
为啥使能DMA半中断,I2C啥都收不到了呢, callback也不来了?

我的是可以的,试一下我的工程。或者可以把工程贴出来,我试一下。

I2C_Slave_DMA.rar

53.16 KB

使用特权

评论回复
fanchenxinok|  楼主 | 2021-3-3 17:13 | 显示全部楼层
本帖最后由 fanchenxinok 于 2021-3-3 17:30 编辑
czq2317 发表于 2021-3-3 15:26
我的是可以的,试一下我的工程。或者可以把工程贴出来,我试一下。

我的还是不行,代码如附件,测试master端发:0x80 0x00 0x81。

i2c_slave_dma.rar

20.63 KB

使用特权

评论回复
里面有晴雨| | 2021-3-3 19:10 | 显示全部楼层
主机和从机究竟是怎么避免冲突的。

使用特权

评论回复
GrootBrain| | 2021-3-3 19:12 | 显示全部楼层
半中断还有要求 5454603f6f1074f25.png


使用特权

评论回复
评论
fanchenxinok 2021-3-5 11:22 回复TA
hi GrootBrain Autochips为啥要将slave接收消息的协议做成最后一个字节发送NACK? 每接收一个字节发ACK,发送端发送完了自然就不发了,也不用Slave通知NACK才停止发送。 
fanchenxinok 2021-3-4 11:56 回复TA
那我的需求就用不了半中断了,我的需求是主机发的命令长度都不一致。我需要先知道发送的命令是啥 然后接收相应的字节。我的做法是先DMA接收一个字节的命令,知道命令后再接收接下来的字节数,这种做法只能用DMA接口不能用中断接口。 
名字是啥样| | 2021-3-4 15:55 | 显示全部楼层
有DMA就是好,速度就是快一些。

使用特权

评论回复
fanchenxinok|  楼主 | 2021-3-5 11:23 | 显示全部楼层

hi GrootBrain Autochips为啥要将slave接收消息的协议做成最后一个字节发送NACK? 每接收一个字节发ACK,发送端发送完了自然就不发了,也不用Slave通知NACK才停止发送。

使用特权

评论回复
便携手到老| | 2021-3-5 16:50 | 显示全部楼层
楼主设置的比较详细,比较好,厉害。点个赞。

使用特权

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

本版积分规则

14

主题

63

帖子

0

粉丝