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.

[参考译文] MSP430FR6043:LPM3下的 ADC 和 REF 电压电流消耗

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1431176/msp430fr6043-adc-and-ref-voltage-current-consumption-in-lpm3

器件型号:MSP430FR6043

工具与软件:

您好!

我正在努力优化定制电路板的电流消耗。 目前、我已经集成了 ADC 和 REF 模块、它们在 LPM3模式下消耗160 µA。

您能帮助我进一步降低电流消耗吗?

每个模块(ADC 和 REF)消耗的电流大小。

#include "driverlib.h"

uint16_t count,tempSCBat,tempVbat;
float vbatRaw,scbatRaw;
float results;
uint8_t secCount=0;

ADC12_B_initParam adc_init;
ADC12_B_configureMemoryParam memory_init1;
ADC12_B_configureMemoryParam memory_init2;


void gpioSetup()
{

    /********************************************************************************************************************************/
    //GPIO Port 1
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN0, GPIO_TERNARY_MODULE_FUNCTION);
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN1, GPIO_TERNARY_MODULE_FUNCTION);
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN2, GPIO_TERNARY_MODULE_FUNCTION);

    GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6);
    GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN7);
    GPIO_setOutputHighOnPin(GPIO_PORT_P3,GPIO_PIN5); //P3.5
    //Output Setting
    GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN3);
    GPIO_setAsInputPinWithPullDownResistor(GPIO_PORT_P1, GPIO_PIN7);

    //GPIO Port 2
    GPIO_setAsInputPin(GPIO_PORT_P2,GPIO_PIN0);
    GPIO_setAsOutputPin(GPIO_PORT_P2,GPIO_PIN1|GPIO_PIN4|GPIO_PIN5);
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2, GPIO_PIN2, GPIO_TERNARY_MODULE_FUNCTION);
    GPIO_setAsInputPin(GPIO_PORT_P2, GPIO_PIN3);
    //Output Setting
    GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN4);
    GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN5);
    GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1);

    //GPIO Port 3
    GPIO_setAsInputPinWithPullDownResistor(GPIO_PORT_P3,GPIO_PIN0);//P3.0
    GPIO_setAsInputPin(GPIO_PORT_P3,GPIO_PIN1);//P3.1
    GPIO_setAsInputPinWithPullDownResistor(GPIO_PORT_P3,GPIO_PIN2);//P3.2

    GPIO_setAsInputPin(GPIO_PORT_P3,GPIO_PIN3);//P3.3
    GPIO_setAsInputPinWithPullDownResistor(GPIO_PORT_P3, GPIO_PIN4); //P3.4


    GPIO_setAsOutputPin(GPIO_PORT_P3,GPIO_PIN5); //P3.5
    GPIO_setOutputHighOnPin(GPIO_PORT_P3,GPIO_PIN5); //P3.5

    GPIO_setAsOutputPin(GPIO_PORT_P3,GPIO_PIN6|GPIO_PIN7); //P3.6 and P3.7

    //GPIO Port 4
    GPIO_setAsOutputPin(GPIO_PORT_P4,GPIO_PIN0);//P4.0
    GPIO_setAsOutputPin(GPIO_PORT_P4,GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);


    GPIO_setOutputHighOnPin(GPIO_PORT_P4,GPIO_PIN0);//P4.0
    GPIO_setOutputHighOnPin(GPIO_PORT_P4,GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);


    //GPIO Port 5
    GPIO_setAsOutputPin(GPIO_PORT_P5,GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setOutputHighOnPin(GPIO_PORT_P5,GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);

    //GPIO Port 6
    GPIO_setAsOutputPin(GPIO_PORT_P6,GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN7);

    GPIO_setOutputHighOnPin(GPIO_PORT_P6,GPIO_PIN4|GPIO_PIN5|GPIO_PIN6);


    //GPIO Port 7
    GPIO_setAsOutputPin(GPIO_PORT_P7,GPIO_PIN0);
    GPIO_setOutputHighOnPin(GPIO_PORT_P7,GPIO_PIN0);

    //GPIO Port J
    GPIO_setAsInputPinWithPullDownResistor(GPIO_PORT_PJ, GPIO_PIN3); //[EVM to disable LED2]
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_PJ, GPIO_PIN4 + GPIO_PIN5, GPIO_PRIMARY_MODULE_FUNCTION);  /* Configure LFXT GPIO pins */
    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_PJ, GPIO_PIN6, GPIO_TERNARY_MODULE_FUNCTION); // Enable monitoring of USSXT_BOUT via PJ.6 pin
    GPIO_setAsOutputPin(GPIO_PORT_PJ,GPIO_PIN7); //PJ.7


    GPIO_setAsInputPinWithPullDownResistor(GPIO_PORT_P3, GPIO_PIN4);
    GPIO_enableInterrupt(GPIO_PORT_P3, GPIO_PIN4);
    GPIO_selectInterruptEdge(GPIO_PORT_P3, GPIO_PIN4, GPIO_LOW_TO_HIGH_TRANSITION);
    GPIO_clearInterrupt(GPIO_PORT_P3, GPIO_PIN4);

    PM5CTL0 &= ~LOCKLPM5;

}

