2017-04-04 202 views
1

我们正在尝试使用SPI与另一个使用atmel atmega328 MCU的IC进行通信。目标集成电路接收命令(代码中的标题),然后将存储在请求的寄存器中的信息(或者如果命令是写入时写入它)反馈给我们。但是,我们在这里遇到两个问题:atmega328上的SPI无法正常工作

  1. 没有任何内容来自SPI,唯一的变化是在CS线上(我们控制的)。没有SPI时钟,数据线上没有数据。

  2. 写入标题时for循环的第一次迭代程序不会进入while循环(端口6上的LED不会打开)。

任何与此有关的帮助将不胜感激,代码如下。

#define DDR_SPI DDRB 
#define DD_MISO DDB4 
#define DD_MOSI DDB3 
#define DD_SCK DDB5 
#define DD_SS DDB6 

void SPI_MasterInit(void) 
{ 
    /* Set MOSI, SCK and CS output, all others input */ 
    DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS); 
    /* Enable SPI, Master, set clock rate = System clock/16 */ 
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0); 
} 

int readfromspilow(uint16 headerLength, const uint8 *headerBuffer, uint32 readLength, uint8 *readBuffer) 
{ 


    PORTB &= ~(1 << PORTB6);    // Set CS low 

    for(int i=0; i<headerLength; i++) 
    { 
     SPDR = headerBuffer[i];    //Send entry i of the header to the spi register 
     sleep_us(5);      // Give the flag time to reset, might be unnecessary 
     PORTD |= (1 << PORTD5);    //LED for diagnostics 
     while(!(SPSR & (1<<SPIF))){   //Wait for SPIFinished flag 
      PORTD |= (1 << PORTD6);   //LED for diagnostics 
     } 

     PORTD &= ~(1 << PORTD3);   //LED for diagnostics 



     //readBuffer[0] = SPDR; // Dummy read as we write the header 
    } 

    for(int i=0; i<readLength; i++) 
    { 
     SPDR = 0xFF;      // Dummy write as we read the message body 
     sleep_us(5);      // Give the flag time to reset, might be unnecessary 
     while(!(SPSR & (1<<SPIF)));   //Wait for SPIFinished flag 
     readBuffer[i] = SPDR ;    //Store the value in the buffer 
    } 

    PORTB |= (1 << PORTB6);     // Set CS high 


    return; 
} 

编辑:增加了对初始化

+0

如何在代码中使用它?什么是DDR_SPI和其他?位匹配? while循环等待SPI完成停止? – tilz0R

+0

我们只需将readfromspilow作为标题(地址和我们希望读取的寄存器)的所需命令调用,并将预期答案的长度作为读取长度,缓冲区存储读取答案的点。我用一个编辑添加了SPI的定义,不确定“位匹配”是什么意思。虽然第一次迭代(不知道为什么)会跳过,但随后又陷入了下一次迭代(可能是因为SPI从未完成信号) – Sebastian

回答

1

你的代码的定义似乎是正确的,但由于您没有使用的SPI中断处理程序,你需要清除的SPSR的SPIF位之前您正在通过SPDR发送数据。 SPDR不接受设置了SPIF标志的任何数据。

1

根据手册19.5.2

或者,SPIF位由第一读取与SPIF集SPI状态 寄存器,然后访问SPI数据寄存器(SPDR)清零。

你的代码不这样做,所以也许有一个标志集永远不会被清除。尝试改变代码:

volatile uint8_t spsr = SPSR;  //Dummy-read the flag register to clear flags 
SPDR = headerBuffer[i];    //Send entry i of the header to the spi register 
PORTD |= (1 << PORTD5);    //LED for diagnostics 
while(!(SPSR & (1<<SPIF))){   //Wait for SPIFinished flag 
    PORTD |= (1 << PORTD6);   //LED for diagnostics 
} 
0

我们解决了这个问题,问题是,在端口B2需要默认SS被定义为初始化阶段的输出,否则MCU可以换到从模式,如果该引脚悬空。这会在每次发生SPIF标志时将其设置为1,这与我们的检查相混淆。