2

AT91SAM7X512のSPIペリフェラルは、書き込みを行うX時間(Xは変化します)で無効になりますSPI_TDR。その結果、プロセッサはでTDREフラグをチェックするwhileループでハングしSPI_SRます。このwhileループはSPI_Write()、ATMELが提供するソフトウェアパッケージ/ライブラリに属する​​関数にあります。問題は任意に発生します。すべてが正常に機能する場合もあれば、繰り返し試行しても失敗する場合もあります(試行=同じバイナリをMCUにダウンロードしてプログラムを実行する)。

構成は次のとおりです(書き込み順に定義)。

  1. SPI_MR
    • MSTR= 1
    • PS= 0
    • PCSDEC= 0
    • PCS= 0111
    • DLYBCS= 0
  2. SPI_CSR[3]
    • CPOL= 0
    • NCPHA= 1
    • CSAAT= 0
    • BITS= 0000
    • SCBR= 20
    • DLYBS= 0
    • DLYBCT= 0
  3. SPI_CR
    • SPIEN= 1

構成を設定した後、コードはSPIENSフラグをチェックすることにより、SPIが有効になっていることを確認します。

次のようにバイトの送信を実行します。

const short int dataSize = 5;
// Filling array with random data
unsigned char data[dataSize] = {0xA5, 0x34, 0x12, 0x00, 0xFF};
short int i = 0;
volatile unsigned short dummyRead;

SetCS3();   // NPCS3 == PIOA15
while(i-- < dataSize) {
    mySPI_Write(data[i]);
    while((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
    dummyRead = SPI_Read(); // SPI_Read() from Atmel's library
}
ClearCS3();
/**********************************/
void mySPI_Write(unsigned char data) {
    while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
    AT91C_BASE_SPI0->SPI_TDR = data;
    while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TDRE) == 0); // <-- This is where
    // the processor hangs, because that the SPI peripheral is disabled
    // (SPIENS equals 0), which makes TDRE equal to 0 forever.
}

質問:

  1. 書き込み時にSPIペリフェラルが無効になる原因は何SPI_TDRですか?
  2. レジスタSPI_Write()を読み取る行のコメントを解除する必要がありますか? つまり、次のコードの4行目:( 4行目は元々コメントとしてマークされています)SPI_RDR

    void SPI_Write(AT91S_SPI *spi, unsigned int npcs, unsigned short data)
    {
        // Discard contents of RDR register
        //volatile unsigned int discard = spi->SPI_RDR;
        /* Send data */
        while ((spi->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
        spi->SPI_TDR = data | SPI_PCS(npcs);
        while ((spi->SPI_SR & AT91C_SPI_TDRE) == 0);
    }
    
  3. 5バイトのデータを送信する上記のコードに何か問題がありますか?

ご注意ください:

  • NPCS行番号。3はGPIOライン(つまり、PIOモード)であり、SPIコントローラーによって制御されません。必要に応じてChipSelect#3(NPCS3)ピンをデ/アサートすることにより、コード内でこの行を自分で制御しています。私がそうしている理由は、SPIコントローラーにこのピンを制御させようとしたときに問題が発生したためです。
  • 私はPDC/DMAコントローラーを使用せず、使用しないことを好みました。
  • SPIペリフェラルを2回リセットしませんでした。これは、リセットを実行した場合にのみエラッタが2回リセットするように指示しているためです。これは実行しません。正誤表の引用:

    ソフトウェアリセット(SPI制御レジスタのSWRST)を実行すると、SPIが正しく動作しない場合があります(チップセレクトの前にクロックが有効になります)。
    問題の修正/回避策
    SPI制御レジスタフィールドのSWRST(ソフトウェアリセット)は次のようになります。正しく設定するために2回書き込まれます。

  • レジスター(in )への書き込みの前に遅延を設定すると、コードが完全に機能し、通信が成功する場合があることに気付きました。SPI_TDRSPI_Write()

便利なリンク:

SPIを初期化し、5バイトの転送を実行する例は、高く評価されており、役に立ちます。

4

1 に答える 1

1

あなたが使う

while(i-- < dataSize)

符号付き整数をインクリメントせずにデクリメントし、オーバーフローが正の値になるまでiアクセスします。何が起こっているのか、どのメモリまたはレジスタにアクセスしているのか誰が知っていますか? 負の値を保持する必要がない場合は、通常、符号なし整数を使用することをお勧めします。data[i]i

TXEMPTYまた、データがシフトレジスタに移動されて送信されることを意味するものをすでに確認しています。そのため、チェックする必要はありませんTDRE。これは、データがシフト レジスタに移動されることを意味しますが、送信されない可能性があることを意味します。

また、データを同時に交換しない場合は、PDC を使用することを強くお勧めしますが、そうではないと思います。

于 2013-05-15T09:18:51.180 に答える