# dsPIC30F: 10-bit ADC. What happens after the bit DONE is set?

Documentation on the 10-bit ADC gives numerous samples. But none of these samples explain in clear what happens and what should the software do once the DONE bit is set.

Let's consider the section 17.16.1 Sampling and Converting a Single Channel Multiple Times. It is the most simple. Documentation gives a very nice chart:

So, what happens after the DONE and ADIF signals are set? It is to the right, outside of this chart.

1. Is it right understanding that module with continue its work filling and refilling the buffer (assuming that software will not do anything)?
2. Will the DONE signal be reset shortly after it was set, when the 17-th conversion will start?
3. If the answer to the first question is true, this means that software has very short time (maybe just a few instruction depending on the system clock speed) when the value in the ADCBUF0 will be overwritten and lost. Is that correct understanding?

How should I modify the setup described in this section if I want ADC to grab 16 samples and stop? After that I will process the interrupt and start a new ADC session later when it will be the right time to do that.

You did not mentioned the exact dsPIC model so I am assuming it is dsPIC30-series and the documentation you are referring to is this one: http://ww1.microchip.com/downloads/en/devicedoc/70064e.pdf

Your assumptions are correct. I don't think there's a way to setup this ADC to automatically stop after certain number of sample / conversions. However, you can manually disable the whole module in the ISR occurring after 16th conversion. This will abort 17th sample / conversion and ADCBUF0 will not be overwritten. You can then later re-enable the ADC when you have processed the buffer.

volatile uint8_t newValues = 0;
{
AD1CON1bits.ADON = 0;   // this must be executed before the end of 17th conversion
newValues = 1;
}

int main(void)
{
AD1CON2bits.SMPI = (16-1);  // interrupt after 16th sample/conversion
AD1CON3bits.SAMC = 31;      // sample time
while(1)
{
if(newValues)
{
newValues = 0;
}
}
return 0;
}


However, I think a better way is to utilize alternating buffer filling mode, described in chapter 17.14.3. In this mode, interrupt will occur twice per full buffer update. Software should have plenty of time (8 * sample / conversion time) to copy ADCBUF values to some other buffer for later processing.

#define ADC_RINGBUF_SIZE     32     // must be multiple of 8
{
{
}
{
}
else
{
}
}

int main(void)
{
AD1CON2bits.SMPI = (8-1);   // interrupt after 8th sample/conversion
AD1CON2bits.BUFM = 1;       // alternate buffer half on each interrupt
AD1CON3bits.SAMC = 31;      // sample time
while(1)
{
{
if((adcRingBufWr - adcRingBufRd) >= 16) // how many values we want to process at a time
{
}
}
{
{
}
}
}
return 0;
}


Note: This is very naive ring buffer implementation (just to show idea).

• Thanks for your answer. It is kind of surprising that with so many registers and flags there is no mode where it grabs samples from a set of inputs and stops. ISR will help, but it brings into the game a lot of additional conditions. There can be ton of situations when other devices are working and require attention right at this point. May 6 '19 at 1:06
• It is possible to stop ADC automatically for one channel or several S/H channels in SIMSAM mode: put no ASAM, set SAMP on from software. After making one sampling session ADC will stop. But for scanning inputs (CSCNA mode) to my understanding ASAM is unavoidable. And this standing ASAM will cause continuation of work after reaching DONE if there is no software intervention. Do you agree with this? May 6 '19 at 1:08
• Regarding the BUFM mode, your comment is right but it has nothing to do with the original question. Question was not on getting help on basic programming. It was on what is not written in the docs. You maybe remove the second part of your answer. May 6 '19 at 1:11
• I tried variant where I clear ADON in the ISR and poll DONE bit in the main thread. This looks to work fine. This way I am avoiding the newValues flag. May 6 '19 at 2:15
• Yes, when SAMP = 1 and ASAM = 0 (with any other parameters), it will make only one sample. You can avoid ISR with BUFM mode, because you don't need to react very fast, unlike with the first example. Just poll AD1IF and do the same what is done in the ISR in my example. May 6 '19 at 18:58