我正在尝试在pic32mx795f512l上做一个小应用程序,但我无法让它工作。 我想要实现的是adc以尽可能高的速率从通道0连续获取当前模拟值。如果填充了16个字缓冲区,它应该触发dma以将该缓冲区保存在ram中。如果ram缓冲区已满,dma应该触发中断。所以我可以在主循环中开始计算。 我现在的问题是dma根本没有被触发。当我在adc上启用中断时,主循环没有运行。 有谁知道我做错了什么? 这是我的源代码:
/*** DEVCFG0 ***/
#pragma config DEBUG = OFF
#pragma config ICESEL = ICS_PGx2
#pragma config PWP = 0xff
#pragma config BWP = OFF
#pragma config CP = OFF
/*** DEVCFG1 ***/
#pragma config FNOSC = PRIPLL
#pragma config FSOSCEN = ON
#pragma config IESO = ON
#pragma config POSCMOD = XT
#pragma config OSCIOFNC = OFF
#pragma config FPBDIV = DIV_8
#pragma config FCKSM = CSDCMD
#pragma config WDTPS = PS1048576
#pragma config FWDTEN = ON
/*** DEVCFG2 ***/
#pragma config FPLLIDIV = DIV_2
#pragma config FPLLMUL = MUL_20
#pragma config FPLLODIV = DIV_1
#pragma config UPLLIDIV = DIV_2
#pragma config UPLLEN = ON
/*** DEVCFG3 ***/
#pragma config USERID = 0xffff
#pragma config FSRSSEL = PRIORITY_7
#pragma config FMIIEN = ON
#pragma config FETHIO = ON
#pragma config FCANIO = ON
#pragma config FUSBIDIO = ON
#pragma config FVBUSONIO = ON
int adcValues[128];
void __ISR(_ADC_VECTOR, IPL7SRS) ADCHandler(void) // interrupt every 8 samples
{
IFS1bits.AD1IF = 0; // clear interrupt flag
}
void __ISR(_DMA0_VECTOR, ipl5) _IntHandlerSysDmaCh0(void)
{
int dmaFlags=DCH0INT&0xff; // read the interrupt flags
/*
perform application specific operations in response to any interrupt flag set
*/
DCH0INTCLR=0x000000ff; // clear the DMA channel interrupt flags
IFS1CLR = 0x00010000; // Be sure to clear the DMA0 interrupt flags
}
unsigned int __attribute__((always_inline)) _VirtToPhys(const void* p) {
return (int) p < 0 ? ((int) p & 0x1fffffffL) : (unsigned int) ((unsigned char*) p + 0x40000000L);
}
void initADC(void) {
AD1PCFG = 0xFFFB; // PORTB = Digital; RB2 = analog
AD1CON1 = 0x0000; // SAMP bit = 0 ends sampling
// and starts converting
// turn ADC on | unsigned 32-bit int output | auto-convert after sample finished |
// don?t stop conversions at interrupt | auto-sample after conversion finished
AD1CON1 = (1 << 15) | (4 << 8) | (7 << 5) | (0 << 4) | (1 << 2);
IPC6bits.AD1IP = 7; // INT priority level 7, for shadow register set
IFS1bits.AD1IF = 0; // clear interrupt flag
IEC1bits.AD1IE = 1; // enable interrupts
AD1CHS = 0x00020000; // Connect RB2/AN2 as CH0 input
AD1CON1SET = 0x8000; // turn on the ADC
}
void initDMA(void) {
IEC1CLR=0x00010000; // disable DMA channel 0 interrupts
IFS1CLR=0x00010000; // clear any existing DMA channel 0 interrupt flag
DMACONSET=0x00008000; // enable the DMA controller
DCH0CON=0x03; // channel off, priority 3, no chaining
DCH0ECON=0;
DCH0ECONbits.CHSIRQ=_ADC_IRQ; // This should map the AD1 ? ADC1 Convert Done Interrupt to start the dma IRQ no. 33 Vector no. 27
// program the transfer
DCH0SSA=_VirtToPhys(&ADC1BUF0); // transfer source physical address
DCH0DSA=_VirtToPhys(adcValues); // transfer destination physical address
DCH0SSIZ=16; // source size 16 bytes
DCH0DSIZ=128; // destination size NUM_SAMPS bytes
DCH0CSIZ=16; // 16 bytes transferred per event
DCH0INTCLR=0x00ff00ff; // clear existing events, disable all interrupts
//DCH0INTSET=0x00090000; // enable Block Complete and error interrupts
DCH0INTbits.CHDDIF=1; //1 = Channel Destination Pointer has reached end of destination (CHDPTR = CHDSIZ)
IPC9CLR=0x0000001f; // clear the DMA channel 0 priority and sub-priority
IPC9SET=0x00000016; // set IPL 5, sub-priority 2
IEC1SET=0x00010000; // enable DMA channel 0 interrupt
DCH0CONSET=0x80; // turn channel on
}
void main(){
INTDisableInterrupts(); // disable interrupts before configuring ADC
initADC();
initDMA();
INTEnableSystemMultiVectoredInt(); // enable interrupts at CPU
while(1);
}
答案 0 :(得分:0)
在我看来,问题是你有两个不同的来源试图消耗来自ADC的中断向量,包括DMA通道和ISR。
根据我的经验,这意味着两者中只有一个会获得中断向量,而且往往是ISR。
我建议您删除ADC的ISR。特别是因为您似乎只是重置了中断标志,但应该可以将ADC配置为自动复位标志并中断每个采样数量(我已经能够在PIC32mx256f128B上执行此操作)