ADC works once but not twice [M9S08QG8]

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

ADC works once but not twice [M9S08QG8]

5,190 次查看
gettism
Contributor I
Hi,
 
My problem is as follows:
 
I initialize the ADC and can read voltages off of Channel 0.  However if I try to read the measurement off of the temperature sensor channel after reading a voltage from Channel 0, the channel of the ADC doesn't change.
 
I have tried to read both the Bandgap reference and the temp sensor after setting the ADC to use channel 0, but to no avail.  If I read either of these before setting the ADC to channel 0 I have no problem.  Both readings are correct.
 
Any thoughts?  Is there something I can do before I do the reading of either the temp of bandgap reference to make sure I don't get another reading from Channel 0?  I am certain I am changed the channel correctly using the ADCSC1 register.
 
Thanks.
标签 (1)
0 项奖励
回复
8 回复数

1,811 次查看
gettism
Contributor I
You guys are totally right.  Thanks.  It will just remain in CH0 once a 0 is put in the register.
 
Thanks.
0 项奖励
回复

1,811 次查看
daniel1
Contributor I
May be I can help you but I need to see your code please send to zeevbs@yahoo.com
I have problems too.
0 项奖励
回复

1,811 次查看
UcTechnoGeek
Contributor II
Sounds like you are not running the ADC in continuous mode.
 
You either need to re-start the ADC each time and wait for the complete flag to be set, or set it up to run continuous conversions.
 
uCTechnoGeek
0 项奖励
回复

1,811 次查看
gettism
Contributor I
Hi,
 
Here is the code I use... (Note I'm using software polling)
/* Channels */
#define ADCCH0           0x00
#define ADCTEMP        0x1A
#define ADCBG             0x1B
#define ADCDISABLE   0x1F
 
byte PTAstate;
byte PTBstate;
word volts;
 
void main(void) { 
 /* Init ADC into single conversion mode, low power hence the stop mode */
 ADCSC1 = 0x1F;    // Disables all channels
 while(1) {
   EnterStop();
   ADCChannel(ADCTEMP);
   volts = ADCCheck();
   ADCChannel(ADCCH0);
   volts = ADCCheck();
 }
}
 
/* Helper Functions */
void ADCChannel(byte Channel) {
 ADCSC1 &= Channel;
}
 
void EnterStop(void) {
 SPMSC2 = 0x00;    /* Make sure stop mode3 is entered */
 PTAstate = PTADD;
 PTBstate = PTBDD;
 PTADD = 0xFF; 
 PTBDD = 0xFF;   /* Set all as output to lower power consumption */
 asm STOP;
 PTADD = PTAstate;
 PTBDD = PTBstate;
}
 
word ADCcheck(void) {
 volatile word DataOut;
 volatile byte DataH;
 DataOut = 0;
 DataH = 0;
 while (ADCSC1_COCO != 1);
 DataOut = ADCRL;
 DataH = ADCRH;
 DataOut += DataH * 256;
 return DataOut;
}
 
Out of this I get the correct temperature the first time.  The second loop time I get the same value I got for channel 0.  This is the same for the Bandgap voltage.  But... if I check the bandgap, then the temperature, there isn't an issue.  It's only when I check channel 0.  I've also tried channel 1 and it works like channel 0, only outputting the same value as the channel I select.
 
I ommited the setup code I used for the ADC.  It uses single conversion, low power, slow, div 8 clock, no compare function and no interrupt.
 
I'm trying to get this to work in a low power fashion hence the stop modes and whatnot.
 
Thanks for your help.  Let me know if I need to clarify more.
0 项奖励
回复

1,811 次查看
thisobj
Contributor III
gettism,

I think it might have to do with the way you are setting up the AD channel bits:

/* Helper Functions */
void ADCChannel(byte Channel) {
ADCSC1 &= Channel; //================= this is a problem.
}

Since this is an AND operation, as soon as you put "0x00" into the register, all following values will result to 0x00. The first trip works because ADCSC1 is init'd to 0x1f.
Try using:

ADCSC1_ADCH = (your value);


Frank
0 项奖励
回复

1,811 次查看
gettism
Contributor I
Thanks I will try that and see if it fixes the problem.  I thought it wouldn't make a difference since that's the way the register was setup with the Processor Expert.  I am using single conversion mode and no interrupts.
 
Still though the way you describe is better programming practise.
0 项奖励
回复

1,811 次查看
bigmac
Specialist III
Hello,
 
If PE uses the same method the set up the register, this would seem to be buggy code, for the reason already given by Frank.
 
For your requirement of single conversion with no interrupts, the following alternative should also work -
ADCSC1 = Channel;
 
or to protect against an improper value in the Channel variable -
ADCSC1 = Channel $ 0x1F;
 
Regards,
Mac
 
0 项奖励
回复

1,811 次查看
thisobj
Contributor III
Are you waiting for the Conversion Complete flag ( COCO ) in status register to set before beginning the next conversion?
0 项奖励
回复