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.

[参考译文] MSP-EXP430FR5994:UART 接收溢出错误标志

Guru**** 2537260 points
Other Parts Discussed in Thread: BQ79616, BQ79600EVM, MSP-EXP430FR5994

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1105954/msp-exp430fr5994-uart-receive-overrun-error-flag

器件型号:MSP-EXP430FR5994
主题中讨论的其他器件:BQ79600EVM

我让 UART 环回示例以1Mbps 波特率工作、没有问题。 我在 UART 时钟上使用了4MHz SMCLK。 这些结果在 MSP430 EVM 上使用了一个永恒的时钟。

当与 BQ79600EVM 和自定义 BQ79616连接时、UART 接收中断会在我尝试执行单个器件读取命令后立即触发。 我可以看到 UCOE 标志被置1。 UART 驱动程序的设置/使用是否有问题?

我已经为 BQ79600芯片设置了一个100位延迟进行响应、因此 MSP430有时间从 UART 发送切换到 UART 接收。 MSP430是否有理想的数字来实现这一点?

在此设置中、我使用的是外部时钟。  

#define BQUART                        EUSCI_A1_BASE
#define BQUART_DISABLE                EUSCI_A_UART_disable
#define BQUART_CLOCKSOURCE            EUSCI_A_UART_CLOCKSOURCE_SMCLK
#define BQUART_PARITY                 EUSCI_A_UART_NO_PARITY
#define BQUART_BITORDER               EUSCI_A_UART_LSB_FIRST
#define BQUART_STOPBIT                EUSCI_A_UART_ONE_STOP_BIT
#define BQUART_MODE                   EUSCI_A_UART_MODE
#define BQUART_OVERSAMPLING           EUSCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION
#define BQUART_INIT                   EUSCI_A_UART_init
#define BQUART_initParam              EUSCI_A_UART_initParam
#define BQUART_enable                 EUSCI_A_UART_enable
#define BQUART_disable                EUSCI_A_UART_disable

#define BQUART_REG                    P2OUT
#define BQUART_TX_PORT                GPIO_PORT_P2
#define BQUART_RX_PORT                GPIO_PORT_P2
#define BQUART_RX_PIN                 GPIO_PIN6
#define BQUART_TX_PIN                 GPIO_PIN5
#define BQUART_SELECT_FUNCTION        GPIO_SECONDARY_MODULE_FUNCTION


#define BQUART_enableInterrupt        EUSCI_A_UART_enableInterrupt
#define BQUART_RX_INT                 EUSCI_A_UART_RECEIVE_INTERRUPT
#define BQUART_clearInterrupt         EUSCI_A_UART_clearInterrupt
#define BQUART_TXBUF                  UCA1TXBUF
#define BQUART_RXBUF                  UCA1RXBUF


#define BQUART_ISR                    USCI_A1_ISR
#define BQUART_VECTOR                 USCI_A1_VECTOR
#define BQUART_IFG                    UCA1IFG
#define BQUART_IV                     UCA1IV

