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

ATtiny841与Raspberry Pi Pico SPI通信异常问题求助

版本1:SPI主机(Raspberry Pi Pico)与从机(ATtiny841)数据传输异常问题

我使用Raspberry Pi Pico作为SPI主机,ATtiny841作为SPI从机。

主机代码:

#include "pico/stdlib.h"
#include "hardware/spi.h"
#include <stdio.h>

#define SPI_PORT spi0
#define PIN_MISO 16
#define PIN_MOSI 19
#define PIN_SCK  18
#define PIN_CS   17

uint8_t tx_dummy = 0xAA;
uint8_t rx_buf[3];

void spi_init_master()
{
    spi_init(SPI_PORT, 1000000);
    gpio_set_function(PIN_MISO, GPIO_FUNC_SPI);
    gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
    gpio_set_function(PIN_SCK,  GPIO_FUNC_SPI);

    gpio_init(PIN_CS);
    gpio_set_dir(PIN_CS, GPIO_OUT);
    gpio_put(PIN_CS, 1);
}

int main()
{
    stdio_init_all();
    spi_init_master();

    while(true)
    {
        gpio_put(PIN_CS, 0); // 选择从机
        tx_dummy = 0xAA;
        for(int i = 0; i < 3; i++)
        {
            spi_write_read_blocking(SPI_PORT, &tx_dummy, &rx_buf[i], 1);
            tx_dummy++;
        }

        gpio_put(PIN_CS, 1); // 取消选择从机

        printf("Ontvangen bytes: ");
        for(int i = 0; i < 3; i++)
        {
            printf("0x%02X ", rx_buf[i]);
        }
        printf("\n");

        sleep_ms(1000);
    }
}

从机代码:

#define SS     PA7
#define MOSI   PA6
#define MISO   PA5
#define SCK    PA4

byte dataToSend[3] = {0xDE, 0xAD, 0xBE};
volatile byte sendIndex = 0;

void setup() {
  pinMode(SCK, INPUT);
  pinMode(MOSI, INPUT);
  pinMode(MISO, OUTPUT);
  pinMode(SS, INPUT);

  SPCR = (1 << SPE) | (1 << SPIE);

  SPDR = dataToSend[0];
}

ISR(SPI_STC_vect) {
  byte received = SPDR;

  
  sendIndex++;
  if (sendIndex >= 3) {
    sendIndex = 0; 
  }
  SPDR = dataToSend[sendIndex];
 
}

void loop() {
}

实际未接收到预期的数组{0xDE, 0xAD, 0xBE},收到的是{0xDE, 0xAA, 0xAB}。

请问如何编写代码,让ATtiny841的SPDR寄存器在主机发起新请求前,用数组的下一个值覆盖主机发送的dummy值?

尝试过中断和非中断方式,但每次都返回主机发送的dummy值,希望通过中断实现需求


版本2:SPI寄存器访问返回值错位问题

通过在ATtiny841的CS引脚触发中断,并在Pico主机代码中添加短延迟,已实现从ATtiny841从机到Pi Pico主机的数据传输。(使用SPI中断时始终返回主机发送的dummy数据)

现在尝试添加寄存器结构:发送2字节(字节1=寄存器地址,字节2=dummy值),每传输一个字节时CS电平拉低再拉高,触发从机中断。

代码几乎可以运行,但主机请求0x01寄存器时得到0x02的值,请求0x02寄存器时得到0x01的值。

请问如何修复这个问题?

主机输出:

Reg value 0x01: 0x99 - 0x01
Reg value 0x02: 0x43 - 0x02
Reg value 0x01: 0x99 - 0x01
Reg value 0x02: 0x43 - 0x02
Reg value 0x01: 0x99 - 0x01
Reg value 0x02: 0x43 - 0x02

主机代码:

#include "pico/stdlib.h"
#include "hardware/spi.h"
#include <stdio.h>

#define SPI_PORT spi0
#define PIN_MISO 16
#define PIN_MOSI 19
#define PIN_SCK  18
#define PIN_CS   17

uint8_t tx_dummy = 0xAA;
uint8_t rx_buf[2];

void spi_init_master()
{
    spi_init(SPI_PORT, 1000000);
    gpio_set_function(PIN_MISO, GPIO_FUNC_SPI);
    gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
    gpio_set_function(PIN_SCK,  GPIO_FUNC_SPI);

    gpio_init(PIN_CS);
    gpio_set_dir(PIN_CS, GPIO_OUT);
    gpio_put(PIN_CS, 1);
}

int main()
{
    stdio_init_all();
    spi_init_master();
    uint8_t adress = 0x01;
    uint8_t test = 0x02;
    while(true)
    {
        gpio_put(PIN_CS, 0);
        sleep_us(10);
        spi_write_read_blocking(SPI_PORT, &adress, &rx_buf[0], 1);
        gpio_put(PIN_CS, 1);
        sleep_us(10);
        gpio_put(PIN_CS, 0);
        sleep_us(10);
        spi_write_read_blocking(SPI_PORT, 0x00, &rx_buf[1], 1);
        gpio_put(PIN_CS, 1);
        sleep_us(10);
        printf("Reg value 0x01: 0x%02X - 0x%02X\n", rx_buf[0], rx_buf[1]);
        sleep_ms(1000);

        gpio_put(PIN_CS, 0);
        sleep_us(10);
        spi_write_read_blocking(SPI_PORT, &test, &rx_buf[0], 1);
        gpio_put(PIN_CS, 1);
        sleep_us(10);
        gpio_put(PIN_CS, 0);
        sleep_us(10);
        spi_write_read_blocking(SPI_PORT, 0x00, &rx_buf[1], 1);
        gpio_put(PIN_CS, 1);
        sleep_us(10);
        printf("Reg value 0x02: 0x%02X - 0x%02X\n", rx_buf[0], rx_buf[1]);
        sleep_ms(1000);      
    }
}

从机代码:

#define SS     PA7
#define MOSI   PA6
#define MISO   PA5
#define SCK    PA4

volatile byte registerMap[3] = {};

volatile bool lastSSState = 0;
volatile byte receivedAddress = 0;
volatile byte transactionStep = 0;

void setup()
{
  pinMode(SCK, INPUT);
  pinMode(MOSI, INPUT);
  pinMode(MISO, OUTPUT);
  pinMode(SS, INPUT);

  SPCR = (1 << SPE);

  SPDR = registerMap[0];

  registerMap[0x01] = 0x43;
  registerMap[0x02] = 0x99;

  PCMSK0 |= (1 << PCINT7);
  GIMSK |= (1 << PCIE0);
  lastSSState = digitalRead(SS);

  sei();
}

void loop(){}

ISR(PCINT0_vect)
{
  bool currentState = digitalRead(SS);

  if(lastSSState && !currentState) //下降沿
  {
    if(transactionStep == 0) //第一次下降沿
    {
      while(!(SPSR & (1 << SPIF)));
      byte received = SPDR;
      receivedAddress = received;

      if(SPSR & (1 << WCOL))
      {
        volatile byte tmp = SPDR;
      }

      SPDR = registerMap[receivedAddress];
      transactionStep = 1;
    }
    else if(transactionStep == 1) //第二次下降沿
    {
      while(!(SPSR & (1 << SPIF)));
      volatile byte dummy = SPDR;
      transactionStep = 0;
      receivedAddress = 0;

      if(SPSR & (1 << WCOL))
      {
        volatile byte tmp = SPDR;
      }
      SPDR = 0x00;
    }
  }
  lastSSState = currentState;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 09:44:49