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.

[参考译文] MSP430F5132:比较器B信道之间是否经常交换存在问题? +代码体系结构反馈

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1096417/msp430f5132-are-there-issues-constantly-swapping-between-comparator_b-channels-code-architecture-feedback

部件号:MSP430F5132

各位专家,您好!

如果您对我的方法有任何问题,我希望您提供意见。 如果您认为有更好的方法在较高级别上构建代码,我也会寻求建议。

我的问题:

1)您是否预计持续切换比较器B信道会出现任何问题?

2)在较高级别上,您能想到更好的代码结构吗?

目标是测量两个独立的信号。 一个信号我称为"AC Fault"(交流故障),另一个信号为"DC Fault"(直流故障)。  当交流或直流信号通过阈值时,我们必须快速跳闸继电器。 LPM不是优先事项,但一旦我们有了工作,就可以实施。

我们的联系将会是这样  

WFP 1.0 :AC比较器

WFP 1.1 :AC ADC,

WFP 1.2 :DC比较器

WFP 1.3 :DC ADC.

代码概述:

快速说明:

答 经常在比较器输入通道之间切换。  

B. 如果比较器中断,则在对应于比较器的通道上触发ADC读数。  

C. 比较器告知MCU输入信号是交流还是直流故障,然后设置ADC10HI继电器跳闸阈值。  

D. 如果输入ADC10HI中断,则触发继电器

谢谢!  

// My idea for the while loop

    while(1){
        if (faultMode == NO_FAULT) {
            // swap between two comparator channels constantly
            if (index) {
                CBCTL0 |= CBIPSEL_2;            // comp_B input channel CBx <-> IPSEL_x

            } else {
                CBCTL0 |= CBIPSEL_0;            // comp_B input channel CBx <-> IPSEL_x
            }
            // Trigger new ADC read, monitor for fault
        } else {
            ADC10CTL0 &= ADC10ENC;
            ADC10CTL0 |= ADC10ENC + ADC10SC;    
            if (index > FAULT_RESET_DELAY) {
                index = 0;
                faultMode = NO_FAULT;
            }
        }
        index++;

    }

// My idea for the while loop

