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.

analog to digital converter for dspic33fj64mc802

Status
Not open for further replies.

nitin.joshi52@gmail.com

Newbie level 5
Joined
Mar 30, 2013
Messages
10
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,396
Gm SIR,
my name is nitin joshi.i am very much new on microchip.
I want to write code for a to d converter ie want to take two analog input ie first one is sine wave(voltage) and another one is an offset voltage.
i am using dsPIC33fj64mc802 IC and writing code in xc 16 compiler.
in this there are 6 analog inputs are given.i want to select two analog input.ie AN0 and AN1.four channels are available and i want to select channel CH1 and CH2 for AN0 and AN1.
right now i am using general data sheet for dspic33 section 16 analog to digital converter and reference manual for dsPIC33.i want specific data sheet to configure a to d for dspic33fj64mc802.
here i am attaching the code also which i have already written.
but this is not working.
also I want to read 2 adc value but I don't know how to read 2 adc value because in the datasheet only one adc buffer is available.
how to write this delay function also because this library delay is not working.
please help .i am very much new may be i forgot to give you some more information.
thanks in advance
here is my code .......

#include<xc.h>
#include<delay.h>
#include<time.h>
#include<p33FJ64MC802.h>
#include<stdint.h>
int ADCValue;

void initAdc1(void)
{

AD1CON1bits.AD12B = 0; // select 10-bit ADC operation


AD1CON2bits.VCFG=0;//Converter Voltage Reference Configuration bits(Avdd & Avss)


AD1CON3bits.ADRC = 0; // ADC Clock is derived from Systems Clock
AD1CON3bits.SAMC = 0; // Auto Sample Time = 0 * TAD
AD1CON3bits.ADCS = 2; // ADC Conversion Clock TAD = TCY * (ADCS + 1) = (1/40M) * 3 =
// 75 ns (13.3 MHz)
// ADC Conversion Time for 10-bit Tconv = 12 * TAD = 900 ns (1.1 MHz)

AD1CON2bits.ALTS =0;//Always uses channel input selects for Sample A
AD1PCFGL = 0xFFFC;//AN0 and AN1 are selected as analog input pins......
//AD1PCFGLbits.PCFG0 = 0; // AN0 as Analog Input


AD1CHS123bits.CH123SA = 0; // CH1 positive input is AN0, CH2 positive input is AN1
AD1CHS123bits.CH123NA = 0; //CH1, CH2, CH3 negative input is VREF-(vss)



AD1CON2bits.CHPS = 3; // Converts channels CH1/CH2



AD1CON1bits.SIMSAM=1; //Samples CH1, CH2 simultaneously


AD1CON1bits.SSRC = 7; // Internal Counter (SAMC) ends sampling and starts conversion
AD1CON1bits.ASAM = 1; // ADC Sample Control: Sampling begins immediately after conversion



AD1CON1bits.FORM = 3; // Data Output Format: Signed Fraction (Q15 format)

AD1CON1bits.ADON = 1; // Turn on the ADC
}




int ADCread(void)
{

AD1PCFGLbits.PCFG0 = 0; // AN0 as Analog Input
IFS0bits.AD1IF = 0; // Clear the Analog-to-Digital interrupt flag bit
IEC0bits.AD1IE = 0; // Do Not Enable Analog-to-Digital interrupt
AD1CON1bits.ADON = 1; // Turn on the ADC
AD1CON1bits.SAMP = 1; // Start sampling
//DelayUs(10); // Wait for sampling time (10us)
AD1CON1bits.SAMP = 0; // Start the conversion
while (!AD1CON1bits.DONE); // Wait for the conversion to complete
//ADCValue = ADC1BUF0; // Read the conversion result

}





void main()
{
initAdc1();


while(1)
{

ADCread();
ADCValue = ADC1BUF0;read the adc value

}
}
 

Greetings,

Here is a code example that I have from a previous project of mine. It is for the dsPIC33FJ32MC302 processor. It might not have the same layout as yours, but it should give you a very good starting point. I have included both the init function that sets up the A/D, and the function that I use to read a value...

