View previous topic :: View next topic |
Author |
Message |
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
PIC24FJ128GA308 ADC Input Scan |
Posted: Wed Mar 10, 2021 6:44 am |
|
|
Hello,
I need some help setting up the PIC24FJ128GA308 to scan specific ADC inputs and interrupt when all results are available.
Trigger could be Timer1 for example.
Is this supported in CCS?
Thanks. _________________ George. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Mar 10, 2021 7:23 am |
|
|
The automated scan on that ADC, is a 'Threshold scan'. It is designed to
compare signals with levels and interrupt when thresholds are met.
I think you would be simpler and better, to just use DMA. The DMA supports
sequencing through ADC channels. You can specify this to interrupt when a
certain number of reading have been done, so you can set it up to give you
(for example) 8 sets of readings from 4 selected ADC channels, and when
you get the interrupt the buffer will have these all neatly stacked in order. |
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Wed Mar 10, 2021 7:33 am |
|
|
Ttelmah,
Thanks for the reply.
Is there any example available?
I already have it working with read_adc(); _________________ George. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Thu Mar 11, 2021 1:11 am |
|
|
This is a little urgent and I cannot afford trial and error.
For now I will read each channel one by one and maybe come back to DMA later in the project.
I was hoping for a more "ready" example.
Thanks for the support as always _________________ George. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Thu Mar 11, 2021 1:24 am |
|
|
Except for the need to change the ADC channel setup to suit your project,
and possibly needing to use the different register to get the scanning to
give the right sequencing (which is probably specific to the chip I was
using), what I posted is a ready to go example. |
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Thu Mar 11, 2021 1:48 am |
|
|
OK, this just prints once to the terminal and stops.
The value is 0 though.
I changed AD1CSS to suit my channels.
Any ideas?
Code: |
int1 DMA_complete; // Flag to test if DMA interupt has been serviced.
#define BUFFER_SIZE 8 //DMA BUFFER Size
#BANK_DMA
unsigned int DMA_BUFFER[BUFFER_SIZE];
//This interrupt gets triggered after 8 DMA transfers(DMACOUNT) are complete
#INT_DMA0
void DMA0_ISR(void)
{
DMA_complete = TRUE;
}
#BIT DMABM=getenv("BIT:DMABM")
#BIT DMAEN=getenv("BIT:DMAEN")
#BIT ASEN=getenv("BIT:ASEN")
#BIT BUFM=getenv("BIT:BUFM")
#BIT ADON=getenv("BIT:ADON")
#BIT ASAM=getenv("BIT:ASAM")
#BIT CSCNA=getenv("BIT:CSCNA")
#BIT ALTS=getenv("BIT:ALTS")
#BIT PUMPEN=getenv("BIT:PUMPEN")
#BIT BUFREGEN=getenv("BIT:BUFREGEN")
#WORD AD1CON1=getenv("SFR:AD1CON1")
#WORD AD1CON2=getenv("SFR:AD1CON2")
#WORD AD1CON3=getenv("SFR:AD1CON3")
#WORD AD1CON4=getenv("SFR:AD1CON4")
#WORD AD1CON5=getenv("SFR:AD1CON5")
#WORD AD1CSS=getenv("SFR:AD1CSSL")
#WORD AD1CSSH=getenv("SFR:AD1CSSH")
#WORD ADC1BUF0=getenv("SFR:ADC1BUF0")
#WORD ADC1BUF=getenv("SFR:ADC1BUF0")
|
Code: |
void launch_dma(void){
SETUP_ADC(ADC_CLOCK_INTERNAL);
SETUP_ADC_PORTS(sAN0 | sAN1 | sAN2 | sAN3 | sAN6 | sAN7 | sAN14 | sAN15 | VSS_VDD);
//Now need to tweak the ADC settings. Must set the individual enable
//bits for the three channels required, and set the mode to automatically
//scan the channels
//Need to disable ADC before configuring
ADON=FALSE;
DMAEN=FALSE; //extended features off
DMABM=FALSE; //default mode
AD1CSS=0b1100000011001111;
AD1CSSH=0; //No other channels used
ASEN=FALSE; //turn off the threshold detect scan
ALTS=FALSE; //single MUX
CSCNA=TRUE; //continuous scan of selected channels
BUFM=TRUE; //This should each read back to ADC1BUF0
PUMPEN=FALSE; //disable charge pump (AVdd=3.3v)
AD1CON2 &= 0xFF83; //SMPI=0000 forces interrupt/DMA on every sample
//trying note from download setting 3 instead - no change
//AD1CON2 |= 0x0080; //every third?
BUFREGEN=FALSE; //All I/O through ADC1BUF0
ASAM=TRUE; //automatic sample timing
AD1CON5 &= 0xFCF3; //ensure ASINT is disabled and WM=00
AD1CON1 = (AD1CON1 & 0xFF0F) | 0x0070; //SSRC=0111, selects Autoconvert mode
//Now enable the ADC again
ADON=TRUE;
//set_adc_channel(1); //select 1 as first channel
DMA_complete = FALSE;
setup_dma(0, DMA_TRIGGER_ADC1, DMA_WORD);
dma_start(0, DMA_CONTINUOUS | DMA_INC_DEST_ADDR | DMA_SOURCE_ADDR_UNCHANGED , DMA_BUFFER , &ADC1BUF, 8); //DMA_INC_DEST_ADDR |
enable_interrupts(INT_DMA0); //dma will now depend on ADC
//Now triggering a read_adc, should force the buffer to fill with 8 samples
read_adc(ADC_START_ONLY);
while(1){
if (DMA_complete){
//here I process the results, then retrigger
DMA_complete=FALSE;
fprintf(USB,"\n\rADC1:%u",DMA_BUFFER[0]);
read_adc(ADC_START_ONLY); //retrigger DMA
}
delay_ms(50);
}
}
|
_________________ George. |
|
|
|