while(1){
    if (faultMode == NO_FAULT) {
        // swap between two comparator channels constantly
        if (index) {
            CBCTL0 |= CBIPSEL_2;            // comp_B input channel CBx <-> IPSEL_x

        } else {
            CBCTL0 |= CBIPSEL_0;            // comp_B input channel CBx <-> IPSEL_x
        }
        // Trigger new ADC read, monitor for fault
    } else {
        ADC10CTL0 &= ADC10ENC;
        ADC10CTL0 |= ADC10ENC + ADC10SC;    
        if (index > FAULT_RESET_DELAY) {
            index = 0;
            faultMode = NO_FAULT;
        }
    }
    index++;

}

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

    您好,Cameron,

    感谢您对您的申请进行如此详细的描述。

    您能否分享有关关键要求的更多信息? 所需的响应时间是多少? 使用集成比较器的速度最快。 但看起来您也将使用ADC对信号进行采样(以确认测量结果?)。 我预计这会在循环中消耗最多的时间。

    例如,如果您要执行ADC测量,为什么不经常采样通道并使用窗口比较器触发中断以使继电器跳闸?

    同样,我不知道什么折衷方案对您的应用程序有意义。

    此外,我看不到在比较器输入通道之间快速切换的问题。 如果您使用的是POWER MODE=HIGH SPEED MODE,则传播时间<1us (参见数据表的5.43)。 我将与我的团队确认。

    此致,
    Evan

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

    您好,Evan:

    感谢您的快速响应!

    [quote userid="41.6841万" url="~/support/micromicrosofts/MSP-low-power micromicrocontroller-group/MSP/f/MSP-low-power microcontroller-forum/109.6417万/msp430f5132-are-5132-here-issues- alinhere-sapping-between-quote_b- channels-architecture-feedback/406.0756万#4060756如果406.0756万如果您没有经常中断比较器/信号,那么为什么不使用信号转换器来执行信号转换/信号转换?

    我喜欢您使用窗口比较器的想法。 我们需要一个小于20毫秒的响应时间。 如果我对采样和保持(ADC10SHT)使用16个clk周期,则ADC读数总共需要28个周期,或在25MHz时钟速度下需要1.12us。 因此,我认为ADC信道之间的交换可以起作用

    [quote userid="41.6841万" url="~ë/support/micromicromicrosoft器/MSP-low-power - micromicromicrocontroller-group/MSP-low-power - micromicromicrocontroller-forum/109.6417万/msp430f5132-are -5132 - here-issues- almers-sapinger-b-channelse-code-architecture-feed/406.0756万#4060756"ADC是否406.0756万是否也要使用信号来确认测量结果(您是否也要确认信号)? 我希望这会在循环中消耗最多的时间。[/QUOT]

    这是正确的。 ADC用于确认是否需要触发继电器。  

    新问题:如果我使用下面的代码,是否必须包括延迟以让ADC完成转换? (16 clk样本和保持+ 12 clk转换时间)

    我评论了我认为需要延迟的地方。

    // My idea for the while loop using ADC polling 
    
    while(1){
        // swap between two ADC channels constantly
        if (index) {
            init_ADC_DC_mode();              //Set ADC10HI_DC            
            ADC10CTL0 &= ~ADC10ENC;          //trigger a reading
            ADC10CTL0 |= ADC10ENC + ADC10SC;
            // Is a delay needed here?
        } else {
            init_ADC_AC_mode();              //Set ADC10HI_AC
            ADC10CTL0 &= ~ADC10ENC;          //trigger a reading
            ADC10CTL0 |= ADC10ENC + ADC10SC;
            // Is a delay needed here?
        }
        index++;
    }

    谢谢!

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

    您好,Cameron,

    感谢您的回复。 我认为使用此设备可实现<20毫秒的响应时间。

    请注意,ADC可运行的最大频率为5MHz (DS中的表5.29)。 但是,我认为应该为您的应用程序留出足够的空间。

    建议不要在主环路中的ADC信道之间手动切换,而是尝试使用ADC10A中的“重复信道序列”功能。 此功能有一些限制:ADC将在ADCINCHx中设置的通道上启动,并按顺序进入通道0。 在您的情况下,这将限制您使用A1和A0,这可能会限制您在电路板布局方面的灵活性。 这是否合理? 用户指南中的27.2 .7.4 部分提供了非常详细的状态图和此过程的说明。

    以下示例说明了如何配置ADC以实现通道的重复序列:

    https://dev.ti.com/tirex/explore/node?node=AFHsHgHjHaWG4XZ9SlF6Kw__IOGqZri__LATEST&search=f5132

    以下示例说明如何使用ADC的窗口比较器函数:

    https://dev.ti.com/tirex/explore/node?node=AGQmMIOB7ZvEnJeoWXev5w__IOGqZri__LATEST&search=f5132

    希望这是一个良好的起点。 如果您有任何其他问题,请告诉我。

    最佳,

    Evan

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

    谢谢Evan!

    这一切都是合理的,我非常熟悉这两个例子。

    我很抱歉再问两个问题

    1)是否可以在下次转换之前立即更改ADC10HI阈值? 我在第27行和第30行显示这一点

    2)是否可以知道哪个ADC通道触发了中断? 我在第26行和第29行展示我的想法... 我尚未测试这是否有效。 我也很好奇,是否有更好的方法来实现这一点。 这一点很重要,因为A0和A1的ADC10HI阈值不同。

    伪代码中的我的想法:

    // ADC10 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=ADC10_VECTOR
    __interrupt void ADC10_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(ADC10_VECTOR))) ADC10_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch(__even_in_range(ADC10IV,12))
      {
        case  0: break;                         // No interrupt
        case  2: break;                         // conversion result overflow
        case  4: break;                         // conversion time overflow
        case  6:                                // ADC10HI
          ADC10IFG &= ~ADC10HIIFG;              // Clear interrupt flag
          // Trip relay
          break;
    
        case  8: break;                          // ADC10LO
        case 10: break;                          // ADC10IN
        case 12:                                 // ADC10IFG0
            ADC_Result = ADC10MEM0;
            if (ADC10MCTL0 & ADC10INCH_1) { // ADC input = A1
                ADC10HI = A0 trip threshold // Adjust HI threshold to A0 for next conversion
            }
            if (ADC10MCTL0 & ADC10INCH_0) { // ADC input = A0
                ADC10HI = A1 trip threshold // Adjust HI threshold to A1 for next conversion
            }
        break;
        default: break;
      }
    }

    谢谢!

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

    问得好。 我在数据表中找不到明确禁止这种行为的地方,但我认为这不是明智之举。 最终可能会生成异常中断。 不良行为的示例:当前ADC值为0xBB ->您将ADC10HI更改为0xAA以准备下一个样本,但是ADC尚未采样下一个样本,在内存中看到0xBB,并触发中断。 为了确定行为,您可能需要进行一些测试

    ADC?4061.0962万? 我在第26行和第29行展示我的想法... 我尚未测试这是否有效。 我也很好奇,是否有更好的方法来实现这一点。 这一点很重要,因为A0和A1的ADC10HI阈值不同。[/QUOT]

    是的,您应该能够读回ADC10INCHx,以获取上次采样的通道。 但是,UG还提到,当您等待触发器或等待启用时,只应读取ADC10INCH。 这可能会使您受到一些限制,因为您将无法使用 ADC10MSC (它会自动重新触发),而您必须自己重新触发ADC。 原因是启用MSC后,您将不会进入等待状态,允许您读取ADC10INCHx。 因此,您可能希望回到更手动的方法。 让我思考一下,明天再与您谈谈。

    Evan

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

    您好,Cameron,

    我想更多关于您的应用程序。 由于您的关键要求(<20毫秒响应时间)不会对系统造成压力,我建议现在使用ADC10MSC=1避免"重复频道顺序"。 即使它会提供最大采样率,代码也会更加复杂。

    简单性和性能的最佳平衡点是按以下方式配置设备:

    • 使用计时器触发ADC。 我不确定您的目标应用是什么,但如果它与安全相关,最好保证您以已知速率采样/响应。 使用计时器可确保情况确实如此。
    • 使用ADC ISR将ADC测量值保存为全局变量
    • 在主循环中,检查全局变量的值以确定是否跳闸。

    此致,

    Evan

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

    感谢Evan!

    这与安全有关,所以我喜欢使用计时器以已知速率采样的方法。