Initialization Code...
Code:
void init_ADC(int port) {

	// AD1CON1 = 0x00E0
	_ADON = 0;		// Turn the device off while we set it up
	_ADSIDL = 0;	// Allow the device to continue operating in idle mode
	_ADDMABM = 0;	// DMA buffers are written in scatter/gather mode.
	_AD12B = 0;		// Use the 10 bit operation mode.
	_FORM = 0b00;	// we're using a signed integer 10-bit operation
	_SSRC = 0b111;	// Allow the internal counter to end sampling and start conversion (auto-convert)
	_SIMSAM = 0;	// Samples on multiple channels are done individually.
	_ASAM = 0;		// Sampling begins when SAMP bit is set.
	_SAMP = 0;		// Do not start sampling yet
	_DONE = 0;		// Clear the Done status bit
	
	// AD1CON2 = 0x0000
	_VCFG = 0b000;	// Set V_REFH to A_VDD and V_REFL to A_VSS
	_CSCNA = 0;		// Do not scan inputs CH0+.
	_CHPS = 0b00;	// Convert CH0.
	_BUFS = 0;		// Not using _BUFM.
	_SMPI = 0b0000;	// Increments the DMA address or generates interrupt after completion of every sample/conversion operation
	_BUFM = 0;		// Start filling the buffer from the start address
	_ALTS = 0;		// always use channel input selects for Sample A
	
	// AD1CON3 = 0x1F02
	_ADRC = 0;		// Use the clock derived from the system clock.
	_SAMC = 0b11111;// Take samples for 31 clock cycles
	_ADCS = 0x02;
	
	AD1CSSL = 0;
	
	switch(port) {
		case 2:	// Set AN0 as an input.
			_PCFG0 = 0;	// Set the analog/digital port to be analog.
			break;
		case 3:	// Set AN1 as an input.
			_PCFG1 = 0;	// Set the analog/digital port to be analog.
			break;
		case 4:	// Set AN2 as an input.
			_PCFG2 = 0;	// Set the analog/digital port to be analog.
			break;
		case 5:	// Set AN3 as an input.
			_PCFG3 = 0;	// Set the analog/digital port to be analog.
			break;
		case 6:	// Set AN4 as an input.
			_PCFG4 = 0;	// Set the analog/digital port to be analog.
			break;
		case 7:	// Set AN5 as an input.
			_PCFG5 = 0;	// Set the analog/digital port to be analog.
			break;
		default:
			error(20);	// Invalid port specified
	}
	
	_ADON = 1;	// Turn the ADC on.
}


Read a Value...
Code:
int ADC_read(int port)
{
	int ADCReading = 0;	// variable to return.
	ADC1BUF0 = 0; 		// Clear the buffer
	_DONE = 0;			// Clear the done bit.
	
	switch(port) {
		case 2:	// Read ADC info from AN0.
			if(0 == _PCFG0) AD1CHS0 = 0x0000;
			else error(81);
			break;
		case 3:	// Read ADC info from AN1.
			if(0 == _PCFG0) AD1CHS0 = 0x0001;
			else error(81);
			break;
		case 4:	// Read ADC info from AN2.
			if(0 == _PCFG0) AD1CHS0 = 0x0002;
			else error(81);
			break;
		case 5:	// Read ADC info from AN3.
			if(0 == _PCFG0) AD1CHS0 = 0x0003;
			else error(81);
			break;
		case 6:	// Read ADC info from AN4.
			if(0 == _PCFG0) AD1CHS0 = 0x0004;
			else error(81);
			break;
		case 7:	// Read ADC info from AN5.
			if(0 == _PCFG0) AD1CHS0 = 0x0005;
			else error(81);
			break;
		default:
			error(80);
			break;
	}
	
	// If there is no reading then take one.
	if(!ADCReading) {
		AD1CON1bits.SAMP = 1;	// start sampling ...
		while (!_DONE);			// wait for it to finish sampling
		ADCReading = ADC1BUF0;	// put the bits in the return variable
	}
	
	return ADCReading;					// return the reading
}


I commented the code, so you should be able to see everything that is being done to read from the A/D. Furthermore, the function that I have written lets you specify which channel you would read from so you can use this to do you readings on both channels...

