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
Solved! Go to Solution.
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
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
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
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..
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
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