Mbed平台SPI从机spi.receive()始终返回0问题求助
关于Mbed SPISlave receive()返回0的问题分析
我刚仔细看了你的代码和问题描述,这其实是对Mbed的SPISlave::receive()函数的用途理解偏差导致的,咱们一步步拆解清楚:
核心误解:receive()的返回值不是"是否有数据"的标志
Mbed的SPISlave::receive()函数不是用来检测数据是否到达的状态判断函数——它的实际作用是:
- 阻塞等待主机发起SPI传输
- 完成一次完整的SPI收发操作(你提前用
reply()设置的字节会发给主机,同时接收主机发来的字节) - 返回的是主机本次发来的字节数据,而非表示"有/无数据"的布尔值
为什么你的if判断会导致通信失败
看你写的这段代码:
if (!spislave.receive()) { receive_value = spislave.read(); }
这个逻辑的意思是:只有当receive()返回0的时候,才去读取数据。但实际场景中:
- 如果主机发送的是非0的有效数据(比如你要传输的控制值),
receive()会直接返回这个非0值,!取反后条件为假,代码就不会执行read(),导致有效数据被留在缓冲区里,你自然拿不到正确值,看起来通信失败 - 当主机还没发起传输时,
receive()可能会阻塞或者返回0,这时候你去read(),拿到的也是无效的0值
而当你去掉这个if判断后,不管receive()返回什么,你都会执行read()——其实这时候receive()已经完成了接收操作,read()只是从缓冲区里取出本次接收的真实数据,所以通信就恢复了。
修正后的正确写法
你完全不需要额外的if判断,直接用receive()的返回值作为接收数据即可,或者配合read()使用(两者效果一致,因为receive()返回的就是缓冲区里的值):
while (1) { transmit_value = 100 * voltage; spislave.reply(transmit_value); // 直接接收主机发来的数据,赋值给receive_value receive_value = spislave.receive(); // 或者分开写也可以: // spislave.receive(); // 等待并完成传输 // receive_value = spislave.read(); // 读取接收缓冲区 led.write(receive_value / 100.0); // 后面的显示代码保持不变... }
补充说明
如果你确实需要主动检测是否有主机发起传输,Mbed的SPISlave提供了is_receive()函数(不同版本可能有细微差异),这个函数才是用来判断是否有数据等待接收的状态位。但在你的循环场景里,receive()本身会阻塞等待主机传输,所以完全不需要额外判断。
内容的提问来源于stack exchange,提问作者szl0834
相关产品推荐
相关产品推荐

