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.

[参考译文] MSP432P401R:SPI 通信:

Guru**** 2510065 points
Other Parts Discussed in Thread: DAC161S055

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/750523/msp432p401r-spi-communication

器件型号:MSP432P401R

您好!

 因为,我正在进行 msp432p401r 和 dac161s055之间的 SPI 免疫工作。我现在有两个问题,需要您的建议。

1) 1)我使用驱动程序库中的 SPI 主站增量示例在 msp432和 dac161s055之间进行通信、在开始时效果非常好。 但是、现在 SDO 端口不再响应、它上面没有信号、它是 P 1.7 (SDO 或 SOMI)。 我的代码中没有任何变化。 此问题可能会出现什么情况?

2)在 dac161s055中,有24位(3字节)数据通信,并且为了发出通信,SCLK 应该打开24个时钟周期,但在我的情况下(使用前面提到的示例),我只得到8个时钟脉冲,这不足以满足我的要求。 请告诉我如何增加 SCLK 的时钟周期?

随附以下代码:

const eUSCI_SPI_MasterConfig spiMasterConfig =

       EUSCI_B_SPI_CLOCKSOURCE_SMCLK、            // SMCLK 时钟源
       24000000、                                  // SMCLK = 24MHZ
       1000000、                                   // SPICLK = 1MHz
       EUSCI_B_SPI_MSB_FIRST、                    // MSB 优先
       EUSCI_B_SPI_PHASE_DATA_Changed_ONFIRST_Captured_On_Next、   //相位
       EUSCI_B_SPI_CLOCKPOLARITY_INACTION_LOW、//高极性
       EUSCI_B_SPI_3引脚
};
/*静态*/
静态易失性 uint_fast16_t resultsBuffer[uint8_MAX];
静态易失性 uint8_t resPos;
静态易失性 uint8_t RXData = 0;
静态 uint32_t TXData=0;

 /*在 SPI 模式下选择 P1.5 P1.6和 P1.7 */
    MAP_GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P1、
              GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7、GPIO_PRIMARY_MODULE_FUNCTION);

  CSB 和 LDACB 为/* P 6.0和 P6.6 *
    MAP_GPIO_setAsOutputPin (GPIO_PORT_P6、GPIO_PIN0);
    MAP_GPIO_setOutputHighOnPin (GPIO_PORT_P6、GPIO_PIN0);
    MAP_GPIO_setAsOutputPin (GPIO_PORT_P6、GPIO_PIN6);
    MAP_GPIO_setOutputHighOnPin (GPIO_PORT_P6、GPIO_PIN6);

P:S:我是嵌入式系统方面的新手。 我的问题可能非常简单。

非常感谢您的友好回复。

此致、

Hasan

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

    1) 1)您要发送什么命令? 我不清楚如果您发送断电(PD)命令、FIFO 如何回读。
    2)每个 SPI 字节都是交换字节:传输(Tx)字节并获取(Rx)字节。 写入 Tx 缓冲器会导致 SCLK 运行(8位)。 要返回三个字节,您需要发送三个字节--一个命令(1B)和一些(可能是虚拟的)数据(2B)。 [参考数据表(SNAS503B)第1.4.1节和第19-20页的表。]

    [编辑:添加了有关 SCLK 的字。]

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

    我只是发送这个虚拟数据来检查 SPI 是否正常工作。

    /*启用中断*/
    SPI_enableInterrupt (EUSCI_B0_BASE、EUSCI_B_SPI_Receive_interrupt);
    INTERRUPT_enableInterrupt (INT_EUSCIB0);
    interrupt_enableSlepOnIsrExit();

    TXData = 0x00FFFF;

    /*轮询以查看 TX 缓冲区是否就绪*/
    while (!(SPI_getInterruptStatus (EUSCI_B0_BASE、EUSCI_B_SPI_Transmit 中断)));

    /*向从设备发送数据*/
    SPI_transmitData (EUSCI_B0_BASE、TXData);
    /*准备睡觉*
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我建议您阅读数据表的"串行接口"部分(第14-15页)。
    1)特别是"有效传输"需要24位(3个字节)。 如果你在中间停下来、很难知道 SDO 是什么样的。
    2) 2)我在命令表中看不到0xFF (第19-20页)、因此我不知道它的作用。 更好的选择可能是 NOP (0x00)。
    3) 3)我看不到您将 CSB 拉低的位置。 它将忽略您、直到您这样做。
    4) 4)您正在启用(RX)中断、但我看不到它的 ISR。

    未经请求:
    > Interrupt_enableSlepOnIsrExit();
    这会将您的程序置于我怀疑您不需要的特定模式。 我建议您删除此行、除非/直至您知道需要它。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    早上好、
    这是上述 intreuupt 的中断选择器。 我刚才获取了 SPI 主配置的给定模板。

    /*启用中断*/
    SPI_enableInterrupt (EUSCI_B0_BASE、EUSCI_B_SPI_Receive_interrupt);
    INTERRUPT_enableInterrupt (INT_EUSCIB0);
    //Interrupt_enableSlepOnIsrExit();
    SPI_enableInterrupt (EUSCI_B1_base、EUSCI_A_SPI_Transmit);
    INTERRUPT_enableInterrupt (INT_EUSCIB1);
    //![简单 SPI 示例]
    TXData = 0x1101;

    /*轮询以查看 TX 缓冲区是否就绪*/
    while (!(SPI_getInterruptStatus (EUSCI_B0_BASE、EUSCI_B_SPI_Transmit 中断)));

    /*向从设备发送数据*/
    SPI_transmitData (EUSCI_B0_BASE、TXData)

    空 EUSCIB0_IRQHandler (空)

    uint32_t status = SPI_getEnabledInterruptStatus (EUSCI_B0_BASE);
    uint32_t jj;

    SPI_clearInterruptFlag (EUSCI_B0_BASE、STATUS);

    IF (STATUS 和 EUSCI_B_SPI_Receive_interrupt)

    /* USCI_B0 TX 缓冲器准备好了吗? *
    while (!(SPI_getInterruptStatus (EUSCI_B0_BASE、EUSCI_B_SPI_Transmit 中断)));

    RXData = SPI_receiveData (EUSCI_B0_BASE);

    /*发送下一个数据包*/
    SPI_transmitData (EUSCI_B0_BASE、+TXData);

    /*从机处理信息的传输之间的延迟*/
    for (jj=50;jj<50;jjj++);


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    ISR 看起来可以正常运行、但它通过发送另一个字节来响应每个 Rx 中断。 在 SPI 中、每个 Tx 都包含一个 Rx。 因此、该逻辑将产生稳定的 Tx 流输出到 DAC。 我认为这是原始示例中的目的、但您只想发送3个字节、而不是无限个数字。

    我的建议:摆脱中断(和 ISR)、只需重复两次(更多)的传输代码。
    --------
    我认为您观察到的真正问题是在传输3个字节之前(之后)未将 CSB 拉为低电平导致的。 我想 DAC 忽略了您。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Bruce、

    我应该在哪里再重复两次传输代码? 在主代码或 ISR 部分中???

    我不知道如何在数据传输期间将 CSB 下拉为低电平和高电平。 我的想法是可以有一个 TXIE、当 TXBUF 为空时将置1、在发送一个字节后、TXIE 将再次置1。 在三个 itterations 中,可以发送3个字节的数据,然后应停止 SPI 进程。 当 CSB 上拉(低电平到高电平)时,应在保持 LDACB 引脚低电平的同时更新 DAC 寄存器中的数据。 主席先生,你对这一想法有何建议?

    主席先生,我非常感谢你的建议。

    我在语言方面的技能也很差,这可能是我无法完全理解这个过程的主要原因
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我建议您阅读数据表的"串行接口"部分(第14-15页)。

    --------------

    [未经测试、但看起来是正确的:]

    GPIO_setOutputLowOnPin (GPIO_PORT_P6、GPIO_PIN0);// CSB 低电平用于选择器
    
    件(!(SPI_getInterruptStatus (EUSCI_B0_BASE、EUSCI_BSPI_Transmit _INTERRUPT));
    SPI_finish Data (SPI_B0_BASE、TXSCI_BASE);//
    
    EUSCI_INTERRUCT_0
    
    
    
    
    
    (EPI_ST_SPI_B0_BUSCI_BUSCI_COMMIT);// EPTIC_EMPTIC_ST_ST_EMPT_0 (EPTIC_ST_COMMIT_ST_ST_COMMANSW_COMMANSW_ST_0);// EPT_COMMIT_COMMIT_COMMIT_COMMIT_COMMIT_COMMIT_COMMIT_COMMIT_COMMIT_COMMANSW_COMMIT_COMMIT_COMMIT_0 (0) 0);(EPT_COMMIT_COMMIT_COMMIT_COMMIT_COMMIT_COMMIT_COMMIT_COMMIT_COMMIT_COMMIT_COMMIT_COMMIT_COMMAND_
    

    --------------

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

    只需帮助我更清楚地理解它。 我已阅读(P14-15)。

    我应该在哪里使用此代码? 我有多了解我可以在主代码中使用此代码、我现在应该替换 ISR。 请改正我的问题
    下面通过 CSB 和 LDAC 位提到了我的代码序列。

    SPI_enableModule (USCI_B0_BASE);
    CSB 和 LDACB 为/* P 6.0和 P6.6 *
    MAP_GPIO_setAsOutputPin (GPIO_PORT_P6、GPIO_PIN0);
    MAP_GPIO_setOutputHighOnPin (GPIO_PORT_P6、GPIO_PIN0);
    MAP_GPIO_setAsOutputPin (GPIO_PORT_P6、GPIO_PIN6);
    MAP_GPIO_setOutputHighOnPin (GPIO_PORT_P6、GPIO_PIN6);

    /*启用中断*/
    SPI_enableInterrupt (EUSCI_B0_BASE、EUSCI_B_SPI_Receive_interrupt);
    INTERRUPT_enableInterrupt (INT_EUSCIB0);
    interrupt_enableSlepOnIsrExit();
    //![简单 SPI 示例]
    TXData = 0x01;

    /*轮询以查看 TX 缓冲区是否就绪*/
    while (!(SPI_getInterruptStatus (EUSCI_B0_BASE、EUSCI_B_SPI_Transmit 中断)));

    /*向从设备发送数据*/
    SPI_transmitData (EUSCI_B0_BASE、TXData);

    PCM_gotoLPM0 ();
    __no_operation();
    空 EUSCIB0_IRQHandler (空)

    uint32_t status = SPI_getEnabledInterruptStatus (EUSCI_B0_BASE);
    uint32_t jj;

    SPI_clearInterruptFlag (EUSCI_B0_BASE、STATUS);

    IF (STATUS 和 EUSCI_B_SPI_Receive_interrupt)

    /* USCI_B0 TX 缓冲器准备好了吗? *
    while (!(SPI_getInterruptStatus (EUSCI_B0_BASE、EUSCI_B_SPI_Transmit 中断)));

    RXData = SPI_receiveData (EUSCI_B0_BASE);

    /*发送下一个数据包*/
    SPI_transmitData (EUSCI_B0_BASE、+TXData);

    /*从机处理信息的传输之间的延迟*/
    for (jj=50;jj<50;jjj++);


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我建议您摆脱 ISR (并且中断使能)。 它会使程序变得复杂、而使用1MHz SPI 时钟会使您减慢速度。

    主代码中的发送代码发送一个字节、而不设置 CSB。 我建议替换该代码、只需重复该序列即可发送3个字节。 它还通过设置(和取消设置) CSB (根据您的注释 P6.0)来括起此事务。 由于 CSB 为低电平有效、因此它将引脚设置为0、然后设置为1。

    我更改了 TXData 名称、以指示您(通常)将发送3个不同的字节。 可以从命令 Table (第19-20页)中选择特定的字节。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    早上好、Bruce、

    我还想无限地发送这三个字节、因为我有来自 ADC 的模拟输入、我将从 DAC 获得模拟输出。 但是、我每次在24个 CLK 周期内都需要三次 itteration、我认为只有当我启用中断并对其进行处理时、这才可能实现。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    通过向 TXBUF 写入三次可获得24=(3*8)个 SCLK。

    我建议您不要将 DAC 输出视为无限/连续的、因为它会导致您 astray:
    1) 1) DAC 的输出为3组、由 CSB 转换成帧。 至少、您需要在 SPI ISR 中添加更多记账功能。
    2) 2)除非数据发生变化、否则没有理由写入 DAC。

    了解数据来自 ADC 可以提供一些观点。 我建议(由于(2))程序中的步速来自 ADC,而不是 DAC -- ADC 将“推”而不是 DAC“拉”。 一种简单的方法:每次从 ADC 接收新样本时、将3个字节(使用 CSB 组帧)写入 DAC 内联。 更复杂的方法:让 ADC 到达打开 TXIE、然后让 SPI ISR 在3个字节后关闭 TXIE。

    DAC 声称能够提供20MHz 的频率、因此您应该能够管理(24/2)=12MHz。 这是一个小的变化、将给上述"简单"方法带来很大的相对优势。