This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
The goal is to start an ADC measurement when a button is activated. A block of 4 readings is to be saved via the DTC. The interrupt vector for the ADC is to average the results. A state machine running in the main software loop responds to the button, initiates ADC conversions, and does more data processing.
The problem is that I've discovered its difficult to get the DTC turned on. By this I mean that although interrupts are enabled, and I understand I'm supposed to load ADC10SA inorder to kick off DTC interrupts, something is broken.
The process I believe I should have to follow is simple:
Initialize the ADC: CONSEQ_2, MSC, ADC10ON, ADC10IE in particular but among others (see below).
Before starting conversions do:
ADC10CTL0 &= ~ENC;
while (ADC10CTL1 & ADC10BUSY);
ADC10SA = (unsigned short) adc10blk; // Prime DTC State Machine
Start the conversions:
ADC10CTL0 |= (ENC + ADC10SC);
At any point to stop the conversion:
ADC10CTL0 &= ~ENC;
But thats not what I ended up having to do. In one failure mode the very first sets of conversions don't get picked up by the DTC -- so there are no interrupts. But after I turn the switch off then on again, the DTC starts generating interrupts. So in response to that data point, I started adding "extra" DTC initiations (I loaded the ADC10SA more times than necessary.) In another failure mode, the first conversions DO kick off the DTC, but after I turn the switch off and on again, the DTC does not begin to generate interrrupts -- although, once again, the ADC is actively converting -- so the peripheral behaves as though I never loaded ADC10SA although I was successful at starting the converter.
After much trial and error, I got the thing to work by doing the following craziness. Note all the extra loadings of ADC10SA. Has anyone else seen this before?
In general I initialize the ADC as follows: (not all settings shown, to try and make this more readable)
ADC10AE0 = 0x00 | VSENS; //VSENS is the name of my analog input pin, A5.
ADC10CTL1 = 0x00 | INCH_5 | CONSEQ_2;
ADC10CTL0 = 0x00 | ADC10ON | MSC |ADC10SHT_
ADC10DTC1 = SAMP_IN_BLK;
In the main software loop, I've found I need to load ADC10SA several times to keep the DTC interrupts coming: Below I'm showing what I do with the ADC in my state machine.
FIRST STATE:
ADC10CTL0 |= ADC10IE; // Enable ADC interrupts
ADC10CTL0 &= ~ENC;
while (ADC10CTL1 & ADC10BUSY);
ADC10SA = (unsigned short) adc10blk; // Prime DTC State Machine - first priming
SECOND STATE
// A button has been pushed, prepare to take a measurement
ADC10CTL0 |= ADC10IE; // Enable ADC interrupts - I probably don't have to do this again.
ADC10CTL0 &= ~ENC;
while (ADC10CTL1 & ADC10BUSY);
ADC10SA = (unsigned short) adc10blk; // Prime DTC State Machine - I definitely have to do this again. - second priming
THIRD STATE
// After a delay of 5-20ms, start conversions.
conv_complete = 0; // The interrupt routine will flip this bit to tell the state machine it is finished.
ADC10CTL0 &= ~ENC;
while (ADC10CTL1 & ADC10BUSY);
ADC10SA = (unsigned short) adc10blk; // 3rd priming and now we will start converting too.
ADC10CTL0 |= (ENC + ADC10SC);
P1OUT ^= TESTB; // This I/O bit flip lets me keep track of progress on the scope.
FOURTH STATE
// if the user hits the button, stop converting and go back to the SECOND STATE (after a one 500 mili-second delay)
ADC10CTL0 &= ~ENC;
while (ADC10CTL1 & ADC10BUSY);
ADC10SA = (unsigned short) adc10blk; // prime DTC. First priming for the NEXT cycle of conversions.
// if there is no button activity but the conversion set is ready, process the data, then kick off a new conversion and stay in this state.
conv_complete = 0;
while (ADC10CTL1 & ADC10BUSY);
ADC10SA = (unsigned short) adc10blk;
ADC10CTL0 |= ENC + ADC10SC;
P1OUT ^= TESTB; // flip bit at beginning of each conversion.
INTERRUPT SERVICE ROUTINE:
TakeAvg(); // Average the samples for later processing.
conv_complete = 1; // Tell state machine we are done.
ADC10CTL0 &= ~ENC; // Just turn off the conversions. State machine will turn them back on.
P1OUT ^= TESTB; // bit flip lets me see on scope that we did indeed have an interrupt.
It almost seems like ADC10SA acts like an on/off switch somehow. Is anyone else seeing signs of that?
***2/8/2013***
Did some more checking this morning and the statement, "ADC10SA = (unsigned short) adc10blk;" acts like a toggle switch in the DTC state machine. I've verified that while I can turn on the DTC interrupts with one repetition of the statement, two repetitions turns the DTC interrupts off and, yes, 3 repetitions turns them on. I didn't see that coming!
In a different thread som epeople reported that they sometimes have to set ADC10SC twice in a row to get the conversion started.
You could try that in third state. It's just a kludge, even if it works, but since no final analysis/explanation/fix of the problem is found yet...
**Attention** This is a public forum