CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

ADC using PIC18F4520

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
boham
Guest







ADC using PIC18F4520
PostPosted: Fri Feb 29, 2008 1:11 pm     Reply with quote

Hi all, I have been searching (hopefully well enough) about this but I was planning on using an external ADC to send the bits to my pic for processing but I found out researching that the PIC will do this for me.

I am not sure where I can find info on creating an ADC with this PIC. I am fairly new to PIC programming so bear with me. Any help would be greatly appreciated.

Thanks.
boham
Guest







PostPosted: Fri Feb 29, 2008 1:13 pm     Reply with quote

Oh one more quick question that I think the answer is no but I have to ask anyway:

Can the PIC do D/A?
jma_1



Joined: 08 Feb 2005
Posts: 147
Location: Wisconsin

View user's profile Send private message

PostPosted: Sun Mar 02, 2008 12:16 pm     Reply with quote

Greetings boham,

The datasheet for the 18F4520 device is listed on the web page :

http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1335&dDocName=en010297

The analog to digital conversion has many examples provide by CCS and postings in the forum. There should even be examples posted by CCS on their website -> compiler information / api / etc. Look for functions like setup_port(), set_adc_channel, read_adc(), etc.

You might be able to use PWM output and filter the signal to get an approximate analog output. This might not be flexible enough depending on your analog ouptut requirements.

Cheers,
jma

A better approach would be to use the SPI or I2C and interface a standalone DAC chip.
boham
Guest







PostPosted: Wed Mar 12, 2008 4:26 pm     Reply with quote

OK, here's what I have so far:
Code:
#include <18F4520.h>
#device ADC=8  //set for 8 bit A/D
#use delay(clock=10000000)
#fuses HS,NOWDT
#include <math.h>

//define the A/D control register
#BYTE ADCON0 = 0x1F
int16 ch1_result;  //variable to hold A/D readings
#DEFINE Vres 0.019608

//define the button press for transmit
#define BUTTON_PRESSED (!input(PIN_A4))

#int_AD
void AD_isr(){
   //possibly could use "if(ADCON0){"
   if (((ADCON0 & 0x38) >> 3) == 1){   //must be channel 1
      ch1_result = read_adc();   //get 8-bit reading for ch 1
   }
   ADCON0 |= 0x4;   //Restart  A/D (sets the GO bit to start conversion)
                    //If the program was not interrupt-based, the GO bit
                    //could be interrogated to determine when the conversion
                    //was completed.
}//AD_isr()


void output_bits(){
   //Vres=((ch1_result*5.0)/255.0)*1000;   //calculation of voltage on ADC channel
   int step;
   step = floor(ch1_result / Vres);
   createBinary(step, ticker);
   // outputloop
}

void createBinary(int number, int ticker) {
   int remainder;

   if(number <= 1) {
      //output to a pin
      OUTPUT_TO_A_PIN   //output to pin A0-A7
   }
   else{
      //output to a pin
      remainder = number%2;
      createBinary(remainder);
      OUTPUT_TO_A_PIN   //output to pin A0-A7
   }
}

void main(){
   setup_adc_ports(ALL_ANALOG);    //Use internal reference all analog channels active
   setup_adc(ADC_CLOCK_DIV_32);    //Divide Fosc by 32 to get below clock maximum
                                   //Divisor = Fosc/635 KHz = 10MHz / 625KHz = 16
                                   //The next higher divisor is 32 so it must be used

   enable_interrupts(INT_AD);      //Unmask A/D interrupt
   enable_interrupts(global);      //Enable all unmasked interrupts
   set_adc_channel(1);             //Choose channel 1
   ADCON0 |= 0x4;                  //Start A/D process
   while(TRUE){

      //If the button is pressed, then start sending bits to Bluetooth
      if(BUTTON_PRESSED){
         output_bits();
      }//if
      //else, just wait for a button to be pressed to transmit

   }//main while loop

}//main()


