Hello.
I am working on the MC9S08DZ128 ADC.
I am facing something strange : when the program runs itself, there in no problem with the value (in my case, I have for example (on 12bits) 0x587). But when I put a breakpoint before the ADC instruction and after the conversion is complete, the value isn't right (it becomes 0x161).
Is there an explanation ? Is it possible to break before and after, to see the value ?
Thank you in advance for your help.
Hello,
Is it possible that the break point occurs after the very first conversion following power up? Normally the result of the first conversion should be discarded. Possibly Vdd may not have stabilised prior to this conversion, especially if large bulk capacitors are present at the power supply output. Make sure you are in single conversion mode.
Also what do you mean by "ADC instruction"? The instruction to read the ADC data register will still need to occur prior to the break, or within the break.
Regards,
Mac
Hello, thank you for your interest.
The result of the conversion is always false when I use breakpoints, not just when power up. I am in single mode.
I put a breakpoint before the function that starts conversion and read the result and another breakpoint after reading the result.
I have another problem but I don't know if it could be my code or the schematic of the board. I am using the ADC on 3 channels : PTA4, PTA5 and PTA6. On PTA6, I have a temperature sensor (STLM20), on PTA4 I am converting voltage.
The problem is that, when something change (voltage or temperature), the other channel change too. When temperature increase, the voltage measured increases too.
Is there a reason to that ? could it be my code ? Or is it just the board that has problem ? Is it possible to make that by code ?
Thank you very much.
Hi,
Perhaps you could post the relevant section of code and where you are placing the breakpoints.
I wonder whether your problem could be too high impedance of your analogue sources. With high impedance the result can tend towards the previous conversions value.
Peg wrote:I wonder whether your problem could be too high impedance of your analogue sources.
I was wondering the same thing. Are your analog inputs buffered? The inputs to the AtoD are not very high impedance, and I have had problems with cross-channel effects when using 50k pots as inputs. 5k pots worked much better, but the cross-channel problems did not go away completely until I buffered the inputs with op-amps.
Hello,
Rocco, I believe that the cross channel interference that you describe is not due to low input resistance of the ADC module, but due to its capacitance, some of which will be present after the channel multiplexer. A high source resistance will increase the time constant of the CR circuit, and full settling may not occur during the sample interval.
The problem would be exacerbated with a number of channels being read in succession, since the starting voltage across the capacitance would be the input level of the previous channel, that may be significantly different from the current input voltage.
For a worst case 1 LSB settling error, the input time constant should be a fraction of the sample interval by the following factors. I might assume that the input capacitance would be of the order of 5pF. The total source resistance would also include the series resistance of the input multiplexer.
Time constant CR <= Tsamp / k
8-bit: k = 5.5
10-bit: k = 6.9
12-bit: k = 8.3
With a moderately high source resistance (maybe 5k or greater), the first step would be to choose the long sample interval. Placing a capacitor, say 100n, at each input pin may also help provided rapid fluctuations of the input levels are not encountered. An additional approach would be to take two readings in succession for each channel, and discard the first reading. If significant errors persist, the additional hardware buffering would need to be considered.
Regards,
Mac
Thank you all for your responses.
Here is my code if it could help.
/* affectation des broches */# define channelT 7 /**< broche pour la mesure de température : PTA6 */# define channelV 5 /**< broche pour la mesure de tension : PTA4 */# define channelI 6 /**< broche pour la mesure de courant : PTA5 *//*** ===================================================================** Method : AD_Init (component ADC)**** Description :** Initializes the associated peripheral(s) and the bean's ** internal variables. The method is called automatically as a ** part of the application initialization code.** This method is internal. It is used by Processor Expert only.** ===================================================================*//*! \fn void AD_Init(void) \brief fonction d'initialisation du convertisseur analogique numérique*/void AD_Init(void){ /* ADCSC1: COCO=0,AIEN=0,ADCO=0,ADCH4=1,ADCH3=1,ADCH2=1,ADCH1=1,ADCH0=1 */ setReg8(ADCSC1, 0x1F); /* Disable the module */ /* ADCSC2: ADACT=0,ADTRG=0,ACFE=0,ACFGT=0,??=0,??=0,??=0,??=0 */ setReg8(ADCSC2, 0x00); /* Disable HW trigger and autocompare */ OutFlg = 0; /* No measured value */ SumChan = 0; ModeFlg = STOP; /* Device isn't running */ /* ADCCFG: ADLPC=1,ADIV1=0,ADIV0=1,ADLSMP=0,MODE1=0,MODE0=1,ADICLK1=0,ADICLK0=0 */ setReg8(ADCCFG, 0xA4); /* Set prescaler bits */ }void AD_MeasureChan(byte Channel, byte *Result){ ModeFlg = SINGLE; /* Set state of device to the measure mode */ SumChan = Channel; /* Set required channel */ if (ModeFlg) { /* Start or stop measurement? */ OutFlg &= ~Table[SumChan]; /* Output value isn't available */ ADCSC1 = Channels[SumChan]; /* Start measurement of next channel */ while (!ADCSC1_COCO) {} /* Wait for AD conversion complete */ ((TWREG*)(&AD_OutV[SumChan]))->b.high = ADCRH; /* Save measured value */ ((TWREG*)(&AD_OutV[SumChan]))->b.low = ADCRL; /* Save measured value */ OutFlg |= Table[SumChan]; /* Value of measured channel is available */ ADCSC1 = 0x1F; /* Stop the device */ ModeFlg = STOP; /* Set the device to the stop mode */ Result[0] = (AD_OutV[Channel]) & (0xFF); /* Save measured values to the output buffer */ Result[1] = ((AD_OutV[Channel]) & (0xF00)) >> 8; /* Save measured values to the output buffer */ }}/*! \fn void mesT (byte *dataT) \brief fonction de mesure de température \param dataT pointeur vers le résultat de la mesure*/void mesT (byte *dataT){ AD_MeasureChan (channelT, dataT); }/*! \fn void mesV (byte *dataV) \brief fonction de mesure de tension \param dataV pointeur vers le résultat de la mesure*/void mesV (byte *dataV){ AD_MeasureChan (channelV, dataV);} interrupt void RTC_Interrupt (void) { byte dataV[2], dataT[2], dataI[2]; byte mesure[3]; // tableau contenant les mesures RTCSC_RTIF = 1; // efface le flag mesV(&dataV); // mesure de tension mesure[0] = (branche<<5) + module ; mesure[1] = dataV[0]; mesure[2] = dataV[1]; send (&mesure, 3, mesures); mesT(&dataT); // mesure de température mesure[0] = (branche<<5) + module ; mesure[1] = dataT[0]; mesure[2] = dataT[1]; send (&mesure, 3, temperature); /* dans le cas d'un module qui mesure le courant */ //# ifdef COURANT if (module_courant == num_module) { mesI(&dataI); mesure[0] = (branche<<5) + module ; mesure[1] = dataI[0]; mesure[2] = dataI[1]; send (&mesure, 3, courant);} }
The problem is with dataT and dataV. The measure of dataI is always 0xFFF.
I tried some changes and somes tests (I put an input voltage on the channel mesured by mesV). Here are my observations.
the same code with short sample time :
0V 1V 2V 3V 4V 5V
mesV 0x000 3A3 718 A83 DED FFF
mesT 0x1AB 31F 4BC 67B 827 991
the same code with long sample time :
0V 1V 2V 3V 4V 5V
mesV 0x000 3A5 6DF A47 DCA FFF
mesT 0x1A7 31C 4A2 65F 823 99B
with short sample time but I do mesV, then mesI and then mesT:
0V 1V 2V 3V 4V 5V
mesV 0x000 35F 6DD A59 DB7 FFF
mesT 0x9C7 9BF 9B5 9AF 9B4 9B7
(here the value measured for temperature is -90°C with 9B5)
with short sample time and two readings in succession for each channel :
0V 1V 2V 3V 4V 5V
mesV 0x000 3AF 6DD A9F DCD FFF
mesT 0x3F2 409 5C7 75A 8F7 A97
with short sample time and two readings in succession for each channel but I do mesV, then mesI and then mesT:
0V 1V 2V 3V 4V 5V
mesV 0x000 360 715 A43 DBF FFF
mesT 0x9E5 AAF AE5 A29 A2F A72
mesV gives the voltage, so it seems to be right.
Please, is there something that I'm doing wrong ??
I don't understand why I have those values.
Sorry for my english, I am french...
Thank you very much for your help.
Hello,
If you have not already done so, I think that you need to confirm, using an oscilloscope, that the voltages applied to the ADC inputs are free of hum and noise. In particular, I notice that the temperature sensor might be prone to instability (oscillation) if operating into a capacitive load of more than 300pF. For example, if you had a 100nF capacitor at the ADC input pin, you would require an isolating series resistance of 470 ohms between the temperature sensor output and the input to ensure stability.
Additionally the input capacitor will need to be returned to the low noise analog ground to prevent injection of noise to the input. There should be a separate bypass capacitor between the VddA/VrefH pins and the VssA/VrefL pins. These pins should be connected to Vdd and Vss pins respectively, right at the MCU package only.
I think that you need to verify your circuit board layout before assuming that there is a coding deficiency. Proper layout is extremely important for 12-bit conversions, much more so than for lower ADC resolutions. Noise fluctuations of more than about 1 millivolt are significant. Sometimes it is necessary to enter wait mode during the conversion process, to eliminate the internal CPU clock noise.
Regards,
Mac