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:ADC12_B 和 REF_A 配置

Guru**** 2448780 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1501270/msp430fr6043-adc12_b-and-ref_a-configuration

器件型号:MSP430FR6043

工具/软件:

您好:

我要根据电源状态配置 ADC12_B 和 REF_A 模块。

供电方 ADC 行为
内部电池 触发 ADC12_B 和 REF_A 1Mb/s 的数据速率 、然后 关闭 ISR 寄存器、以节省功耗。
外部电源 ADC12_B 和 REF_A 被重新配置为在中运行 返回电流 的工作模式 连续转换

内部电池模式配置:

void ADC_initInternalMode()
{
    ADC12_B_disableConversions(ADC12_B_BASE, ADC12_B_PREEMPTCONVERSION);
    ADC12_B_disable(ADC12_B_BASE);

    // Disable reference and wait for it to be free
    REFCTL0 &= ~REFON;
    while (REFCTL0 & REFGENBUSY);
    REFCTL0 |= REFVSEL_1 | REFON; // 2.0V internal ref
    while (!(REFCTL0 & REFGENRDY));
    __delay_cycles(75); // Allow settling time

    // ADC hardware 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;

    // Configure channels: Battery (A8), Valve (A9), External (A14)
    // Memory buffer setup (0 to 2)
    // End-of-sequence marked on last channel

    memory_init1 = (ADC12_B_configureMemoryParam){
        .memoryBufferControlIndex = ADC12_B_MEMORY_0,
        .inputSourceSelect = ADC12_B_INPUT_A8,
        .refVoltageSourceSelect = ADC12_B_VREFPOS_INTBUF_VREFNEG_VSS,
        .endOfSequence = ADC12_B_NOTENDOFSEQUENCE
    };

    memory_init2 = (ADC12_B_configureMemoryParam){
        .memoryBufferControlIndex = ADC12_B_MEMORY_1,
        .inputSourceSelect = ADC12_B_INPUT_A9,
        .refVoltageSourceSelect = ADC12_B_VREFPOS_INTBUF_VREFNEG_VSS,
        .endOfSequence = ADC12_B_NOTENDOFSEQUENCE
    };

    memory_init3 = (ADC12_B_configureMemoryParam){
        .memoryBufferControlIndex = ADC12_B_MEMORY_2,
        .inputSourceSelect = ADC12_B_INPUT_A14,
        .refVoltageSourceSelect = ADC12_B_VREFPOS_INTBUF_VREFNEG_VSS,
        .endOfSequence = ADC12_B_ENDOFSEQUENCE
    };

    ADC12_B_init(ADC12_B_BASE, &adc_init);
    ADC12_B_setupSamplingTimer(ADC12_B_BASE, ADC12_B_CYCLEHOLD_32_CYCLES,
                               ADC12_B_CYCLEHOLD_4_CYCLES,
                               ADC12_B_MULTIPLESAMPLESENABLE);
    ADC12_B_configureMemory(ADC12_B_BASE, &memory_init1);
    ADC12_B_configureMemory(ADC12_B_BASE, &memory_init2);
    ADC12_B_configureMemory(ADC12_B_BASE, &memory_init3);

    ADC12_B_clearInterrupt(ADC12_B_BASE, 0, ADC12_B_IFG2);
    ADC12_B_enableInterrupt(ADC12_B_BASE, ADC12_B_IE2, 0, 0);
    ADC12_B_enable(ADC12_B_BASE);
    ADC12_B_startConversion(ADC12_B_BASE, ADC12_B_START_AT_ADC12MEM0, ADC12_B_SEQOFCHANNELS);
}

外部电源模式配置:

void ADC_initExternalMode()
{
    ADC12_B_disableConversions(ADC12_B_BASE, ADC12_B_PREEMPTCONVERSION);
    ADC12_B_disable(ADC12_B_BASE);

    REFCTL0 &= ~REFON;
    while (REFCTL0 & REFGENBUSY);
    REFCTL0 |= REFVSEL_1 | REFON;
    while (!(REFCTL0 & REFGENRDY));
    __delay_cycles(75);

    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;

    // Same memory configuration as internal mode
    ADC12_B_init(ADC12_B_BASE, &adc_init);
    ADC12_B_setupSamplingTimer(ADC12_B_BASE, ADC12_B_CYCLEHOLD_32_CYCLES,
                               ADC12_B_CYCLEHOLD_4_CYCLES,
                               ADC12_B_MULTIPLESAMPLESENABLE);
    ADC12_B_configureMemory(ADC12_B_BASE, &memory_init1);
    ADC12_B_configureMemory(ADC12_B_BASE, &memory_init2);
    ADC12_B_configureMemory(ADC12_B_BASE, &memory_init3);

    ADC12_B_clearInterrupt(ADC12_B_BASE, 0, ADC12_B_IFG2);
    ADC12_B_disableInterrupt(ADC12_B_BASE, ADC12_B_IE2, 0, 0);
    ADC12_B_enable(ADC12_B_BASE);
    ADC12_B_startConversion(ADC12_B_BASE, ADC12_B_START_AT_ADC12MEM0, ADC12_B_REPEATED_SEQOFCHANNELS);
}

 

