PIC18F25K22 & ADC problem

Discussion in 'Embedded Systems and Microcontrollers' started by nerdegutta, Jul 8, 2012.

  1. nerdegutta

    Thread Starter Moderator

    Dec 15, 2009
    2,515
    785
    Hi.

    I'm trying to learn ADC. I've googled and read datasheets to get started, and I thought I got pretty far, until ...

    I got the 2 x 20 LCD connected right, with RS on RA3, RW on RA2, EN on RA1. D4-D7 is connected to RB0-RB3. The display is working properly.

    I have a POT connected to 5vDC and GND, with the middle pin going to RA0, which is the pin I will use to read from. The problem is that I only get what seems like random characters on the LCD display. I've tried with different configuration in the ADCInit function - but with no luck.

    I think my hardware is set up correctly, so that leaves the program.

    Program listing:
    Code ( (Unknown Language)):
    1.  
    2. /*
    3. Program         :   main.c
    4. IDE     :   MPLAB 8.83
    5. Compiler    :   Hi TECH C v9.80
    6. PIC     :   PIC 18F25K22
    7. Date        :   April 2012
    8. Description :   Interfaceing PIC with LCD and ADC
    9. */
    10.  
    11. // Include and definitions
    12. #include <htc.h>
    13. #include <pic18f25k22.h>
    14. #include <stdlib.h>
    15. #include "lcd.h"
    16. #include "delay.h"
    17.  
    18. #define _XTAL_FREQ 4000000
    19.  
    20. // Configuration bits
    21. #pragma config FOSC = INTIO67   //     FOSC = INTIO67       Internal oscillator block
    22. #pragma config PLLCFG = ON  //     PLLCFG = ON          Oscillator multiplied by 4
    23. #pragma config PRICLKEN = ON    //     PRICLKEN = ON        Primary clock enabled
    24. #pragma config FCMEN = OFF  //     FCMEN = OFF          Fail-Safe Clock Monitor disabled
    25. #pragma config IESO = OFF   //     IESO = OFF           Oscillator Switchover mode disabled
    26. #pragma config PWRTEN = ON  //     PWRTEN = ON          Power up timer enabled
    27. #pragma config BOREN = OFF  //     BOREN = OFF          Brown-out Reset disabled in hardware and software
    28. #pragma config WDTEN = OFF  //     WDTEN = OFF          Watch dog timer is always disabled. SWDTEN has no effect.
    29. #pragma config CCP2MX = PORTB3  //     CCP2MX = PORTB3      CCP2 input/output is multiplexed with RB3
    30. #pragma config PBADEN = OFF //     PBADEN = OFF         PORTB<5:0> pins are configured as digital I/O on Reset
    31. #pragma config CCP3MX = PORTC6  //     CCP3MX = PORTC6      P3A/CCP3 input/output is mulitplexed with RC6
    32. #pragma config HFOFST = ON  //     HFOFST = ON          HFINTOSC output and ready status are not delayed by the oscillator stable status
    33. #pragma config T3CMX = PORTB5   //     T3CMX = PORTB5       T3CKI is on RB5
    34. #pragma config P2BMX = PORTC0   //     P2BMX = PORTC0       P2B is on RC0
    35. #pragma config MCLRE = EXTMCLR  //     MCLRE = EXTMCLR      MCLR pin enabled, RE3 input pin disabled
    36. #pragma config STVREN = OFF //     STVREN = OFF         Stack full/underflow will not cause Reset
    37. #pragma config LVP = OFF    //     LVP = OFF            Single-Supply ICSP disabled
    38. #pragma config XINST = OFF  //     XINST = OFF          Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
    39. #pragma config DEBUG = OFF  //     DEBUG = OFF          Disabled
    40.  
    41. // Global variables
    42. unsigned char adc_value[3];
    43. unsigned char i;
    44.  
    45. // Prototype functions
    46. void ADCInit();
    47.  
    48. // Functions
    49. void ADCInit(){
    50. ADCON0 =    0b00000000;
    51.             //0             Unimplemented
    52.             //-00000--      Analog Channel Select bit,00000=AN0
    53.             //------0-      A/D conversion status bit. 1=in progress
    54.             //-------0      ADC enable bit. 0=ADC disabled. 1=ADC enable
    55.  
    56. ADCON1 =    0b00000000;
    57.             //0-------      Trigger select bit, 0=CCP5, 1=CTMU
    58.             //-000----      Unimplemented
    59.             //----00--      A/D VRef+ connected to internal signal
    60.             //------00      A/D Vref- connected to internal signal
    61.  
    62. ADCON2 =    0b10000111;
    63.             //1-------      0=left justify, 1=right justify
    64.             //-0------      Unpmplemented
    65.             //--000---      ADC clock source selected to Frc
    66.             //-----111      Clock from internal oscillator
    67. }
    68.  
    69. unsigned int ADCRead(unsigned char ch){
    70. if (ch>13) return 0;        // Invalid channel
    71. ADCON0 = (ch<<0);       // Select ADC Channel
    72. ADON=1;             // Switch on the ADC module
    73. GODONE=1;           // Start conversion
    74. while(GODONE);          // Wait forthe conversion to finish
    75.  ADON=0;            // Switch off ADC
    76. return ADRES;           // Return value of the ADC
    77. }
    78.  
    79. // Main
    80. void main(void){
    81. OSCCON = 0x53;          // Setup oscillator
    82.  
    83. CM1CON0 = 0b00000000;       // Turn off comparators
    84. CM2CON0 = 0b00000000;
    85.  
    86. ANSELA = 0b00000000;        // Turn off Analog Input Control
    87. ANSELB = 0b00000000;
    88. ANSELC = 0b00000000;
    89.  
    90. TRISA = 0b00000000;     // Setting tris register to output
    91. TRISB = 0b00000000;
    92. TRISC = 0b00000000;              
    93.  
    94. PORTA = 0b00000000;     // Setting all pins LOW
    95. PORTB = 0b00000000;
    96. PORTC = 0b00000000;
    97.  
    98. lcd_init(FOURBIT_MODE);     // Initialize LCD in fourbit_mode
    99. lcd_clear();
    100. lcd_puts("ADC Test");       // String on line one
    101. lcd_goto(0x40);         // Switch to line 2
    102. lcd_puts("Version 1");      // String on line 2
    103.    
    104. for(i=0;i<10;i++){      // Short delay. When code works, it will be
    105.     __delay_ms(10);     // Changed to be a little longer
    106. }
    107.  
    108. unsigned int val;
    109.  
    110. ADCInit();          // Initialize the ADC module
    111.  
    112. while (1) {
    113.  
    114. lcd_clear();
    115. val = ADCRead(0);
    116.  
    117. itoa(adc_value, val, 10);   // Convert int to ascill
    118.  
    119. lcd_puts(adc_value);
    120.  
    121. __delay_ms(100);        // Short delay
    122.  
    123.  
    124. }               // End while
    125. }               // End main
    126.  
    Can anyone see any obvious errors or faults?
    If so, what's wrong and how do I fix it?
     
  2. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    Could it be something simple that
    Code ( (Unknown Language)):
    1. unsigned char adc_value[3];
    2.  
    should be
    Code ( (Unknown Language)):
    1.  
    2. unsigned char adc_value[4];
    3.  
    4.  
    You must have 1 space for the string terminator also (the \0 that terminate C strings). If the string terminator is overwritten by other code. The LCD output function will just keep pushing everything onto the LCD until it finds a \0
     
  3. debjit625

    Well-Known Member

    Apr 17, 2010
    790
    186
    I really don’t have that datasheet of your mcu right now... but their are some mistakes...
    In HTC compilers once you include htc header file"#include <htc.h> ,you don’t need to include device header file "#include <pic18f25k22.h>".

    When their are function definition after main() function or any other function or the function definition is on other file,we need function prototype ,you have defined your
    ADCInit() function before main() so you don’t need its prototype.

    Code ( (Unknown Language)):
    1.  
    2. [FONT=Verdana][COLOR=black]ADCON0 = (ch<<0); // Select ADC Channel[/COLOR][/FONT]
    3.  
    Here you have used left shift operator but as per your code you are shifting 0 bits to left that really doesn’t make sense .I could understand that you are trying to select the channel using functions parameter but I can't halp you with this code much as I don’t have the datasheet and have no idea how ADCON0 is oriented .So just be sure to correct the code.

    I don’t know if you have correctly configured ADCON0,ADCON1,ADCON2 check the datasheet.

    In the main() function you have did this
    Code ( (Unknown Language)):
    1.  
    2. [COLOR=black][FONT=Verdana]ANSELA = 0b00000000; // Turn off Analog Input Control [/FONT][/COLOR]
    3. [FONT=Verdana][COLOR=black]ANSELB = 0b00000000; [/COLOR][/FONT]
    4. [FONT=Verdana][COLOR=black]ANSELC = 0b00000000; [/COLOR][/FONT]
    5.  
    6. [FONT=Verdana][COLOR=black]TRISA = 0b00000000; // Setting tris register to output[/COLOR][/FONT]
    7. [FONT=Verdana][COLOR=black]TRISB = 0b00000000;[/COLOR][/FONT]
    8. [FONT=Verdana][COLOR=black]TRISC = 0b00000000;[/COLOR][/FONT]
    9.  
    First of all ADC module is an analog input you cant turn it off and I think the ADC's input pins are on PORTA or PORTB ,you have configured them as output pins unless they are input they will not work.

    Good Luck
     
  4. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    Try this
    Code ( (Unknown Language)):
    1. // Include and definitions
    2. #include <htc.h>
    3. #include <stdlib.h>
    4. #include "lcd.h"
    5. //#include "delay.h"
    6. #define _XTAL_FREQ 4000000
    7. // Configuration bits
    8. #pragma config FOSC = INTIO67 //     FOSC = INTIO67       Internal oscillator block
    9. #pragma config PLLCFG = ON //     PLLCFG = ON          Oscillator multiplied by 4
    10. #pragma config PRICLKEN = ON //     PRICLKEN = ON        Primary clock enabled
    11. #pragma config FCMEN = OFF //     FCMEN = OFF          Fail-Safe Clock Monitor disabled
    12. #pragma config IESO = OFF //     IESO = OFF           Oscillator Switchover mode disabled
    13. #pragma config PWRTEN = ON //     PWRTEN = ON          Power up timer enabled
    14. #pragma config BOREN = OFF //     BOREN = OFF          Brown-out Reset disabled in hardware and software
    15. #pragma config WDTEN = OFF //     WDTEN = OFF          Watch dog timer is always disabled. SWDTEN has no effect.
    16. #pragma config CCP2MX = PORTB3 //     CCP2MX = PORTB3      CCP2 input/output is multiplexed with RB3
    17. #pragma config PBADEN = OFF //     PBADEN = OFF         PORTB<5:0> pins are configured as digital I/O on Reset
    18. #pragma config CCP3MX = PORTC6 //     CCP3MX = PORTC6      P3A/CCP3 input/output is mulitplexed with RC6
    19. #pragma config HFOFST = ON //     HFOFST = ON          HFINTOSC output and ready status are not delayed by the oscillator stable status
    20. #pragma config T3CMX = PORTB5 //     T3CMX = PORTB5       T3CKI is on RB5
    21. #pragma config P2BMX = PORTC0 //     P2BMX = PORTC0       P2B is on RC0
    22. #pragma config MCLRE = EXTMCLR //     MCLRE = EXTMCLR      MCLR pin enabled, RE3 input pin disabled
    23. #pragma config STVREN = OFF //     STVREN = OFF         Stack full/underflow will not cause Reset
    24. #pragma config LVP = OFF //     LVP = OFF            Single-Supply ICSP disabled
    25. #pragma config XINST = OFF //     XINST = OFF          Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
    26. #pragma config DEBUG = OFF //     DEBUG = OFF          Disabled
    27. // Global variables
    28. unsigned char adc_value[5];//max value will be 1023=4 char and 1 place for the /0 total 5 bytes
    29. unsigned char i;
    30. // Prototype functions
    31. void ADCInit(void);
    32. // Functions
    33. void ADCInit(void)
    34. {
    35. ADCON0bits.CHS=0; //AN0
    36. ADCON0bits.ADON=1;
    37. ADCON1bits.PVCFG=0;
    38. ADCON1bits.NVCFG=0;
    39. ADCON2bits.ADFM=1;
    40. ADCON2bits.ACQT=5;
    41. ADCON2bits.ADCS=1;
    42. }
    43. void osc_conf(void)
    44. {
    45.  /*Primary Clock modes are selectable by the
    46. FOSC<3:0> bits of the CONFIG1H Configuration
    47. register. The primary clock operation is further defined
    48. by these Configuration and register bits:
    49. 1. PRICLKEN (CONFIG1H<5>)
    50. 2. PRISD (OSCCON2<2>)
    51. 3. PLLCFG (CONFIG1H<4>)
    52. 4. PLLEN (OSCTUNE<6>)
    53. 5. HFOFST (CONFIG3H<3>)
    54. 6. IRCF<2:0> (OSCCON<6:4>)
    55. 7. MFIOSEL (OSCCON2<4>)
    56. 8. INTSRC (OSCTUNE<7>)*/
    57.  OSCCON2bits.PRISD=1;
    58.  OSCTUNEbits.PLLEN=1;
    59.  OSCCONbits.IRCF=0b011;
    60.  OSCCONbits.SCS=3;
    61.  OSCCON2bits.MFIOSEL=0;
    62.  OSCTUNEbits.INTSRC=0;
    63.  //OSCCON = 0x53;   // Setup oscillator
    64. }
    65. void ADCRead(void){
    66. //if (ch>13) return 0;  // Invalid channel
    67. //ADCON0 = (ch<<0);  // Select ADC Channel
    68. //ADON=1;    // Switch on the ADC module
    69. GODONE=1;   // Start conversion
    70. while(GODONE);   // Wait forthe conversion to finish
    71.  //ADON=0;   // Switch off ADC
    72. //return ADRES;   // Return value of the ADC
    73. }
    74. // Main
    75. void main(void)
    76. {
    77.  osc_conf();
    78.  CM1CON0 = 0b00000000;  // Turn off comparators
    79.  CM2CON0 = 0b00000000;
    80.  ANSELA = 0b00000001;   // Turn off Analog Input Control for all but RA0
    81.  ANSELB = 0b00000000;   //enable RB as analog input  
    82.  ANSELC = 0b00000000;
    83.  TRISA = 0b00000001;  // Setting tris register to output RA= must be 1 due to ADC
    84.  TRISB = 0b00000000;
    85.  TRISC = 0b00000000;    
    86.  //PORTA = 0b00000000;  // Setting all pins LOW
    87.  //PORTB = 0b00000000;
    88.  //PORTC = 0b00000000;
    89.         lcd_init(FOURBIT_MODE);  // Initialize LCD in fourbit_mode
    90.  lcd_clear();
    91.  lcd_puts("ADC Test");  // String on line one
    92.  lcd_goto(0x40);   // Switch to line 2
    93.  lcd_puts("Version 1");  // String on line 2
    94.  ADCInit();   // Initialize the ADC module
    95.  while (1) {
    96.    lcd_clear();
    97.    ADCRead();
    98.    itoa(adc_value, ADRES, 10); // Convert int to ascill
    99.                    lcd_puts(adc_value);
    100.                     lcd_goto(0);
    101.    LATA7=!LATA7;
    102.     for(i=0;i<10;i++)
    103.        {// Short delay. When code works, it will be
    104.         __delay_ms(10);  // Changed to be a little longer
    105.        }
    106.  
    107.  
    108.  
    109.     }    // End while
    110. }
     
    Last edited: Jul 9, 2012
    nerdegutta and MMcLaren like this.
  5. nerdegutta

    Thread Starter Moderator

    Dec 15, 2009
    2,515
    785
    Actually, I knew that. Thanks
    Really? I didn't know that. I like to have them over the main(), guess that's from my time programming in Turbo Pascal...
    Neither did I.
    I tried both with RA0 set as 1, and TRISA = 0b00000001, but nothing...

    Thanks...

    Amazing.

    I did CTRL+A, CTRL+C, opened my main.c program and did a CTRL+A and CTRL+V, pressed F10 and voila...

    No errors, everything works as expected. Now I need to understand the code.

    Thanks guys!
     
Loading...