QD4 ADC problem

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

QD4 ADC problem

Jump to solution
1,964 Views
abicash
Contributor III

Hello

 

I am trying to use the AD2 in QD4 as an ADC input.

This is measuring a +5V max signal.I am testing it at 2.5V.

 

For this I wrote this code

void main(void)   {  ICSTRM = ICSTRM_FLASH;  ICSC2 = 0x00;  ICSC1 = 0x06;  //Wait until output FLL is selected (CLKST=0)  while (ICSSC & 0x04)    ;                      SOPT1_COPE = 0;    //disable COP            // set up adc  ADCSC1_ADCH = 0x1f; // disables the ADC during config  ADCCFG_ADICLK = 0;// bus clk   ADCCFG_MODE = 0b00; // conversion mode, 00 = 8 bit, 10 = 10 bit mode  ADCCFG_ADLSMP = 1;  // sample time, 1 = long sample time  ADCCFG_ADIV = 1;    // clock divide, 1 = input clock/2  ADCCFG_ADLPC = 1;  // low power config, 1 = low power    ADCSC2_ADTRG = 0;   // trigger select, 0 = software trigger  ADCSC2_ACFE = 1;    // compare function, 1 = enable compare function  ADCSC2_ACFGT = 1;   // 1 = compare function greater than    ADCSC1_ADCO = 1;    // enable single conversion, 1 is continuous conversion  ADCSC1_AIEN = 1;    // enable ADC interrupt  APCTL1_ADPC2 = 1;   // disable I/O control on pin      ADCCVL = 0x80;      // set a compare value      PTADD_PTADD0 =  0x01;    PTAD_PTAD0 = 0;     //reset LED      ADCSC1_ADCH = 0x02;   //ADP2 enable              EnableInterrupts;   // enable interrupts           ADCSC1_COCO = 0;   for(;;)     {    //__RESET_WATCHDOG();  feeds the dog     } //loop forever      /* please make sure that you never leave this function */                                                        }// end main interrupt 19 void ADC_ISR(void)   {     PTAD_PTAD0 =1;    ADCSC1_ADCH = 0x1f; // disable the ADC      }

 But even if ADCRL is <0x80, the ADC interrupts,which it should not.

 

I want to interrupt only on ADCRL>=ADCCVL but this is not happening.

 

I am using this on USBSPYDER.

 

Am I doing something silly?

 

Please help...Thanks and Regards :smileyhappy:


Labels (1)
0 Kudos
Reply
1 Solution
623 Views
bigmac
Specialist III

Hello,

 


abicash wrote:


I have put a resistor divider to simulate this process where the upper arm is a Preset and the lower is a fixed Resistor.

 

If the preset and the fixed resistor are of equal values, this means that the input voltage  cannot go below approximately Vdd/2 (as determined by component tolerances)  Do you actually measure the voltage between the input pin and Vss (ground) using a DVM?

 

The code jumps to the ADC interrupt routine all the time even if the voltage is 0V.

 

How are you achieving this - you cannot use the preset?  You would need to apply a direct short circuit between the pin and Vss (across the fixed resistor).

 

Now when I set the ADCCVL value to 0xFF ,everything is behaving as it should.

 

I suspect you would never get an interrupt because the value 0xFF cannot be exceeded by ADCRL register value. 

 

I checked for some values above 0x80 and I found that above 0x88 for ADCCVL, code is waiting for ADC interrupt ,otherwise every step lands in the ADC interrupt routine.

 

I assume that the preset is adjusted to give minimum voltage.  The component tolerances for the voltage divider might account for the slightly different threshold.  

 

 


Regards,

Mac

View solution in original post

0 Kudos
Reply
4 Replies
623 Views
bigmac
Specialist III

Hello,

 

I am not entirely sure what is causing the problem, but writing 0 to the COCO bit after the first conversion has commenced will abort that conversion, and is totally unnecessary because it has no affect on the state of the COCO flag. Get rid of the line.

 

Within the ISR code, you have not read the value within ADCRL prior to disabling the ADC module.  Therefore any read of ADCRL from outside the ISR will not give a valid result.  Read ADCRL from within the ISR code, and this action will also clear the COCO flag (although disabling the ADC module will also do this).

 

Some other comments about your code, not related to the current problem.  I notice that you tend to write separately to individual bits of a register.  While this is less code efficient that writing to all bits simultaneously, in some cases it is not really advisable, even though it may currently work.

 

Registers such as SOPT1 are write once.  Therefore, if more than one bit requires changing from its powerup default value, all bits must be simultaneously written.  Even though you are currently changing only a single bit, it is good practice to write all bits, to allow for future changes to the code.

 

Each write of the ADCSC1 register will abort any conversion in progress, and start a new conversion.  I assume that writing a single bit anywhere within the register will also do this - probably not what you would intend.  The solution is to simultaneously write to all bits to commence a conversion, e.g. ADSC1 = 0xA2;  // Commence continuous conversion, Ch 2

 

I would also do the same for ADSC2 and ADCCFG registers, but that is a personal preference.

 

Regards,

Mac

0 Kudos
Reply
623 Views
abicash
Contributor III

bigmac wrote:

Hello,

 

I am not entirely sure what is causing the problem, but writing 0 to the COCO bit after the first conversion has commenced will abort that conversion, and is totally unnecessary because it has no affect on the state of the COCO flag. Get rid of the line.

 

Hello Bigmac..glad to see you agaiin :smileyhappy:

 

I had added the COCO line out of desperation and wasn't there earlier.

 

Within the ISR code, you have not read the value within ADCRL prior to disabling the ADC module.  Therefore any read of ADCRL from outside the ISR will not give a valid result.  Read ADCRL from within the ISR code, and this action will also clear the COCO flag (although disabling the ADC module will also do this).

 

This I have done with no effect.

 

Some other comments about your code, not related to the current problem.  I notice that you tend to write separately to individual bits of a register.  While this is less code efficient that writing to all bits simultaneously, in some cases it is not really advisable, even though it may currently work.

 

This is done for trial.So that I don't have to figure out the value all the time.Only changing the concerned bit does it..

 

Registers such as SOPT1 are write once.  Therefore, if more than one bit requires changing from its powerup default value, all bits must be simultaneously written.  Even though you are currently changing only a single bit, it is good practice to write all bits, to allow for future changes to the code.

 

Each write of the ADCSC1 register will abort any conversion in progress, and start a new conversion.  I assume that writing a single bit anywhere within the register will also do this - probably not what you would intend.  The solution is to simultaneously write to all bits to commence a conversion, e.g. ADSC1 = 0xA2;  // Commence continuous conversion, Ch 2

 

I would also do the same for ADSC2 and ADCCFG registers, but that is a personal preference.

 

I will incorporate that in final version.

 

Regards,

Mac


I have put a resistor divider to simulate this process where the upper arm is a Preset and the lower is a fixed Resistor.

 

The code jumps to the ADC interrupt routine all the time even if the voltage is 0V.

 

Now when I set the ADCCVL value to 0xFF ,everything is behaving as it should.

 

I checked for some values above 0x80 and I found that above 0x88 for ADCCVL, code is waiting for ADC interrupt ,otherwise every step lands in the ADC interrupt routine.

 

What could be this?

 

Thanks and regards..

0 Kudos
Reply
624 Views
bigmac
Specialist III

Hello,

 


abicash wrote:


I have put a resistor divider to simulate this process where the upper arm is a Preset and the lower is a fixed Resistor.

 

If the preset and the fixed resistor are of equal values, this means that the input voltage  cannot go below approximately Vdd/2 (as determined by component tolerances)  Do you actually measure the voltage between the input pin and Vss (ground) using a DVM?

 

The code jumps to the ADC interrupt routine all the time even if the voltage is 0V.

 

How are you achieving this - you cannot use the preset?  You would need to apply a direct short circuit between the pin and Vss (across the fixed resistor).

 

Now when I set the ADCCVL value to 0xFF ,everything is behaving as it should.

 

I suspect you would never get an interrupt because the value 0xFF cannot be exceeded by ADCRL register value. 

 

I checked for some values above 0x80 and I found that above 0x88 for ADCCVL, code is waiting for ADC interrupt ,otherwise every step lands in the ADC interrupt routine.

 

I assume that the preset is adjusted to give minimum voltage.  The component tolerances for the voltage divider might account for the slightly different threshold.  

 

 


Regards,

Mac

0 Kudos
Reply
623 Views
abicash
Contributor III

bigmac wrote:

Hello,

 


 

If the preset and the fixed resistor are of equal values, this means that the input voltage  cannot go below approximately Vdd/2 (as determined by component tolerances)  Do you actually measure the voltage between the input pin and Vss (ground) using a DVM?

 Yes it is little less than 2.5V to 5V  since the preset is a larger value


How are you achieving this - you cannot use the preset?  You would need to apply a direct short circuit between the pin and Vss (across the fixed resistor).

 Yes i was putting the pin to ground


 

I suspect you would never get an interrupt because the value 0xFF cannot be exceeded by ADCRL register value. 

 


 

I assume that the preset is adjusted to give minimum voltage.  The component tolerances for the voltage divider might account for the slightly different threshold.  

 

Okay i changed the scheme and now i have a 0v-2.5V sweep....and I can achieve this..so embarrassed for this mistake and thanks as always for pointing that out ..I will check some more and get back if I have any more problems


Regards,

Mac


Thanks as always :smileyhappy:

0 Kudos
Reply