我正在寻找通过 DMA 而不是中断在 MSP430 上为 USCI (UART) 提供服务的示例代码



我有一段代码可以通过中断读取USCI(UART),但TI SimpliciTI堆栈占用CPU,在维修无线电时会丢弃UART字节。

我认为DMA是可行的,但我找不到使用USCI作为输入的DMA的完整示例。

以下是我最终所做的。它有效!

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;
}

最新更新