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.

[参考译文] MSP430G2553:在 3 个不同引脚上读取 ADC、然后进入 lpm4 模式请参阅 330uA 的高睡眠电流

Guru**** 2782445 points

Other Parts Discussed in Thread: ENERGYTRACE

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1620395/msp430g2553-adc-read-on-3-different-pin-then-go-to-lpm4-mode-see-high-sleep-current-330ua

器件型号: MSP430G2553
主题中讨论的其他部件: ENERGYTRACE

  uint16_t 超时= 5000;
  ADC10CTL0 = ADC10SHT_2 | ADC10ON | ADC10IE;
  ADC10CTL1 =通道| ADC10SSEL_3;

  IF (channel = INCH_1) ADC10AE0 |= BIT1;
  IF (channel = INCHION_3) ADC10AE0 |= BIT3;
  IF (channel = INCHION_5) ADC10AE0 |= BIT5;

  ADC10CTL0 |= ENC | ADC10SC;
  __bis_SR_register (LPM0_bits | GIE); //睡眠、直到 ADC 完成
  while (ADC10CTL1 和 ADC10BUSY)&&- TIMEOUT);
  ADC10CTL0 且=~ENC;
  超时= 5000;
  while (ADC10CTL1 和 ADC10BUSY)&&- TIMEOUT);
  ADC10CTL0 &=~(ADC10ON | ADC10IE | ADC10SC);
  ADC10AE0 = 0;

 

这是我的代码。 我发现有一些奇怪的错误、比如我执行此测量后、电流消耗始终保持在 330uA 左右。  

这里、我已将装置置于 lpm0 模式以等待 ADC 结果、但我的 MCU 固件也有其他中断、例如 port 和 i2c。 因此、我还 在睡眠后执行繁忙检查、然后执行 ADC 停止和禁用。

我的问题是为什么 ADC 在我未使用时仍然通电。 我尝试使用 ADC10SSEL_3 和 ADC10SSEL_0 都有相同的问题。

