ADC - My First Code

Discussion in 'Embedded Systems and Microcontrollers' started by SteveO, Nov 18, 2009.

  1. SteveO

    Thread Starter Active Member

    May 15, 2008
    33
    0
    Hi all, please criticize my code. It is my first use of the ADC, and worked first go :D

    The operation is to use an external voltage divided on AN0 and if the value is ~1/2 of Vdd turn high (LED connected) RA2. Approximately half since I only check the high register (justified left) of the ADC result.

    Code ( (Unknown Language)):
    1. #include <htc.h>
    2. #define _XTAL_FREQ 4000000
    3. __CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT & UNPROTECT);
    4.  
    5. void main(void){
    6.     int i;
    7.     PORTA = 0x00;       // PORTA low
    8.     CMCON0 = 0x07;      // turn off comparators
    9.  
    10.     TRISA = 0x01;       // RA2 output, RA0/AN0 input
    11.     TRISC = 0x00;
    12.     ADCON0 = 0b00000001; // turn on ADC
    13.     ADCON1 = 0b00000000; // conversion clock selected pins
    14.     ANSEL = 0b00000001;     // AN0 analouge inout
    15.  
    16.         while(1){
    17.                 ADCON0 = 0b00000011; // start ADC
    18.                 __delay_ms(10);
    19.                 if(ADRESH >= 0b10000000){
    20.                     RA2 = 1;
    21.                 }
    22.                 else{
    23.                     RA2 = 0;
    24.                 }
    25.  
    26.         }
    27. }
    Myu only issue is I am having problems denoting a single bit of a register to a variable eg.

    ANSEL7 = ..
    ANSEL.7 = ..

    both produce errors.
     
  2. BMorse

    Senior Member

    Sep 26, 2009
    2,675
    234
    try ANSEL,7


    What C Compiler are you using Hi-Tech?
     
    Last edited: Nov 18, 2009
  3. SteveO

    Thread Starter Active Member

    May 15, 2008
    33
    0
    Again no luck with the ','. And yes, I am using Hi-Tech C Compiler.
     
  4. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    Consider changing compilers to MikroC (now called MikroC Pro but it still has a free 2K demo version).

    MikroC has good bit handling features, and if you feel the need to get right into PICs then you can one of these beauties for as little as $139 (I recommend it heartily!);
    http://www.mikroe.com/en/tools/easypic6/
     
  5. cheezewizz

    Active Member

    Apr 16, 2009
    82
    10
    You could double check the variable name in the relevant include file for your uC.
     
  6. eng1

    New Member

    Oct 25, 2009
    13
    0

    I add these macros at the beginning of almost every C program in order to access single bits of a variable, I don't see why that shouldn't work with SFRs:
    Code (Text):
    1.  
    2. #define bitset(var,bitno) (var|=1<<bitno)
    3. [COLOR=black]#define bitclr(var,bitno) (var&=~(1<<bitno))[/COLOR]
    4.  
    Then, you should write for example:
    Code (Text):
    1.  
    2. bitset(ANSEL,7);
    3.  
    They get translated into efficient asm code by C18 for example (= BSF or BCF).

    However, in this case I think that it's not a good idea to SET single bits of the ANSEL register; for most PICs its value on start-up is 0xFF. Be careful!
     
  7. SteveO

    Thread Starter Active Member

    May 15, 2008
    33
    0
    Thanks eng1, this bitset/bitclr seems to work :). and THE_RB, that is a beauty. I'm working with the very basics pickit1 until I can get my fundamentals down. Then I'll move on to the big boys ;)

    Thanks all once again
     
  8. eng1

    New Member

    Oct 25, 2009
    13
    0




    Great! :) Back to you ADC code, a couple of points:
    • after you start a conversion, 10 ms is a huge delay. You can check if the conversion is finished polling the GO/DONE bit (=ADCON0.1 for the PIC16F690).
    • you should select the adc clock according to table 9.1 of the datasheet.
    Code ( (Unknown Language)):
    1.  
    2. #include <htc.h>
    3. #define _XTAL_FREQ 4000000
    4. #define bitset(var,bitno) (var|=1<<bitno)
    5. [COLOR=black]#define bitclr(var,bitno) (var&=~(1<<bitno))[/COLOR]
    6.  
    7. __CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT & UNPROTECT);
    8.  
    9. void main(){
    10.        int i;
    11.        PORTA = 0x00; // PORTA low
    12.        CMCON0 = 0x07; // turn off comparators
    13.  
    14.        ANSEL = 0b00000001; // AN0 analouge inout
    15.  
    16.        TRISA = 0x01; // RA2 output, RA0/AN0 input
    17.        TRISC = 0x00;
    18.  
    19.        ADCON1 = 0b00010000; // conversion clock
    20.        ADCON0 = 0b00000001; // turn on ADC
    21.  
    22.        while(1){
    23.                 // start conversion
    24.                 GODONE = 1; // bitset(ADCON0,1)
    25.                 while(GODONE); // wait for result
    26.  
    27.                 if(ADRESH >= 0b10000000){
    28.                          RA2 = 1;
    29.                          }
    30.                 else{
    31.                          RA2 = 0;
    32.                          }
    33.  
    34.        }
    35. }
    36.  
     
  9. SteveO

    Thread Starter Active Member

    May 15, 2008
    33
    0
    Thanks again for the help! Remember reading about setting the clock but didn't even think to remember.

    So I've been playing around with a 3x 7segment display for my next 'get to know the PIC' project. Still using the PIC16F684. Basically started with one display 1 digit number and I can now display any three digit number that is fixed into the program (no decimals yet). I am at the step where I have selected a pin that will be used as my analogue input and have connected it through a pot/resistor divider to simulate the thermsistor.

    I have not played around with interrupts yet so it is simply in a while loop forever, samples the ADC and then displays, repeat. As soon as I implemented this the digits on my display got very dim.

    Would this be due to it not being able to provide the needed power and I should add external op-amps/inverters or is it possible that while I am waiting for the ADC it is not displaying so they just look dimmer?

    Probably answered my own question, guess I should learn interrupts!

    Cheers all.
     
  10. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    If you are multiplexing the 3 displays (you didn't state) then the 3 will be dimmer than 1 directly driven display because each is only on for a third of the time.
     
  11. SteveO

    Thread Starter Active Member

    May 15, 2008
    33
    0
    Right... my plan for the code was - turn on display 1 - display digit - turn off display1/on display 2 - display digit, etc.

    Right 1 to 3 will definitely be dimmer, but this was always 3 displays, I had just added the ADC conversion and noticed significant dimming. I am almost certain it is due to my time delays, I'm working on the ADC interrupt as we speak and hope this gives me the extra time to keep it bright.

    Thanks.

    edit: Got the ADC interrupt working and seems to be performing much better. Just going to take some of the calculations out of my display portion of the code, do those before hand and should get good performance. I figure as a final case solution I can always slightly lower the resistors to the display.

    Thanks again for replies all.
     
    Last edited: Nov 21, 2009
  12. eng1

    New Member

    Oct 25, 2009
    13
    0
    Yes, it's certainly due to the delays. I would suggest you try and implement the display multiplexing with interrupts, for example using TMR2. You can still poll the GODONE bit, this will not affect multiplexing.
    This is exactly how I implemented A/D conversion with 3-digit displays ;).
     
  13. SteveO

    Thread Starter Active Member

    May 15, 2008
    33
    0
    Thanks again for the help. I will definitely take a look into this.

    I'm pretty happy with my progress thus far :D, things never seemed to go so smoothly working with assembly in school. Its much more enjoyable because your doing it for the hell of it.

    Cheers.
     
  14. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    I don't know if you have already got them but it might be a good idea to have transistors for the common inputs to the LED displays, especially if you are going to lower the resistors. The common input has to deal with up to 8 times as much current as the rest of the pins. For a common cathode display use pretty much any NPN transistor with a 1K resistor from the microcontroller to the base of the transistor, the emitter to ground and the collector to the common cathode.
     
  15. SteveO

    Thread Starter Active Member

    May 15, 2008
    33
    0
    Thanks Mark. I haven't thought about that, but makes perfect sense. I'm actually running common Anode, but I will implement with PNP.
     
Loading...