dsPIC33FJ128GP802 マイクロコントローラ用の SD カード (FatFS を使用) に書き込むプロジェクトを再作成しようとしています。
現在、SPI から日付を収集するために、512 回ループして SPI バッファーにダミー値を書き込む do/while を使用し、SPI フラグを待ってから、次のように SPI 値を読み取ります。
int c = 512;
do {
SPI1BUF = 0xFF;
while (!_SPIRBF);
*p++ = SPI1BUF;
} while (--c);
DMA 割り込みを使用してこれを再現しようとしていますが、期待どおりに動作しません。私は 1 つの DMA チャネルを使用しています。SPI は当面 8 ビット モードであるため、DMA はバイト モードであり、「ヌル書き込み」モードでもあり、ピンポンなしで連続します。私のバッファーは 1 つのメンバー配列のみであり、DMA は一致しています。
DMA2CONbits.CHEN = 0; //Disable DMA
DMA2CONbits.SIZE = 1; //Receive bytes (8 bits)
DMA2CONbits.DIR = 0; //Receive from SPI to DMA
DMA2CONbits.HALF = 0; //Receive full blocks
DMA2CONbits.NULLW = 1; //null write mode on
DMA2CONbits.AMODE = 0; //Register indirect with post-increment
DMA2CONbits.MODE = 0; //continuous mode without ping-pong
DMA2REQbits.IRQSEL = 10; //Transfer done (SPI)
DMA2STA = __builtin_dmaoffset(SPIBuffA); //receive buffer
DMA2PAD = (volatile unsigned int) &SPI1BUF;
DMA2CNT = 0; //transfer count = 1
IFS1bits.DMA2IF = 0; //Clear DMA interrupt
IEC1bits.DMA2IE = 1; //Enable DMA interrupt
null書き込みモードから私が理解していることから、DMAは読み取りが実行されるたびにnull値を書き込みます。ただし、CPU による最初の書き込みが実行されるまで DMA は開始されないため、手動/強制の方法で DMA を開始しました。
DMA1CONbits.CHEN = 1; //Enable DMA
DMA1REQbits.FORCE = 1; //Manual write
割り込みが開始され、エラーなしで実行されます。ただし、コードは後でコレクションが正しくないことを示しています。
私の割り込みは、収集したデータ (上記で割り当てられた DMA バッファーに配置されていると想定) を、プログラム全体で使用されるポインターに配置するだけであるという点で単純です。
void __attribute__((interrupt, no_auto_psv)) _DMA2Interrupt(void) {
if (RxDmaBuffer == 513) {
DMA2CONbits.CHEN = 0;
rxFlag = 1;
} else {
buffer[RxDmaBuffer] = SPI1BUF;
RxDmaBuffer++;
}
IFS1bits.DMA2IF = 0; // Clear the DMA0 Interrupt Flag
}
割り込みが 512 回実行されたら、DMA を停止してフラグをスローします。
私は何が欠けていますか?これは非 DMA 方式とどのように同じではないのですか? SPIの送信完了を待つwhileループ(while(!_SPIRBF);)が無いのが原因でしょうか。残念ながら、null 書き込みモードでは SPI データを自動的に送受信するため、手動で待機することはできません。
また、2 つの DMA チャネル (1 つは書き込み用、もう 1 つは読み取り用) を使用してみましたが、これも機能しませんでした (さらに、後で SD カードに適切に書き込むときに、そのチャネルが必要になります)。
どんな助けでも素晴らしいでしょう!