Here is an example of how you would accomplish obtaining data from two different channels...

1. Declare two variables that you will use to store data. Let's call them data1 and data2.
2. Initialize the ADC.... init_ADC(AN0); (You can use any port you want when you initialize).
3. Perform the first reading on the first channel and store the value... data1 = ADC_read(AN0);
4. Perform the second reading on the other channel... data2 = ADC_read(AN1);

Hope this helps.

Kind Regards,
Willis
 

thanks for warm reply..........................
It helped me a lot but my problem is I don't have so many buffers(ADCBUF) in dspic33fj64mc802.
I have only 1 ADCBUF.
I want to read two value first for sine wave and other for offset voltage and that to simultaneous sampling not sequential.
I want to read two analog input ie AN0 from channel1 and AN1 from channel2 simultaneously.
my problem is how to read those values in ADCRead function.
here is the attachment of my programme.
please help.

#include<xc.h>
#include<p33FJ64MC802.h>






void initAdc1(void)
{
AD1CON1 =0x10EC;
AD1CON2 =0x0300;
AD1CON3 = 0x1F02;
AD1CON4 =0;
AD1CSSL =0;
AD1CHS123bits.CH123SA =0;
AD1CHS123bits.CH123NA =0;
AD1PCFGL = 0xFFFF;
AD1PCFGLbits.PCFG0 = 0; // AN0 as Analog Input
AD1PCFGLbits.PCFG1 = 1; // AN1 as Analog Input
AD1CON1bits.ADON = 1; // Turn on the ADC


}

void initDma0(void)
{
//unsigned int BufferA[8] __attribute__((space(dma)));
//unsigned int BufferB[8] __attribute__((space(dma)));

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 = 0;
DMA0REQ = 13;
DMA0STA = 0;
DMA0STB = 0;
//DMA0STA = __builtin_dmaoffset(BufferA);
//DMA0STB = __builtin_dmaoffset(BufferB);
IFS0bits.DMA0IF = 0; //Clear the DMA interrupt flag bit
IEC0bits.DMA0IE = 1; //Set the DMA interrupt enable bit
DMA0CONbits.CHEN = 1;
}



void initTIMER3(void)
{
TMR3 = 0x0000;
PR3 = 4999; // Trigger ADC1 every 125 ?s @ 40 MIPS
IFS0bits.T3IF = 0; // Clear Timer3 interrupt
IEC0bits.T3IE = 0; // Disable Timer3 interrupt
T3CONbits.TON = 1; //Start Timer3
}



int ADCReading =0;
void ADC_read()
{
if(!ADCReading) {
AD1CON1bits.SAMP = 1; // start sampling ...
while (!_DONE); // wait for it to finish sampling
ADCReading = ADC1BUF0; // put the bits in the return variable
}

}


main()
{
initAdc1();
initDma0();
initTIMER3();
while(1)
{
ADC_read();
}

}
 

thanks...
I am not able to understand your question??
I am very much new to this coding.
yes that I know that I can read only one ADC channel at a time and in fact I want the same.
I want to read AN0 from channel 1 and AN1 from channel 2.
I want simultaneous sampling of an1 and an2.
now I know how to configure ADC1 and somehow how to configure DMA also.
my problem is I don't know how to write code to read this value.
whatever I did for ADCReading that I copied from given example.
i am little bit confuse about DMAxSTB regs also.
please help.
 

You cannot do simultaneous sampling. When I said you can only read one channel at a time then it means that reading adc channels cannot be simultaneous. You read channel 1 first and then channel 2. When you read channel 1 then save the adc value to variable1 and then when 2nd channel is read save the value to another variable variable2. The use those values to do whatever operation you want to do. Microcontroller can only do one thing at a time because it can only execute one instruction at a time.
 

