4.1 DMX Controller with DMA
In the case of a DMX controller, the microcontroller will send up to 513 bytes (including the start code) from a preloaded buffer. The start code should be included as the first byte of the buffer. This makes the complete DMX packet transmission automated through the DMA. The DMA module is setup to move one byte of data at a time from the buffer to the UxTXB register. The DMA operation can be triggered by the UART Transmit Interrupt Flag (UxTXIF). Every time a byte is transmitted out of the buffer, the DMA is triggered to move the next data byte. The DMA module can be configured to stop or restart at the end of the DMX packet. The source address will increment in this case, but the destination address remains static.
The example code below is for the DMA setup to transfer 300 bytes of data into the U1TXB register. Note that the UART configuration is still required as mentioned in the section Setup for DMX Controller. The firmware required to load a byte of data into the U1TXB register is eliminated using the DMA module.
Code snippet for DMA setup to work with DMX Controller
void DMA1_Initialize(void)
{
DMA1SSA = &TX_DATA; //set source start address
DMA1DSA = &U1TXB; //set destination start address
DMA1CON1 = 0x03; //DMODE=00|DSTP=0|SMR=00|SMODE=01|SSTP=1
DMA1SSZ = 0x012C; //set source size = 300 bytes
DMA1DSZ = 0x0001; //set destination size = 1 byte
DMA1SIRQ = 0x1C; //set DMA Transfer Trigger Source = U1TX
DMA1AIRQ = 0x00; //set DMA Transfer abort Source
PIR2bits.DMA1DCNTIF = 0; //clear Destination Count Interrupt Flag
PIR2bits.DMA1SCNTIF = 0; //clear Source Count Interrupt Flag
PIR2bits.DMA1AIF = 0; //clear abort Interrupt Flag
PIR2bits.DMA1ORIF = 0; //clear overrun Interrupt Flag
PIE2bits.DMA1DCNTIE = 0; //disable Destination Count Interrupt
PIE2bits.DMA1SCNTIE = 0; //disable Source Count Interrupt
PIE2bits.DMA1AIE = 0; //disable abort Interrupt
PIE2bits.DMA1ORIE = 0; //disable 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
}
DMA1CON0bits.SIRQEN = 1;