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.

[参考译文] MSP430FR2533:ADC 寄存器 ADCSC 和 ADCBUSY 位在初始 ADC 中断后保持置位

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/844103/msp430fr2533-adc-register-adcsc-and-adcbusy-bits-remain-set-after-initial-adc-interrupt

器件型号:MSP430FR2533

我们在大约0.5%的 MSP430FR2533IRHB 芯片上发现、在设置 ADC 并接收到第一个中断后、我们不再接收后续 ADC 中断。 设置断点后、我可以看到 ADCSC 位(寄存器 ADCCTL0)和 ADCBUSY 位(寄存器 ADCCTL1)被置位、从未清零。

其余99.5%的芯片工作正常。 我们已验证 ADC 的输入与已知良好芯片的匹配。 实际上、我们已将 IC 换用为已知良好的 IC、问题出在 IC 上。

我们的工厂已向 TI 发送已知的故障样片、他们声称 ADC 正常工作、但我们清楚地看到它不是。  

很明显、固件是第一个指向手指的地方、但它跟随芯片的事实似乎让我怀疑。 更不用说、擦除 FRAM 并加载已知良好的固件映像(我们已在数千个其他产品上加载)不能纠正此问题。

您建议在这方面走什么路?  

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

    您好、Jacob、

    这是非常奇怪的、我没有看到任何与此相关的勘误表。 您是否曾尝试清除故障器件上 SW 的 ADCSC 位以查看该问题是否得到解决? 您能给我一点应用背景吗? 您在软件中启用了哪些其他中断?

    谢谢、

    Mitch

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

    如果您可以发布用于驱动 ADC 的代码、可能有人会看到一些东西。 我会寻找一个代码序列、该序列通常有效、但容易受到微移的影响、例如、如果 ADC 时钟以4.5MHz 而非5MHz 的频率运行。 (各个芯片之间存在差异。) 即使您一直坚持"这就是它的工作方式"、也可能有权变措施。

    在某些模式下、ADCBUSY=1 始终处于此状态。 我已经看到(但没有研究) SC 保持开启状态的一些情况、例如、如果 SC 设置为 SHS>0 (但并非始终如此)。

    您是否知道 TI 对他们测试的芯片究竟说了什么? 他们选择的词语可能是相关的。

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

    Bruce、您好、感谢您的回答。

    我们的规范相当简单。 只有3个函数适用于 ADC、其中一个函数是 ISR:

    (请小心、下面代码段中的一些注释看起来不正确)

    void App_adcInit (void)
    {
    ADC_val = 0;
    ADC_INTERRUPT = false;
    adcIntVal = 3;
    
    P2OUT |= GPIO_PIN7;
    
    //输入通道6 |
    ADCMCTL0 = ADCINCH_6;//选择默认基准(AVCC 和 AVSS);0110b = A6 (对于 P1.6输入通道)
    
    ADCCTL0 = ADCSHT_15;
    //信号来源于采样定时器|时钟源为 ACLK | 3分频
    ADCCTL1 = ADCSHP | ADCSSEL0_L | ADCDIV0;
    
    ADCCTL2 = ADCSR | ADCPDIV0;//预分频1;8位分辨率;二进制无符号读回、200ksps 采样率
    
    //启用中断
    ADCIE = ADCIE0;
    
    ADCCTL0 |= ADCON | ADCENC | ADCSC;//启用 ADC
    
    ADCLO = 0x00;
    ADCHI = 0x00;
    __delay_cycles (300000);//等待30ms 让 ADC 稳定
    }
    
    void setAdcLowPower (bool set)
    {
    //进入低功耗模式
    if (设置)
    {
    //停止 ADC 转换
    ADCCTL0 &=~(ADCON | ADCENC);
    
    P2OUT &=~(GPIO_PIN7);
    }
    其他
    {
    app_adcInit();
    }
    }
    
    #pragma vector=ADC_vector
    __interrupt void ADC_ISR (void)
    {
    //获取 ISR 已触发的原因
    unsigned int IFG =_even_in_range (ADCIFG、0x0c);
    
    /*如果 ISR 已触发的原因是它已退出
    *、将中断标志设置为
    * true 并在 QCC 处于唤醒状态时发出警报。
    *
    // FIXME:这应该在 ISR 之外...
    IF (((IFG 和 ADCHIIFG)||(IFG 和 ADCLOIFG))
    {
    //获取当前值
    ADC_val = ADCMEM0;
    
    //重置高/低值以生成中断
    ADCLO =(ADC_val < adcIntVal)? 0x00:adc_val - adcIntVal;
    ADCHI =(ADC_val >(255 - adcIntVal))? 255:adc_val + adcIntVal;
    updateADCReg ();
    }
    
    ADCIFG = 0;
    
    //开始下一次转换...
    ADCCTL0 |= ADCSC;
    
    }
    

    TI 的答复非常简短:

    测试部件:MSP430FR2533IRHB

    测试引脚:P1.6

    测试功能:ADC (10位)

    电源:3.3V

    测试电压点:0V 0.2V 1.2V 1.5V 1.8V 3.3V

    测试结果:

    输入电压(V)

    0

    0.2.

    1.2.

    1.5

    1.8

    3.3.

    AD_VALUE

    0

    61.

    369.

    462.

    549.

    1022.

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

    您好 Mitch、

    您可以在对@Bruce McKenneny47378的答复中看到下面发布的代码。 我们设置 ADC、在初始读取后、我们设置 LO 和高电平比较器、以便在读取超出某个范围时触发中断。 我们还有一个主处理器、它将断电并通知 MSP430它正在断电、此时 MSP 将禁用 ADC 以降低功耗。 此外、ADC 读数会报告回主处理器。 请注意、MSP 是 I2C 从设备、因此会将 GPIO 引脚置为有效、以通知主处理器 MSP 可以说什么、此时主处理器将发出对当前 ADC 值的 I2C 读取。

    我们启用了以下中断:41、44、45、54、55、 56、57

    我将尝试清除 SW 中的 ADCSC 位并返回报告。

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

    当您查看 ADC 寄存器时、ADCON 的值是多少? 此外、您如何驱动 ACLK (晶体与 REFO)?

    我这里没有我的设备、但我有一些观察结果。

    这里的动态变化有点不寻常(与"错误"不同、但可能会打开不同的窗口)。 SSEL0/PDIV0/DIV0的组合可为您提供32kHz/4/2=4kHz 的 ADC 时钟、该时钟相当慢。 与 SHT=15 (1k ADC 时钟)组合使用、输出速率约为4sps。 根据 CPU 的运行速度(MCLK)、在这个300k 时钟延迟期间、第一次转换可能会完成、也可能不会完成。 我提到这一点,因为这可能影响到第一次完成后的失败观察。

    > ADCCTL0 &=~(ADCON | ADCENC);  

    这在中频转换中几乎肯定会发生。 UG (SLAU445I)第21.2.7.1节中提到了转换期间设置 ADCON=0的影响、其中"中断标志[IS]的值不可预测"、这向我建议 ISR 可以被调用、也可以不被调用。 如果调用 ISR、它将在 ADCON=0时设置 SC;在这种情况下、如果 SC (可能是忙)保持持续、我不会感到惊讶。 如果"不可预测"的结果因芯片而异、我也不会感到惊讶。 而(相对)较慢的 ADC 时钟可能会在 ADC 单元内的任何小竞争中成为更大的目标。 我建议使用"软停止"机制、例如使用 ISR 和 setAdcLowPower 之间共享的"下次停止"标志。 (或者:设置 IE=0、设置 ENC=0、针对 BUSY=0进行自旋、然后设置 ON=0。)

    我问 ACLK、因为低速晶振的启动时间很长、如果这在单个芯片之间有所不同、我也不会感到惊讶。

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

    您好、Jacob、

    我想指出的一点是、我注意到您正在打开 ADC 并在同一线路中启动转换:

    ADCCTL0 |= ADCON | ADCENC | ADCSC;//启用 ADC 

    我们建议在开始转换前至少打开 ADC 100ns、以避免转换错误:

    以下示例说明了我们如何建议配置 ADC 并启动转换:

    //配置 ADC10
    ADCCTL0 |= ADCSHT_2 | ADCON; // ADCON、S&H=16 ADC 时钟
    ADCCTL1 |= ADCSHP; // ADCCLK = MODOSC;采样定时器
    ADCCTL2 |= ADCRES; // 10位转换结果
    ADCMCTL0 |= ADCINCH_1; // A1 ADC 输入选择;Vref=AVCC
    ADCIE |= ADCIE0; //启用 ADC 转换完成中断
    
    while (1)
    {
    ADCCTL0 |= ADCENC | ADCSC; //采样和转换开始
    _bis_SR_register (LPM0_bits | GIE); // LPM0、ADC_ISR 将强制退出
    __no_operation(); //仅用于调试
    如果(ADC_RESULT < 0x1FF)
    P1OUT &=~BIT0; //清除 P1.0 LED 关闭
    其他
    P1OUT |= BIT0; //将 P1.0 LED 设置为打开
    __DELAY_CYCLES (5000);
    } 

    我建议在使用 ADCSC 位开始转换之前设置 ADCON 位、如上例所示。 这并不能解释 ADCBUSY 和 ADCSC 位为什么保持高电平、而只是想指出这一点。

    深入探究原始问题-您能否发布 更新 ADCReg ()函数代码? 我想看看该函数在做什么。

    此外、您能否告诉我您以多高的频率运行 CPU?

    谢谢!

    Mitch

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

    CPU @ 8MHz

    void updateADCReg (void)
    {
    如果(!请勿打扰)
    {
    interruptFlagReg |=(1 << SS_REG_INT_FLAG_ADC);
    
    //清除中断标志
    HWREG16 (FUNCHTIONTIME__PERIPHERAL_OFS_TAxCCTL2)&=~(COV | CCIFG);
    //将翻转设置为距离当前计时器 val 100ms (实际上更像是45-55ms)
    HWREG16 (FUNCHTIONTIME__PERIPHERAL_OFS_TAxCCR2)=
    HWREG16 (FUNCHTIONTIME__PERIPHERAL_OFS_TAxR)
    + timer_cycles_100ms;
    //启用计时器
    HWREG16 (FUNCHTIONTIME__PERIPHERAL_OFS_TAxCCTL2)|= CCIE;
    
    //将 QCC 的中断设置为高电平(并将方向设置为 OUT。
    P1DIR |= GPIO_PIN5;
    P1OUT |= GPIO_PIN5;
    }
    }
    

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

    谢谢 Jacob、

    您能告诉我代码 App_adcInit()和 setAdcLowPower()被调用的位置吗? 进一步探究 Bruce 的想法、我想了解一下这些函数之间的相互接近程度。

    此外、您能否确认您的 ACLK 频率是多少?

    谢谢、

    Mitch

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

    我没有 FR2533可供使用、但我希望 FR2311是一个合适的代理。

    一些观察结果:

    1) 1)您不能在同一步中设置 ADCON=0和 ADCENC=0。 如果您尝试、ADCON 保持为1。 (即:此程序中的 ADCON=1始终。)

    2) 2)如果在 ENC=0时设置 SC=1、它将保持在1、至少直到 ENC=1再次。 无忙信号=1。

    我没有(SOI FAR)能够通过快速打开/关闭来暂停。

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

    您好 Mitch、

    ACLK 设置为使用 REFO、因此为32kHz。


    Main()>> App_init()>> App_adcInit()


    void main (void)
    {
    WDTCTL = WDTPW | WDTHOLD;
    bsp_configureMCU();
    _bis_SR_register (GIE);
    app_init();
    CAPT_AppStart();
    ...
    } 

    在调用 App_adcInit()之前,从 App_init()调用 setAdcLowPower (false) 

    setAdcLowPower()也是在主处理器发出命令后从 I2C ISR 调用的。

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

    您好、Jacob、

    很抱歉耽误你的回答。  

    您是否曾尝试过 Bruce 的建议、看看您是否仍然看到同样的行为?

    此外、还可以将 ADC 时钟更改为 MODOSC (5MHz)、看看是否仍然出现故障。 30ms 延迟对于4kHz ADC 时钟来说可能存在问题。

    谢谢、

    Mitch

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

    您好、Jacob、

    想要办理入住手续、看看您是否仍然遇到问题?

    谢谢、

    Mitch

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

    您好 Mitch、

    感谢您对此采取后续行动。 是的、我仍然对此有疑问。

    我根据 Bruce 和您的建议进行了更改、并且能够再次触发中断、但它们不一致。 有时、当更改 ADC 上的电压时、中断将会触发、有时则不会触发。

    迄今的变化:

    • 不再同时清除 ADCON 和 ADCENC
      • 等待直到 ADCBUSY 被清零、然后再继续  
    • 不再同时设置 ADCON 和 ADCENC
    • 将 ADC 时钟更改为 MODOSC
    • 在 ISR 中设置一个标志、向主循环指示存在 HI/LO 中断。 主循环将读取 MEM 寄存器并执行相应的操作。

    是否有方法使用调试器确定当前或之前的 LPM 电平?

    -Jake

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

    您好 Mitch、

    此处需要注意的一点是:

    我已恢复到原始代码(根据此主题中的建议删除了更改)、并且仅对 ADC 时钟进行了以下更改:

    //时钟分频为~10kHz
    ADCCTL1 = ADCSHP | ADCSSEL_0 | ADCDIV_7;//来自采样定时器的信号|时钟源为 MODCLK |除以8
    ADCCTL2 = ADCSR | ADCPDIV__64; //预分频64;8位分辨率;二进制无符号读回、50ksps 采样率 

    原始时钟配置如下:

    //时钟被分频为4kHz
    ADCCTL1 = ADCSHP | ADCSSEL_1 | ADCDIV_1;//来自采样定时器的信号|时钟源为 ACLK |除以2
    ADCCTL2 = ADCSR | ADCPDIV__4; //预分频4;8位分辨率;二进制无符号读回、50ksps 采样率 

    当新时钟源以~10kHz 的频率运行时、一切都正常。 我无法真正解释原因。 我尝试使用 ACLK 作为8kHz 和16kHz 的 ADC 源、但两者都不起作用。 因此、它不仅仅是增加的时钟速度、还必须是其他运行的东西。

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

    、对此有什么想法吗?

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

    您好、Jacob、

    很抱歉耽误你的时间。  

    更改时钟源似乎可以解决该问题、这一点非常有趣。 只是为了澄清- ADC 位保持置位、但器件没有完全锁定、对吧?

    我将使用您提供的软件运行一些测试、并在下周进行更新。  

    谢谢、

    Mitch

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

    您好 Mitch、

    是的、在单个时钟更改的情况下、一切都按预期工作。

    我如何通过电子邮件发送您的源代码? 我甚至可以向您发送一个具有 MSP430处于此状态的电路板。

    -Jake

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

    这将起作用! 我向您发送了一个 E2E 连接请求。

    谢谢、

    Mitch

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

    您好、Jacob、  

    由于我们要将此对话脱机、我现在将关闭该主题。

    谢谢、

    Mitch