7.3 Example-3
This example shows the code snippet for the setup of the DMA module to transfer data from a look-up table stored in the Program Flash Memory into the PWM duty cycle register. Each byte transfer is triggered by the roll-over of Timer0. The code also sets up an abort trigger when an Interrupt-on-Change (IOC) is detected. The data is stored in an array called “PWM_DATA” and each time the Timer0 rolls over a byte is transferred from the array into the PWM duty cycle register. User firmware does not need to set the DGO bit in the DMA1CON0 register as the timer overflow will automatically set it. Since the SSTP and DSTP bits are cleared, the DMA module will continue to operate until an abort trigger is detected. When an abort trigger is detected, the DGO, AIRQEN and SIRQEN bits are cleared. User firmware has to set the SIRQEN and AIRQEN to re-enable the DMA module.
void DMA1_Initialize(void)
{
DMA1SSA = &PWM_DATA; //set source start address
DMA1DSA = &PWM5DCH; //set destination start address
DMA1CON1 = 0x0A; //DMODE = 00 | DSTP = 0 | SMR = 01 | SMODE = 01 | SSTP = 1
DMA1SSZ = 0x00AC; //set source size = 172 bytes
DMA1DSZ = 0x0001; //set destination size
DMA1SIRQ = 0x1F; //set DMA Transfer Trigger Source = TMR0
DMA1AIRQ = 0x07; //set DMA Transfer abort Source = IOC
PIR2bits.DMA1DCNTIF = 0; //clear Destination Count Interrupt Flag bit
PIR2bits.DMA1SCNTIF = 0; //clear Source Count Interrupt Flag bit
PIR2bits.DMA1AIF = 0; //clear abort Interrupt Flag bit
PIR2bits.DMA1ORIF = 0; //clear overrun Interrupt Flag bit
PIE2bits.DMA1DCNTIE = 0; //disable Destination Count 0 Interrupt
PIE2bits.DMA1SCNTIE = 0; //disable Source Count Interrupt
PIE2bits.DMA1AIE = 1; //enable abort Interrupt
PIE2bits.DMA1ORIE = 0; // isable overrun Interrupt
asm("BCF INTCON0,7"); //disable Global Interrupts
asm ("BANKSEL PRLOCK"); //
asm ("MOVLW 0x55"); //
asm ("MOVWF PRLOCK"); //Arbiter Priority lock
asm ("MOVLW 0xAA"); //sequence
asm ("MOVWF PRLOCK"); //
asm ("BSF PRLOCK, 0"); //
asm("BSF INTCON0,7"); //enable Global Interrupts
DMA1CON0 = 0x80; //EN = 1 | SIRQEN = 0 | DGO = 0 |xx| AIRQEN = 0 |x| XIP = 0
}
User firmware can set the SIRQEN bit whenever the DMA transaction needs to start. This can be done by the following line of code.
DMA1CON0bits.SIRQEN = 1;
The following lines of code need to be used to restart the DMA module and it will continue to run until an abort trigger is received.
DMA1CON0bits.SIRQEN = 1;
DMA1CON0bits.AIRQEN = 1;