通过PIC32上的DMA接收SPI数据

我知道这个话题(DMA和SPI)已经在微芯片论坛的众多线程中被讨论过了,实际上我已经阅读了搜索结果的所有15个页面,关键字为“dma”,并阅读了有关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); 
    } 
} 
所以我最终在这条线上永远等待:while(!DmaRxIntFlag); 我在中断向量中放置了断点,它们从未被调用过。 在持续等待期间,这是几个寄存器的状态: DMACON 0x0000C800 DMASTAT 0x00000001 我使用SPI1A端口,所以SPI1ABUF和_SPI1A_RX_IRQ DCH1SPTR 0x5 DCH1SSIZ 0x2B DCH2DPTR 0x6 DCH2DSIZ 0x2B DCH2CON 0x00008083 DCH2ECON 0x1B10 DCH2INT 0x00800C4 DCH2SSA 0x1F805820 DCH2DSA 0x00000620 通道1用于传输 通道2用于接收     
已邀请:
你错过了这些:
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); 
祝好运!     
你是否在从机模式下使用SPI?或者您处于主模式,尝试读取命令的某些响应? 你有没有检查过这个芯片的硅片勘误表? dspic 33fj系列存在SPI从模式无法正常工作的问题。 除此之外,我认为忙于等待DmaRxIntFlag更改不是一个好主意。您应该配置DMA传输并继续主循环。 DMA将触发中断处理程序。 希望这可以帮助。     

要回复问题请先登录注册