Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] question about ADC module on uC

Status
Not open for further replies.

silverwolfman

Junior Member level 1
Junior Member level 1
Joined
Feb 22, 2013
Messages
16
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Visit site
Activity points
1,408
MPLAB X16, dsPIC33FJ
Hi guys,
Its my first time tried to use the ADC module and it really gives me some hard time, I've tried to use AN1 & AN2 as the analog input, 12bit accuracy, using scan method and only opened muxA, I saw the value change in ADC1BUF0(its fluctuated because its switching between AN1 and AN2), the device I am using is with DMA, I have 2 questions:

1.what should I do to read out the these two value sperately? I am not quite familiar with the DMA. Can I have some examples how to setup and use the DMA for ADC?

2.another question is, if I have to match the two Analog input to DMA, does that mean the device with DMA is slower? In stead of reading directly from register(ADC1BUF0,ADC1BUF1....in device without DMA) I have to write the value into memory first and then read back?

Thanks ahead.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/********* Initialize ADC  **************************************/
void InitADC(void){
 
        TRISB|=0x0001;
        TRISA|=0x0003;
        AD1PCFGL=0xFFF8;         //AN0=external reference, AN1, AN2
        AD1CON1bits.ADON=0;     //turn off the adc
        AD1CON1bits.AD12B=1;    //12bit conversion CH0
    AD1CON1bits.ASAM=1;    //Sampling begins after conversion auto sampling
        AD1CON1bits.SSRC=7;     //Automatic sampling the data
    AD1CSSL=0x0006;    //Sample scan channels AN1& AN2
        AD1CON1bits.FORM=1;     //signed data
 
    AD1CON2bits.CSCNA=1;    //select scan auto sampling
    AD1CON2bits.SMPI=0x0001;//select 2 conversion after sampling
    AD1CON2bits.VCFG=0; //select reference source
    AD1CON2bits.ALTS=0; //Just use the scan channel
 
        AD1CON3bits.ADRC=0; //system clock as sampling
    AD1CON3bits.SAMC=0x1;   //sample clock
        AD1CON3bits.ADCS=63;   //ADC clock frequency=100kHz
 
        AD1CHS0=0x0101;   //scan AN1 and AN2 using MuxA
        AD1CON1bits.ADON=1;   //enable ADC
 
}

 
Last edited:

there are some example of using dsPIC33 ADCs with DMA on Microchip's code examples page
**broken link removed**

below is code I used with a dsPIC33EP256MU806 adapted from one of microchip's examples
Code:
#if defined(__dsPIC33E__)
#include "p33exxxx.h"
#elif defined(__PIC24E__)
#include "p24exxxx.h"
#endif

#include "hardware.h"
#include <libpic30.h>		// for __delay_us FCY must be defined!
#include "adc1.h"

// User Defines



#define NUMSAMP	256
//int BufferA[NUMSAMP] __attribute__((space(dma)));
//int BufferB[NUMSAMP] __attribute__((space(dma)));
#ifdef _HAS_DMA_
__eds__ int BufferA[NUMSAMP] __attribute__((eds,space(dma)));
__eds__ int BufferB[NUMSAMP] __attribute__((eds,space(dma)));
#else
 int BufferA[NUMSAMP] __attribute__((space(xmemory)));
int BufferB[NUMSAMP] __attribute__((space(xmemory)));
#endif
void ProcessADCSamples(__eds__ int * AdcBuffer);



