如何使用SPI解决从机到主机的数据传输问题



我尝试使用SPI在两个AVR(ATmega128(之间进行通信。

数据从主设备正确地传输到从设备,但数据从从设备错误地传输到主设备,第一个采样位总是错误的。

从设备向主设备发送(0X7E(,但接收到的数据为(0X3F(。

错误在哪里?

MASTER代码

#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#define ACK 0x7E
void spi_init_master(void)
{
DDRB = (1<<0)|(1<<1)|(1<<2);              //Set MOSI, SCK, SS as Output
PORTB |= 1; 
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0); //Enable SPI, Set as Master, Prescaler: Fosc/16
}
//Function to send and receive data
unsigned char spi_tranceiver(unsigned char data)
{
PORTB &= ~(1<<0);
SPDR = data;                       //Load data into the buffer
while (!(SPSR & (1<<SPIF) ));       //Wait until transmission complete
PORTB |= (1<<0);
return (SPDR);                      //Return received data
}
int main(void)
{
spi_init_master();                  //Initialize SPI Master

unsigned char data;
unsigned char ret;

while (1) 
{
ret = spi_tranceiver(data);
}
}

SLAVE代码

#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#define ACK 0x7E
void spi_init_slave(void)
{
DDRB = (1<<3);                                  //MISO as OUTPUT
SPCR = (1<<SPE);                                //Enable SPI
}
//Function to send and receive data
unsigned char spi_tranceiver(unsigned char data)
{
SPDR = data;                                  //Load data into buffer
while (!(SPSR & (1<<SPIF) ));                  //Wait until transmission complete
return (SPDR);                                 //Return received data
}

int main(void)
{
spi_init_slave();                             //Initialize slave SPI
unsigned char data;

while (1) 
{
data = spi_tranceiver(ACK);
}
}

也许问题出在重新加载数据寄存器@SLAVE上。在您的代码中,这是通过轮询完成的。因此,如果您的时钟速度很高,从机就没有足够的时间来正确地重新加载寄存器。

重要提示:

SPI的时钟速度必须为从属设备上的F_CPU/4(参见第168页的数据表(

尝试在master上设置延迟。所以从机有一些时间重新加载寄存器:

#define F_CPU ?????????UL  // Clock speed of system in Hz
unsigned char spi_tranceiver(unsigned char data);
#include <util/delay.h>
int main(void)
{
// ...

while (1) 
{
ret = spi_tranceiver(data);
}
}
unsigned char spi_tranceiver(unsigned char data)
{
_delay_ms(10);
PORTB &= ~(1<<SS);
SPDR = data;
while (!(SPSR & (1<<SPIF)));
PORTB |= (1<<SS);
return (SPDR);
}

尝试在启动master之前启动slave

最新更新