版本 1:
我使用 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); // Select slave
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); // Deselect slave
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 寄存器在主机请求新值之前用数组的下一个值覆盖主机的虚拟值?
我试过用中断,也试过不用中断。但每次我收到的都是来自主设备的虚拟值作为输入。我更喜欢用中断。
版本 2:
通过在 ATtiny841 的 CS 引脚上生成中断并在 Pico 上的主代码中放置一些小的延迟,我能够将数据从 ATiny841 从属设备传输到 Pi Pico 主设备。
(使用 SPI 中断总是返回我从主机发送到从机的虚拟数据)
现在我尝试通过发送两个字节(字节1 = 寄存器地址,字节2 = 虚拟值)来添加一个寄存器结构。每个字节的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) //Falling edge
{
if(transactionStep == 0) //First falling edge
{
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) //Second falling edge
{
while(!(SPSR & (1 << SPIF)));
volatile byte dummy = SPDR;
transactionStep = 0;
receivedAddress = 0;
if(SPSR & (1 << WCOL))
{
volatile byte tmp = SPDR;
}
SPDR = 0x00;
}
}
lastSSState = currentState;
}