LL库STM32SPI+DMA接收数据发生偏移

文章讨论了在使用LL库进行SPI接收时,由于DMA和SPI操作时间差导致的数据接收顺序问题。提出两种解决方案:在DMA中断中处理SPI接收或使用信号量等待SPI接收完成,以及在软件层面进行数据映射以修正首包数据的偏移。
摘要由CSDN通过智能技术生成

LL库,Receive only Master。Data size16,DMA mode Normal。初始化没啥特别的,CubeMX生成。然后配置DMA:

LL_DMA_ConfigAddresses(DMA2, LL_DMA_STREAM_0, LL_SPI_DMA_GetRegAddr(SPI1),

          (uint32_t)buf,LL_DMA_GetDataTransferDirection(DMA2, LL_DMA_STREAM_0));
LL_DMA_EnableIT_TC(DMA2, LL_DMA_STREAM_0);
LL_SPI_EnableDMAReq_RX(SPI1);

每次开始接收:

LL_DMA_DisableStream(DMA2, LL_DMA_STREAM_0);
LL_DMA_SetDataLength(DMA2, LL_DMA_STREAM_0,8);
LL_SPI_Enable(SPI1);
LL_DMA_EnableStream(DMA2, LL_DMA_STREAM_0);

还有中断:

void DMA2_Stream0_IRQHandler(void)
{
    if(LL_DMA_IsActiveFlag_TC0(DMA2))
    {
        // 清除传输完成标志位
        LL_DMA_ClearFlag_TC0(DMA2);
        LL_SPI_Disable(SPI1);
        spi_rcv();
    }
}

每次接收2*8字节,原本以为buf里面数据的顺序为data0,data1...data7(为short类型),实际上却是data1,data2...data7,data0。逻辑分析仪查波形,SPI传过来的顺序是对的,怎么到这里就出错了?

仔细想想,数据从SPI接收,到DMA搬运,一定是先接收后搬运。这里必定有个时间差,搬运完成16字节数据之后再关闭SPI,这期间SPI在做什么?如果是停下来了,那么不会有顺序的错误。但如果是在继续接收数据呢?那么也就意味着,SPI实际上多接收了数据,但是被DMA关在了门外。等下一次再次开始接收,被关在门外的这2字节多余的数据如果没有被抛弃,就会第一时间进来,占据原本应该是data0的位置,新的data0就会往后推,但dma觉得自己还是接收满了8*2字节后,就会再次进入中断,于是,第二次接收,DMA得到的数据就变成了data0(旧),data0(新),data1,data2...data6。没错,这次是data7被关在了DMA门外。第三次接收,顺序就变成了data7(旧),data0,data1...data6.之后也会依此顺序。这似乎就和观察到的现象对上号了。但是如何验证?

中断,关SPI,之后SPI继续工作直至新的2字节接收完成,这应该可以通过SPI的CLK佐证。另外,第一次接收,CLK的数量不是2*8*8,而是2*9*8.没错,佐证的关键就在于抓到第一次接收的CLK波形,为了验证中断处理的时间点,用一个IO,进出中断的时候分别操作其置低和置高。逻辑分析仪观察这两路信号。

向下脉冲的位置就是中断处理的位置,每次都关掉SPI之后,CLK持续了一段时间,尤其是第一包数据(图里面的不是第一包),CLK正好是2*9*8.似乎和猜测能对得上。不过这里面还有一些细节问题可能和猜测的不大一样:

譬如SPI被disable之后,旧数据是在重新开始接收之后被搬运过来的,还是LL_DMA_ClearFlag_TC3(DMA1);并且SPI那边接收完这些多余的数据之后就开始传了?

具体如何解决,这个说一下思路吧:

1 既然是多了这包数据,在DMA完成中断里面开个SPI接收中断,或者如果用了操作系统,抛出个信号量啥的,在外面等SPI接收完,然后把数据搬出来,直接扔掉(注意DMA这期间要关掉);

2 反正知道它是怎么个偏移的规律,那就直接软件上做个映射就好了。简单粗暴,唯独第一包数据要注意一下

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值