2013-12-10 5 views
4

У меня есть код, который работает «нормально» для чтения USCI (UART) через прерывания, но стек TI SimpliciTI является CPU hog, и он обнуляет байты UART при обслуживании радиостанции.Я ищу пример кода для обслуживания USCI (UART) на MSP430 через DMA, а не прерывания

Я предполагаю, что DMA - это путь, но я не смог найти полный пример DMA, используя USCI в качестве входных данных.

ответ

6

Вот что я в итоге сделал. Оно работает!

struct { 
#ifndef USE_DMA 
    volatile uint8_t rx_head ; 
#endif 
    volatile uint8_t rx_tail ; 
    uint8_t rx_buffer[128]; 
} uart = { 0,0}; 


void UART_Init(void) 
{ 
#ifndef USE_DMA 
    uart.rx_head = 0; 
#endif 
    uart.rx_tail = 0; 


    WDTCTL = WDTPW + WDTHOLD;     // Stop WDT 

    PMAPPWD = 0x02D52;      // Get write-access to port mapping regs 
    P1MAP5 = PM_UCA0RXD;      // Map UCA0RXD output to P1.5 
    P1MAP6 = PM_UCA0TXD;      // Map UCA0TXD output to P1.6 
    PMAPPWD = 0;        // Lock port mapping registers 

    P1DIR |= BIT6;       // Set P1.6 as TX output 
    P1SEL |= BIT5 + BIT6;      // Select P1.5 & P1.6 to UART function 

    UCA0CTL1 = UCSWRST;      // **Put state machine in reset** 
#ifdef UART_9600 
    UCA0CTL1 |= UCSSEL_1;      // CLK = ACLK 
    UCA0BR0 = 0x03;       // 32kHz/9600=3.41 (see User's Guide) 
    UCA0BR1 = 0x00;       // 
    UCA0MCTL = UCBRS_3+UCBRF_0;    // Modulation UCBRSx=3, UCBRFx=0 
#elif defined(UART_9600_SMCLK) 
    UCA0CTL1 |= UCSSEL_2;      // SMCLK 
    UCA0BR0 = 0xE2;       // 12MHz/12500 
    UCA0BR1 = 0x04;       // 
    UCA0MCTL = UCBRS_2+UCBRF_0;    // Modulation UCBRSx=3, UCBRFx=0 
#elif defined(UART_115200) 
    UCA0CTL1 |= UCSSEL_2;      // SMCLK 
    UCA0BR0 = 104;       // 12MHz/115200 
    UCA0BR1 = 0;        // 
    UCA0MCTL = UCBRS_1 + UCBRF_0;   // Modulation UCBRSx=1, UCBRFx=0 
#else 
#error Please select one of the supported baudrates. 
#endif 
    UCA0CTL1 &= ~UCSWRST;      // **Initialize USCI state machine** 

#ifdef USE_DMA 
    memset(uart.rx_buffer,0,sizeof(uart.rx_buffer)); 
    DMACTL0 = DMA0TSEL_16;    // USCIA0 RX trigger 
    DMA0SAL = (uint16_t) &UCA0RXBUF; // Source address 
    DMA0DAL = (uint16_t) uart.rx_buffer; // Destination address 
    DMA0SZ = sizeof(uart.rx_buffer);  // Block size. this counts down to 0, then reloads. 
    DMA0CTL = DMADSTINCR_3 + DMASBDB + DMADT_4 + DMALEVEL; 
    DMA0CTL |= DMAEN; 
#else 
    UCA0IE |= UCRXIE;       // Enable USCI_A0 RX interrupt 
#endif 
} 


int UART_GetChar(void) 
{ 
#ifdef USE_DMA 
    if (DMA0SZ + uart.rx_tail != sizeof(uart.rx_buffer)) 
#else 
    if ( uart.rx_head != uart.rx_tail) 
#endif 
    { 
     int c; 
     c = uart.rx_buffer[uart.rx_tail]; 
     uint8_t next = uart.rx_tail + 1; 
     if (next >= sizeof(uart.rx_buffer)) next = 0; 
     uart.rx_tail = next; 
     return c; 
    } 

return -1; 
}