gpt4 book ai didi

c - 在 PIC32 上通过 DMA 接收 SPI 数据

转载 作者:行者123 更新时间:2023-12-02 00:03:41 27 4
gpt4 key购买 nike

我知道这个主题(DMA 和 SPI)已经在微芯片论坛的许多线程中讨论过,实际上我已经阅读了关键字“dma”搜索结果中的所有 15 页,并阅读了所有主题关于 DMA 和 SPI。

我仍然被我的问题困扰,我希望有人可以帮助我:)

问题就在这里。

我的芯片是PIC32MX775F512H。我正在尝试通过 DMA 使用 SPI 接收(仅接收)数据。由于您不能“仅”在 SPI 中接收,并且仅当您写入 SPIBUF(对我来说 SPI1ABUF)时,SPI 内核才开始切换 SPI 时钟,因此我尝试使用 2 个 DMA channel 接收数据。DMA_CHANNEL1为发送部分。DMA_CHANNEL2为接收部分。

我复制粘贴了 http://www.microchip.com/forums/tm.aspx?tree=true&high=&m=562453&mpage=1# 中的代码

并试图让它发挥作用,但没有任何运气。它只接收几个字节(5 或 6)。

我已将两个 DMA channel 的事件启用标志设置为 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);

我在中断 vector 中放置了断点,但它们从未被调用。

这是在持续等待期间几个寄存器的状态:

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

channel 1用于传输
channel 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);

祝你好运!

关于c - 在 PIC32 上通过 DMA 接收 SPI 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5170924/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com