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.

[参考译文] MSPM0G3507:等待 ADC 转换完成

Guru**** 2555630 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1533516/mspm0g3507-waiting-for-an-adc-conversion-to-finish

器件型号:MSPM0G3507


工具/软件:

我可以在 GPIO 触发器正边沿上同时转换正常运行的 ADC。 一切都很好。

我写入引脚 CCK、这将开始转换。

我想知道它何时完成,然后我开始下一次转换....这只是挂起:

while (1){

//写入 GPIO 以触发转换
DL_GPIO_setPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);
//等待启动
while (DL_ADC12_isConversionStarted (ADC12_0_INST)= false)
;
//等待完成
while (DL_ADC12_isConversionStarted (ADC12_0_INST)= true)
;
//切换  
DL_GPIO_clearPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);

}

有任何线索请?

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

    我在 TRM 中未找到任何内容表明 SC 针对硬件触发器进行切换(明显)。  

    我可能会轮询 CPU_INT.RIS.MEMRESIFG0、因为这会在没有竞赛的情况下锁存完成状态。

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

    谢谢。 混淆了。
    您是否说、如果 ADC 当前正在进行转换(这将包括采样和 SAR 转换阶段)CPU_INT.RIS.MEMRESIFG0。 ->我没有启用中断...

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

    你好。

    我尝试过以下操作:
    //使用事件触发 ADC 转换
    DL_GPIO_setPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);
    while (DL_ADC12_getRawInterruptStatus (ADC12_0_INST、0x100)= false);
    ;
    但 work....it 并不总是传递“ while “、即使我不触发 ADC 转换也是如此。
    此外、我有一个必须使用 0x100、因为 未定义 CPU_INT.RIS.MEMRESIFG0…
    非常困惑……
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我的错误...标记已设置...先清除。

    这似乎有效:

    //触发 ADC 转换

    DL_GPIO_setPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);

    //等待完成

    while (DL_ADC12_getRawInterruptStatus (ADC12_0_INST、ADC12_CPU_INT_IMASK_MEMRESIFG0_MASK)= false);
      ;
    但在这里、我使用 DMA 将 memres0 传输到缓冲区(工作正常)...我认为 DMA 读取 memres0 没有清除中断标志、我认为它应该清除该中断标志??
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    DMA 清除 DMA_TRIG:RIS:MEMRESIFG0、但不清除 CPU_INT:RIS:MEMRESIFG0【观察到的行为】。 要使用此机制、您需要在发出 CCK 触发器之前清除前者(我认为这就是您所说的操作?)。

    还有 status:busy (DL_ADC12_getStatus ())、从描述中可以或多或少地按照您期望 SC 的行为方式进行操作。 (我没有试过。) 我预计这将 容易受到与之前相同的种族(TRIGGER 和第一次 getStatus 调用之间的杂散中断)的影响。

    [编辑:您是否有用于 dma_done 的 ISR(即,这会将其清除)? 如果没有、也许这是您真正要触发的 RIS 位? 我对这里的动态不是很清楚。]

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

    您好 Bruce、谢谢。 更清晰。

    附上我尝试做的事情、即 ADC 结果 DMA 到  缓冲区。

    CK 为 750ns 至 1us。

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

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

    因此、如果您的目标是 CK 的最短高电平周期(在限制范围内)、则 MEMRESIFG 似乎非常接近(或 STATUS:BUSY)。 我在 TRM 图 12-1 中看不到任何会将采样信号[图 12-2]带入外部的内容。 (面对来自其他渠道的竞争,DMA 不是确定性的,但我期望它足够快。)

    在论坛上、我看到了一些提示、ADC 可能对在繁忙时触发很敏感、因此如果 CK 低电平周期与上面的示例一样短、那么出于这个原因、您可能需要等待完成 (BUSY==0)。

    您是否仍计划使用 MISO(还是它是 MOSI)来执行 CK 触发器、而不是讨价还价 GPIO? 我问道、因为前者的占空比为 50%、但不需要 GPIO(或计时器)。

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

    谢谢...明白了。 我现在有了以下内容:

    //禁用转换
    DL_ADC12_disableConversions (ADC12_0_INST);
    //将 ADC 模式更改为 8 位、50ns 采样时间、不进行均值计算
    // ADC 0 — 这一切都正常
    DL_ADC12_initSingleSample (ADC12_0_INST、
    DL_ADC12_REPEAT_MODE_ENABLED、DL_ADC12_SAMPLING_SOURCE_AUTO、DL_ADC12_TRIG_SRC_EVENT、
    DL_ADC12_SAMP_CONV_CONV_RES_8_BIT、DL_ADC12_SAMP_CONV_DATA_FORMAT_unsigned);

    DL_ADC12_setSampleTime0 (ADC12_0_INST、2);//2    = 50 n

    DL_ADC12_configConversionMem (ADC12_0_INST、ADC12_0_ADCMEM_0、
    DL_ADC12_INPUT_CHAN_0、DL_ADC12_REFERENCE_VOLTAGE_EXTREF、DL_ADC12_SAMPLE_TIMER_SOURCE_SCOMP0、DL_ADC12_AVERAING_MODE_DISABLED、
    DL_ADC12_BURN_OUT_SOURCE_DISABLED、DL_ADC12_TRIGGER_MODE_TRIGGER_NEXT、DL_ADC12_Windows_COMP_DISABLED);
    DL_ADC12_enableConversions (ADC12_0_INST);
    //现在执行 CCK 以触发 ADC(GPIO OUT -> GPIO IN ->事件触发,正边沿)
    DL_GPIO_setPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);
    //从 CCK 正边沿开始转换(采样)有延迟、因此状态只是基准缓冲器就绪高电平
    while (DL_ADC12_getStatus (ADC12_0_INST)= ADC12_STATUS_REFBUFRDY_READY)
    ;
    //转换(样本)必须已开始、等待转换完成
    while (DL_ADC12_getStatus (ADC12_0_INST)=(ADC12_STATUS_BUSY_ACTIVE | ADC12_STATUS_REFBUFRDYE_READY))
    ;
    // CCK 低
    DL_GPIO_clearPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);
    我希望随着我改变采样时间,我的 CCK 的脉冲宽度将  change....it 不会...令人费解!
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我的代码中有错误、未使用 Vref 缓冲区...

    然而,如果我现在这样做,它只是挂起,永远不存在循环??

    //现在执行 CCK 以触发 ADC(GPIO OUT -> GPIO IN ->事件触发,正边沿)
    DL_GPIO_setPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);
    //从 CCK 正边沿开始转换(采样)存在延迟
    DL_GPIO_setPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);

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

    哪个回路被卡住?  (正如我所说,我没有尝试 status:busy ;我想它的工作原理与广告一样。

    是否有理由将 CCK 引脚(高电平)设置两次?

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

    第一个循环...

    '是否有理由将 CCK 引脚(高电平)设置两次?'

    这是星期一…

    这适用于第一个 CCK

    DL_GPIO_setPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);

    while (DL_ADC12_getRawInterruptStatus (ADC12_0_INST、ADC12_DMA_TRIG_IMASK_MEMRESIFG0_SET)= false)
       ;
    但不适用于后续 CCK 、因为我猜该位需要重置...但 DMA 在读取时不重置该位吗???
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    当您之前询问过这一点时、我做了一个实验(ADC12_max_freq_DMA 的有点黑客版本)、让我确信 DMA 清除 DMA_TRIG.RIS.MEMRESIFG0、而不是 CPU_INT.RIS.MEMRESIFG0。

    MEMRES0 的 DMA 读取(在 TRM 表 12-20 中)本身显然不被计为“读取“、而是 DMA-ACK 来清除 RIS 位、而清除 CPU_INT.RIS.MEMRESIFG0 需要从 CPU 读取。 TRM 的第 12.2.14.1 节和第 12.2.14.3 节 暗示了这种区别、但前者没有明确提及 MEMRES 寄存器。

    DL_ADC12_clearInterruptStatus () 指的是 CPU_INT。 DMA_TRIG 的相应调用是 DL_ADC12_clearDMATriggerStatus()。

    您看到了不同的行为吗?

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

    你好...是的、我认为、有点...

    //现在执行 CCK 以触发 ADC(GPIO OUT -> GPIO IN ->事件触发,正边沿)
    DL_GPIO_setPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);
    转换= 0;
    //通过 DMA 握手等待转换结束、用伪变量计算时间、“convert"</s>“
    while (DL_ADC12_getRawInterruptStatus (ADC12_0_INST、ADC12_DMA_TRIG_RIS_MEMRESIFG0_MASK)= FALSE)
      convert++;
    // CCK 低
    DL_GPIO_clearPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);
    //现在执行剩余的 64 CCKS
    #pragma GCC 展开 64
    对于 (I=0;I<64;I++){
    转换= 0
    DL_GPIO_setPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);
    while (DL_ADC12_getRawInterruptStatus (ADC12_0_INST、ADC12_DMA_TRIG_RIS_MEMRESIFG0_MASK)= FALSE)
        convert++;
    DL_GPIO_clearPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);
    }
    //完成
    第一个 CCK、在 for-loop 之前、我得到 convert=7……与我使用的大量采样时间一致。
    如果我在 for 循环之前设置了中断 、可以看到 ADC12_DMA_TRIG_RIS_MEMRESIFG0 设置为零。
    但在 for 循环转换中始终为零、这表明 RIS 始终设置为????
    我在 CCK....changing 采样时间中看到这改变了第一个 CCK 的宽度。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    放置一个电阻器

    DL_GPIO_setPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);

    插入

    > DL_ADC12_clearInterruptStatus (ADC12_0_INST、ADC12_DMA_TRIG_RIS_MEMRESIFG0_MASK );//清除过时

    由于 DMA 不执行此操作(这在本例中实际上是一项优势)、因此您必须执行此操作。

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

    谢谢,但不应该 DMA 每次进行传输时都清除此内容?

    8.2.5.4 硬件事件处理

    如果是源自 DMA 触发 (DMA_TRIG) 或通用事件 (GEN_EVENT) 的事件、则 IIDX

    未使用寄存器。 在生成事件的外设之间执行四次事件握手

    和订阅事件的硬件实体(例如,DMA 或辅助外设)。

    四次事件握手将清除 RIS 和 MIS 寄存器中相应的中断状态位

    自动化。

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

    有 3 个不同的 RIS 寄存器。 如果在第二个 setPins 调用处断点、我预计您将看到 DMA_TRIG.RIS 具有 MEMRESIFG0=0、但 CPU_INT.RIS 具有 MEMRESIFG0=1。 这也与代码的行为一致。

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

    …、对不起、我是哑吧、我在循环中使用 DMA RIS、为什么 DMA 不清除它上面的 TRM 说它死了???

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

    DL_ADC12_getRawInterruptStatus 的定义如下所示:

    __STATIC_INLINE uint32_t DL_ADC12_getRawInterruptStatus(
        const ADC12_Regs *adc12, uint32_t interruptMask)
    {
        return (adc12->ULLMEM.CPU_INT.RIS & interruptMask);
    }

    即、它仅查看 CPU_INT.RIS。 相比之下、您可以使用以下命令来获得 DMA_TRIG.RIS:

    __STATIC_INLINE uint32_t DL_ADC12_getRawDMATriggerStatus(
        const ADC12_Regs *adc12, uint32_t dmaMask)
    {
        return (adc12->ULLMEM.DMA_TRIG.RIS & ~(dmaMask));
    }
     

    [那“~“肯定看起来不对,是吗? 我想知道是否有人使用过此函数。]

    实际上、每个外设中(多个)RIS 寄存器的 RIS 位定义相同(也是 IMASK/ICLR/等)、但命名不同(CMSIS 要求)、因此 (ADC12_DMA_TRIG_RIS_MEMRESIFG0_MASK == ADC12_CPU_INT_RIS_MEMRESIFG0_MASK );使用备用位名称不会引用不同的 RIS 寄存器。

    [编辑:在上面我建议的代码中、我没有注意到你在使用 DMA_TRIG_RIS 定义--我只是复制了你的定义。 但它仍然有效。]

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

    你(们)好、谢谢。

    我想我必须以不同的方式做到这一点。

    尽管你(出色)的努力,我只是不明白为什么我必须:

    放置一个电阻器

    > DL_GPIO_setPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);

    插入

    > DL_ADC12_clearInterruptStatus (ADC12_0_INST、ADC12_DMA_TRIG_RIS_MEMRESIFG0_MASK );//清除过时

    由于 DMA 不执行此操作(这在本例中实际上是一项优势)、因此您必须执行此操作。

    由于 TRM 提示 RIS 位在每个 DMA 后都会复位、所以为什么我需要清除它????

    8.2.5.4 硬件事件处理

    如果是源自 DMA 触发 (DMA_TRIG) 或通用事件 (GEN_EVENT) 的事件、则 IIDX

    未使用寄存器。 在生成事件的外设之间执行四次事件握手

    和订阅事件的硬件实体(例如,DMA 或辅助外设)。

    四次事件握手将清除 RIS 和 MIS 寄存器中相应的中断状态位

    自动化。

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

    每次 DMA 后 RIS 位会复位“。 关键是:哪个 RIS[:MEMRESIFG0]位? ADC 中有 3 个 RIS:MEMRESIFG0 位。 观察到的行为是 DMA 只清除其中 1 个、并且一个不是您要查看的。 (如果它清除了所有 3x,则发生的速度太快,您的循环无法看到它很高,并且您的代码的行为会有所不同。)

    当您插入我上面建议的 DL_ADC12_clearInterruptStatus () 调用时、您看到了什么行为?  

    非邀约:您正在编写一次性实验、还是您打算以何种方式长期进行触发? 状态:BUSY 检查可能会在 99%的时间内工作[假设不是 0%]、因此可能足以进行实验。

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

    今天我有机会尝试 status:忙碌,我认为它不会做你想要的。 TRM 第 12.2.13 节指出“对于重复单次转换、它表示重复单次操作已开始但尚未结束。“ 根据观察到的行为、我认为这需要从字面上理解。 模式是“重复单次“、而不是“单次“、具有重复能力、它从第一个触发器开始(进入忙状态)、从不结束(除非切换 ENC)。

    这也与您之前的实验结果一致。

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

    尊敬的 Filip:

    关于您关于 DMA 的问题、我想跳转 一下、添加一些注释。

    M0 支持三种不同的事件系统、CPU_INT 用于 CPU 中断请求。

    第二个是 GEN 事件、用于外设触发、如事件系统所用的 GPIO 触发 ADC。

    最后一个是 DMA 事件、因此如果发生 DMA 传输、DMA 将由硬件清除该事件。

    至于 ADC 转换状态监控器、通常 会轮询 CPU_INT RIS、然后应该清除 CPU_INT RIS、因为它不会被 DMA 清除。

    B.R.

    Sal

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

    谢谢。

    这似乎有效:

    //清除中断 memres0

    DL_ADC12_clearInterruptStatus (ADC12_0_INST、ADC12_CPU_INT_IMASK_MEMRESIFG0_MASK);

    // 64 个时钟
    #pragma GCC 展开 64

    对于 (I=0;I<64;I++){
    // CCK 为高电平、通过事件触发 ADC
    DL_GPIO_setPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);
    //等待 memres0
    while (DL_ADC12_getRawInterruptStatus (ADC12_0_INST、ADC12_CPU_INT_IMASK_MEMRESIFG0_MASK)= false)
             ;
    // CCK 低
    DL_GPIO_clearPins (GPIO_SA3_CCK_PORT、GPIO_SA3_CCK_PIN);
    //清除中断 memres0
    DL_ADC12_clearInterruptStatus (ADC12_0_INST、ADC12_CPU_INT_IMASK_MEMRESIFG0_MASK);
    NOP_10;//十个 NOP 延迟
    }//结束
    但是...当我看 CCK 在一个'镜,很难理解为什么 CCK 是高的一微秒?
    DL_ADC12_setSampleTime0 (ADC12_1_INST、15);//2 = 50ns
    很好、我可以通过向上变化来调制 CCK 高电平。

    8.1.5 事件传播延迟  

    通用路由通道在发布实体和之间实现了四路硬件握手

    订阅实体。 此握手需要四个 ULPCLK 周期才能完成:

    在我的示例中、ULPCLK 为 25ns、因此以上时为 100ns。
    采样时间从上面也是 375ns。
    我也有这种情况:

    (c) 当 ADCCLK 以 ULPCLK 为时钟源时、同步延迟 (tsync) 被旁路、并且采样信号使用 ADC 触发变为有效

    ADC 8 位转换需要 9 个时钟周期、包括写入 memres0。

    因此、我认为所需的一切:100ns + 300ns + 9*25ns = 625ns

    然后把 CCK 低。。

    似乎是一个巨大的差异。。。

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

    我只能想到的是 DMA 干扰了 CPU 总线(轮询)活动。 阅读 TRM 的第 5 章、我从未清楚 CPU 或 DMA 是否会优先处理总线活动(以及具体粒度)。

    一个快速(可能的)实验可能是删除启用 DMA 通道的代码行(DMA 请求和数据只是丢失)、并查看波形是否发生变化。