You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何此SPI代码中数据无法写入SPDR寄存器?

问题分析与解决方案

核心问题:SPDR读取值为0的本质原因

SPI主机模式下,发送数据的同时会同步接收从机返回的数据,SPDR寄存器在传输完成后存储的是从机发来的字节,而非你发送的字节。由于你未连接任何从机,MISO引脚处于浮空状态,此时读取到的SPDR值是不确定的(可能固定为0、随机值,取决于引脚浮空时的电平)。你期望SPDR等于发送的0xAA是错误逻辑——主机的SPDR是发送缓冲区与接收缓冲区共用的物理寄存器,但发送和接收是独立流程:

  • 写SPDR是加载要发送的数据
  • 读SPDR是获取从机返回的数据

配置排查与修正点

  1. 引脚定义缺失验证:你的代码使用了MOSI_pin、SCK_pin等宏,但未给出具体定义,请确认对应ATmega328的正确引脚:
    • Arduino Uno标准SPI引脚:MOSI=PB3(数字11)、SCK=PB5(数字13)、MISO=PB4(数字12)、SS=PB2(数字10)
    • 确保MISO引脚(PB4)处于输入模式(默认即为输入,无需修改DDRB,不要误设为输出)
  2. CS引脚控制逻辑:SPI主机模式下,CS是手动控制的从机选通信号,当前代码中PORTB |= (1 << CS_pin)拉高CS的操作没问题,后续连接从机时只需在发送前拉低、发送后拉高即可。
  3. SPI传输等待逻辑:spi_send函数中等待SPIF标志位的写法是正确的,该标志位会在传输完成后置1,确保数据发送完成。

验证主机功能的可行方案

如果要确认SPI主机发送功能正常,无需依赖SPDR返回值,可通过以下方式测试:

  1. 硬件观测:用示波器或逻辑分析仪查看MOSI和SCK引脚,调用spi_send(0xAA)后,MOSI应输出二进制10101010的波形,SCK会产生对应时钟脉冲。
  2. 回环测试:将MOSI与MISO引脚短接,此时发送的数据会被自身接收,SPDR读取值将等于发送值,可直接验证收发链路是否正常。
  3. 简化测试逻辑:去掉对SPDR的无效判断,改为验证spi_send是否能正常执行完成:
    void led(){
      spi_send(0xAA);
      // 传输完成后点亮LED,说明spi_send执行成功
      PORTD |= (1 << LED_pin);
      _delay_ms(2500);
      PORTD &= ~(1 << LED_pin);
      _delay_ms(2500);
    }
    

补充代码:引脚宏定义示例

确保引脚宏与硬件对应,比如:

// Arduino Uno引脚对应定义
#define MOSI_pin 3   // PB3(数字11)
#define SCK_pin 5    // PB5(数字13)
#define CS_pin 2     // PB2(数字10)
#define RST_pin 0    // 根据你的硬件需求修改
#define LED_pin 7    // PD7(数字7)

内容的提问来源于stack exchange,提问作者Chandler Thornton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 01:40:11