13.4.9.2 Fixed to Block

In Fixed to Block mode, the source address remains unchanged throughout the transfer, but the destination address is incremented or decremented (depending on the DAMODEx setting). This works well for receiving data from the single-word buffer of a serial communication peripheral and filling a block of addresses designated as a buffer.

Code for Fixed to Block Continuous Transfer (Peripheral to Memory) shows sample code for Fixed to Block Addressing. The source address (UART receive) generates an interrupt when the UART buffer has received four bytes; the UART Receive Interrupt Flag (U2RIF) will trigger the transfer.

Code for Fixed to Block Continuous Transfer (Peripheral to Memory)

void UartInit(void);
unsigned char Array2[32];

int main() 
{
    UartInit();
    
    for (int i = 0; i < 32; i++) 
    {
        Array2[i] = 0;             //fill with 0
    }
    
    DMACONbits.ON = 1;            //Enable DMA

    DMAHIGH = 0x5000;             //set lower and upper address limit
    DMALOW = 0x4000;
    DMA0SRC = (uint32_t) &U1RXB;
    DMA0DST = (uint32_t) &Array2[0]; // load destination address
    DMA0CNT = 4; //When the UART buffer has 4 bytes, do an interrupt and transfer 4 bytes
    DMA0CH = 0;
    
    DMA0CHbits.SIZE=0;            //One byte transferred at a time
    DMA0CHbits.SAMODE = 0;        //Source address increment mode: do not increment
    DMA0CHbits.DAMODE = 1;        //Destination address increment mode: increment 1
    DMA0CHbits.TRMODE = 2;        //Transfer mode: Continuous
    
    DMA0SELbits.CHSEL = 15;       //Trigger DMA channel 0 on UART1 Receive
    DMA0CHbits.DONEEN=1;          //Enable interrupt on DONE being set
    DMA0CHbits.CHEN = 1;          //Channel 0 enable
    
    IFS2bits.DMA0IF = 0;
    //Wait for the bytes to be transferred (triggered by UART reception)
    while (!IFS2bits.DMA0IF);    //DONE=1;CHAEN=0,DMA0IF=1 and transfer complete with one trigger
    
    IFS2bits.DMA0IF = 0;
    
    //4 bytes received from UART1 are now be stored in Array2.
    //DMA0DST will point at Array2[4], and further bytes can be transferred by enabling the channel again.
    
    while (1);
}


//Enable UART1 for 115200 baud rate using RH1 as UART1 TX and RD1 as UART1 RX.
void UartInit(void) 
{
    //Enable CLKEN8 to provide clock to UART
    CLK8CONbits.ON = 1;
    
    // RP114 - RH1, configure as UART TX
    _TRISH1 = 0;
    _RP114R = _RPOUT_U1TX;
    
    // RP50 - RD1, configure as UART RX
    _TRISD1 = 1;
    _U1RXR = 50;
    
    U1CONbits.CLKMOD = 1;             //Use fractional baud rate generation
    U1CONbits.CLKSEL = 1;             //Select CLKGEN8 as clock source
    
    U1CONbits.MODE = 0;               //Asynchronous 8-bit UART
    
    //Enable RX and TX functionality
    U1CONbits.RXEN = 1;
    U1CONbits.TXEN = 1;
    
    //In fractional baud rate mode, UxBRG = Input clock / baud rate, for 8MHz and 115200 baud
    U1BRG = (8000000 / 115200);
    
    U1STATbits.RXWM = 3;             //Interrupt after 4 transfers
    
    //Lastly, enable UART1
    U1CONbits.ON = 1;
    
    _U1RXIF = 0;
}