void adcRefVoltageSetup()
{
    if(Ref_A_isRefGenBusy(REF_A_BASE))
    Ref_A_disableTempSensor(REF_A_BASE);
    else
        _NOP();

    // Configure internal reference
    while (REFCTL0 & REFGENBUSY);            // If ref generator busy, WAIT

    REFCTL0 |= REFVSEL_1 | REFON;           // Select internal ref = 2.0V // Internal Reference ON

    while (!(REFCTL0 & REFGENRDY));          // Wait for reference generator
                                             // to settle

    //Delay (~75us) for Ref to settle
    __delay_cycles(75);

}

void adcSetup()
{
    /***** adc hw setup ******/
    adc_init.clockSourceSelect = ADC12_B_CLOCKSOURCE_ACLK;
    adc_init.clockSourceDivider = ADC12_B_CLOCKDIVIDER_1;
    adc_init.clockSourcePredivider = ADC12_B_CLOCKPREDIVIDER__1;
    adc_init.internalChannelMap = ADC12_B_NOINTCH;
    adc_init.sampleHoldSignalSourceSelect = ADC12_B_SAMPLEHOLDSOURCE_SC;

    /*****  sc bat channel A8 setup ******/
    memory_init1.memoryBufferControlIndex = ADC12_B_MEMORY_0;
    memory_init1.inputSourceSelect = ADC12_B_INPUT_A8;
    memory_init1.refVoltageSourceSelect = ADC12_B_VREFPOS_INTBUF_VREFNEG_VSS;
    memory_init1.endOfSequence = ADC12_B_NOTENDOFSEQUENCE;
    memory_init1.windowComparatorSelect = ADC12_B_WINDOW_COMPARATOR_DISABLE;
    memory_init1.differentialModeSelect = ADC12_B_DIFFERENTIAL_MODE_DISABLE;

    /***** bat inv channel A14 setup ******/
    memory_init2.memoryBufferControlIndex = ADC12_B_MEMORY_1;
    memory_init2.inputSourceSelect = ADC12_B_INPUT_A14;
    memory_init2.refVoltageSourceSelect = ADC12_B_VREFPOS_INTBUF_VREFNEG_VSS;
    memory_init2.endOfSequence = ADC12_B_ENDOFSEQUENCE;
    memory_init2.windowComparatorSelect = ADC12_B_WINDOW_COMPARATOR_DISABLE;
    memory_init2.differentialModeSelect = ADC12_B_DIFFERENTIAL_MODE_DISABLE;

    /***** adc initialization ******/
    ADC12_B_init(ADC12_B_BASE, &adc_init);

    /***** adc sampling timer ******/
    ADC12_B_setupSamplingTimer(ADC12_B_BASE, ADC12_B_CYCLEHOLD_32_CYCLES,
                               ADC12_B_CYCLEHOLD_4_CYCLES,
                               ADC12_B_MULTIPLESAMPLESENABLE);

    /***** configuring Memory 0 ******/
    ADC12_B_configureMemory(ADC12_B_BASE, &memory_init1);

    /***** configuring Memory 1 ******/
    ADC12_B_configureMemory(ADC12_B_BASE, &memory_init2);

    /***** clear adc interrupt ******/
    ADC12_B_clearInterrupt(ADC12_B_BASE, 0, ADC12_B_IFG1);

    /***** enable adc interrupt on memory 1 ******/
    ADC12_B_enableInterrupt(ADC12_B_BASE, ADC12_B_IE1, 0, 0);

    /***** enable adc ******/
    ADC12_B_enable(ADC12_B_BASE);

    /***** start conversion ******/
    ADC12_B_startConversion(ADC12_B_BASE, ADC12_B_START_AT_ADC12MEM0,
                            ADC12_B_SEQOFCHANNELS);
}