thanks.....
1.it is possible to sample simultaneously(SIMSAM=1).
2.the conversion is sequential(one at a time) say AN0 first & AN1 next.
3.AD1BUF0 when filled with first conversion ie value of AN0 will interrupt for DMA transfer, DMA hence will transfer AN0 value from ADC1BUF0(0x300) to the first DMA buffer location ie (0x4000).
4.on next convert of AN1, ADC1BUF0 will have new value of AN1 and interrupt DMA for transfer.
5.we want this new AN1 value to be read in DMA buffer at address location 0x4001 and so on.......
6.we want to read DMA buffer specific locations,0x4000 for AN0 & 0X4001 for AN1.

if you want more information I can give you.
please help
thanks again
 

Ok. You can do simulataneous conversion. AD1CON2bits.CHPS = 3; // Converts channels CH1/CH2 should be AD1CON2bits.CHPS = 1; // Converts channels CH1/CH2
 

I have already configured that thing sir.........:-o
my problem is something else.
how to read that value.
 

22.3ADC and DMA
If more than one conversion result needs to be buffered
before triggering an interrupt, DMA data transfers can
be used. ADC1 can trigger a DMA data transfer. If
ADC1 is selected as the DMA IRQ source, a DMA
transfer occurs when the AD1IF bit gets set as a result
of an ADC1 sample conversion sequence.
The SMPI<3:0> bits (AD1CON2<5:2>) are used to
select how often the DMA RAM buffer pointer is
incremented.
The ADDMABM bit (AD1CON1<12>) determines how
the conversion results are filled in the DMA RAM buffer
area being used for ADC. If this bit is set, DMA buffers
are written in the order of conversion. The module
provides an address to the DMA channel that is the
same as the address used for the non-DMA
stand-alone buffer. If the ADDMABM bit is cleared, then
DMA buffers are written in Scatter/Gather mode. The
module provides a scatter/gather address to the DMA
channel, based on the index of the analog input and the
size of the DMA buffer.

Which Compiler are you using? mikroC PRO dsPIC?
 

22.3ADC and DMA
If more than one conversion result needs to be buffered
before triggering an interrupt, DMA data transfers can
be used. ADC1 can trigger a DMA data transfer. If
ADC1 is selected as the DMA IRQ source, a DMA
transfer occurs when the AD1IF bit gets set as a result
of an ADC1 sample conversion sequence.
The SMPI<3:0> bits (AD1CON2<5:2>) are used to
select how often the DMA RAM buffer pointer is
incremented.
The ADDMABM bit (AD1CON1<12>) determines how
the conversion results are filled in the DMA RAM buffer
area being used for ADC. If this bit is set, DMA buffers
are written in the order of conversion. The module
provides an address to the DMA channel that is the
same as the address used for the non-DMA
stand-alone buffer. If the ADDMABM bit is cleared, then
DMA buffers are written in Scatter/Gather mode. The
module provides a scatter/gather address to the DMA
channel, based on the index of the analog input and the
size of the DMA buffer.

Which Compiler are you using? mikroC PRO dsPIC?




my compiler is xc16 .......................device is microstick(dspIC33fj64mc802)
 

my compiler is xc16 .......................device is microstick(dspIC33fj64mc802)


hi.....
I have a query.......
I can not understand your ADCReading function..........
will you please elaborate ....


case2; // Read ADC info from AN0.
if(0 == _PCFG0) AD1CHS0 = 0x0000;
else error(81);
break;
case 3: // Read ADC info from AN1.
if(0 == _PCFG0) AD1CHS0 = 0x0001;
else error(81);
break;
case 4: // Read ADC info from AN2.
if(0 == _PCFG0) AD1CHS0 = 0x0002;
else error(81);
break;
case 5: // Read ADC info from AN3.
if(0 == _PCFG0) AD1CHS0 = 0x0003;
else error(81);
break;
case 6: // Read ADC info from AN4.
if(0 == _PCFG0) AD1CHS0 = 0x0004;
else error(81);
break;
case 7: // Read ADC info from AN5.
if(0 == _PCFG0) AD1CHS0 = 0x0005;
else error(81);
break;
default:
error(80);
break;
}

// If there is no reading then take one.
if(!ADCReading) {
AD1CON1bits.SAMP = 1; // start sampling ...
while (!_DONE); // wait for it to finish sampling
ADCReading = ADC1BUF0; // put the bits in the return variable
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top