EmbeddedRelated.com
Forums

strange ADC12 problems

Started by Rolf F. February 26, 2004
Hi,

i have two strange problems with the ADC12 in the MSP430F149:

- When i set MCLK = SMCLK = ACLK = LFXT1 (2768 Hz ) with BCSCTL2 SELM1 + SELM0;
i get a hangup independent from the ADC12 core clock 
(tested with ACLK and ADC12OSC). With switched of ADC12 the low cpu 
clock is no problem.

- Setting ADC12IFG = 0 at the end of the ADC12 ISR does not clear the 
interrupt flags; i get approx. 14.000 ADC12 irqs per second!
   When i set
   volatile unsigned int trash = ADC12IV + ADC12MEM0 + ... + ADC12MEM15;
   the interrupt flags are cleared and i do get the usual 721  ADC12 
irqs per second.

I'm using IAR 1.26 and a repeated sequence of channels mode which works 
fine with internal temperature measurement and others.
What might be the reasons of these strange bugs?

Regards

Rolf F.



Beginning Microcontrollers with the MSP430

Rolf F. wrote:

> Hi,
> 
> i have two strange problems with the ADC12 in the MSP430F149:
> 
> - When i set MCLK = SMCLK = ACLK = LFXT1 (2768 Hz ) with BCSCTL2 > SELM1
+ SELM0; 

Lets examine this first.

BSCTL2 = SELM0+SEM1 sets MCLK = LFXT1CLK
DIVMx = 0 so MCLK = /1
ACLK = LFXT1CLK by default
SELS = 0 so SMCLK = DCO
DIVSx = 0 so SMCLK = DCO/1
DCOR = internal resistor.

Your first statement is wrong. You haven't shown any of the settings for 
ADC12 either


i get a hangup independent from the ADC12 core clock
> (tested with ACLK and ADC12OSC). With switched of
ADC12 the low cpu 
> clock is no problem.
> 
> - Setting ADC12IFG = 0 at the end of the ADC12 ISR does not clear the 
> interrupt flags; i get approx. 14.000 ADC12 irqs per second!

All to do with slow MCLK vs fast ADC clock I suggest. If you select ACLK 
as the source for ADC12CLk then you have  avery slow ADC clock that may 
(since we can't see your ADC config) be specifiying values that become 
illegal, ie conversion times too long, on the other hand ADC12OSC is 
nominally 5MHz, if you used this with high speed convrsion settings you 
could be converting faster than the slow MCLK can handle.

>    When i set
>    volatile unsigned int trash = ADC12IV + ADC12MEM0 + ... + ADC12MEM15;
>    the interrupt flags are cleared and i do get the usual 721  ADC12 
> irqs per second.

What is usual? This statement suggests that you have set up your sample 
and conversion rates as if the ADC12CLk was derived from MCLK, when it 
doesn't appear to be (although you haven;'t given the ADC config) This

precisely explains the behaviour of the above. While your slow MCLK is 
clearing adc12IFG other interrupts are occuring, and ADC12IV is set, you 
have effectively cleared all of the pending ints through the back door.

Cheers

Al

> 
> I'm using IAR 1.26 and a repeated sequence of channels mode which
works 
> fine with internal temperature measurement and others.
> What might be the reasons of these strange bugs?
> 
> Regards
> 
> Rolf F.



Hi,

> SELS = 0 so SMCLK = DCO

thanks, that's the bug because the MSP430F149 is a three oszillator 
system (although with the ADC12OSC it has four oscillators) and 
therefore only DCOCLK or XT2CLK and not XT1CLK can be selected.


> If you select ACLK
> as the source for ADC12CLk then you have avery slow ADC clock that may
> (since we can't see your ADC config) be specifiying values that become
> illegal, ie conversion times too long, on the other hand ADC12OSC is
> nominally 5MHz, if you used this with high speed convrsion settings you
> could be converting faster than the slow MCLK can handle.

That must be the reason.


>> When i set
>> volatile unsigned int trash = ADC12IV + ADC12MEM0 + ... + ADC12MEM15;
>> the interrupt flags are cleared and i do get the usual 721 ADC12
>> irqs per second.
>
>
> What is usual? This statement suggests that you have set up your sample
> and conversion rates as if the ADC12CLk was derived from MCLK, when it
> doesn't appear to be (although you haven;'t given the ADC config)
This
> precisely explains the behaviour of the above. While your slow MCLK is
> clearing adc12IFG other interrupts are occuring, and ADC12IV is set, you
> have effectively cleared all of the pending ints through the back door.


That can't be the reason because with


  WDTCTL = WDTPW + WDTHOLD;     // Stop watchdog timer
  BCSCTL1 = 0x87;               // ACLK = LFXT1CTL, divide by 1, lowest 
nominal frequency, lf oscillator, oscillator on, XT2OFF
  WDTCTL = 0x5a1f;              //  WD as Timer, 512 Hz
  TBCTL = 0x0256;
  TBCCR0 = 41430;
  TBCCTL0 = 0x0080;
  //ADC12                       // Sample rate approx 1.56 ms
  ADC12CTL0 &= ~0x0002;         // Clear ENC (Stop ADC12)
  ADC12CTL0 = 0x00b0;           // ADC12 On, REF=1.5V On, Multiple Conv 
On, Tsample=4xADC12CLK,
  ADC12CTL1 = 0x0a0e;           // Repeat sequence of channel mode, 
ACLK, Div by 1, TimerB.Out0
  ADC12MCTL0 = 0x10;            // Channel=0 (Hand puls sample 1), 
Vref=Vref+/AVss
  ADC12MCTL1 = 10 + SREF_1;     // temperature diode, first reference 
voltage
  ADC12MCTL2 = 10 + SREF_1;
  ADC12MCTL3 = 0x10;
  ADC12MCTL4 = 10 + SREF_1;
  ADC12MCTL5 = 10 + SREF_1;
  ADC12MCTL6 = 0x10;
  ADC12MCTL7 = 10 + SREF_1;
  ADC12MCTL8 = 10 + SREF_1;
  ADC12MCTL9 = 0x10;
  ADC12MCTL10 = 10 + SREF_1;
  ADC12MCTL11 = 0x80 + 10 + SREF_1;     // end of cyle ( ADC12MCTL12..15 
unused)
  ADC12IE = 0x0fb6;             // ADC12 memory 1,2,4,5,7,8,9,10,11 
interrupts enable (period 6.23 ms)
  // = Enable Temperature (Chest Puls) IRQs
  ADC12CTL0 |= 0x0002;          // Set ENC (Start ADC12)

#ifndef QuArTz
  BCSCTL1 |= 0x07;              // set RSEL for highest possible DCO 
frequency
  BCSCTL2 = SELM0;              // 0x00 or SELM0: divide by 1 for SMCLK 
and MCLK, internal resistor on for failsafe mode, source DCOCLK.
  DCOCTL = 0xff;                // highest possible frequency with 
highest 3 bits set
#else
  BCSCTL1 &= ~XT2OFF;           // XT2on
  do                            // wait for MCLK from quartz
  {
    volatile unsigned char foo;
    IFG1 &= ~OFIFG;             // Clear OSCFault flag
    for (foo=0xff; foo; foo--);                // Time for flag to set
  }
  while (IFG1 & OFIFG);         // OSCFault flag still set?
  BCSCTL2 = SELM1 + SELS;       // LFXT2: use HF quartz (XT2), internal 
resistor on, divide by one, MCLK = SMCLK = XT2 (safe)
  DCOCTL = 0xe0;
#endif


i get 14 kHz (instead of 721 Hz) ADC12-irqs without trash= ...  int 
ADC12-ISR or reading the data register associated with the ADC12-IRQ.
The software works good with measuring temperature and analog voltages 
but for tests i took the software and set ADC12IFG=0 in the ADC12-ISR 
because i don't neet the ADC values. But that's not enough for
clearing 
the ADC12-irqs and i don't know why.

Regards

Rolf F.



Rolf F. wrote:

> Hi,
> 
> 
>>SELS = 0 so SMCLK = DCO
> 
> 
> thanks, that's the bug because the MSP430F149 is a three oszillator 
> system (although with the ADC12OSC it has four oscillators) and 
> therefore only DCOCLK or XT2CLK and not XT1CLK can be selected.

Glad to help, there were a few possibilities, so I gave all I could 
think of.

> 
> 
> 
>>If you select ACLK
>>as the source for ADC12CLk then you have avery slow ADC clock that may
>>(since we can't see your ADC config) be specifiying values that
become
>>illegal, ie conversion times too long, on the other hand ADC12OSC is
>>nominally 5MHz, if you used this with high speed convrsion settings you
>>could be converting faster than the slow MCLK can handle.
> 
> 
> That must be the reason.
> 
> 
> 
>>>When i set
>>>volatile unsigned int trash = ADC12IV + ADC12MEM0 + ... +
ADC12MEM15;
>>>the interrupt flags are cleared and i do get the usual 721 ADC12
>>>irqs per second.
>>
>>
>>What is usual? This statement suggests that you have set up your sample
>>and conversion rates as if the ADC12CLk was derived from MCLK, when it
>>doesn't appear to be (although you haven;'t given the ADC
config) This
>>precisely explains the behaviour of the above. While your slow MCLK is
>>clearing adc12IFG other interrupts are occuring, and ADC12IV is set, you
>>have effectively cleared all of the pending ints through the back door.
> 
> 
> 
> That can't be the reason because with

Ah but I never saw this code, hence my suggestions were based on the 
little data I had. It looks like SMCLK is still DCO, that Timer B is 
derved from SMCLK /2, and that you still have a timing problem. Even 
without the divides, TB is meant to start a sequence of conversions, 
hence 41430 x your nominal conversion rate of 721/sec gives oscillator 
speed, and 41430 x 721 = 29,871,030, faster even than I've clocked an 
MSP. You are also only allowing 4 clocks to sample the signal. To get 
the most out of the in built ADC requires a very fine balance between 
adequate sample time/ conversion rate, and the ability of the CPU clock 
to process the data.

Cheers

Al

> 
> 
>   WDTCTL = WDTPW + WDTHOLD;     // Stop watchdog timer
>   BCSCTL1 = 0x87;               // ACLK = LFXT1CTL, divide by 1, lowest 
> nominal frequency, lf oscillator, oscillator on, XT2OFF
>   WDTCTL = 0x5a1f;              //  WD as Timer, 512 Hz
>   TBCTL = 0x0256;
>   TBCCR0 = 41430;
>   TBCCTL0 = 0x0080;
>   //ADC12                       // Sample rate approx 1.56 ms
>   ADC12CTL0 &= ~0x0002;         // Clear ENC (Stop ADC12)
>   ADC12CTL0 = 0x00b0;           // ADC12 On, REF=1.5V On, Multiple Conv 
> On, Tsample=4xADC12CLK,
>   ADC12CTL1 = 0x0a0e;           // Repeat sequence of channel mode, 
> ACLK, Div by 1, TimerB.Out0
>   ADC12MCTL0 = 0x10;            // Channel=0 (Hand puls sample 1), 
> Vref=Vref+/AVss
>   ADC12MCTL1 = 10 + SREF_1;     // temperature diode, first reference 
> voltage
>   ADC12MCTL2 = 10 + SREF_1;
>   ADC12MCTL3 = 0x10;
>   ADC12MCTL4 = 10 + SREF_1;
>   ADC12MCTL5 = 10 + SREF_1;
>   ADC12MCTL6 = 0x10;
>   ADC12MCTL7 = 10 + SREF_1;
>   ADC12MCTL8 = 10 + SREF_1;
>   ADC12MCTL9 = 0x10;
>   ADC12MCTL10 = 10 + SREF_1;
>   ADC12MCTL11 = 0x80 + 10 + SREF_1;     // end of cyle ( ADC12MCTL12..15 
> unused)
>   ADC12IE = 0x0fb6;             // ADC12 memory 1,2,4,5,7,8,9,10,11 
> interrupts enable (period 6.23 ms)
>   // = Enable Temperature (Chest Puls) IRQs
>   ADC12CTL0 |= 0x0002;          // Set ENC (Start ADC12)
> 
> #ifndef QuArTz
>   BCSCTL1 |= 0x07;              // set RSEL for highest possible DCO 
> frequency
>   BCSCTL2 = SELM0;              // 0x00 or SELM0: divide by 1 for SMCLK 
> and MCLK, internal resistor on for failsafe mode, source DCOCLK.
>   DCOCTL = 0xff;                // highest possible frequency with 
> highest 3 bits set
> #else
>   BCSCTL1 &= ~XT2OFF;           // XT2on
>   do                            // wait for MCLK from quartz
>   {
>     volatile unsigned char foo;
>     IFG1 &= ~OFIFG;             // Clear OSCFault flag
>     for (foo=0xff; foo; foo--);                // Time for flag to set
>   }
>   while (IFG1 & OFIFG);         // OSCFault flag still set?
>   BCSCTL2 = SELM1 + SELS;       // LFXT2: use HF quartz (XT2), internal 
> resistor on, divide by one, MCLK = SMCLK = XT2 (safe)
>   DCOCTL = 0xe0;
> #endif
> 
> 
> i get 14 kHz (instead of 721 Hz) ADC12-irqs without trash= ...  int 
> ADC12-ISR or reading the data register associated with the ADC12-IRQ.
> The software works good with measuring temperature and analog voltages 
> but for tests i took the software and set ADC12IFG=0 in the ADC12-ISR 
> because i don't neet the ADC values. But that's not enough for
clearing 
> the ADC12-irqs and i don't know why.
> 
> Regards
> 
> Rolf F.
> 
> 
> 
> 
> .
> 
>  
> Yahoo! Groups Links
> 
> 
> 
>  
> 
> 


Hi,

>Ah but I never saw this code, hence my suggestions
were based on the
>little data I had. It looks like SMCLK is still DCO, that Timer B is
>derved from SMCLK /2, and that you still have a timing problem. Even
>without the divides, TB is meant to start a sequence of conversions,
>hence 41430 x your nominal conversion rate of 721/sec gives oscillator
>speed, and 41430 x 721 = 29,871,030, faster even than I've clocked an
>MSP. You are also only allowing 4 clocks to sample the signal. To get
>the most out of the in built ADC requires a very fine balance between
>adequate sample time/ conversion rate, and the ability of the CPU clock
>to process the data.

With the DCO at maximum frequency the 41430 give a frequency of 60 Hz.
Because every adc sequence has 12 channels i get appox. 720 conversions/second.
But this does not affect the bug that ADC12IFG=0 does not work; i still have to
use
volatile unsigned int trash = ADC12IV + ADC12MEM0 + ... + ADC12MEM15;

By the way: Does someone has a guide for translating ANSI/ISO-C to IAR-C?
I have some software which works fine on the PC but can't be compiled with
one of the IAR compilers because they don't know e. g. the qualifier
restrict.

Regards

Rolf F.