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.

[参考译文] MSP430FR5994:MSP430FR5994 SPI 问题

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1492759/msp430fr5994-msp430fr5994-spi-issue

器件型号:MSP430FR5994
主题中讨论的其他器件: ADS8866MSPM0G3507

工具与软件:

MSP430FR5994 SPI 通信、使用16MHz 时钟、在发送一个字节后跟下一个字节时、每个字节之间是否存在6.63µs 间隙?

//******************************************************************************
// SPI SRAM I/O Initial *******************************************************
//******************************************************************************
void SPI_IO_SRAM_initial(void)
{
    // Configure SPI
    P6SEL0 |=  BIT4 | BIT5 | BIT6;
    P6SEL1 &= ~(BIT4 | BIT5 | BIT6);

    SLAVE_SRAM_CS_DIR |= SLAVE_SRAM_CS_PIN;
    SLAVE_SRAM_CS_OUT |= SLAVE_SRAM_CS_PIN;

}

//******************************************************************************
// SPI SRAM register Initial  *************************************************
//******************************************************************************
void SPI_register_SRAM_initial(void)
{
    //Clock Polarity: The inactive state is high
    //MSB First, 8-bit, Master, 3-pin mode, Synchronous
    UCB3CTLW0 = UCSWRST;                       // **Put state machine in reset**
    UCB3CTLW0 |= (  UCCKPH | UCMSB | UCSYNC        =// V: UCCKPH  ; VV UCCKPL ; V ~UCCKPL & ~UCCKPH ;
                  | UCMST | UCSSEL__SMCLK );      // 3-pin, 8-bit SPI Slave


    UCB3BRW = 0x00; //0x20
    //    UCMCTLW = 0;
    UCB3CTLW0 &= ~UCSWRST;                     // **Initialize USCI state machine**
    UCB3IE |= UCRXIE;                          // Enable USCI0 RX interrupt
}

//******************************************************************************
// SPI_SRAM_Master_Write_data  *************************************************
//******************************************************************************
void SPI_SRAM_Master_Write_data(uint32_t Write_SRAM_start_Address,uint8_t *data_buf ,uint16_t Write_SRAM_len)
{

    uint16_t i= 0;

    SRAM_MasterMode = SRAM_TX_DATA_MODE;

    SRAM_ReceiveIndex = 0;
    SRAM_RXByteCtr = 0;

    SRAM_TransmitIndex = 0;
    SRAM_TXByteCtr = (SRAM_Instruction_len + SRAM_Address_len + Write_SRAM_len);     // Total SRAM_TransmitIndex length.

    SRAM_TransmitBuffer[0] = 0x02;             // SEQUENTIAL WRITE (SPI MODE)
    //Read address 3 byte.
    SRAM_TransmitBuffer[1] = ((Write_SRAM_start_Address >> 16) & 0xFF);  // Address h byte.
    SRAM_TransmitBuffer[2] = ((Write_SRAM_start_Address >> 8) & 0xFF);   // Address m byte.
    SRAM_TransmitBuffer[3] = (Write_SRAM_start_Address & 0xFF);          // Address l byte.

    for(i= 0; i < Write_SRAM_len; i++)
    {
        SRAM_TransmitBuffer[4+i] = data_buf[i];
    }

    SLAVE_SRAM_CS_OUT &= ~(SLAVE_SRAM_CS_PIN);

    UCB3TXBUF = SRAM_TransmitBuffer[SRAM_TransmitIndex++];  //Send first to start.

    SRAM_Processing_falg = 1;

    __bis_SR_register(/*CPUOFF + */GIE);                        // Enter LPM0 w/ interrupts

    while(SRAM_Processing_falg);

    SLAVE_SRAM_CS_OUT |= SLAVE_SRAM_CS_PIN;

}

//******************************************************************************
// SPI SRAM SendUCB1Data  *****************************************************
//******************************************************************************
void SendUCB3Data(uint8_t val)
{
    while (!(UCB3IFG & UCTXIFG));              // USCI_B3 TX buffer ready?
    UCB3TXBUF = val;
}


