4.2 DMX Receiver with DMA
In the case of DMX receiver, the microcontroller will need to receive a range of data from the complete DMX packet. As mentioned earlier, the UART module is capable of filtering unwanted data bytes, but the firmware still needs to read the necessary bytes from the UxRXB register. Using the DMA module, the received data bytes can be transferred to a buffer in the RAM area without the involvement of the CPU.
The DMA module is setup to read the incoming byte from the UxRXB register and transfer it to a location in the RAM area. The destination address will increment in this case, but the source address remains static. The DMA operation can be triggered by the UART Receive Interrupt Flag (UxRXIF). When a byte is received into the buffer, the DMA is triggered to move it to the buffer. Note that the receive interrupt will set only for the valid address range defined in the UART configuration. The DMA module can be configured to stop or restart every time the destination counter reloads.
The example code below is for the DMA setup to receive 16 bytes of data starting from address 20. Note that the start code is always received and transferred into the RAM buffer. So the DMA count should be one more than the number of required bytes. Note that the UART configuration is still required, as mentioned in section Setup for DMX Receiver.
Code snippet for DMA setup to work with DMX Recevier
void DMA1_Initialize(void)
{
DMA1SSA = &U1RXB; //set source start address
DMA1DSA = &RX_DATA; //set destination start address
DMA1CON1 = 0x60; //DMODE=01|DSTP=1|SMR=00|SMODE=00|SSTP=0
DMA1SSZ = 0x0001; //set source size = 1 byte
DMA1DSZ = 0x0011; //set destination size = 17 bytes
DMA1SIRQ = 0x1B; //set DMA Transfer Trigger Source = U1RX
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;