ADC 16f877 8 bit wrong pattern

Status
Not open for further replies.

maria258

Member level 2
Joined
Feb 10, 2011
Messages
42
Helped
2
Reputation
4
Reaction score
2
Trophy points
1,288
Activity points
1,577
this program will read an analog i/p from a pot and display its binary equivalent on portb leds and then converted for the lcd and when im changing the pot resistance it is incrementing by 51 everytime and will make this pattern twice till i switch it on fully that is the pattern is this: o, 51, 102, 153, 204, 255, 51, 102, 153, 204 and 255 again.
can someone help me see whats wrong with it?
Code:
//This is a Test Program to read analog i/p CH_0 Pin_2
 //and display the binary equivalent on PORTB LEDs. Also,
 //the value is converted to DECimal & ASCII respectively
 //to be displayed on a 16x2 LCD.
 //Pin_5 Vref+ must be connected to +5V.
 //Header file for PIC Micro’s
 #include<htc.h>
 //Set Configuration Fuses PIC16F877 from Software
 __CONFIG (0x3F72);
 //define ports for easier reading
 #define LEDS PORTB
 #define LCD PORTD
 #define RS RC0
 #define R_W RC1
 #define EN RC2
 //Prototype Functions declared here
 void swait(unsigned char itime);
 void cmnd(unsigned char *patt, unsigned char lenght);
 void dat(unsigned char *patt, unsigned char lenght);
 void dat_2(unsigned char value);
 void USDELAY(unsigned char utime);
 void MSDELAY(unsigned char mtime);
 //Main Function Block
 void main(void)
 {
 unsigned char cmds[4]={0x38,0x0C,0x01,0x80};
 unsigned char mess_1[12]="TEMPERATURE:";
 //line 2,pos.5
 unsigned char cmdl2p5[1]={0xC5};
 //line 2,pos.6
 unsigned char cmdl2p6[1]={0xC6};
 //line 2,pos.7
 unsigned char cmdl2p7[1]={0xC7};
 //line 2,pos.8
 unsigned char cmdl2p8[1]={0xC8};
 //line 2,pos.9
 unsigned char cmdl2p9[1]={0xC9};
 //8bit data-type variables
 //store of ADC low byte
 unsigned char x;
 //store of ADC high byte
 unsigned char y;
 //store final ADC result
 unsigned char value;
 unsigned char value2,a,n;
 unsigned char dec1,dec2,dec3;
 unsigned char units,tens,hundreds;
 //make Port B o/ps
 TRISB=0x00;
 //make Port A i/ps
 TRISA=0xFF;
 //make Port D o/ps
 TRISD=0x00;
 //make Port C o/ps
 TRISC=0b00000000;
 //clear/switch off LEDS
 LEDS=0xFF;
 //Initialise LCD
 //4 elements in cmds array
 cmnd(cmds,0x04);
 //Send message to LCD
 dat(mess_1,0x0C);
 //display deg
 cmnd(cmdl2p8,0x01);
 dat_2(0xDF);
 //display Celcius C
 cmnd(cmdl2p9,0x01);
 dat_2('C');
 //repeat forever loop
 while(1)
 {
 //ADFM=1, all i/ps analog, +VREF enabled
 //Configure the functions of the Port bits
 ADCON1=0x81;
 //clock/channel select & enable bits
 //controls the operation of the A/D module
 ADCON0=0xC1;
 //no.of loops of 255 loops
 //wait for acquire time
 swait(1);
 //Start a2d conversion
 //Set GO bit (ADCON0=ADCON0|1;)
 GODONE=1;
 //wait end-of-conversion (conversion complete)
 while(GODONE==1);
 //store low byte
 x=ADRESL;
 //shift 1bit to the right
 x=x>>1;
 //store high byte
 y=ADRESH;
 //shift left 7 bit positions
 y=y<<7;
 //combine high & low bytes
 value=x+y;
 //output result on PortB LEDs
 
 
 LEDS=~value;
 
 
 
 
 //make 1st division by ten
 //a is first quotion
 a=value/10;
 //take the 1st remainder LSB
 //Units in decimal
 dec1=value%10;
 //take the 2nd digit/middle
 //remainder Tens in decimal
 dec2=a%10;
 //take the 3rd digit MSB
 //Hundreds in decimal
 dec3=a/10;
 //make units digit ASCII
 units=dec1|0x30;
 //make tens digit ASCII
 tens=dec2|0x30;
 //make hundreds digit ASCII
 hundreds=dec3|0x30;
 //display
 cmnd(cmdl2p7,0x01);
 dat_2(units);
 //display
 cmnd(cmdl2p6,0x01);
 dat_2(tens);
 //display
 cmnd(cmdl2p5,0x01);
 dat_2(hundreds);
 //micro stop here
 //while(1){};
 }
 }
 //Function to send Commands to LCD
 void cmnd (unsigned char *patt, unsigned char lenght)
 {
 unsigned char i;
 for(i=0;i<lenght;i++)
 {
 LCD=patt[i]; //get value from array
 RS=0; //for command
 R_W=0; //for write
 //H-to-L Pulse required
 EN=1;
 USDELAY(70); //?us delay
 EN=0;
 MSDELAY(100); //give display some time
 }
 }
 //Function to send Data to LCD
 void dat (unsigned char *patt, unsigned char lenght)
 {
 unsigned char i;
 for(i=0;i<lenght;i++)
 {
 LCD=patt[i]; //get value from array
 RS=1; //for data
 R_W=0; //for write
 //H-to-L Pulse required
 EN=1;
 USDELAY(70); //?us delay
 EN=0;
 MSDELAY(10); //give display some time
 }
 }
 //Function to send Data to LCD
 void dat_2 (unsigned char value)
 {
 LCD=value;
 RS=1; //for data
 R_W=0; //for write
 //H-to-L Pulse required
 EN=1;
 USDELAY(70); //?us delay
 EN=0;
 MSDELAY(10); //give display some time
 }
 //some delay needed
 void swait(unsigned char itime)
 {
 unsigned char i,j;
 for(i=0;i<itime;i++)
 for(j=0;j<255;j++);
 }
 //used for LCD ENable Pulse
 void USDELAY (unsigned char utime)
 {
 //8-bit data type variables
 unsigned char i;
 //single-loop
 for(i=0;i<utime;i++);
 }
 //used for in between Characters
 void MSDELAY (unsigned char mtime)
 {
 //8-bit data type variables
 unsigned int i,j;
 //nested for-loops
 for(i=0;i<mtime;i++)
 for(j=0;j<455;j++);
 }
 

