Part Number: MSP430FR6043
Tool/software:
Hello,
I want to configure the ADC12_B and REF_A module based on the power state.
| Power Source | ADC Behavior |
|---|---|
| Internal Battery | ADC12_B and REF_A is triggered once every 1 second, then turned off in the ISR to save power. |
| External Supply | ADC12_B and REF_A is reconfigured to run in repeated sequence mode for continuous conversion. |
Internal Battery Mode configuration:
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);
}
External power mode configuration:
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);
}
In internal battery mode, the ADC ISR is enabled. At each ISR trigger, I turn off both the ADC12_B and REF_A modules. They are re-enabled after a 1-second timeout.
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
}
In external supply mode, both modules are reconfigured and run continuously without the ADC ISR. Could anyone confirm if my implementation is correct?
To reduce power consumption I made this setup.
Regards,
Sakhan