//******************************************************************************
// SPI USCI_B3_VECTOR Interrupt ***********************************************
//******************************************************************************

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_B3_VECTOR
__interrupt void USCI_B3_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B3_VECTOR))) USCI_B3_ISR (void)
#else
#error Compiler not supported!
#endif
{
    uint8_t ucB3_rx_val = 0;
    switch(__even_in_range(UCB3IV, USCI_SPI_UCTXIFG))
    {
        case USCI_NONE: break;
        case USCI_SPI_UCRXIFG: //SPI Rx interrupt
                    ucB3_rx_val = UCB3RXBUF;
                    UCB3IFG &= ~UCRXIFG;
                    switch (SRAM_MasterMode)
                    {
                        case SRAM_TX_REG_ADDRESS_MODE:
                        {
                            __no_operation();
                        }
                        break;
                        case SRAM_TX_DATA_MODE:
                        {
                            if (SRAM_TransmitIndex < SRAM_TXByteCtr)
                                SendUCB3Data(SRAM_TransmitBuffer[SRAM_TransmitIndex++]);
                            else
                            {

                                SRAM_MasterMode = SRAM_IDLE_MODE;
//                                __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
                                SRAM_Processing_falg = 0;
                            }

                            __no_operation();
                        }
                        break;
                        case SRAM_RX_DATA_MODE:
                        {
                            __no_operation();
                        }
                        break;
                        case SRAM_TX_RECEIVE_DATA_SEND_MODE:
                        {
                            if (SRAM_TransmitIndex < SRAM_TXByteCtr)
                                SendUCB3Data(SRAM_TransmitBuffer[SRAM_TransmitIndex++]);
                            else
                            {
                                SRAM_MasterMode = SRAM_TX_RECEIVE_DATA_REC_MODE;
                                SendUCB3Data(DUMMY);
                            }

                            __no_operation();
                        }
                        break;
                        case SRAM_TX_RECEIVE_DATA_REC_MODE:
                        {
                                if (SRAM_RXByteCtr){
                                    SRAM_rec_data_buffer[SRAM_ReceiveIndex++] = ucB3_rx_val;
                                    //Transmit a dummy
                                    SRAM_RXByteCtr--;
                                }
                                if (SRAM_RXByteCtr == 0){
                                    SRAM_MasterMode = SRAM_IDLE_MODE;

                                    __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
                                }
                                else{
                                    SendUCB3Data(DUMMY);
                                }
                        }
                        break;
                        default:
                            __no_operation();
                        break;
                    }

                    break;
        case USCI_SPI_UCTXIFG:  //SPI Tx interrupt
        {

        }
        break;
    }
}

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

    您是否能够尝试不使用中断并使用您的  SendUCB3Data ()函数直接发送它?

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

    1.我修改了 SendUCB3Data、以一次发送3个字节、但 CS 准备时间有点长、结果似乎有点出乎意料。 发送数据后、无法将 CS 拉至高电平。



    //******************************************************************************
    // SPI SRAM SendUCB1Data  *****************************************************
    //******************************************************************************
    void SendUCB3Data(uint8_t val)
    {
        int i = 0;
    
    
        while (!(UCB3IFG & UCTXIFG));              // USCI_B3 TX buffer ready?
        for(i = 0;i < 3; i++)
        {
            UCB3TXBUF = val+i;
        }
        while (!(UCB3IFG & UCTXIFG));              // USCI_B3 TX buffer ready?
    //    UCB3TXBUF = val;
    }



    另一个问题是我的目标采样频率是50KHz、我需要完成声音的采集。 对于外部 ADC (ADS8866)和外部 SRAM (23AA04M)、必须在20us 内完成。 MSP430FR5994是否能够满足这些条件? 如果没有、您是否有推荐的 MCU?

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

    1)当 SCK=SMCLK=MCLK 时、一个 SPI 字节需要8个 CPU 时钟、可能是1-3条 CPU 指令。 (这就是不在循环中检查 TXIFG 的原因。) 这是非常严格的时序、我怀疑 CPU 不能正常工作。

    这里常见的答案是 DMA、但事实证明、通过 DMA 通道/触发器分配[参考数据表(SLASE54D)表9-11] DMA 偶尔仅对 UCB1/2/3有用(仅限 Tx)。 在您的设计中切换到 UCB0是否太晚?

    我不确定我在分析器跟踪中看到的 是什么——具体来说:SCK 下面的那条线是什么?

    2) 2)您可以在1us 内发送(交换) 2个 SPI 字节、但 SRAM 至少需要5个字节来执行任何操作。 ADC 中的折叠(增加2倍的字节加上转换时间)将使时序更加严格。 即使使用 DMA、管理片选也需要 CPU 干预。 这可能是可行的(勉强适用)、但您的 MCU 将无法执行任何其他操作。

    TI 当前在小型/廉价/快速(er)类别中提供的产品是 MSPM0系列。 MSPM0G35x 系列可以在80MHz 上运行、并且具有7个 DMA 通道(均为通用通道)。 [我不在 TI 工作、您可以在产品页面上浏览产品系列。]

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

    这似乎是任务和硬件之间的不匹配。 MSP430非常适合大部分时间处于低功耗模式的低功耗应用。 这是一项需要快速执行某项操作的任务。 低功耗似乎不是一项要求。

    在50Ksps 时、每个样本有320个 MCLK 可执行所有操作。 从 ADC 读取数据、然后将数据写入外部 SRAM。 它可能是可行的。 可能需要使用汇编语言进行严格的编码。 在这一点上、您应该考虑其他一些具有更高时钟速度的器件。

    100MHz 上的时钟可以与多个臂配合使用。

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

    Bruce、您好!

    切换到 UCB0可能太晚了、但我倾向于认为更多的是 MSP430本身的限制。 对于我来说、中断仍然是一个更好的架构设计;SCK 下的线路是 CS。

    2.我来尝试 MSPM0G3507、我恰好手头有一个板来测试它。 感谢您发送编修。

    此致、

    Anthony

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

    尊敬的 David:

    随后、我将使用较高时钟的 MCU 进行测试。 为 MSP430FR5994分配50k SPS 采样率确实是太大的负担。 非常感谢您的建议。

    此致、

    Anthony