This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP430F5659:使用 DMA 实施 UART、从而使用 UART 接收和传输256字节数据

Guru**** 2473260 points
Other Parts Discussed in Thread: MSP430F5659, MSP430F6736

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1322277/msp430f5659-implement-uart-using-dma-to-receive-and-transfer-data-of-256-bytes-using-uart

器件型号:MSP430F5659
主题中讨论的其他器件: MSP430F6736

大家好!

我正在处理一个项目、需要使用 MSP430F5659上的 DMA 实现 UART 通信。 具体来说、我需要通过 UART 可靠地接收和传输256字节的数据包。 我知道 DMA 可以显著减轻 CPU 的负载并提高此类任务的效率。

有人能提供指导或分享一些示例代码、说明如何与 DMA 建立 UART 通信以高效处理256字节数据传输吗? 我特别关注如何配置 DMA 通道、UART 外设以及无缝操作所需的任何中断处理。

任何见解或代码片段都会不胜感激!

提前感谢。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我想 TI 没有提供一个完全可以做到这一点的示例。 我建议您从 Tx 侧开始、因为这会更简单一点。 为此、我(仍然)建议这里的示例 msp430f665x_dma_02.c:

    https://dev.ti.com/tirex/explore/node?node=A__AOA7HJs5vP6JteXGeExmkQ__msp430ware__IOGqZri__LATEST

    正如我提到过的、这使用了一种相当不寻常的触发机制(使用计时器)。 通常的方法是替换:

    >  DMACTL0 = DMA0TSEL_1;            // 0-CCR2IFG

    实现

    >  DMACTL0 = DMA0TSEL_21;           //根据 SLAS700E 表9-13触发 UCA1TXIFG

    其中我从数据表的 DMA 触发表中得到了"21"。 我还建议更改

    >  DMA0CTL = DMADT_4 | DMASRCINCR_3 | DMASBDB | DMAEN;// Rpt、inc src、ENABLE

    至  

    >  DMA0CTL = DMADT_4 | DMASRCINCR_3 | DMASBDB | DMAEN | DMALEVEL;// Rpt、inc src、enable、level trigger

    以避免错误的首字节。 传输将立即开始、因为这将设置 DMAEN=1。 可以摆脱计时器代码。

    如果您运行此程序、它将重复发送"Hello"(调试方便)。 要仅执行一次、请将 DMADT_4 -> DMADT_0更改为 DMADT_0。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    高底座、

    您是说您需要使用 DMA 接收 UART 数据、将其传输到存储器中、然后再次使用 DMA 通过 UART 传输出去吗?

    我可以提供一段我编写的代码以便接收 UART 数据并将其传输到内存。 我没有代码可用于设置第二个 DMA 以便从存储器传输到 UART TX、但片段可以帮助您开始、Bruce 的上述输入也将非常有用。 我将粘贴的代码片段是为 MSP430F6736编写的、因此您需要检查引脚和寄存器、但流程应该类似、因为它们是同一个器件系列。  

    片段只是以9600波特接收 UART 数据、并使用接收到的数据填充缓冲区。 当接收到的数据填充缓冲区时、它开始覆盖缓冲区的开头。 请参阅以下内容:

    #include <msp430.h>
    #include <stdint.h>
    
    #define NUM_OF_BYTES (10)                  // Update this with the number of bytes to receive over
                                                // UART and store in the buffer
    
    // UART RX Values
    unsigned int DMA_DST[NUM_OF_BYTES] = {0x00};
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;               // Stop WDT
    
        // Setup P1.4 UCA1RXD, P1.5 UCA1TXD
        P1SEL |= BIT4 | BIT5;                   // Set P1.4, P1.5 to non-IO
        P1DIR |= BIT4 | BIT5;                   // Enable UCA1RXD, UCA1TXD
    
        // Setup eUSCI_A1
        UCA1CTLW0 |= UCSWRST;                   // **Put state machine in reset**
        UCA1CTLW0 |= UCSSEL__SMCLK;                  // SMCLK
        UCA1BRW_L = 6;                          // 1MHz 9600 (see User's Guide)
        UCA1BRW_H = 0;                          // 1MHz 9600
        UCA1MCTLW = UCBRF_13 | UCOS16;          // Modln UCBRSx=0, UCBRFx=0x13,
                                                // over sampling
        UCA1CTLW0 &= ~UCSWRST;                  // **Initialize USCI state machine**
    
        // Setup DMA0
        DMACTL0 = DMA0TSEL_18;                                                  // UCA1RXIFG triggered
        __data20_write_long((uintptr_t) &DMA0SA, (uintptr_t) &UCA1RXBUF);       // Source block address
        __data20_write_long((uintptr_t) &DMA0DA, (uintptr_t) &DMA_DST);         // Destination single address
        DMA0CTL &= ~DMAIFG;                                                     // Clear DMA interrupt flag
        DMA0SZ = NUM_OF_BYTES;                                                  // DMA0 size = 100
        DMA0CTL = DMADT_4 | DMASRCINCR_0 | DMADSTINCR_3 | DMAIE | DMAEN;        // Repeat single transfer, increment destination address
                                                                                // Unchaged source address, Repeated single transfer
                                                                                // Enable DMA Interrupt, DMA
    
        __bis_SR_register(LPM0_bits | GIE);
        while(1);
    }
    
    //------------------------------------------------------------------------------
    // DMA Interrupt Service Routine
    //------------------------------------------------------------------------------
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=DMA_VECTOR
    __interrupt void DMA_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(DMA_VECTOR))) DMA_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
        switch (__even_in_range(DMAIV, 16))
        {
            case DMAIV_NONE: break;             // No interrupts
            case DMAIV_DMA0IFG:                 // DMA0IFG = DMA Channel 0
                __delay_cycles(1000000);        // Optional delay
                __no_operation();               // Optional section for code once the 100 DMA transfers are complete
                break;
            case DMAIV_DMA1IFG: break;          // DMA1IFG = DMA Channel 1
            case DMAIV_DMA2IFG: break;          // DMA2IFG = DMA Channel 2
            case 8: break;                      // Reserved
            case 10: break;                     // Reserved
            case 12: break;                     // Reserved
            case 14: break;                     // Reserved
            case 16: break;                     // Reserved
            default: break;
        }
    }
    
    

    我将添加:有一段时间没有阻止我、那就是启用相应的中断后、DMA 不会触发。 在该示例中、我最初启用了 UART RX 中断、但无法获取 DMA 触发。 确保将中断保持禁用状态、如果需要第二个 DMA 通道、则确保 TX 中断也处于禁用状态。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Dylan 和 Bruce:

    谢谢您的帮助、让我遵循您的指导原则、如果我遇到任何问题、我会回来的。 再次感谢。