你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 SPI 主从通信,主机接收到从机数据第一位数据不对

[复制链接]
dogpi 提问时间:2022-3-1 13:03 / 未解决

主机发送0xa2,从机接收主机发送的数据,判断接收到的数据是不是0xa2,如果从机接收到的数据是0xa2,从机发送:0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c给主机.但是主机接到的是:0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b.

```
uint16_t SPI2_ReadWriteByte(uint16_t TxData)
{                                          
        while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);        // 等待发送区空  
        SPI_I2S_SendData(SPI2, TxData);                                                                 // 通过外设SPIx发送一个byte数据
        while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);// 等待接收完一个byte  
        return SPI_I2S_ReceiveData(SPI2);                                                                 // 返回通过SPIx最近接收的数据                  
}
uint8_t SPI_TxBuffer[12] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c};
void SPI2_IRQHandler(void)
{
        if(LL_SPI_IsActiveFlag_RXNE(SPI2)==SET){
                SPI_IT_Rec=SPI2->DR;
                if(SPI_IT_Rec == 0xa2){
                        for(uint8_t i=0;i<12;++i){

                                SPI_RxBuffer[i]= ReadWriteData(SPI_TxBuffer[i]);
                        }
                        SPI_Flag = 1;
                }
        }
}
```
收藏 评论14 发布时间:2022-3-1 13:03

举报

14个回答
dogpi 回答时间:2022-3-1 16:17:46

废鱼 发表于 2022-3-1 15:35
首先你的主机,读取的时候,也是由你来产生的CLK。对方在收到A2命令后,需要通过写入空数据让从机将数 ...

[md]我使用的是全双工模式,MISO,MOSI都用到了.我主机发送了0xA2,后面连续发送了12个0x00,用来接收从机回复的12个数据.主机发送0xA2,同时也接收到了从机在DR中写入的默认值0x00.当主机发送第一个0x00时,接收到的还是0x00.主机发送第二个0x00,接收到的才时0x01.

从机的逻辑时,接收主机发送的数据,判断数据是不是0xA2,如果是0xA2,for循环发送0x01-0x0C

dogpi 回答时间:2022-3-1 13:17:47
主机发送0xa2,从机接收主机发送的数据,判断接收到的数据是不是0xa2,如果从机接收到的数据是0xa2,从机发送:0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c给主机.但是主机接到的是:0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b.
如果再中断一次接收到的数据就会是:0x0c,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b
dogpi 回答时间:2022-3-1 13:19:41
是不是要在接收A2的时候就要填充发送缓冲区啊?
废鱼 回答时间:2022-3-1 13:44:56

楼主,SIP读取时,需要主机产生信号再进行读取,写入也是类似。每次发送完一个数据都要先读取。在开启中断前,先把数据读取完毕后,再开启。另外,终端中尽量不要写这种死循环的代码,一旦发生异常,中断就出不来了。你这样的使用还不如直接用查询的方式读取。

dogpi 回答时间:2022-3-1 15:15:42

废鱼 发表于 2022-3-1 13:44
楼主,SIP读取时,需要主机产生信号再进行读取,写入也是类似。每次发送完一个数据都要先读取。在开启 ...

[md]主机发送A2命令时时钟就会开启了,这时从机的移位寄存器中的值会被主机读取到.您的意思是从机不在中断中进行读取主机发送的数据吗?

废鱼 回答时间:2022-3-1 15:35:46

首先你的主机,读取的时候,也是由你来产生的CLK。对方在收到A2命令后,需要通过写入空数据让从机将数据传输出来。

发送A2时使用SPI2_ReadWriteByte这个函数即可。楼主,你用的是双线还是三线模式?建议看看SPI通讯协议。

butterflyspring 回答时间:2022-3-1 16:11:03

如同楼上TX所说,SPI全双工通讯时,主发送的同时也收到从发的信息,因为时钟是由主提供的。所以楼主注意这个细节,调整一下判断逻辑就可以了。

废鱼 回答时间:2022-3-1 16:36:33

楼主,我不太明白的你的设计思路。主机和从机的程序都是你写的是吗?如果都是自己写的,注意一下时序。可以用逻辑分析仪或者示波器抓波形,自己理解一下SPI的通讯过程。

dogpi 回答时间:2022-3-1 16:39:00

dogpi 发表于 2022-3-1 16:17
我使用的是全双工模式,MISO,MOSI都用到了.我主机发送了0xA2,后面连续发送了12个0x00,用来接收从机回 ...

[md]第一次发送0xA2:

image.png

第二次发送0xA2:

image.png

废鱼 回答时间:2022-3-1 16:50:45

dogpi 发表于 2022-3-1 16:39
第一次发送0xA2:</p>
<p>!(data/attachment/forum/202203/01/163739vjt9zz9tgc9gbct1.png?imageMogr2/auto- ...

[md]第二次发送A2时,看一下寄存器的值是不是0C,说明在上次通讯完成前,还是有没有及时读取的数据。楼主用的SPI器件是什么?

dogpi 回答时间:2022-3-1 16:56:34

废鱼 发表于 2022-3-1 16:50
第二次发送A2时,看一下寄存器的值是不是0C,说明在上次通讯完成前,还是有没有及时读取的数据。楼主 ...

[md]F103VET6做的从机

废鱼 回答时间:2022-3-1 16:59:53

dogpi 发表于 2022-3-1 16:56
F103VET6做的从机

那应该是你逻辑的问题,建议看一下SPI的通讯协议。

dogpi 回答时间:2022-3-1 17:01:37

废鱼 发表于 2022-3-1 16:59
那应该是你逻辑的问题,建议看一下SPI的通讯协议。

好的,感谢老哥帮忙

废鱼 回答时间:2022-3-1 17:10:11

dogpi 发表于 2022-3-1 17:01
好的,感谢老哥帮忙

不谢,有问题发帖就好。

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版