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.

[参考译文] MSP430FR5969:使用 DMA 通过 UART 发送

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1434775/msp430fr5969-transmit-over-uart-using-dma

器件型号:MSP430FR5969

工具与软件:

当按下按钮1或按钮2时、我的代码使用 DMA 通过 UART 发送数据、但它仅执行一次、因为即使我在 DMA 中断处理程序中将其清除、UCA0TXIFG 标志仍保持置位状态。 但是、如果我在 UCA0TXIFG 标志被清除前、在 DMA 中断处理程序内插入一个断点、那么当按下任一按钮时、代码都会一直发送数据。 当我检查寄存器值时、没有断点、UCA0IFG 寄存器内的 UCATXIFG 保持置位。   问题可能是什么? 我的代码基本上与下面的代码类似。

#include "MSPEXP430FR5969.h"
#include <string.h>

char Button_1[] = "Button 1\r\n";
char Button_2[] = "Button 2\r\n";

/**
 * main.c
 */
int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer

    conf_gpio();
    PM5CTL0 &= ~LOCKLPM5;
    gpio_clearAllInts();

    conf_cs();
	conf_uart();
	conf_dma();
	
    __enable_interrupt();
    __delay_cycles(1000);
	enable_gpio_ints();
	enable_dma_int();

    while(1);

    return 0;
}

#pragma vector=PORT1_VECTOR
__interrupt void Port1_ISR(void)
{
    __data20_write_long( (uint32_t) &DMA0SA, (uint32_t) Button_2 );
	__data20_write_long( (uint32_t) &DMA0DA, (uint32_t) &UCA0TXBUF );
	DMA0SZ = strlen( Button_2 );
	DMA0CTL |= DMAEN;
    P1IFG &= ~BIT1;
    return;
}

#pragma vector=PORT4_VECTOR
__interrupt void Port4_ISR(void)
{
    __data20_write_long( (uint32_t) &DMA0SA, (uint32_t) Button_2 );
	__data20_write_long( (uint32_t) &DMA0DA, (uint32_t) &UCA0TXBUF );
	DMA0SZ = strlen( Button_1 );
	DMA0CTL |= DMAEN;
    P4IFG &= ~BIT5;
    return;
}

#pragma vector=DMA_VECTOR
__interrupt void DMA_ISR(void)
{
    UCA0IFG &= ~UCATXIFG; // When I insert a breakpoint here, it works properly.
}

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

    除非数据正在写入 TXBUF、否则 TXIFG 将置1。 因此、当 UART 空闲时、TXIFG 将始终置位。 这对于边沿敏感的 DMA 控制器来说是一个问题。 我通过直接写入第一个字节来处理该问题。 第二、

      UCA0TXBUF = 0xff;
      // the transmit hold register should clear almost instantly
      while(!(UCA0IFG&UCTXIFG))  
        ;
    
      DMA0CTL |= DMAEN;           // enable DMAC
      UCA0TXBUF = SYNC;           // transmit first byte of packet
    

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

    方法有效。 但我仍然不明白的是、  当我在 DMA_ISR 中有断点时、为什么我的代码可以清除其中的 UCATXIFG、但无法在没有断点的情况下清除它。 为什么它在处理断点时可以正常工作?

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

    Andy、您好!

    断点不应影响硬件逻辑。  可能发生了一些时序问题。

    我假设您将在 DMA 传输完成后进入断点。 然后再次运行代码、等待另一个按钮。 您现在可以再次设置断点、查看标志状态。

    B.R.

    SAL

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

    DMA 传输完成并调用中断。 但在中断中、有断点。 我可以看到寄存器更新是 UCTXIFG 清除的结果。 我在 main 中退出中断、回到 while (1)。 我暂停微控制器、检查寄存器、仍然将其清除。 我恢复微控制器、然后按下其中一个按钮。 它的工作原理是这样。

    但是、如果我禁用或删除 DMA_ISR 中的断点、请按下其中一个按钮、UART 传输将只执行一次、不再执行。 我暂停微控制器以检查寄存器、我看到 UCTXIFG 仍被置位。

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

    当它的最后一个字节被写入 TXBUF 时、DMA 完成、而不是当 UART 进入空闲状态时。 当到达 DMA ISR 后、UART 从下一个字节移出到最后一个字节的可能性并不大、并且 TXBUF 仍然为满;在这种情况下、TXIFG=0、因此清除它无效。  

    当你遇到断点时、时钟需要花费少量的时间来停止。 (这是观察到的行为;它似乎因 MCU 模型而异。) 根据您的观察结果、该时间足够长、足以完成下一个字节到最后一个字节、因此当您查看时、移位寄存器会重新加载、并且 TXIFG=1。

    考虑到这场比赛、你最好不要抖动 TXIFG、而是使用 David 建议的"DMA 启动"方法。

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

    有。 这就是所发生的事情。 在发送最后一个字节后置1 UCATXIFG 之前、DMA_ISR 会清除 UCATXIFG。