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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/724511/msp432p401r-unexpected-behaviour-waiting-on-spi-interrupt-flag

器件型号:MSP432P401R

我注意到库函数出现了一种奇怪的行为

uint_fast8_t SPI_getInterruptStatus (uint32_t moduleInstance、uint16_t mask) 

在 Breif 中、用于检查 UCxTXBUF 在多字节传输期间是否为新字节做好准备、如果之前发送的字节 MSB 为"1"、则将 SPI SIMO 引脚设置为高电平。

我更换了

while (!SPI_getInterruptStatus (DevHandle->SensorSpiModule、SENSE_SPI_Transmit _INTERRUPT)); 

和以下指令

while (!(UCTXIFG 和 SENSE_SPI_INTERRUPT_FLAG_REGTER)); 

规避该问题、实际上会对与从 SPI 传感器的通信产生负面影响。

是否仍然是 SPI_getInterruptStatus 的预期行为?

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

    该函数(源位于\TI 中)只需读取 USCI IFG 寄存器、然后使用您提供的掩码对其进行读取。

    您所描述的是读取 IFG 会改变(Tx)数据流的效果、这似乎是不可能的。 这不仅仅是对硬件的信任--我已经看到了大量使用这种技术的代码,没有人报告过这样的效果。

    您的 driverlib 源是否有损坏的机会? (我做过一次。) 您如何确保"DevHandle->SensorSpiModule"正确?

    这里是否有更多上下文?

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

    尊敬的 Bruce:

    我也很惊讶。 遗憾的是、我没有保存任何示波器迹线。 无论如何、我正在配置 SPI 传感器、该传感器需要从主器件(MCU)向从器件(传感器)发送 uint16_t 值的序列。

    我只能说、我无法从特定寄存器读回数据、是的、更奇怪的是:其他寄存器工作正常。

    我将按顺序配置寄存器、对每个寄存器重复以下写入-读取过程:

    1. 以 uint8_t 值的形式发送寄存器地址、MSB ='0'
    2. 发送配置字节
    3. 以 uint8_t 值的形式发送寄存器地址、MSB ='1'
    4. 发送虚拟字节
    5. 检索值

    用示波器仔细分析总线流量我注意到 MOSI 导线在地址字节和虚拟字节之间始终设置为高电平、显然没有理由。 无论如何、它不是在时钟上升沿进行采样、因此从理论上讲、它并不是问题。 在发送配置字节之前、写入例程没有发生这种情况。 更改读忙等待方法可以解决所有问题。

    我会尽快重现这种情况、可能是因为库混乱、或者我无意中对代码进行了一些其他更改、现在不管我是如何实现忙等待的、它都能正常工作。

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

    尊敬的 Bruce:

    您可以查看下面的示波器迹线:

      黄色->芯片选择

      蓝色-> MOSI

      粉红色->时钟

      绿色-> MISO

    你说得对:我实际上是在轮询接收标志、

    while (!SPI_getInterruptStatus (DevHandle->SensorSpiModule、SENSE_SPI_Transmit _INTERRUPT)); 

    按预期工作:

    我对 SPI 控制器进行编程、以便在发送字节之前清除接收中断标志、并在发送字节后等待该标志。 最后、根据 SPI 协议、您可以假设从器件在您返回一个字节后已完全接收到一个字节、对吧? 将以下代码放入读取例程中

    //发送地址字节
    SPI_transmitData (DevHandle->SensorSpiModule、(uint_fast8_t)(地址|(1<<7)));
    //等待 RX 缓冲区准备就绪
    while (!SPI_getInterruptStatus (DevHandle->SensorSpiModule、SENSE_SPI_Receive_interrupt));
    //清除中断标志
    SPI_clearInterruptFlag (DevHandle->SensorSpiModule、SENSE_SPI_Receive_interrupt);
    //发送虚拟字节
    SPI_transmitData (DevHandle->SensorSpiModule、0x00); 

    转到以下跟踪:

    在复位或轮询中断标志寄存器时、微控制器似乎不可能毫无理由地设置 MOSI。 因此、获取了最后一个屏幕截图(3)、将传感器 SDI 与 MCU 断开。 意外的 MOSI 信号来自微控制器。 然而、在发送虚拟字节之前进行复位、MOSI 干扰不应影响读取过程、不是吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我用 Launchpad 偷了一些东西,看起来 MOSI 是基于前一个字节的 MSbit 的空闲状态的,不是我猜的那样,但我不知道它在内部是如何工作的。

    这两条布线之间的区别在于、第一条布线应保持"管道"为满、因此绝不会发生空闲、第二条布线应(适当)让管道为空、这会导致 MOSI 可以空闲的暂停。 也就是说、在 RXIFG 上读取(旋转)不会导致 MOSI 变为高电平、只是(间接)使其可见。

    如果我们对其进行平方、我们可能会看到不同的情况、但在我看来、MOSI 在两种情况下都"及时"变低。 但是、即使我们假设它没有、它也会是一个不寻常的器件、它会关心"虚拟"字节的内容是什么。

    这就为寄存器0x20的设置在第二种情况下似乎不能保持不变提供了一个神秘面纱。 我不知道答案。 您能告诉我这是什么传感器吗?

    解决方法:如果您运行流水线(第一个跟踪)但使用 SPI_isBusy()等待完成,会得到什么结果? 即、让其溢出、然后挑选出最终字节(即您需要的字节)。 [这在黑色 Launchpad 上不起作用、但您应该可以使用任何其他平台。]
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Bruce:

    很抱歉、我的回答很晚、但我在回复之前一直在等待收集更多详细信息。

    首先:感谢解决方法提示、这是一种有趣的方法来了解何时可以提取数据。

    该传感器是 STM 中的 LIS3DSH。 我联系了他们的技术帮助、他们为我提供了一个在备用 STM32eval 上运行的示例项目。 根据示波器迹线、它们管理 SPI 总线的方式与我最初在 MSP432上实施的方式非常相似。 主 SDO 在有效数据字节被传输前保留地址 LSB (最后发送的位)(不是 MSB)、但是在任何情况下读取/写入操作都成功。

    怠速运行后、SPI 外设会在 MISO 引脚设置为输出时唤醒、从而影响传感器输出信号吗?

    我从 STM 环境中附加一对采集:

    写入:

    阅读:

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    主驱动器 MISO (低)的概念也似乎很低、因为如果它这么做几乎不起作用。 我所说的"怠速"一点也不例外。 对于短期交易、我很少尝试将流水线填满。 如果我曾看到 MOSI 在字节之间变高、我可能不会对此给予任何关注。

    LIS3DH 数据表也没有表明它关心什么是"虚拟"字节值、因此即使主器件在转换 MOSI 时有点晚、从器件也不会注意到。

    我仍然觉得有趣的是、您只能在寄存器0x20 ("其他寄存器正常工作")上看到此影响、到目前为止、仅在值0x02 (如果我读的是正确的)下看到此影响。 在 CTRL_REG1中仅设置 Yen 似乎是合法的、但规范在某些位置中有点"稀疏"。

    不幸的是、我这里没有 LIS3DH、所以我能做的就是猜测。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Bruce:

    我做了一些额外的测试、并尝试对问题的根本原因进行猜测。

    您可以查看以下链接以了解更多信息。

    https://community.st.com/s/question/0D50X00009kHRHISA4/failure-reading-from-lis3dsh-spi-interface

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Giovanni、
    与 Bruce 一样、我仍然认为您只在单个寄存器中观察到问题、而不是在一般通信中观察到问题是可疑的。 您可以尝试使用逻辑分析仪观察事务、以更清楚地了解正在传输的数据。
    -Bob L.
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Bob:

    很高兴再次听到你的声音!

    您是否查看过我上一篇文章中的链接? 请告诉我您对它的看法,很多人都在看它,但没有人回答。

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

    为了使保持时间计算变得混乱、我尝试使用 SPI_isBusy ()、如下所示:

    //发送数据字节
    SPI_transmitData (SensorInse->ModuleInstance、(uint_fast8_t) SpiTxByte);
    //等待 TX 缓冲区准备就绪
    while (!spi_getInterruptStatus (SensorInUse->ModuleInstance、SPI_Transmit interrupt_FLAG));
    //等待 SPI 准备就绪
    while (SPI_isBusy (SensorInUse->ModuleInstance));
    //设置 CS
    GPIO_setOutputHighOnPin (SensorInUse->CsPort、SensorInUse->CsPin); 

    但在传输结束之前、ChipSel 会变为高电平。

    (P.S. 我知道、等待 TX 缓冲区准备就绪也可能是冗余的)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    拼写错误警告! (不、不是您的。) 我多次查看了这个、但仍然没有看到它。 从 driverlib.c:

    >bool EUSCI_B_SPI_isBusy (uint32_t baseAddress)
    >{
    >//返回总线忙状态。
    >返回 BITBAND_PERI (EUSCI_B_CMSIS (baseAddress)->rSTATW/r、UCBBUSY_OFS);
    >}

    应该是 UCBUSY_OFS (=0、即(1<0))、而不是 UCBBUSY_OFS (=4、即(1 << 4))。 测试的是 I2C 忙、而不是 SPI 忙。

    此代码位于 ROM 中、因此我不希望快速修复。 作为一种权变措施、我建议:

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

    我执行了你的建议。

    //降低 CS
    GPIO_setOutputLowOnPin (SensorInUse->CsPort、SensorInUse->CsPin);
    
    //等待建立时间
    while (--Timeout);
    
    //等待 TX 缓冲区准备就绪
    while (!SPI_getInterruptStatus (SensorInUse->SerialPeripheral、SPI_Transmit _interrupt_FLAG));
    //发送地址字节
    SPI_transmitData (SensorInUse->SerialPeripheral、(uint_fast8_t)(SpiActiveAddress|(1<<7)));
    //等待 TX 缓冲区准备就绪
    while (!SPI_getInterruptStatus (SensorInUse->SerialPeripheral、SPI_Transmit _interrupt_FLAG));
    //发送虚拟字节
    SPI_transmitData (SensorInUse->SerialPeripheral、0x00);
    //等待 SPI 模块准备就绪
    while (SensorInse->SpiModuleAddress->STATW 和 EUSCI_B_STATW_SPI_BUSY);
    
    //设置 CS
    GPIO_setOutputHighOnPin (SensorInUse->CsPort、SensorInUse->CsPin); 

    似乎工作正常,太差了!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您将其驱动到地面。 我将相应地提交一个错误。

    此致、
    Chris