在内部电池模式下、会启用 ADC ISR。 在每次 ISR 触发时、我都会关闭 ADC12_B 和 REF_A 模块。 在1秒超时后将重新启用这些选项。

void ADC_Handler()
{
// ADC handler running in 10ms timer loop
   if(PowerstateSwitch == "Internal")
   {
   //ADC_UPDATE_DURATION is 1000
       if (ADC_capture_enable_counter >= ADC_UPDATE_DURATION) {
           Ref_A_enableReferenceVoltage(REF_A_BASE);
           if(Ref_A_isRefGenActive(REF_A_BASE))
           {
               ADC12_B_enable(ADC12_B_BASE);
               ADC12_B_startConversion(ADC12_B_BASE, ADC12_B_START_AT_ADC12MEM0, ADC12_B_SEQOFCHANNELS);
               ADC_capture_enable_counter = 0;
           }
           ADC_DataRead();
       } else {
           ADC_capture_enable_counter += 10;
       }
   }
   else
   {
       ADC_DataRead();
   }
}

#pragma vector=ADC12_B_VECTOR
__interrupt void ADC12ISR(void)
{
    if (PowerstateSwitch == false) // internal supply
    {
        ADC12_B_disable(ADC12_B_BASE); // Save power
        Ref_A_disableReferenceVoltage(REF_A_BASE); // Save more power
    }

    ADC12_B_clearInterrupt(ADC12_B_BASE, 0, ADC12_B_IFG2);
    ADC_DataRead(); // Read the latest values
}

在外部供电模式下、这两个模块都会重新配置并持续运行、无需 ADC ISR。 有人能确认我的实施是否正确吗?

为了降低功耗、我进行了此设置。

此致、

Sakhan

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

    > Ref_a_enableReferenceVoltage (REF_A_BASE);
    > IF (Ref_a_isRefGenActive (REF_A_BASE)))

    这似乎是期望 REF 立即准备就绪、我预计这不会是真的。 我认为您需要的函数是"ref_a_isVariableReferenceVoltageOutputReady (REF_A_BASE)// REFGENRDY?"、它应该处于类似于"init"函数中的循环中。

    除此之外、我没有看到任何明显的错误。  

    -----

    未经请求:您可能需要 查看 用户指南(SLAU367P)第34.2.4节("自动断电")、因为 ADC+REF 可以为您完成大部分此工作。

    如果 REF 由其中一个 VRSEL-s 使用、则基准会自动开启、然后在转换后关闭;对于突发/连续采样(ADC12_B_MULTIPLESAMPLESENABLE)、基准会在突发中保持开启状态。 "成本"是第一次转换必须等待 REF 启动(典型值为40usec)、但在1sps 时、我认为您不会注意到这一点。

    [编辑:轻微澄清]

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

    尊敬的 Sakan:

    同意 Bruce 的建议。

    我要说明的一点是、ADC 处理程序是如何触发的? 如果未启用 ADC 模块、我认为 ADC ISR 不会进入。

    B.R.

    Sal

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

    您好 Bruce、

    感谢您的答复。

    根据您的建议、我对 ADC 处理程序进行了更改。

    如果(ADC_CAPTURE_ENABLE_COUNTER >= ADC_UPDATE_DURATION){
    REF_A_enableReferenceVoltage (REF_A_BASE);
    if (Ref_a_isVariableReferenceVoltageOutputReady (REF_A_BASE)))


    }
     否则{
    }

    此致、

    Sakhan

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

    尊敬的 Sal Ye:

    在10ms 计时器环路中、ADC 处理程序持续运行。  

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

    尊敬的 Sakan:

    看起来不错。

    至于代码、我建议您使用 while 循环来轮询 VREF 状态并等待它准备就绪。

    B.R.

    Sal