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.

[SOLVED] Test program to check ADC.

Status
Not open for further replies.

shomikc

Member level 4
Joined
Apr 19, 2013
Messages
71
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,951
Hello all,

I have written a test program that will take a voltage(square pulse of 4V max for 1 second and 2V min for 1 second and then repeat) and check if it is more than 3 volts or less than 3 volts.
My understanding of ADCON registers is nowhere near complete.

Can anyone please spare the time and please check the program listed below and tell me if it is wrong.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#pragma config OSC = INTIO67    
#pragma config FCMEN = OFF      
#pragma config IESO = OFF       
 
// CONFIG2L
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = OFF      
#pragma config BORV = 3         // Brown-out Reset Voltage bits (Minimum setting)
 
 
// CONFIG2H
#pragma config WDT = OFF       
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)
 
// CONFIG3H
#pragma config CCP2MX = PORTC 
#pragma config PBADEN = OFF     
#pragma config LPT1OSC = OFF    
#pragma config MCLRE = ON       
 
// CONFIG4L
#pragma config STVREN = ON      
#pragma config LVP = OFF        // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config XINST = OFF     
 
#include <p18f4520.h>
#include <delays.h>
 
#define vref    5.00
 
void adc_INIT();
 
int adc_READ(int);
 
void main()
    {
        int digital;
        float voltage;
 
        OSCCON  =   0x72;   //  Set internal oscillator frequency to 8 MHz
        adc_INIT();
 
        while(1)
            {
                digital = adc_READ(1);
                voltage = digital*(((float)vref)/((float)1023));
                TRISB = 0 ;         //  Set Port B as Output 
                    if(voltage > 3.0)
                        {
                                LATBbits.LATB0 = 1;     //  RB_0 is high
                        }
                    else if(voltage < 3.0)
                        {
                                LATBbits.LATB1 = 1;     //  RB_1 is high
                        }
            }
    }
 
void adc_INIT()
    {
        TRISA   =   0xFF;       //  Set Port A as the input port
        ADCON1  =   0x0D;       //  Set AN0 and AN1 as Analog Input
        ADCON0  =   0x05;       //  Select Channel 1 (AN1) and set AD Module ON (ADON = 1)
        ADCON2  =   0x92;       //  Right justified, 4*Tad, Fosc/32
    }
 
int adc_READ(int channel)
    {
        int digital;
        ADCON0 |= 0x02;             //  
            while(ADCON0bits.GO == 1)       
                {
                    digital = (ADRESH*256)|(ADRESL);
                }
        return(digital);
            }


Thanks and Regards,

Shomik.
 

You did not mention what is going wrong, even though the logic above is a little weird. You are raising to the high level different uC pins at opposite conditions (at above lines 50 and 54), but you are not resetting them anywhere. Try working with just one pin, either switching to high or low level at each condition. Another unusual stuff is that you are updating TRISB at the loop, whereas it is expected to be at the init(), running just once.
 
Hi,

You don't give an error description.

Some issues I see:
LATBbits.LATB0 = 1; // RB_0 is high
LATBbits.LATB1 = 1; // RB_0 is high
They are only set to 1, but never set to 0,
Thus it is expectable that both bits saturate as 1

voltage = digital*(((float)vref)/((float)1023));
I've seen this many times that programmers use "1023" instead of "1024" like given in the datasheet....even when they know it is not correct.

Klaus
 
Hello all,

I have changed my program to read like this.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
TRISBbitsB1 = 0 ;         //  Set Port B bit 1 as Output 
      TRISBbitsB2 = 0 ;         //  Set Port B bit 2 as Output 
 
     PORTB         = 0;
 
 
    while(1)
            {
                digital = adc_READ(1);
                    if(digital >= 0x199)
                        {
                                LATBbits.LATB1 = 1;     //  RB_1 is high
                        }
                    else if(voltage < 2.0)
                        {
                                LATBbits.LATB1 = 0;     //  RB_1 is low                       
                         }
 
                  voltage = digital*(((float)vref)/((float)1023));
                      if(voltage >= 2.0)
                        {
                                LATBbits.LATB2 = 1;     //  RB_2 is high
                        }
                    else if(voltage < 2.0)
                        {
                                LATBbits.LATB2 = 0;     //  RB_2 is low                       
                         }
            }
    }
 
void adc_INIT()
    {
        TRISA   =   0xFF;       //  Set Port A as the input port
        ADCON1  =   0x0D;       //  Set AN0 and AN1 as Analog Input
        ADCON0  =   0x05;       //  Select Channel 1 (AN1) and set AD Module ON (ADON = 1)
        ADCON2  =   0x92;       //  Right justified, 4*Tad, Fosc/32
   }



This works fine for channel 1(RA1/AN1/ pin no. 3 ) which is supplied with a square wave of 4V peak from function generator at frequency 0.5 Hz and 50% duty cycle and I get two leds(connected to RB1 and RB2) blinking on and off at 1 sec interval. But when I change to channel2 adc_READ(2) and ADCON0 to 0x09 and ADCON1 to 0x0B I don't get any output.

And also is it possible to take to analog inputs simultaneously maybe by somehow implementing parallel processing.

Thanks.
 

Review commands if and else if at above lines 10 and 14; it doesn`t make any sense evaluating different variables to determine whether output will turn high or low.
 
Review commands if and else if at above lines 10 and 14; it doesn`t make any sense evaluating different variables to determine whether output will turn high or low.

I am really sorry. line 14 should read else if (digital<0x199).

Thanks
 

If it is possible I recommend to set ADC to generate predefined output pattern, e.g. the ramp (digital values from 0 to MAX with step = +1).
Then whatever the analog input is, the ADC generates the ramp output. This can be used to verify many things, i.e. PCB design, clock architecture, ADC malfunction and idelay values (in FPGA).
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top