UART DMA for arrays of various sizes

Using MPLAB X 1.70 with the dsPIC33FJ128GP802 microcontroller.

I have an application that collects data from two sensors with different sampling rates (one at 50 Hz, the other at 1000 Hz), both sensor packets also have different sizes (one at 5 bytes, the other at 21 bytes), I’m still used manual UART transmission as shown below:

void UART_send(char *txbuf, char size) {
    // Loop variable.
    char i;

    // Loop through the size of the buffer until all data is sent. The while
    // loop inside checks for the buffer to be clear.
    for (i = 0; i < size; i++) {
        while (U1STAbits.UTXBF);
        U1TXREG = *txbuf++;
    }
}

Masses of various sizes (5 or 21 bytes) were sent to this function with their size and simple loops laid out by each byte and displayed through the UART tx U1TXREG register.

DMA, . DMA UART ADC, . - , , , 21- , .

DMA, .

void UART_TX_DMA_init() {

        DMA2CONbits.SIZE  = 0;                                  // 0: word; 1: byte
        DMA2CONbits.DIR   = 1;                                  // 0: uart to device; 1: device to uart
        DMA2CONbits.AMODE = 0b00;
        DMA2CONbits.MODE  = 1;                                  // 0: contin, no ping pong; 1: oneshot, no ping pong; 2: contin, ping pong; 3: oneshot, ping pong.

        DMA2PAD = (volatile unsigned int) &U1TXREG;

        DMA2REQ = 12;                   // Select UART1 Transmitter

        IFS1bits.DMA2IF  = 0;           // Clear DMA Interrupt Flag
        IEC1bits.DMA2IE  = 1;           // Enable DMA interrupt
}

DMA . DMA, :

char TXBufferADC[5] __attribute__((space(dma)));
char TXBufferIMU[21] __attribute__((space(dma)));

void UART_send(char *txbuf, char size) {

    // Loop variable.
    int i;

    DMA2CNT = size - 1; // x DMA requests

    if (size == ADCPACKETSIZE) {
        DMA2STA = __builtin_dmaoffset(TXBufferADC);
        for (i = 0; i < size; i++) {
            TXBufferADC[i] = *txbuf++;
        }
    } else if (size == IMUPACKETSIZE) {
        DMA2STA = __builtin_dmaoffset(TXBufferIMU);
        for (i = 0; i < size; i++) {
            TXBufferIMU[i] = *txbuf++;
        }
    } else {
        NOTIFICATIONLED ^= 1;
    }

    DMA2CONbits.CHEN = 1; // Re-enable DMA2 Channel
    DMA2REQbits.FORCE = 1; // Manual mode: Kick-start the first transfer
}

-. DMA2STA, , . , DMA, (DMA2CNT), , , for, .

, , DMA / . , , . , ; ...

.

+4
1

, , .

, , , DMA , , , . , UART :

while (! U1STAbits.TRMT);

DMA , , DMA.

, , , :

void sendData() {
    // Check that last transmission has completed.
    while (!U1STAbits.TRMT);

    DMA2CNT = bufferSize - 1;

    DMA2STA = __builtin_dmaoffset(data);

    DMA2CONbits.CHEN = 1; // Re-enable DMA0 Channel
    DMA2REQbits.FORCE = 1; // Manual mode: Kick-start the first transfer
}

DMA , , DMA2CNT, DMA .

DMA:

DMA2CONbits.SIZE = 1;
DMA2CONbits.DIR = 1; 
DMA2CONbits.AMODE = 0b00;
DMA2CONbits.MODE = 1;

DMA2PAD = (volatile unsigned int) &U1TXREG;

DMA2REQ = 12;                               // Select UART1 Transmitter

IFS1bits.DMA2IF = 0;                        // Clear DMA Interrupt Flag
IEC1bits.DMA2IE = 1;                        // Enable DMA interrupt

, -, UART1 TX.

, - , PIC.

+1