the adc is making a funny pattern: o, 51, 102, 153, 204, 255, 51, 102, 153, 204 and 255 again. the step size is not good. but dont know how to change it.
 

friend,
that's variation made according to the variation of your input DC voltage (pot resistor), so you have to replace your pot resistor with long range one
 

its not the resistor cos the pattern is being shown twice. its the coding that is wrong
 
i cant cos at school, the rules are to write in c :s
 

Hi Maria;

I don't know tis PIC ( working on PIC18 ) but seems your code is wrong with the 10 bit ADC result handling.
Please read the datasheet carefully:
If you are using the right justified mode (?, ADFM, ADCON2.7 = 1, set it so !) then
value = (256 * adresh) + adresl // 0000 00xx - xxxx xxxx
but in case of left justified mode (ADFM = 0, default !) then
value = (4 * adresh) + (adresl >> 6) // xxxx xxxx - xx00 0000
 

hi zuisti, at the moment the code is only for an 8 bit. the adfm is set in register adcon1, ie 1.
therefore i tried your "value = (255 * adresh) + adresl" it didnt work.
 

Now the datasheet is downloaded : - )
I see now the ADFM is ADCON1.7 here (sorry)

your code:

//ADFM=1 (right justified, ok), all i/ps analog, +VREF enabled (on RA3, applied?)
//Configure the functions of the Port bits
ADCON1=0x81; // use 0x80 instead (Vref+ = Vcc)

and
if "at the moment the code is only for an 8 bit"
then (was right justified)
0000 00HH - LLLL LLxx

HH00 0000 (adresh << 6)
+
00LL LLLL (adresl >> 2)
=
HHLL LLLL

so
value = (adresh << 6) + (adresl >> 2)

Working in Proteus?
Then use the device POT-HG as potenciometer (high resolution pot).

---------- Post added at 13:45 ---------- Previous post was at 12:48 ----------

If the ADFM = 0 (left just.) then adresh contains the 8 bit result value w/o any calculation !!

so
value (8bit) = adresh
 

i tried putting the value = adresh and also the shifting of 6 and 2 but none worked :s
 

If ADFM (ADCON1.7) = 0 then value8 = adresh, this is sure.
Maybe your displaying routines are wrong elsewhere.

Sorry but your code is not really clear for me (which compiler are you using?),
and I don't have time enough now to understood it.
I don't know the real circuit either (Proteus DSN ?)

My recommendation:
-first use fix (known) "value" values to test (and debug) your displaying routines.
-if this is working as well, then examine the proper ADC settings, and the circuit itself.
Good luck
zuisti
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…