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
相关产品推荐
相关产品推荐

