|
|
View previous topic :: View next topic |
Author |
Message |
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
Has anyone played with PIC24 DMA sampling multi-channels? |
Posted: Sun Jan 14, 2018 10:35 am |
|
|
Hi,
Trying to implement the ability to sample three channels sequentially with DMA on a PIC24FJ256GA702.
Now according to the data, it appears you can set the channels you want to sample in the AD1CSS register, use legacy mode (so the channel data is stored sequentially rather than indexed by channel number), select 'autoconvert' mode, with a suitable Tad multiplier programmed to acquire, enable autoscanning (CSCNA=TRUE), and specify the number of samples you want it to perform, set the DMA to trigger on ADC1, start the DMA transaction. Then trigger the ADC to start and when it completes the DMA should keep cycling through the selected channels for the selected number of cycles.
I currently have the clock divider to give 312.5uSec and 3.12uSec acquire time.
Now unfortunately the CCS example on ADC's like this only handles one channel, and is on a chip where the setup is a little different (offers DMA_IN_ADC1, rather than DMA_TRIGGER_ADC1).
I'm actually getting correct results right through the buffer, but for AN1 only.
Will query CCS about this, but wondered if anyone had played with this type of setup?.
My 'play' code so far is:
Code: |
int1 DMA_complete; // Flag to test if DMA interupt has been serviced.
#define BUFFER_SIZE 54 //DMA BUFFER Size
#BANK_DMA
unsigned int DMA_BUFFER[BUFFER_SIZE];
//This interrupt gets triggered after 54 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 ADC1BUF=getenv("SFR:ADC1BUF0")
void launch_dma(void)
{
//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=0b0000000000110010; //AN1, 4 & 5 in the scan
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, 54); //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 54 samples
read_adc(ADC_START_ONLY);
}
//Then where I check for the results:
if (DMA_complete)
{
//here I process the results, then retrigger
DMA_complete=FALSE;
read_adc(ADC_START_ONLY); //retrigger DMA
}
|
I seem actually to be getting results, but only from AN1.
There is a thread showing doing this on a PIC33 in the code library, but here scatter/gather is used, rather than the sequential sampling. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Thu Jan 18, 2018 9:19 am |
|
|
as an update to this.
Anyone else trying on this chip, there appear to be some 'discrepancies' between the chip and the data sheet. Currently investigating.
Code slightly patched, working OK on a PIC24GJGB210, but refusing to work properly on the PIC24FJ256GA702.... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Sat Jan 20, 2018 3:49 pm |
|
|
As a final update.
On these chips it turns out the data to feed to the DMA is not available on ADC1BUF0. It is instead on a register called AD1RESDMA. If you define this and use it to feed the DMA routines, everything starts addressing as it should. It is listed in the data sheet, but with no reference to what it is for. The application note for the chip has the data being read from ADC1BUF0. However if you use this it 'sort of works', you don't get the proper data indexing.
You don't even have to enable PIA addressing. It is like a virtual 'window' that automatically sequences the available ADC data.
A caveat for anyone playing with this in the future... |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|