我的应用是、一旦完成所有 ADC 和其他活动、就会进入 lpm4 模式、这时会出现高电流 330uA 等问题

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

    我经常觉得麻烦的一件事是您如何处理 ADC10AE0。 可能您始终有一个模拟信号驱动这些引脚。 但通过清除该寄存器、可以启用数字端口缓冲器等。 此处可能存在两个问题:

    引脚配置为输出。 导致模拟信号难以驱动它。

    引脚配置为输入。 在某些情况下、使用模拟信号进行驱动会导致产生额外电流。 (22.2.2.1)

    将具有模拟信号的引脚设置为模拟模式、并按该方式保留这些引脚。

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

    是的,谢谢 David Schultz 我有三个针脚,在那里我测量电压... 因此、在测量我需要做的事情后、请提供一些代码...  

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

    正如 David 所说、只需添加:

    > ADC10AE0 |=(BIT1 | BIT3 | BIT5);//模拟输入

    关键参数、然后让它们保持这样。 (这假设它们始终是模拟输入,这种情况通常都是如此。)

    具体来说:AE0 寄存器禁用引脚上的施密特触发器。 当输入引脚悬空时、它会导致触发器“抖动“、从而耗尽电量。 它真的可以相加。

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

    现在我已经做了这样的代码。  

      uint16_t 超时= 5000;
      ADC10CTL0 = ADC10SHT_2 | ADC10ON | ADC10IE;
      ADC10CTL1 = INPUT_PIN | ADC10SSEL_3;

      如果 (INPUT_PIN = INCHION_0) ADC10AE0 |= BIT0;
      IF (INPUT_PIN = INCH/1) ADC10AE0 |= BIT1;
      IF (INPUT_PIN = INCH/2) ADC10AE0 |= BIT2;

      ADC10CTL0 |= ENC | ADC10SC;

      __bis_SR_register (LPM0_bits | GIE);  //睡眠、直到 ADC 完成
      while (ADC10CTL1 和 ADC10BUSY)&&- TIMEOUT);
      ADC10CTL0 且=~ENC;
      超时= 5000;
      while (ADC10CTL1 和 ADC10BUSY)&&- TIMEOUT);
      ADC10CTL0 &=~(ADC10ON | ADC10IE | ADC10SC);

    我仍然可以看到、运行条件下的功耗为 450uA、而 lpm4 睡眠电流为 330uA。 如果我阻断了 ADC、那么我确实看到稳定的电流消耗为 150uA。

    所以这是我的痛苦点。 我以 10 秒的固定间隔使用 ADC 读数。 这是不常见的。 但当我这样做时、我会继续消耗 300uA 的更多功耗... 我有一个单元正在处理电池、这正在杀死我们的系统。

    在这里、我的用例就像系统正在运行、那么我们需要以固定的 10 秒间隔进行 ADC、一旦系统关闭、就会进入 lpm4 模式以实现低功耗、但这种 ADC 使我像在 lpm4 模式下消耗了 330uA 电流。  

    希望现在清除我的痛苦点... 因此、如果我们有任何示例可以在 ADC 运行时消耗功率、那么在 ADC 测量完成后、只需禁用模块。 我非常感谢您的答复。  

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

    当我在 SET_ANALOC=0(您的用例)下运行以下程序时 、EnergyTrace 分别测量到空闲/繁忙状态下的消耗约为 10/27uA。 当它设置为=1 时、我会得到 0.8/1.0uA 的空闲/繁忙状态。 这告诉我:

    1) AE0 位与(设置+清除)AE0 位之间的差异是可测量的。

    2) 有一些事情之外的代码,你发布这是大大提高基线.

    未经请求:我建议您不要将中断/LPM 用于 ADC10。 在如此低的采样率下(您的情况):(a) 中断实际上不会得到任何好处 (b) 使用 LPM 会引入一个竞赛、可能会让您卡在 LPM0 中。

    ///
    //  main.c
    //
    #include <msp430.h>
    #include <stdint.h>
    
    #define SET_ANALOG 1
    unsigned vals[6] ; // A0-A5
    extern unsigned read_adc(unsigned channel); // Forward
    
    int 
    main(void)
    {
        volatile unsigned int i;
        WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
        P1DIR |= 0x01;                            // Set P1.0 to output direction
        P1OUT = 0x00;P1REN = (0xFF & ~(BIT0|BIT1|BIT3|BIT5));      // Input pulldown
        P2OUT = 0x00;P2REN = (0xFF & ~0x00);      // Input pulldown
        P3OUT = 0x00;P3REN = (0xFF & ~0x00);      // Input pulldown
    #if SET_ANALOG
        ADC10AE0 |= (BIT1|BIT3|BIT5); // A1/3/5
    #endif // SET_ANALOG
        IFG1 &= ~WDTIFG;
        IE1 |= WDTIE;
        BCSCTL3 |= LFXT1S_2; // VLO  
        WDTCTL = WDT_ADLY_250;
        __enable_interrupt();
        while(1)
        {
          //P1OUT ^= BIT0;
          LPM3;
          vals[1] = read_adc(INCH_1);
          vals[3] = read_adc(INCH_3);
          vals[5] = read_adc(INCH_5);
        }
        /*NOTREACHED*/
        return(0);
    }
    
    unsigned
    read_adc(unsigned channel)
    {
      uint16_t timeout = 5000;
      unsigned r;
        ADC10CTL0 = ADC10SHT_2 | ADC10ON | ADC10IE;
        ADC10CTL1 = channel | ADC10SSEL_3;
    #if !SET_ANALOG
        if (channel == INCH_1) ADC10AE0 |= BIT1;
        if (channel == INCH_3) ADC10AE0 |= BIT3;
        if (channel == INCH_5) ADC10AE0 |= BIT5;
    #endif // SET_ANALOG
    
        ADC10CTL0 |= ENC | ADC10SC;
        __bis_SR_register(LPM0_bits | GIE);   // Sleep until ADC completes
        while ((ADC10CTL1 & ADC10BUSY) && --timeout);
        ADC10CTL0 &= ~ENC;
        timeout = 5000;
        while ((ADC10CTL1 & ADC10BUSY) && --timeout);
        ADC10CTL0 &= ~(ADC10ON | ADC10IE | ADC10SC);
    #if !SET_ANALOG
        ADC10AE0 = 0;
    #endif // SET_ANALOG
        if (timeout == 0)
            r = (unsigned)-1;
        else
            r = ADC10MEM;
        return(r);
    }
    #pragma vector=ADC10_VECTOR
    __interrupt void
    adc10_isr(void)
    {
        LPM4_EXIT;  // Superset includes LPM0
    }
    #pragma vector=WDT_VECTOR
    __interrupt void
    wdt_isr(void)
    {
        LPM4_EXIT;  // Superset includes LPM0
    }