Also, you are doing some monster math with all those multiplies and
divides:
>> DegC = ((((long)ADCresult-1615)*704)/4095);
>> DegF = ((DegC * 9/5)+32);
I don't know if your selected MSP430 device has a hardware multiplier
or not, but if not, that is a lot of code execution to complete those
temperature conversions (more runtime = less low power mode).
If you have lots of free flash space, you may want to consider using
a look-up table for the most common temperature ranges and saving the
hard math for temperatures outside of your expected range. Or just
build everything into a table, but that would be 4K for a 12-bit ADC
value range.
<...short pause for some quick math...>
Okay, it looks like for every incremental increase in the ADC12
reading (for example, reading 2000d versus 2001d), the temperature
resolution would be 0.1719 degrees C (66.1880C vs. 66.3599C). Since
the decimal values get lopped off anyway, you could easily shift your
12-bit readings down to, say, 10 bit by throwing away the lowest two
bits and still maintain a Celcius resolution of 0.687 degrees C.
That makes your entire Celius lookup table only 1KBytes in size.
Create a Fahrenheit table of like size (1KBytes) and you have a
decreased your execution time by several factors. You just need to
use a spreadsheet or simple C/Basic/Perl/your-favorite-language
program to pre-generate the values from your equations and load them
as a header file into your source code at compile time.
Just my $0.02 worth; Hope it helps.
--- In m..., "old_cow_yellow"
wrote:
>
> I think your TimerA0 isr is faulty. You should have moved most of
that
> to the while(1) loop in main after "_BIS_SR(LPM3_bits
+ GIE);".
>
> "for (i = 0; i < 0x3600; i++);" wasts energy.
>
> "__bis_SR_register(LPM0_bits);" will not make your TimerA0 isr
enter LPM0.
>
> Nesting the ADC12 interrupt inside TimerA0 interrupt is unnecessary
> and incorrectly done.
>
> Calling library routines inside isr may cause problems too.
>
> --- In m..., "emil.marinov" wrote:
> >
> > Hi~
> >
> > I am doing some testing with the MSP430FG461x processor right now
in
> > an attempt to get the current consumption under 100
microamperes.
> > The program uses the ADC to obtain temperature,
then display it
onto
> > the LCD. Whenever I measure the current on the
board, it shows
up as
> > lower 500 to upper 600 microamps. This is sounding
an alarm in
my
> > head because 1) while not interrupting, the current
should be
MUCH
> > lower than that (I measured it at 9 microamps
before adding the
ADC
> > part) 2)I was told by someone else who's
worked with this
> > microprocessor before that for a program like this, the current
> > consumption should stay under 100 microamps. I've pasted the
code
> > below.
> >
> >
> >
> >
> >
> >
> > #include
> > #include
> > #include "msp430xG46x.h"
> > #include
> > #include "string.h"
> > #include
> >
> >
> > volatile unsigned int i,k;
> > volatile unsigned int ADCresult;
> > volatile unsigned long int DegC, DegF;
> > int stringLength;
> > char displayBuffer[10];
> >
> > void ReverseArray(char*orig,unsigned short int b);
> > //----------------------------
----
> > ---------
> > void main(void)
> > {
> > WDTCTL = WDTPW + WDTHOLD; // Stop WDT
> >
> >
> > P1DIR = (0xff & ~(BIT0+BIT1)); // P1.0, P1.1 input, others
output
> > P1OUT = 0;
> > P2DIR = (0xff & ~BIT5); // P2.5 must be input
> > P2OUT = 0;
> > P3DIR = (0xff & ~BIT5); // P3.5 must be high
> > P3OUT = (BIT1 + BIT2); // '2013 could possibly tied these high
> > P4DIR = 0xff;
> > P4OUT = 0;
> > P5DIR = 0xff;
> > P5OUT = 0;
> > P6DIR = 0xff;
> > P6OUT = 0;
> > P7DIR = 0xff;
> > P7OUT = 0;
> > P8DIR = 0xff;
> > P8OUT = 0;
> > P9DIR = 0xff;
> > P9OUT = 0;
> > P10DIR = 0xff;
> > P10OUT = 0;
> >
> >
> > FLL_CTL0 |= XCAP14PF; // Configure load caps
> > TACTL = TASSEL_1 + TACLR; // Clock = ACLK
(32768),
> > clear
> > TACCTL0 = CCIE; // CCR0 interrupt
enabled
> > TACCR0 = 32768-1; //
#counts for 1s
> > TACTL |= MC_1; // Setting mode bits
> > starts timer
> > while(1)
> > {_BIS_SR(LPM3_bits + GIE);} // Enter LPM3
> > }
> > //----------------------------
----
> > ---------
> > // Timer A0 interrupt service routine
> > #pragma vector=TIMERA0_VECTOR
> > __interrupt void Timer_A (void)
> > {
> > initLCD_A();
> > dispChar(15,0);
> >
> > ADC12CTL0 = ADC12ON + REFON + REF2_5V + SHT0_7;
> > // Turn ADC,ref on. Ref = 2.5V,
> > sampling time
> > ADC12CTL1 = SHP; // Use sampling timer
> > ADC12MCTL0 = INCH_10 + SREF_1; // Select channel
A10,
> > Vref+
> > ADC12IE = 0x01; // Enable ADC12IFG.0
> > for (i = 0; i < 0x3600; i++); // Delay for
reference
> > start-up
> > ADC12CTL0 |= ENC; // Enable conversions
> > __enable_interrupt(); // Enable interrupts
> >
> >
> > ADC12CTL0 |= ADC12SC; // Start conversion
> > __bis_SR_register(LPM0_bits); // Enter LPM0
> >
> > // DegC = (Vsensor - 986mV)/3.55mV
> > // Vsensor = (Vref)(ADCresult)/4095)
> > // DegC -> ((ADCresult - 1615)*704)/4095
> > __no_operation(); // SET BREAKPOINT
> >
> > sprintf(displayBuffer,"%ld",DegF);
> > stringLength = strlen(displayBuffer);
> > ReverseArray(displayBuffer,stringLength);
> > for(i=0;i
> > {dispChar(displayBuffer[i]-0x30, i+1);}
> >
> >
> > }
> > //----------------------------
----
> > ---------
> > #pragma vectorC12_VECTOR
> > __interrupt void ADC12ISR(void)
> > {
> > ADCresult = ADC12MEM0; // Move results, IFG
is
> > cleared
> > DegC = ((((long)ADCresult-1615)*704)/4095);
> > DegF = ((DegC * 9/5)+32); // Calculate DegF
> > __no_operation(); // SET BREAKPOINT
> >
> >
> > __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
> > }
> > //----------------------------
----
> > ---------
> > void ReverseArray(char*orig,unsigned short int b)
> > {
> > unsigned short int a;
> > int swap;
> >
> > for(a=0;a<--b;a++) //increment a and decrement b until they
meet
> > eachother
> > {
> > swap=orig[a]; //put what's in a into swap space
> > orig[a]=orig[b]; //put what's in b into a
> > orig[b]=swap; //put what's in the swap (a) into b
> > }
> >
> > }
>