//Functions:
//initAdc1() is used to configure A/D to convert ANchannel in 12bit mode
//at 500Ksamples/second throughput rate. ADC clock is configured at Tad=150
//  assuming an FCY of 60MIPS
void initAdc1(int ANchannel)
{


		AD1CON1bits.FORM   = 0;		// Data Output Format: integer
		AD1CON1bits.SSRC   = 7;		// Interan Counter (SAMC) ends sampling and starts convertion
		AD1CON1bits.ASAM   = 0;		// ADC Sample Control: Sampling begins immediately after conversion
		AD1CON1bits.AD12B  = 1;		// 12-bit ADC operation

		AD1CON2bits.CHPS  = 0;		// Converts CH0
     
		AD1CON3bits.ADRC=0;			// ADC Clock is derived from Systems Clock
		AD1CON3bits.SAMC=2; 		// Auto Sample Time = 0*Tad		
		AD1CON3bits.ADCS=5;		    // 12 bit ADC Conversion Clock Tad=Tcy*(ADCS+1)= (1/60M)*4 = 150nSec approx
									// ADC Conversion Time for 10-bit Tc=12*Tad =  900ns (1.1MHz)
									// ADC Conversion Time for 12-bit Tc=14*Tad =  2000ns (500Ksamples/sec)
					
		AD1CON1bits.ADDMABM = 1; 	// DMA buffers are built in conversion order mode
		AD1CON2bits.SMPI    = 0;	// SMPI must be 0
		AD1CON4bits.ADDMAEN  = 1;		// Converts in ADC1BUF0

  		//AD1CHS0/AD1CHS123: A/D Input Select Register
	    AD1CHS0bits.CH0SA=ANchannel;		// MUXA +ve input selection (AIN0) for CH0 AN24 RE0
		AD1CHS0bits.CH0NA=0;		// MUXA -ve input selection (Vref-) for CH0
	
	    //AD1CHS123bits.CH123SA=0;	// MUXA +ve input selection (AIN0) for CH1
		//AD1CHS123bits.CH123NA=0;	// MUXA -ve input selection (Vref-) for CH1

        IFS0bits.AD1IF = 0;			// Clear the A/D interrupt flag bit
        IEC0bits.AD1IE = 0;			// Do Not Enable A/D interrupt 
        
        AD1CON1bits.ADON = 1;		// Turn on the A/D converter	
        
        __delay_us(20);			// Delay for 20uS to allow ADC to settle (25nS * 0x320 = 20uS)
        
        AD1CON1bits.ASAM = 1;		// Sampling begins immediately after last conversion. SAMP bit is auto-set

}

// DMA0 configuration
// Direction: Read from peripheral address 0-x300 (ADC1BUF0) and write to DMA RAM 
// AMODE: Register indirect with post increment
// MODE: Continuous, Ping-Pong Mode
// IRQ: ADC Interrupt
// ADC stores results stored alternatively between DMA_BASE[0]/DMA_BASE[16] on every 16th DMA request 

void initDma0(void)
{
	DMA0CONbits.AMODE = 0;			// Configure DMA for Register indirect with post increment
	DMA0CONbits.MODE  = 2;			// Configure DMA for Continuous Ping-Pong mode

	DMA0PAD=(int)&ADC1BUF0;
	DMA0CNT=(NUMSAMP-1);				
	
	DMA0REQ=13;	
	#ifdef _HAS_DMA_
	DMA0STAL = __builtin_dmaoffset(&BufferA);
	DMA0STAH = __builtin_dmapage(&BufferA);

	DMA0STBL = __builtin_dmaoffset(&BufferB);
	DMA0STBH = __builtin_dmapage(&BufferB);
	#else
	DMA0STAL = (unsigned int)&BufferA;
	DMA0STAH = (unsigned int)&BufferA;

	DMA0STBL = (unsigned int)&BufferB;
	DMA0STBH = (unsigned int)&BufferB;
	#endif
	
	IFS0bits.DMA0IF = 0;			//Clear the DMA interrupt flag bit
    IEC0bits.DMA0IE = 1;			//Set the DMA interrupt enable bit
	
	DMA0CONbits.CHEN=1;


}





/*=============================================================================
_DMA0Interrupt(): ISR name is chosen from the device linker script.
=============================================================================*/
unsigned int DmaBuffer = 0;

void __attribute__((interrupt, auto_psv)) _DMA0Interrupt(void)
{
		if(DmaBuffer == 0)
		{
			ProcessADCSamples(BufferA);
		}
		else
		{
			ProcessADCSamples(BufferB);

		}

		DmaBuffer ^= 1;
static int count=0;
	if(count++ > 100) {LED1=!LED1; count=0; }
//		__builtin_btg((unsigned int *)&LATA, 6); // Toggle RA6		
        IFS0bits.DMA0IF = 0;				 	 //Clear the DMA0 Interrupt Flag
}


int ADCdata;
void ProcessADCSamples(__eds__ int * AdcBuffer)
{
	/* Do something with ADC Samples */
ADCdata=AdcBuffer[0];
}
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top