iVenky 0 Posted February 25, 2012 Share Posted February 25, 2012 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 } Quote Link to post Share on other sites
Sir Ferdek 8 Posted February 25, 2012 Share Posted February 25, 2012 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 (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 ): #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. iVenky 1 Quote Link to post Share on other sites
iVenky 0 Posted February 25, 2012 Author Share Posted February 25, 2012 I have some questions- Will the sampling and analog to digital conversion take place when the interrupt function is being executed? How to set DCO to 16 Mhz? Thanks in advance. Quote Link to post Share on other sites
Sir Ferdek 8 Posted February 25, 2012 Share Posted February 25, 2012 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 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 iVenky 1 Quote Link to post Share on other sites
iVenky 0 Posted February 25, 2012 Author Share Posted February 25, 2012 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. Quote Link to post Share on other sites
Sir Ferdek 8 Posted February 26, 2012 Share Posted February 26, 2012 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." iVenky 1 Quote Link to post Share on other sites
iVenky 0 Posted February 28, 2012 Author Share Posted February 28, 2012 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(; { } } Quote Link to post Share on other sites
Sir Ferdek 8 Posted February 28, 2012 Share Posted February 28, 2012 I'm not sure, but shouldn't you enable ADC first in order to activate the ADC12CLK? It's just a hunch, but msp430 has many energy-saving features that may affect that. Try setting ADC12CTL to some correct values, especially the ADC12ON bit then report again, please Quote Link to post Share on other sites
gwdeveloper 275 Posted February 28, 2012 Share Posted February 28, 2012 Yes, the clock won't output if it's not operating. You'll need to start the conversion to see the clock. ADC12CTL0 |= ADC12ENC + ADC12SC; Quote Link to post Share on other sites
iVenky 0 Posted February 29, 2012 Author Share Posted February 29, 2012 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(; { } } Quote Link to post Share on other sites
gwdeveloper 275 Posted February 29, 2012 Share Posted February 29, 2012 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] Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.