Hi everyone,
I am stuck with the following and I don't know if this is a C language issue, compiler, IDE, or something else?
By the way, I am using KDS 3.0 and I am not using PE.
After setting up the ADC, I start a conversion, then follow it with an if statement waiting for COCO to set.
if (ADC_SC1 & ADC_SC1_COCO_MASK) //Wait until the conversion is complete
Analog_This.ui24V = ADC->R; //Retrieve the conversion
The issue is that after the if statement, if I step through the code, it never executes (Analog_This.ui24V = ADC->R;).
I also tried this:
if (ADC->SC1 & ADC_SC1_COCO_MASK) //Wait until the conversion is complete
I also tried this:
if ((ADC->SC1 & ADC_SC1_COCO_MASK) == 1) //Wait until the conversion is complete
I also tried this:
if ((ADC_SC1 & ADC_SC1_COCO_MASK) == 1) //Wait until the conversion is complete
All these combinations didn't work!
Thank you,
Neil
Neil
To wait on conversion complete you need:
while ((ADC_SC1A & ADC_SC1A_COCO_MASK) == 0) {} // wait for conversion to complete
Did you mix if/while or is your "if" test called periodically?
Regards
Mark
Hi Mark,
The if test is called periodically.
The screen shot above is at the point where the execution pointer is on the if statement:
--> if ((ADC_SC1 & ADC_SC1_COCO_MASK) == 1)
after stepping through the if statement, the COCO bit is cleared???
According to documentation, the only time COCO is cleared, is by writing to the ADC_SC1 or by reading from ADC_R.
Not sure what's happening here.......
Neil
If you step the code with the debugger's register open it will be reading the ADC value and resetting the flag before your code sees it.
Either close the register view or disable it from updating and maybe it works then - if not it will be likely that the ADC never started the conversion so the problem is in the code starting it.
Regards
Mark
Hi Mark,
I don't believe that this statement can be correct "Either close the register view or disable it from updating and maybe it works then"
If this was true, it will be very difficult to troubleshoot code, but because I tried just about everything and nothing seems to work, I
tested the same line of code/w the register and bit open on another Kinetis processor K64F and the COCO bit doesn't clear unless
a condition was met (a write from the ADC_SCI or a read from ADC_R).
So, with that said, I will look at the configuration once again, because starting a conversion, according to the documentation is as
simple as writing to ADC_SCI.
Regardless, thank you so much for taking the time to look into this issue for me.
Neil
Unfortunately, that is 'most true' indeed! These peripherals have a lot of 'clear when read' flags, AND the 'debugger' does NOT have a 'special no-side-effect-read', so that a 'read' by the debugger is the SAME as a read from your code, and WILL clear indicator-flags on you! And YES, that does make it a B**** to debug!
Hi Earl,
I tried closing the register to make sure that, it was not causing a side-effect and the test failed regardless.
But if you read again, what I replied to Mark, noticed that we tried the same thing on a Kinetis K64
and we didn't have any issues? Unless, there is an errata for the MKE02Z processors, that explains
this behavior? I have not looked into it yet, but I will. I feel maybe I am either not configuring something
correctly or there's something terribly bad with this Freescale part!
Thank you.
Neil
Neil
I have attached a binary for the FRDM-KE02Z (in case you have this).
It reads the NTC (THER_A) input once every 3 seconds and send the HEX value to the OpenSDA virtual COM interface.
Either in COCO polling mode or using the conversion flag interrupt the result is normal.
The following is simplest code that configures and waits for the conversion to complete before returning the result:
POWER_UP(6, SIM_SCGC6_ADC0); // enable clocks to module ADC_SC3 = (ADC_CFG1_ADIV_8 | ADC_CFG1_ADLSMP_LONG | ADC_CFG1_MODE_10 | ADC_CFG1_ADICLK_BUS2); ADC_SC2 = 0; // software trigger ADC_APCTL1 |= (ADC_APCTL1_AD12); // enable the pin's ADC function ADC_SC1 = ADC_SC1_ADCH_12; // start conversion on channel 12 while ((ADC_SC1 & ADC_SC1_COCO) == 0) {} // wait for conversion to complete return (ADC_R); // return the value
Compare with what you have and if you still have difficulties you will need to show the code that you use.
Regards
Mark
Hi Mark,
I reviewed your code snippet, it looks similar to my setup. Here is the comparison:
POWER_UP(6, SIM_SCGC6_ADC0); // enable clocks to module (yours)
SIM_SCGC |= SIM_SCGC_ADC_MASK; // Enable the ADC module (mine)
ADC_SC3 = (ADC_CFG1_ADIV_8 | ADC_CFG1_ADLSMP_LONG | ADC_CFG1_MODE_10 | ADC_CFG1_ADICLK_BUS2); // (yours)
ADC_SC3 = ADC_SC3_ADLPC_MASK | ADC_SC3_ADLSMP_MASK | ADC_SC3_MODE1_MASK | ADC_SC3_ADIV(3); // (mine)
ADC_SC2 = 0; // software trigger (yours)
ADC_SC2 = 0x00; //Software trigger, Default voltage reference (mine)
ADC_APCTL1 |= (ADC_APCTL1_AD12); // enable the pin's ADC function (yours)
ADC_APCTL1 = ADC_APCTL1_ADPC5_MASK; (mine)
ADC_SC1 = ADC_SC1_ADCH_12; // start conversion on channel 12 (yours)
ADC_SC1 = ADC_12VSignal_MASK; (mine)
(yours)
while ((ADC_SC1 & ADC_SC1_COCO) == 0) {} // wait for conversion to complete
return (ADC_R); // return the value
(mine)
if (ADC_SC1 & ADC_SC1_COCO_MASK) //Is the conversion is complete
Analog_This.ui24V = ADC->R; //Read the conversion
I am following this example straight from the KE02 Sub-Family Reference Manual
Example: 24.5.1.2.1 General ADC initialization routine
void ADC_init(void)
{
/* The following code segment demonstrates how to initialize ADC by low-power mode,
long
sample time, bus frequency, software triggered from AD1 external pin without FIFO
enabled
*/
ADC_APCTL1 = ADC_APCTL1_ADPC1_MASK;
ADC_SC3 = ADC_SC3_ADLPC_MASK | ADC_SC3_ADLSMP_MASK | ADC_SC3_MODE0_MASK;
ADC_SC2 = 0x00;
ADC_SC1 = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH0_MASK;
}
My research regarding an existing ERRATA for the MKE02Z32VQH4 came back empty!
Freescale is not reporting an issue with what I am seeing????
Just as a test, I did the following line after my code to see what would happen:
ADC_APCTL1 = ADC_APCTL1_ADPC5_MASK; //APCTL1 is used to control the pins associated with channels 0-31
ADC_SC3 = ADC_SC3_ADLPC_MASK | ADC_SC3_ADLSMP_MASK | ADC_SC3_MODE1_MASK | ADC_SC3_ADIV(3); //Low power configuration,Long
ADC_SC2 = 0x00; //Software trigger, Default voltage reference
ADC_SC1 = ADC_12VSignal_MASK; //One Conversion Enable ;Input Channel AD4; Input Channel AD5
if (10 & 12) <--------- useless line just to see what happens......
bla bla bla......
just right before execution:
---> if (10 & 12) ******** COCO = 0x01
after stepping ******** COCO = 0x00
Very frustrating and by the way, it doesn't matter if I have the register open (where I am looking at it or not).
Anyway, why hasn't someone from Freescale jumped in to this post/issue/conversation (either confirming it or commenting about it)????
Thank you Mark for keeping up with me on this. Your probably scratching your head as I am.....
Regards,
Neil
Neil
Do you use a custom board? Could it be that if the ADC power pins are not connected correctly (for example) it causes the ADC to not function correctly?
I have tried with 10 and 12 bit modes, high and low power with no difficulties.
As reference, these are the ADC register values as I step the code that I showed:
1. Before starting the conversion:
2. After the write to ADC_SC1 (to start the conversion on a particular channel):
Note that the COCO bit is not shown set but the channel number is seen and also the result is seen (or seen to change).
This will now hang waiting for the COCO bit to be set, showing that the debugger probably caused the flag to already be reset. In fact the ADC_SC1 value remains unchanged forever. This is the situation that you have because the COCO flag is never seen to be set and so the result is never collected/returned.
3. I repeat with a breakpoint after the detection of the COCO flag and don't step, but instead let the code execute.
This time it hits the breakpoint - although the ADC register view still shows the same as 2) I can see the value 0x8c in the processor's R0 register which was tested. This means that the COCO bit was set and read by the processor.
4. I repeat the stepping method but with the ADC register view disabled. Now when I step I also arrive at the same point as in 3)
I don't know whether you are testing exclusively by stepping code but this does show that the debugger can have an influence since it is in fact 'impossible' to directly see the COCO flag in the ADC_SC1 register but the processor does read it because its conditional expression is true and one can also see the value that was read to its CPU register for the check.
Also this confirms that the COCO operation is as expected and described in the user's guide.
Unless you do have a problem with your HW/chip my conclusion is that you are still being fooled by your debugger's behavior and your code should operate if run normally.
Regards
Mark
P.S. Out of interested I put a counter in the while loop and it counted to 58 before the COCO flag was detected, giving some indication of the amount of instructions/clock cycles required for the conversion to complete at the used speed.
Also, I read the ADC_R result register on the first execution to see whether prematurely reading it would stop the COCO flag from being set.The result was that it didn't have and influence so the only way to lose the flag is to read the value after it was been set.
Thank you Mark.
By the way, yes this is a custom board we laid out. I have checked out the pins and there is continuity
and they are connected to the correct pins on the processor.
I need to do more testing, because the results are different each time? Sometimes if I step the code,
then I get the AD reading (meaning the COCO flag did get set) and sometimes it seems to be locked
in, but since I have the register view disable to prevent false triggering, then I can't really tell.
Then of course is the other question, which is, why with a K64 Kinetis processor I don't have this issue?
Meaning, I can keep the ADC view open and not affect its behavior???
Anyways, thank you for your support,
Neil