Need Help on PIC Functions for A/D converter! Help please :)

Discussion in 'Embedded Systems and Microcontrollers' started by GammaRay86, Dec 19, 2009.

  1. GammaRay86

    Thread Starter Member

    Dec 9, 2007
    14
    0
    Hey guys,

    I want to know some things about some PIC registers and hopefully some of you can help me.

    I'm working on the A/D conversion on the PIC16F684. Here is my code so far:

    Code ( (Unknown Language)):
    1.  
    2. #pragma chip PIC16F684
    3. #include "delay.h"
    4.  
    5. void main(void){
    6.  
    7. int adval, a, b;    // adval is the ADC value
    8. TRISA.0 = 1;        // Set RA0/AN0 (pin 13) as I/P
    9. TRISC.2 = 0;        // Set RC2/AN6 (pin 8) as a dig O/P
    10. ANSEL.0 = 1;        // Set RA0/AN0 (pin 13) as analog I/P
    11. ADCON1 = 0b.0011.0000;  // Clock set to internal Frc
    12.  
    13. while(1){
    14. //Do the sensor conversion
    15. delay_us(50);           // Set delay of 50 us for sampling (TAD)
    16. ADCON0 = 0b.1000.0011;      // Right justified, Vref = Vdd,
    17.                 // Read from AN0 (pin 13), Go/Done = 1, ADC Enabled
    18. while(ADCON0.1 == 1){}      // A/D conversion started, continue to check Go/Done, when 0 it is completed
    19.                 // Bit 1 of ADCON0 is cleared when finished
    20. a = ADRESH.1;           // Read bit 1 of ADRESH into variable a
    21. a = a * 512;            // Multiply "a" by the position of that bit (2^9)
    22. b = ADRESH.0;           // Read bit 0 of ADRESH into variable b
    23. b = b * 256;            // Multiply "b" by the position of that bit (2^8)
    24. adval = ADRESL + a + b;     // ADC value is the sum of ADRESL, a, and b
    25.  
    26. if(adval <369){         // LED on at  RC2 (pin 8) when AN0 < 1.8V, off > 1.8V
    27.     PORTC = 0b.0000.0100;
    28. }
    29. else {
    30. PORTC = 0b.0000.0000;
    31. }
    32. }
    33. }
    This code does not seem to be working. It kinda works in that the LED blinks on and off but not at the 1.8 V like it should. It seems to turn off ONLY at values of like 2 V. But is on ABOVE and BELOW that which my code clearly does not say. So I need to ask some questions.

    1. Do I need to set port A to be initially 0? e.g. PORTA = 0?

    2. What is the difference between the ANSEL register and the CHS bits on ADCON0?

    3. Do I need to set a delay between turning the ADC on and making the Go/Done bit 1?

    4. Am I doing the AD value calculation correct assuming left justification? I assume the ADRESH bits should be multiplied by 2^8 (256) and 2^9 (512)?

    5. I set the clock to internal RC. Is this okay?

    5. ANYTHING anyone can see that is wrong? I saw some code where a comparator was shut off before the ADC. Is this required?

    Thanks for any help
     
  2. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    1:I don't think so but it would only affect the first conversion, because it isn't turned off. It only needs turning off if you want to save a few microwatts.
    (just checked and there is a calculation for Taqc but the example they gave was only 8 microseconds)
    2:ANSEL selects which pins are analog input rather than digital input or output, CHS bits choose which of the analog pins the ADC is connected to - there is only 1 ADC but it can be connected to any analog input.
    3:No
    4:No idea, I don't understand C.
    5:probably safe, but see other post
    5:Yes, set CMCON0 to 7 to turn off comparators
     
    Last edited: Dec 19, 2009
  3. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    Oops, answer to the second 5 should be no.
    The bits default to 0 and that sets the comparator off but the pins as analog.
    7 would set them to digital.
     
  4. GammaRay86

    Thread Starter Member

    Dec 9, 2007
    14
    0
    Thanks for the help Mark!

    I wish I could get this to work though, I don't know what's wrong.

    Do you know if I have to connect the MCLR pin to the Vdd? I hear this is required, I have tried it but it still doesn't get it to work. But I'd still like to know.

    In my TRISC.2 = 0 line, does that really change the RC0 pin to digital output? Because it does change it to output but is it digital by default?
     
  5. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    MCLR depends on the configuration, it should be connected to VDD by a resistor if it is configured as a reset.
    I think you need a clrf Ansel before your ansel.0 =1 line, the default for ansel is b'11111111'. I should have spotted it earlier.
    The bold in the below table is how defaults are shown.
     
  6. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    By clrf ansel I mean ANSEL = 0, or you could just put ANSEL=1 and ignore the ansel.0=1
     
  7. GammaRay86

    Thread Starter Member

    Dec 9, 2007
    14
    0
    If ANSEL is b'11111111' by default, why would I even need to put ANSEL = 1? Wouldn't it be fine to keep as all analog since the datasheet says it does not affect digital output?

    Edit: Also, you posted on my other thread:

    How can I check what my device frequency is? Because if it's greater than 1 MHz it says I should avoid using the FRC clock source. How would I know which one to choose if I don't use the FRC clock source? Thanks again!
     
  8. GammaRay86

    Thread Starter Member

    Dec 9, 2007
    14
    0
    Nevermind, the default device frequency is 4 MHz. I'm going to try the ADC clock source at Fosc/8 and Fosc/16 to see if they make a difference.

    My question about the ANSEL still stands though, I don't understand why I need to set it at all.
     
  9. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    Sorry, there is no need. I am used to using a 12F675 where ANSEL affects outputs.
     
  10. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,866
    988
    I am just getting started in this whole thing myself so I am a bit ignorant on the subject but perhaps we can stumble through this together.

    I don't see you setting ADCON2 anywhere. It makes it a lot easier to set to right justification.

    Here is some sample code to read an ADC in high precision:

    Code ( (Unknown Language)):
    1.  
    2. unsigned int ADC_Convert(void)
    3. { // start an ADC conversion and return the 8 most-significant bits of the result
    4.    
    5.     unsigned i;
    6.  
    7.     ADCON0bits.GO_DONE = 1;             // start conversion
    8.     while (ADCON0bits.GO_DONE == 1);    // wait for it to complete
    9.     i = (ADRESH * 256);
    10.     i = ADRESL + i;
    11.     return  i;               // return high byte of result
    12. }
    13.  
    You might want o pick up one of the PIC demo boards. It makes learning this stuff a lot easier.
     
  11. GammaRay86

    Thread Starter Member

    Dec 9, 2007
    14
    0
    In that code, if you're only wanting an 8-bit result, why do you need both ADRESH and ADRESL. Assuming a left justification, you would only need ADRESH*256 for 8-bits no?
     
  12. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,866
    988
    You do not need to multiply for 8 bits. Just read ADRESH.


    Code ( (Unknown Language)):
    1.  
    2. unsigned char ADC_Convert(void)
    3. { // start an ADC conversion and return the 8 most-significant bits of the result
    4.     ADCON0bits.GO_DONE = 1;             // start conversion
    5.     while (ADCON0bits.GO_DONE == 1);    // wait for it to complete
    6.     return ADRESH;                      // return high byte of result
    7. }
    8.  
    You will need to multiply to obtain your actual voltage.


    l = ADC_IN * VoltsPerBit

    VoltsPerBit = VMaxIn / 256 (or 1024 for 10 bit)
    You will then want to multiply that result by 100, 1,000, 10,000 or pretty much whatever you want.

    When you display your result, remember to adjust for appropriate decimal point.
     
  13. GammaRay86

    Thread Starter Member

    Dec 9, 2007
    14
    0
    If I wanted to only use the highest 7 bits, would adval = ADRESH - ADRESH.0 work?

    Would my VoltsPerBit = VmaxIn / (2^7) in this case?
     
  14. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,866
    988
    Sorry just getting started myself so I am not sure.

    Why do you want to use only 7 bits? Why make it so complicated? If you want to use 7 bits then for your formula to work, you would need to shift 1.

    Otherwise, I would think it is still 2^ 8.
     
Loading...