2011-03-02 41 views
3

我知道這個話題(DMA & SPI)已經在微芯片論壇的衆多線程中討論過了,實際上我已經閱讀了關鍵字「 dma「並閱讀關於dma & spi的所有主題。在PIC32上通過DMA接收SPI數據

,我仍然堅持我的問​​題,我希望有人能幫助我:)

這是問題所在。

我的芯片是PIC32MX775F512H。 我想通過DMA接收(只接收)使用SPI的數據。 由於您不能在SPI中接收數據,並且只有在寫入SPIBUF(SPI1ABUF)時,SPI內核纔開始翻轉SPI時鐘,因此我試圖使用2個DMA通道接收數據。 DMA_CHANNEL1發送部分。 DMA_CHANNEL2用於接收部分。

我複製從http://www.microchip.com/forums/tm.aspx?tree=true&high=&m=562453&mpage=1#

粘貼代碼,並試圖使它沒有任何的運氣工作。它只接收幾個字節(5或6)。

對於這兩個dma通道,我都設置了事件啓用標誌爲DMA_EV_BLOCK_DONE,沒有發生中斷。

你有什麼想法嗎?

這裏是我使用的代碼:

int Spi_recv_via_DMA(SPI_simple_master_class* SPI_Port, int8u *in_bytes, int16u num_bytes2) 
{ 
DmaChannel dmaTxChn=DMA_CHANNEL1; 
DmaChannel dmaRxChn=DMA_CHANNEL2; 
SpiChannel spiTxChn=SPI_Port->channel; 
    int8u   dummy_input; 

    DmaChnOpen(dmaTxChn, DMA_CHN_PRI3, DMA_OPEN_DEFAULT); 
    DmaChnOpen(dmaRxChn, DMA_CHN_PRI3, DMA_OPEN_DEFAULT); 

    DmaChnSetEventControl(dmaTxChn, DMA_EV_START_IRQ_EN | DMA_EV_START_IRQ(_SPI1A_RX_IRQ)); 
    DmaChnSetEventControl(dmaRxChn, DMA_EV_START_IRQ_EN | DMA_EV_START_IRQ(_SPI1A_RX_IRQ)); 

    DmaChnClrEvFlags(dmaTxChn, DMA_EV_ALL_EVNTS); 
    DmaChnClrEvFlags(dmaRxChn, DMA_EV_ALL_EVNTS); 
    DmaChnSetEvEnableFlags(dmaRxChn, DMA_EV_BLOCK_DONE); 
    DmaChnSetEvEnableFlags(dmaTxChn, DMA_EV_BLOCK_DONE); 

    //SpiChnClrTxIntFlag(spiTxChn); 
    //SpiChnClrRxIntFlag(spiTxChn); 

    DmaChnSetTxfer(dmaTxChn, tx_dummy_buffer, (void *)&SPI1ABUF, num_bytes2, 1, 1); 
    DmaChnSetTxfer(dmaRxChn, (void *)&SPI1ABUF, in_bytes, 1, num_bytes2, 1); 

    while ((SPI1ASTAT & SPIRBE) == 0) 
     dummy_input = SPI1ABUF; 
    SPI1ASTAT &= ~SPIROV; 

    DmaRxIntFlag = 0; 
    DmaChnEnable(dmaRxChn); 
    DmaChnStartTxfer(dmaTxChn, DMA_WAIT_NOT, 0); 


    while(!DmaRxIntFlag); 
    return 1;  
} 

與這兩個中斷處理程序:

// handler for the DMA channel 1 interrupt 
void __ISR(_DMA1_VECTOR, ipl5) DmaHandler1(void) 
{ 
int evFlags;  // event flags when getting the interrupt 
    //LED_On(LED_CFG); 
INTClearFlag(INT_SOURCE_DMA(DMA_CHANNEL1)); // acknowledge the INT controller, we're servicing int 

evFlags=DmaChnGetEvFlags(DMA_CHANNEL1); // get the event flags 

    if(evFlags&DMA_EV_BLOCK_DONE) 
    { // just a sanity check. we enabled just the DMA_EV_BLOCK_DONE transfer done interrupt 
     DmaTxIntFlag = 1; 
    DmaChnClrEvFlags(DMA_CHANNEL1, DMA_EV_BLOCK_DONE); 
    } 
    // LED_Off(LED_CFG); 
} 

void __ISR(_DMA2_VECTOR, ipl5) DmaHandler2(void) 
{ 
int evFlags;  // event flags when getting the interrupt 

INTClearFlag(INT_SOURCE_DMA(DMA_CHANNEL2)); // acknowledge the INT controller, we're servicing int 

evFlags=DmaChnGetEvFlags(DMA_CHANNEL2); // get the event flags 

    if(evFlags&DMA_EV_BLOCK_DONE) 
    { // just a sanity check. we enabled just the DMA_EV_BLOCK_DONE transfer done interrupt 
     DmaRxIntFlag = 1; 
    DmaChnClrEvFlags(DMA_CHANNEL2, DMA_EV_BLOCK_DONE); 
    } 
} 

所以我最終在該行永遠等待:而(!DmaRxIntFlag);

我在中斷向量中放置了斷點,它們從不被調用。

這是幾個寄存器不斷持續等待時的狀態:

DMACON 0x0000C800
DMASTAT 00000001

我使用SPI1A端口,所以SPI1ABUF和_SPI1A_RX_IRQ

DCH1SPTR 0x5的
DCH1SSIZ 0x2B

DCH2DPTR 0x6
DCH2DSI ž0x2B訪問

DCH2CON 0x00008083
DCH2ECON 0x1B10
DCH2INT 0x00800C4
DCH2SSA 0x1F805820
DCH2DSA 0x00000620

通道1是用來傳輸
頻道2,用於接收

+0

SPI連接的另一端是什麼類型的器件?我不得不假設它已經處於發送數據的模式中了? –

回答

0
  1. 你在從模式下使用SPI?或者您處於主模式,試圖讀取命令的某些響應?
  2. 你有沒有檢查芯片的硅勘誤? dspic 33fj系列存在SPI從模式根本無法工作的問題。

除此之外,我不認爲這是忙於等待DmaRxIntFlag更改的好主意。您應該配置DMA傳輸並繼續您的主循環。 DMA將觸發中斷處理程序。

希望這會有所幫助。

1

你缺少這些:

INTEnable(INT_SOURCE_DMA(dmaTxChn), INT_ENABLED); // Tx 
INTEnable(INT_SOURCE_DMA(dmaRxChn), INT_ENABLED); // Rx 

分辯之前

DmaRxIntFlag = 0; 
DmaChnEnable(dmaRxChn); 
DmaChnStartTxfer(dmaTxChn, DMA_WAIT_NOT, 0); 

祝你好運!