#define BQUART_BUSY                   (UCA1STATW&UCBUSY)
void Clock_Init()
{
#ifdef EXT_CLK
    GPIO_setAsPeripheralModuleFunctionInputPin(
         GPIO_PORT_PJ,
         GPIO_PIN4 + GPIO_PIN5,
         GPIO_PRIMARY_MODULE_FUNCTION
     );


     // Set PJ.6 and PJ.7 as Primary Module Function Input, HFXT.
     GPIO_setAsPeripheralModuleFunctionInputPin(
            GPIO_PORT_PJ,
            GPIO_PIN6 + GPIO_PIN7,
            GPIO_PRIMARY_MODULE_FUNCTION
            );

     // Check if one FRAM waitstate is needed for 5962, 5994 device as well!
     FRAMCtl_A_configureWaitStateControl(FRAMCTL_A_ACCESS_TIME_CYCLES_1);

     uint32_t u32ClockFrequencyCheck = 0u;

     // JA - Enable lxft & HXFT
     CS_setExternalClockSource(32768, 16000000);


     CS_initClockSignal(CS_SMCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_4);

     CS_initClockSignal(CS_MCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);

     //Set ACLK=LFXT
     CS_initClockSignal(CS_ACLK, CS_LFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);


     //Set the appropriate drive values for each oscillator for the launchpad vs. actual schematic.
     CS_turnOnLFXT(CS_LFXT_DRIVE_3);
//       CS_turnOnLFXT(CS_LFXT_DRIVE_0);

     CS_turnOnHFXT(CS_HFXT_DRIVE_16MHZ_24MHZ);
 // JA - SMCLK appears to be running extremely slowly when sourced from HFXT


      // JA - Check SMCLK, MCLK clock frequencies
      u32ClockFrequencyCheck = CS_getMCLK();
      u32ClockFrequencyCheck = CS_getSMCLK();
#endif

#ifdef DCO_CLK
      // Configure one FRAM waitstate as required by the device datasheet for MCLK
      // operation beyond 8MHz _before_ configuring the clock system.
      FRCTL0 = FRCTLPW | NWAITS_1;

      // Clock System Setup
      CSCTL0_H = CSKEY_H;                                     // Unlock CS registers
      CSCTL1 = DCOFSEL_0;                                     // Set DCO to 1MHz

      // Set SMCLK = MCLK = DCO, ACLK = VLOCLK
      CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK;

      // Per Device Errata set divider to 4 before changing frequency to
      // prevent out of spec operation from overshoot transient
      CSCTL3 = DIVA__4 | DIVS__4 | DIVM__4;                   // Set all corresponding clk sources to divide by 4 for errata
      CSCTL1 = DCOFSEL_4 | DCORSEL;                           // Set DCO to 16MHz

      // Delay by ~10us to let DCO settle. 60 cycles = 20 cycles buffer + (10us / (1/4MHz))
      __delay_cycles(60);
      CSCTL3 = DIVA__1 | DIVS__4 | DIVM__1;                   // SMCLK=2Mhz MCLK=16MHz
      CSCTL0_H = 0;                                           // Lock CS registers
#endif
}



void UART_Init(void){

    GPIO_setAsPeripheralModuleFunctionInputPin(
          BQUART_TX_PORT,
          BQUART_TX_PIN + BQUART_RX_PIN,
          BQUART_SELECT_FUNCTION
    );

    BQUART_initParam param = {0};

    param.clockPrescalar = 4,
    param.firstModReg = 0,
    param.secondModReg = 0,
    param.selectClockSource = BQUART_CLOCKSOURCE;
    param.parity =            BQUART_PARITY;
    param.msborLsbFirst =     BQUART_BITORDER;
    param.numberofStopBits =  BQUART_STOPBIT;
    param.uartMode =          BQUART_MODE;
    param.overSampling =      BQUART_OVERSAMPLING;

    if(STATUS_FAIL == BQUART_INIT(BQUART, &param))
    {
       return;
    }

    BQUART_enable(BQUART);
    BQUART_clearInterrupt(BQUART, BQUART_RX_INT);
    BQUART_enableInterrupt(BQUART, BQUART_RX_INT);

}

void uartSend(int length, uint8_t * data){
    uint8_t i;

    for (i = 0; i < length; i++){
        while (!(UCA1IFG & UCTXIFG));
        BQUART_TXBUF = data[i];
    }

}

void uartReceive(BYTE * data, BYTE length){
    while (length > 0){
        while (BQUART_BUSY);
        *data = BQUART_RXBUF;
        data++;
        length--;
    }
}

