STM32/STM8技术william hill官网
直播中

王莉

7年用户 302经验值
私信 关注
[问答]

spi中断接收模式***扰后数据会一直错位



硬件是这样设计的:
芯片为STM32f103vb,作为从设备接收SPI主设备发送过来的固定长度的数据,现定为每秒发送一次,数据为9个16位数据。
从机的PC6引脚检测到有上升沿,表明主设备将要发送数据过来。发送完数据后,过一段时间PC6被拉低。

一开始是想用DMA方式接收的,PC6上升沿中断的回调函数里调用DMA接收函数,接收9个数据。
结果发现,用万用表表笔或示波器表笔碰触SCLK引脚,会产生数据错位。且,一旦错位,以后接收的数据会始终保持错位。

后来就想先改成SPI中断方式接收。同样再PC6上升沿中断回调函数里调用SPI中断接收函数,接收9个数据,并在PC6下降沿时关闭SPI中断。
结果可能是主设备开机时发送的数据不正常,如果主从设备同时开机的话,从设备就总是接收溢出错误。
后来在溢出错误处理部分的关闭SPI中断后,又清了一次溢出错误标志,开机问题算是解决了。
但,同样存在,用表笔碰触SCLK引脚,会造成接收数据移位的问题。


请大家帮忙分析下为何错位会一直存在?

回帖(22)

王莉

2018-12-26 09:05:01
举报

王莉

2018-12-26 09:16:24
举报

王莉

2018-12-26 09:22:58
尝试在PC6下降沿,也即片选信号结束时,关闭SPI,然后再打开SPI。结果依旧。
举报

黄思

2018-12-26 09:41:35
CLK 电压表接触会有电压啊  ,应该是改变了时钟的顺序,导致时序错误  ,提前接上电压表试试1
举报

李衍安

2018-12-26 09:58:09
关电重启应该恢复正常吧?
对于用表笔接触下SCLK会导致错位,可以这样试下:
1.那个SPI速度是可以设置的,看看调低点速率,会不会这样。
2.在SPI接口的数据线与CLK线,全部上拉,有可能时,最好主从间还串联个10欧姆的电阻,这两个方法主要是为了在传输数据是,保证电平稳定的措施。
举报

王莉

2018-12-26 10:12:51

提前接上电压表可能会避免这种问题。
但如果在实际工作环境中,有其他干扰加在了SCLK上而产生了问题,该怎么办呢?
受干扰后接收出错不怕,怕的是无法纠正过来。

现在想想,应该是SCLK上多余的脉冲使SPI的移位寄存器上接收了额外的数。怎样能纠正过来呢?
举报

黄思

2018-12-26 10:18:01
你可以建立回答机制,一问一答  那样的话效率低了,或者CRC校验
举报

张志诚

2018-12-26 10:36:27
把SPI的通信线都接上上拉,同时加上滤波电容。能增强干扰能力。
举报

王莉

2018-12-26 10:51:43
引用: cdkjwdjqw 发表于 2018-12-26 11:16
你可以建立回答机制,一问一答  那样的话效率低了,或者CRC校验

就是对效率有要求...
不过即使采用回答机制,也不能纠正从机的错位吧?
CRC校验其实用上了,倒数第二个数据既是。

问答机制或CRC校验可以检测出接收错误,但如何使下次接收数据不再保持错位?
目前的做法是重新初始化SPI,但感觉初始化SPI执行的操作太多了。
举报

王莉

2018-12-26 11:10:57
引用: 60user189 发表于 2018-12-26 11:34
把SPI的通信线都接上上拉,同时加上滤波电容。能增强干扰能力。

都有上拉的。当然实际使用未必会因为干扰造成这种结果。我是偶然发现SCLK上引入干扰后会造成这种接收数据持续错位的问题。
主要是想通过软件来解决干扰消失后依旧错位的问题。
举报

黄思

2018-12-26 11:27:17
你的时钟线有干扰么,一般时钟我们都不测量的,用示波器,万用表不靠谱
举报

张桂芝

2018-12-26 11:45:26
把SPI的通信线都接上上拉,同时加上滤波电容
举报

李富贵

2018-12-26 12:03:41
楼主在使能SPI后,
有没有第一时间清除接收缓冲区中断标志?
举报

王莉

2018-12-26 12:18:33

用的HAL库,SPI初始化时有清寄存器。
在程序中是反复调用
HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
这个函数来实现中断接收的。这个函数里只有是能SPI接收中断及是能SPI,没有清中断标志。
举报

康大争

2018-12-26 12:36:19
把SPI的通信线都接上上拉,同时加上滤波电容。能增强干扰能力。
举报

蔡妮芩

2018-12-26 12:47:52
类似问题我有遇到过。目测你的SPI时钟是连续的,就是什么每个byte(假设初始化为8bit模式)之间的时钟是没有间隙。STM32的SPI时钟默认是字节于字节之间没有间隙。可以尝试,1,查阅数据手册看是否可以设置在每个byte之间的时钟插入间隙(空闲),或者在主机端采用单字节发送略加延时;2,楼上有人已经说了,硬件上加上拉电阻或滤波电容等手段加强硬件的抗干扰能力;3,看看芯片对于有没有IT模式,若有的话采用IT模式传输也是提高数据正确率的一种手段;4,直接采用硬件SPI_CS作为片选脚,而不是采用GPIO外部中断去判断,再来个中断嵌套什么的!从代码和设置模式来看,或许你对SPI从模式理解的可能不是很透彻。SPI从模式,配置中断接收或DMA接收模式,有数据来的时候会自动触发,而不需要你额外加中断去通知它。另外,你的外部中断,GPIO的响应速度或者消抖处理等都可能影响数据通信。还有,你要测SPI通信,最好用示波器,而不是万用表,万用表的原理大家都懂。
举报

罗玉婧

2018-12-26 12:53:01
SPI采集数据是以时钟的边沿采集数据,当你用表笔触碰时钟线后,造成了时钟脉冲的丢失,导致接收数据端收到的时钟脉冲丢失,采集数据位也就响应丢失,导致整个数据帧都对不齐了。我看你用的是HAL库,在你调用void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)函数里,用判寄存器方式将SPI缓存里的数据读空,问题应该就解决了。其实在调用HAL_SPI_RxCpltCallback函数的时候,是你自己定义的spi2RecvDate缓存数据满了才进到那个回调函数里,其实SPI接收数据缓存里还有数据。
举报

王莉

2018-12-26 13:10:40

应该就是SCLK多了脉冲或少了脉冲而使数据帧对不起了。
请教,如何清掉SPI缓存里的数据?
我现在使在每次PC6下降沿重新初始化下SPI2,虽然不再出现这个问题了,但感觉多了太多的操作了。
HAL_SPI_DeInit(&hspi2);        HAL_SPI_Init(&hspi2);  这两个函数也行,但是仍感觉操作太多了。
举报

罗玉婧

2018-12-26 13:17:28
不管三七二十一 直接多读几次就可以了 变量= hspi2.Instance->DR;
举报

更多回帖

发帖
×
20
完善资料,
赚取积分