void timerSetup()
{
    TA0CCTL0 = CCIE;                              // TACCR0 interrupt enabled
    TA0CTL = TASSEL__ACLK |ID__2| MC__UP;        // SMCLK, UP mode
    TA0CCR0 = 16000;  //164 = 10ms
}

void readADCData()
{
    tempSCBat=ADC12MEM0;
    tempVbat=ADC12MEM1;
    scbatRaw=(float) ((0.001 * tempSCBat) - 0.0026);
    vbatRaw=((0.0039*tempVbat)-0.0963);
}

void clockSetup()
{
    // Unlock CS registers
    CSCTL0_H = CSKEY >> 8;
    // Set DCO to 8MHz
    CSCTL1 = DCORSEL | DCOFSEL_3;
    // Configure clock dividers all dividers
    CSCTL3 = (DIVA__1 | DIVS__1 | DIVM__1);

    // Set SMCLK = MCLK = DCO, ACLK = LFXTCLK
    CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK;
    CSCTL4 |= (LFXTDRIVE_3);
    CSCTL4 &= ~(LFXTOFF);
    CSCTL0_H = 0;

    PJSEL0 |= BIT4 | BIT5;
    PM5CTL0 &= ~LOCKLPM5;
}

int main(void) {

    WDT_A_hold(WDT_A_BASE);

    clockSetup();
    gpioSetup();
    adcRefVoltageSetup();
    timerSetup();
    adcSetup();
    __bis_SR_register(LPM3_bits | GIE);

    return (0);
}


#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer0_A0_ISR (void){

    secCount=secCount+1;
    readADCData();

    if(secCount>5)
    {
        /**** enable adc *****/
        ADC12_B_enable(ADC12_B_BASE);

        /**** start conversion *****/
        ADC12_B_startConversion(ADC12_B_BASE, ADC12_B_START_AT_ADC12MEM0,
                                ADC12_B_SEQOFCHANNELS);
        secCount=0;
    }
}

//ADC12 interrupt service routine
#pragma vector=ADC12_B_VECTOR
__interrupt void ADC12ISR (void)
{
    ADC12_B_disable(ADC12_B_BASE);

    /***** clear adc interrupt ******/
    ADC12_B_clearInterrupt(ADC12_B_BASE, 0, ADC12_B_IFG1);
}

此致、

Sarwath

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

    您好、Sarwath、您在这里的目标功耗是多少、您轮询 ADC 的频率如何?

    -Brian

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

    尊敬的 Brian Dempsey:

    我们希望达到小于或等于75uA。 在10ms 计时器 ISR 中、我将读取 ADC 结果。

    此致、

    Sarwath

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

    什么10ms 计时器 ISR? 我看到的是一个计时器、设置为在 ACLK/2上运行、计数为16,000。 也约为每秒一次。 甚至会在触发 ADC 之前再次分频。 过量电流不会来自 ADC。

    第一步是通过简化代码来找出原因。 剥离定时器和 ADC 设置 、直接进入 LPM3。 然后找出问题

    我还看到了使用 ACLK 的 ADC 设置。 如果您可以接受降低的功率(多少?)、这可能是可以的 运行速度极慢、影响准确度。

    此外、ADC 电流数据没有显示电流中的时钟频率之间存在严格比例关系。 它很可能平均需要较少的电流从更快的时钟运行。 因为它完成速度更快且花费更多时间处于非活动状态。

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

    尊敬的 David Schultz:  

    在提供的代码中、我创建了一个1秒的 TimerA ISR 来启动 ADC 转换。 在此代码中、电路板仅消耗160 µA。

    在 LPM 模式下、我将所有外设时钟设置为 ACLK、以优化电流。

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

    尊敬的 David Schultz:

    我的任何更新。

    提前感谢、

    Sarwath

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

    没有。 但是、还有一次:

    剥离代码中的所有计时器和 ADC 材料。 只需进入 LPM3。 测量所需的电流。 约为1uA? 很好。

    添加到 ADC 代码中、看看效果会怎样。