I want an 8 bit A/D from 0V-5V.

5 Volts to 8 bits gives me a Vresolution ~ .01960784V for every bit.

So .01960784 VDc is a 1 in my case which does HEX2DEC = 00000001
1.969908 VDc is a 100 which does HEX2DEC = 01100100
and so on to 255 which is 5.003708 Vdc


so what I have done here is when the analog voltage is read, convert it to a hex based on a number you can see what I did with the floor function to get approximate.

Basically, I am receiving an Analog signal, converting it to an 8 Bit binary number and sending the binary number to the outputs of the PIC to be received by a bluetooth transceiver.

Am I on the right track?

You can see in my createBinary function: OUTPUT_TO_A_PIN where I am not too sure where to go from there.

Am I completely off track or am I close? Thank you all for your help!
Ttelmah
Guest







PostPosted: Wed Mar 12, 2008 4:56 pm     Reply with quote

Don't use the ADC interrupt.
The _only_ reasons to use this, are:
1) You are triggering the ADC conversion with the CCP.
2) You are using the 'sleep' ability of the processor while the ADC conversion is being done, and you need the interrupt to wake the processor.
As it stands, the ADC conversion, will take about 90 instruction times, and you will be spending all your time in the interrupt (the overhead associated with the interrupt handler is a total of about 60 instructions, add the time in the handler itself, and you have no time to do anything much else....). Also, the ADC, has a acquisition requirement _between_ samples, and retriggering the ADC in the interrupt, will almost certainly not give enough time for this. Being in this interrupt so much of the time, will almost certainly also interfere with timings needed for the data output...
To trigger the interrupt (if you want to do what you are doing), use the CCS function read_adc(ADC_START_ONLY). Basically, you are using C, and should use C functions, unless you have very good reasons to do things directly. This helps portability in the future.
If you want repeated automatic acquisitions, use a _timer_ interrupt at a much lower frequency. Otherwise, just use the normal read_adc function.
The PIC ADC, is slightly unusual, in that because of where the actual 'switch' points occur, the steps should be considered as being Vref/1024, rather than Vref/1023 (in your case Vref/256, rather than Vef/255). There is an application note in the Microchip website about this.
Remember floating point arithmetic is _slow_. You are giving your result in integer mV, so do the maths in integer:
Code:

int16 result;
result = ((int32)(read_adc())*5000)/256;

You don't need be fiddling around with floor, and fp maths at all...
Remember that the standard 'RS232' serial routines, output a byte in serial bitwise format on a pin. The bluetooth transmitter, is almost certain to expect either standard async serial othis type, or something like SPI (for which again, there is hardware present...).

Best Wishes
ccs@x1a4.net
Guest







PostPosted: Sat Apr 12, 2008 2:33 am     Reply with quote

Try looking at this site for some example code: qwikandlow.com

My professor wrote a book about using the 18f452 and the code should work on the newer one. There is also a pdf book available for download.

I'm gonna be working on programming some similar stuff with a pic18f4520 this weekend and next week, so send me an email if you have any questions, I'd be glad to help out and i like looking at other code to get new ideas.

Mike - ccs@x1a4.net

(put NOT-SPAM in the subject line in case I have to filter that address if bots pick it up)
stereo
Guest







PostPosted: Wed Jan 06, 2010 2:18 am     Reply with quote

What is the software to compile the code here? I'm using mplab ide v7.6. Looking at the code in this forum, I think it is not supported if I use the code.

Anyway, I have problem displaying decimal point of the reading voltage on the lcd screen. Instead of 4.99v, it displays 499v.

And how can I measure current and display it on the lcd screen?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 06, 2010 2:04 pm     Reply with quote

This is the CCS C compiler forum for PIC microcontrollers . If you're
using a different C compiler such as Hi-Tech, CC5X, FED, SourceBoost,
C18, etc., then you need to go to the forum for your compiler. Most
compilers have a forum.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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