2017-04-04 138 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,這與我們的檢查相混淆。