我正在尝试为dsPIC33FJ128GP802微控制器重新创建一个写SD卡(使用FatFS)的项目。
目前要从SPI收集日期我有一个do / while循环512次并将伪值写入SPI缓冲区,等待SPI标志,然后读取SPI值,如下所示:
int c = 512;
do {
SPI1BUF = 0xFF;
while (!_SPIRBF);
*p++ = SPI1BUF;
} while (--c);
我正在尝试使用DMA intterupts重新创建它,但它不像我希望的那样工作。我正在使用一个DMA通道,SPI暂时处于8位模式,因此DMA处于字节模式,它也处于'空写'模式,并且连续没有乒乓。我的缓冲区只有一个成员数组,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
根据我从空写模式的理解,DMA将在每次执行读操作时写入空值。但是,DMA在CPU执行初始写入之前不会启动,所以我使用了manual / force方法来启动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);)。不幸的是,当空写入模式自动发送和接收SPI数据时,我无法手动进行任何类型的等待。
我也尝试过使用两个DMA通道,一个用于写入,一个用于读取,但这也不起作用(此外,当我正确写入SD卡时,我需要该通道。)
任何帮助都会很棒!