//******************************************************************************
// SPI_B1 Interrupt ************************************************************
//******************************************************************************
#pragma vector=BQUART_VECTOR
/*******************************************************************************
  USCI_B1_ISR ******************************************************************
 *******************************************************************************
* Function: B1 Interrupt Routine
********************************************************************************/
__interrupt void BQUART_ISR(void)
{
    switch(__even_in_range(BQUART_IV, USCI_UART_UCTXCPTIFG))
    {
        case USCI_NONE: break;
        case USCI_UART_UCRXIFG:
            BQUART_IFG &= ~UCRXIFG;
            __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 on reti
        break;
        case USCI_UART_UCTXIFG:  break;
        case USCI_UART_UCSTTIFG: break;
        case USCI_UART_UCTXCPTIFG: break;
        default: break;
    }
}
#endif

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

    1) 1)将 UCBUSY 用于接收只是平面输出错误。 如果接收到稳定的数据流、则接收器状态机完成(在最后一个停止位的某处)到下一个开始位的时间间隔很短。 在 1Mbps 时非常短。

    2) 2)读取 IV 寄存器将复位 RXIFG、因此无需在 ISR 中再次复位。

    3) 3)整理主任务以处理数据将不起作用。 通常的方法是将数据放入队列中。 然后、主任务可以检查队列中是否有数据。

    4) 4)即使使用16MHz 时钟、您也没有太多时间处理每个字节的数据。

    5) 5) MSP430无需花费任何时间将 UART 从发送切换到接收。 实际上、它们是同时工作的。 这意味着您可以在传输代码完成之前获得接收中断。

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

    我查看了回送示例、我看到在接收 ISR 中完成的唯一处理是分配的  

    EUSCI_A_UART_receiveData (EUSCI_A0_BASE)。

    我省去了 ISR 中的其他东西。  

    我的设置是 MSP-EXP430FR5994 -> BQ79600EVM ->定制 BQ79616

    从 BQ79600EVM 读取时、会为特定寄存器发出读取命令。

    然后发出 ReadFrameReq。 这涉及通过 UART 写入消息。

    在这里、您可以说、即使在传输结束之前也可以进行接收。 您能更详细地解释一下发送和接收同时工作的情况吗? 见第769页的 SLAU367P 中的图30-1。

    固件中没有 RTOS,则有一个主循环。 下面是我尝试重组 UART 接收的内容,我不再有 uartReceive 了。 这仍然不奏效。 我可以使用更多的指针。

    1. ReadReg
    2. ReadFrameReq
      1. 设置 idx、rxComplete = 0;分配 uartRxLen
      2. 通过 UART 编译和发送写入帧。

    #pragma vector=BQUART_VECTOR
    /*******************************************************************************
      USCI_B1_ISR ******************************************************************
     *******************************************************************************
    * Function: B1 Interrupt Routine
    ********************************************************************************/
    __interrupt void BQUART_ISR(void)
    {
        switch(__even_in_range(BQUART_IV, USCI_UART_UCTXCPTIFG))
        {
            case USCI_NONE: break;
            case USCI_UART_UCRXIFG:
                RXData[idx] = EUSCI_A_UART_receiveData(BQUART);
                idx++;
                if (idx == uartRxLen)
                   rxComplete = 1;
    
            break;
            case USCI_UART_UCTXIFG:  break;
            case USCI_UART_UCSTTIFG: break;
            case USCI_UART_UCTXCPTIFG: break;
            default: break;
        }
    }
    #endif
    

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

    接收器和发送器是独立的。 共享一个比特率发生器、而不是太多其他内容。 因此、如果数据在发送器发送数据时到达、接收器将对其进行处理。

    您说它不起作用。 它是如何工作的? 接收缓冲区中是否根本没有数据? 数据看起来是错误的? 数据不足? 所有这些都是问题的线索。 (过多的数据会导致故障和缓冲区溢出。)

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

    我在第一步 ReadReg 处有一个断点。 如果我单步执行、它直接进入 UART ISR、溢出标志被置位。 我不是单步执行、而是在 WriteFrame 处放置一个断点并运行程序、直到这里。 然后、我在 ISR 中放置一个断点并运行程序、直到这里。 我发现接收到一个字节(不是预期的字节)、idx 递增、然后 ISR 在 uartRxLen 之前不会继续触发。

    即使我在 uartSend 之前等待启用接收中断、UART ISR 也会以某种方式触发。 这是怎么做的? 如果接收到所有 uartRxLen、我将禁用接收中断。

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

    您是否尝试使用 DMA 进行 UART 接收和发送操作?  

    如 David 所建议的、使用队列通过 DMA 推送数据、并在 DMA 传输完成后检查队列