簡體   English   中英

atmega328上的SPI無法正常工作

[英]SPI on atmega328 not working

我們正在嘗試使用SPI與使用Atmel atmega328 MCU的另一IC進行通信。 目標IC接收命令(代碼中的標頭),然后將存儲在請求的寄存器中的信息反饋給我們(如果命令是寫操作,則將其寫入)。 但是,我們這里有兩個問題:

  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;
}

編輯:添加了初始化的定義

您的代碼似乎是正確的,但是由於您沒有使用SPI中斷處理程序,因此在通過SPDR發送數據之前,需要清除SPSR中的SPIF位。 SPDR不接受設置了SPIF標志的任何數據。

根據手冊19.5.2

或者,通過首先讀取設置了SPIF的SPI狀態寄存器,然后訪問SPI數據寄存器(SPDR),來清除SPIF位。

您的代碼不會執行此操作,因此可能存在一個永遠不會清除的標志集。 嘗試將代碼更改為:

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
}

我們解決了這個問題,問題是在初始化階段需要將端口B2上的默認SS定義為輸出,否則,如果該引腳懸空,則MCU可以更改為從設備操作模式。 每次將SPIF標志設置為1,這與我們的檢查混亂了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM