Jump to content
43oh

adc sampling time problem


Recommended Posts

I tried adc using the ADC12 in msp430fg4618 experimenter's board. I saw the datasheet and it says the frequency of ADC12OSC oscillator is 5Mhz. I used that clock. According to the user guide about 15 cycles of ADC12OSC is spent for sampling and analog to digital conversion. After this the data will be stored in ADC12MEM register and I call the interrupt. There I tried to send the data in that register outside bit by bit. I also toggled one led (LED4) to see when the interrupt is called ( i.e. entire sampling time). I encounters this problem-

*Initially I just tried to toggle without sending any data outside. At that time the frequency of the LED4 that I got in the oscilloscope is 32 Khz.

*The next time I sent 2 bits of the ADC12MEM register to the i/o pins. Then I saw the frequency of LED4 and it had changed to 1khz!

*The next time I included the entire code where I sent the 12 bits of ADC12MEM register to the i/o pins and the frequency of LED4 was 263 Hz!!!

 

I need a sampling rate of 22Khz and not 263 hz.

 

Here's the code

 

 

#include "msp430xG46x.h"

long int data[12];

 

void main(void)

{

WDTCTL = WDTPW + WDTHOLD; // Stop WDT

ADC12CTL0 = SHT0_0 + ADC12ON; // Sampling time, ADC12 on

ADC12CTL1 = SHP; // Use sampling timer

ADC12IE = 0x01; // Enable interrupt

ADC12CTL0 |= ENC;

P6SEL |= 0x01; // P6.0 ADC option select

P5DIR |= 0x02; // P5.1 output

P4DIR=0xFF;

P3DIR=0xF0;

 

 

while (1)

{

ADC12CTL0 |= ADC12SC; // Start sampling/conversion

 

__bis_SR_register(LPM0_bits + GIE); // LPM0, ADC12_ISR will force exit

}

}

 

#pragma vector = ADC12_VECTOR

__interrupt void ADC12_ISR(void)

{

int a[4];

// Toggled this to check the sampling rate

P5OUT^=0x02;

//This is the part where I send the converted data to the pins.

//I extracted each bit here-

data[0]=( ADC12MEM0 & 0x0001);

data[1]=( ADC12MEM0 & 0x0002);

data[2]=( ADC12MEM0 & 0x0004);

data[3]=( ADC12MEM0 & 0x0008);

data[4]=( ADC12MEM0 & 0x0010);

data[5]=( ADC12MEM0 & 0x0020);

data[6]=( ADC12MEM0 & 0x0040);

data[7]=( ADC12MEM0 & 0x0080);

data[8]=( ADC12MEM0 & 0x0100);

data[9]=( ADC12MEM0 & 0x0200);

data[10]=( ADC12MEM0 & 0x0400);

data[11]=( ADC12MEM0 & 0x0800);

// This is done so that it goes to the pins 7,6,5,4 of the port3.

a[0]=data[8]/0x0010;

a[1]=data[9]/0x0010;

a[2]=data[10]/0x0010;

a[3]=data[11]/0x0010;

//This is the place where I have sent the data to the i/o pins.

P4OUT=data[7]|data[6]|data[5]|data[4]|data[3]|data[2]|data[1]|data[0];

P3OUT=a[3]|a[2]|a[1]|a[0];

__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0

}

Link to post
Share on other sites

Hello.

First of all, set GIE bit only once, before the 'while(1)' loop:

__bis_SR_register(GIE);
while (1)
{
ADC12CTL0 |= ADC12SC; // Start sampling/conversion
__bis_SR_register(LPM0_bits); // LPM0, ADC12_ISR will force exit
}

 

Next, rewrite your interrupt procedure and learn some GNU C tricks :P (dunno if it works with IAR/CCS, but if they call them C compilers, it should :think: ). Honestly, this is the part of your code that makes sampling so freaking slow. You're simply killing CPU with unneeded calculations and memory operations. Try this (not tested :P):

#pragma vector = ADC12_VECTOR
__interrupt void ADC12_ISR(void) //oh yeah, another IAR/CCS user 
{
// Toggled this to check the sampling rate
P5OUT^=0x02;
P4OUT = ADC12MEM0;
P3OUT = ADC12MEM0 >> 4; //or ((ADC12MEM0 >> 4) && 0xF0) if you like.
__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
}

Nice, huh? :)

 

If it doesn't help, then set DCO to something like 8~16MHz and let the smile on your face appear.

Link to post
Share on other sites

Will the sampling and analog to digital conversion take place when the interrupt function is being executed?

In your case (single channel single-conversion mode) the answer is: no, not automaticaly. You start ADC by setting ADC12SC bit, which is automagicaly cleared after the conversion. And you set it in the while(1) loop, after waking up from LPM0 :P

How to set DCO to 16 Mhz?

Try this:

if (CALBC1_16MHZ ==0xFF || CALDCO_16MHZ == 0xFF)
  while(1);		                    // If calibration data is erased
				                            // trap CPU
 BCSCTL1 = CALBC1_16MHZ; 					// Set range
 DCOCTL = CALDCO_16MHZ;  					// Set DCO step + modulation

Link to post
Share on other sites

Another question.

 

I wish to check if I am getting the correct clock frequency from ADC12OSC. I saw the datasheet and according to it the pin P2.7 is assigned to ADC12OSC. What does this mean? Can I see the frequency of the clock if I connect that pin to the oscilloscope?

Should I change any register if I should get the clock in that pin?

 

Thanks in advance.

Link to post
Share on other sites

If you want to connect ADC12OSC to oscilloscope you need to:

1) set ADC12CLK to use ADC12OSC (this is default, so no need to do that)

2) using P2SELx and P2SEL2x change function of P2.7 to give you the output of ADC12CLK

 

For instance, when using launchpad, I would have to:

P1DIR |= BIT3;
P1SEL |= BIT3;
P1SEL2 &= ~BIT3;

 

Be warned:

"The ADC10OSC, generated internally, is in the 5-MHz range, but varies with individual devices, supply

voltage, and temperature. See the device-specific data sheet for the ADC10OSC specification."

Link to post
Share on other sites

Hello I tried it. I am getting SMCLK correctly but I don't get ADC12CLK. Instead I get a high value in the ADC12CLK pin. I don't know what the problem is.

 

Here's the code

 

void main(void)

{

WDTCTL=WDTPW|WDTHOLD;

// This is for SMCLK which worked perfectly.

P1DIR|=BIT4;

P1SEL|=BIT4;

//This is for ADC12CLK and I got only high in that pin and I never saw a clock in the oscilloscope.

P2DIR|=BIT7;

P2SEL|= BIT7;

for(;;)

{

 

}

}

Link to post
Share on other sites

I tried this and it's still not working. I am still getting a high value in that ADC pin.

 

Here's the modified code---

 

/*

* main.c

*/

#include "msp430fg4618.h"

#include "stdint.h"

#include "intrinsics.h"

void main(void)

{

WDTCTL=WDTPW|WDTHOLD;

P1DIR|=BIT4;

P1SEL|=BIT4;

ADC12CTL0 |= ENC + ADC12SC;

P2DIR|=BIT7;

P2SEL|= BIT7;

for(;;)

{

 

}

}

Link to post
Share on other sites

Your first post of the code had more of the ADC12 setup. You'll need those pieces of code to finish setting up the ADC.

 

Are you using CCS v5? You should launch the TI resource explorer to see software examples for what you need. I checked and there are plenty. From CCS "View -> TI Resource Explorer"

 

[attachment=0]4618.JPG[/attachment]

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...