Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

urgent help in Code!!!!

Status
Not open for further replies.
Well engkhlaif, it's not 877A code but it works now. Took me a long time to find a foolish programming error that was messing up the LCD display of the result.

"Final" working 30F4013 code for continuously reading a Sharp GP2D12 and displaying the result on an LCD:
Code:
#include "p30f4013.h"
#include <stdlib.h>

_FOSC(FRC)				//osc
_FWDT(WDT_OFF)
_FBORPOR(MCLR_EN & PWRT_OFF)		//MCLR enable & power-up timers off

int readADC(void);
void lcd_line1(void);			//function prototypes
void lcd_line2(void);
void lcd_cmd(unsigned char);
void lcd_char(char);
void e_togg(void);
void lcd_init(void);
void lcd_string(char *);
void lcd_busy(void);
void lcd_16number(int);
void beep(int);
void delay(void);

#define	E		LATDbits.LATD9
#define	RS		LATAbits.LATA11
#define RW		LATCbits.LATC14
#define	busyflag	PORTBbits.RB12
#define RW_TrisBit	TRISCbits.TRISC14
#define D7_TrisBit	TRISBbits.TRISB12
#define piezo		LATCbits.LATC13

char number[] = "     ";

int main(void)
{
	int a;
	TRISA = TRISB = TRISC = TRISD = 0x0000;
	ADPCFG = 0xffff;			//all digital
	ADCON1 = 0x00E0;			// auto convert after end of sampling
	//0000 0000 1110 0000
	ADCSSL = 0;				// no scanning required 
	ADCON3 = 0x1F3f;			// max sample time = 31Tad, Tad = 2 x Tcy = 125ns >75ns
	//0001 1111 0011 1111
	ADCON2 = 0;				// use MUXA, AVss and AVdd are used as Vref+/-
	ADCHS = 0;				// select analog input channel
	ADCON1bits.ADON = 1;			// turn on the ADC
	RW = 0;					//set R/W low
	E = 0;					//set E low
	lcd_busy();				//wait for LCD to settle
	lcd_init();

	while(1)
	{
		TRISB = 0x0001;
		ADPCFG = 0xfffe;		//RB0 = analog
		a = readADC();
		ADPCFG = 0xffff;		//all digital
		TRISB = 0x0000;
		lcd_line1();
		lcd_16number(a);
		lcd_string(number);
		delay();
	}
	return 0;
}

void lcd_16number(int num)
{
	number[0]=(char)(abs(num/10000)+0x30);
	num=num-abs(num/10000)*10000;
	
	number[1]=(char)(abs(num/1000)+0x30);
	num=num-abs(num/1000)*1000;
	
	number[2]=(char)(abs(num/100)+0x30);
	num=num-abs(num/100)*100;
	
	number[3]=(char)(abs(num/10)+0x30);
	num=num-abs(num/10)*10;
	
	number[4]=(char)(num+0x30);
}

int readADC(void)
{
	ADCON1bits.SAMP = 1;			// start sampling, automatic conversion will follow
	delay();
	while (!ADCON1bits.DONE);		// wait to complete the conversion
	return ADCBUF0;				// read the conversion result
}

void lcd_string(char *senpoint)
{
	while(*senpoint != '\0')
	{
		lcd_char(*senpoint);
		senpoint++;
	}
}	

void lcd_busy(void)
{
	RW_TrisBit = 1;				//make R/W input (read)
	D7_TrisBit = 1;				//make D7 input
	RS = 0;					//set RS low
	RW = 1;					//set R/W high
	E = 1;					//set E high
	while(busyflag);			//wait for busy flag to go low
	E = 0;					//set E low
	RW = 0;					//set R/W low
	TRISB = 0;				//make D7 output
	RW_TrisBit = 0;				//make R/W output (write)
}	
	
void lcd_line1(void)
{
	lcd_cmd(0x80);
}

void lcd_line2(void)
{
	lcd_cmd(0xc0);
}		

void lcd_cmd(unsigned char letter)
{
	LATB = letter;					//put char in PORTB
	asm("nop");
	PORTB = PORTB << 5;				//shift over to output high 4 bits on RB9,10,11,12
	RS = 0;						//RS low
	e_togg();					//latch the data
	lcd_busy();
	LATB = letter;					//put char in PORTB
	asm("nop");
	PORTB = PORTB << 9;				//shift over to output low 4 bits
	RS = 0;						//RS low
	e_togg();					//latch it
	lcd_busy();
}

void lcd_char(char letter)
{
	LATB = letter;					//put char in PORTB
	asm("nop");
	PORTB = PORTB << 5;				//shift over to output high 4 bits on RB9,10,11,12
	RS = 1;						//RS high
	e_togg();					//latch the data
	lcd_busy();
	LATB = letter;					//put char in PORTB
	asm("nop");
	PORTB = PORTB << 9;				//shift over to output low 4 bits
	RS = 1;						//RS high
	e_togg();					//latch it
	lcd_busy();
}

void lcd_init(void)
{
	LATB = 0x0600;					//send 3
	e_togg();
	lcd_busy();
	LATB = 0x0600;
	e_togg();
	lcd_busy();
	LATB = 0x0600;
	e_togg();
	lcd_busy();
	LATB = 0x0400;					//send 2 - set 4-bit mode
	e_togg();
	lcd_busy();
	lcd_cmd(0x28);					//set 4-bit mode and 2 lines
	lcd_busy();
	lcd_cmd(0x10);					//cursor move & shift left
	lcd_busy();
	lcd_cmd(0x06);					//entry mode = increment
	lcd_busy();
	lcd_cmd(0x0d);					//display on - cursor blink on
	lcd_busy();
	lcd_cmd(0x01);					//clear display
	lcd_busy();
}

void e_togg(void)
{
	E=1;
	E=0;
}

void beep(int tone)
{
	int x,y;
	for(x=0;x<80;x++)
	{
		piezo = 1;
		for(y=0;y<tone;y++){}
		piezo = 0;
		for(y=0;y<tone;y++){}
	}
}	

void delay(void)
{
	int x,y;
	for(x=0;x<10;x++)
	{
		for(y=0;y<10000;y++){}
	}
}
 
Last edited:
Futz,

I assume the nop is to avoid the RMW problem. Can you do this instead?
Code:
	LATB = letter;		//put char in PORTB
	LATB = LATB << 5;	//shift over to output high 4 bits on RB9-12

Mike.
 
Pommie said:
I assume the nop is to avoid the RMW problem. Can you do this instead?
Code:
	LATB = letter;		//put char in PORTB
	LATB = LATB << 5;	//shift over to output high 4 bits on RB9-12
Ya, the compiler was complaining. Will shifting the bits over in LATB work? So they'll show up in PORTB by the next instruction, right? Sounds like a plan. I'll try it tomorrow. :D

Thanks Mike.
 
Just had a quick look at the original code.

The main problems I can see are,
ADCON1=7 needs to be ADCON1=0.
The input pin needs to be setup as input.
Assuming the voltage is on AN1 (not AN0) then TRISA needs to be 0x02.

Mike.
 
Pommie said:
Just had a quick look at the original code.

The main problems I can see are,
ADCON1=7 needs to be ADCON1=0.
The input pin needs to be setup as input.
Assuming the voltage is on AN1 (not AN0) then TRISA needs to be 0x02.

Mike.
i have done what u say befor as i set ADCON1=0 INSTEAD OF 7
I GET THE RESULT : -24421.138
i dont know why
also i put TRISA=1 WHICH MEANS INPUT AND ALSO THE SAME RESULT MIKE
so what u advice my to do
 
Which port pin have you got your signal on? Setting TRISA=1 will set AN0 (PortA,0) to input but x=read_a2d(1); will read the voltage on AN1 (PortA,1).

Mike.
 
Pommie said:
I assume the nop is to avoid the RMW problem. Can you do this instead?
Code:
	LATB = letter;		//put char in PORTB
	LATB = LATB << 5;	//shift over to output high 4 bits on RB9-12
Yup, that works fine. Sped it up and added a proximity alarm for objects closer than ~6 inches.
Code:
	while(1)
	{
		TRISB = 0x0001;
		ADPCFG = 0xfffe;		//RB0 = analog
		a = readADC();
		ADPCFG = 0xffff;		//all digital
		TRISB = 0x0000;
		if(a>1400)
		{
			beep(75);
		}
		lcd_line1();
		lcd_16number(a);
		lcd_string(number);
		delay();
    }

Now I gotta learn how to properly calculate TAD. I spent an hour scratchin my head and ended up just stuffing in guessed numbers.
 
Last edited:
futz said:
Any analog pin is fine. They all work the same. Just adjust your code to suit.
i did so but iam shocked with the result i got
because it gives -24423.12 i dont know from where is this result came from!!!
as the main code is that :

Code:
while(1)
        {
           lcd_clear() ;
           lcd_goto(0) ;
           lcd_puts( "welcome " ) ;
           x=read_a2d(1); // must connect output at A1
           voltage=(x/255.0)*(5.0);  // caculate the voltage and then i need to display it on an LCD 
           lcd_goto(40);
           sprintf(outString,"A2D = %d.%d volts",voltage);
           lcd_puts(outString);
           //lcd_puts("Real time ") ;
           DelayMs(1500);

         }

}
 
engkhlaif said:
i will get the signal on pin A0 ?? is that wrong!!!!
i thaink that i have to put it on pin A1 !!!!:confused:

If you have it on A0 then you need to change your code to x=read_a2d(0);

Mike.
 
Pommie said:
If you have it on A0 then you need to change your code to x=read_a2d(0);

Mike.
i will do that in the laboratory tomoro
but i want to ask why the result is always gives :-24264.1331, while iam moving an object in the line of sight with the sensor !!!
and is that right to write the code :
 
engkhlaif said:
i will do that in the laboratory tomoro
but i want to ask why the result is always gives :-24264.1331, while iam moving an object in the line of sight with the sensor !!!
Impossible to say. Have you looked at the actual result in memory with the debugger (before it gets sent to LCD)?

My A/D code was working fine for a long time, but the program displayed garbage because the code translating the results into something the LCD could display was wrong.

-24264.1331 would be a float value, right? Since you're left justifying the AD result, I assume you want to drop the two bottom bits (noise) and use it as an 8-bit value. So how does that unsigned char AD value end up displaying as a float?

Does the number change when you move your hand in front of the sensor? If it does then you're on the right track. If not then you need to write some small sub-programs to test various code sub-sections by themselves. Test the AD by itself to see if it returns proper values. Then test the LCD with hard-coded values of the type/size you expect from your AD. Then put it all together.
 
Last edited:
Had the day off today, so I got Hi-Tech PICC working on the 16F877 and ported my 30F4013 AD/LCD code for GP2D12 over to it. Seems to work pretty well so far.

pic16f877_ADsm.jpg

Here's the code:
Code:
#include <pic.h>
#include <htc.h>
#include <stdlib.h>

__CONFIG(XT&WDTDIS&LVPDIS);

void lcd_line1(void);				//function prototypes
void lcd_line2(void);
void lcd_cmd(unsigned char);
void lcd_char(char);
void e_togg(void);
void lcd_init(void);
void lcd_string(char *);
void lcd_busy(void);
unsigned char read_a2d(void);
void lcd_16number(int);
void delay(void);

#define	E		RD2
#define	RS		RD0
#define RW		RD1
#define	busyflag	RB3
#define RW_TrisBit	TRISD1
#define D7_TrisBit	TRISB3

char number[] = "     ";

int main(void)
{
	char x;
	unsigned char a;
	ADCON1 = 0b00001110;
	ADCON0 = 0b10000000;
	ADON = 1;
	TRISB = TRISD = 0;
	RW = 0;					//set R/W low
	E = 0;					//set E low
	lcd_busy();				//wait for LCD to settle
	lcd_init();

	while(1)
	{
		a = read_a2d();
		lcd_line1();
		lcd_16number(a);
		lcd_string(number);
		delay();
	}
}

unsigned char read_a2d(void)
{
	ADGO=1;
	while(ADGO){}
	return(ADRESH);
}

void lcd_string(char *senpoint)
{
	while(*senpoint != '\0')
	{
		lcd_char(*senpoint);
		senpoint++;
	}
}	

void lcd_busy(void)
{
	RW_TrisBit = 1;					//make R/W input (read)
	D7_TrisBit = 1;					//make D7 input
	RS = 0;						//set RS low
	RW = 1;						//set R/W high
	E = 1;						//set E high
	while(busyflag);				//wait for busy flag to go low
	E = 0;						//set E low
	RW = 0;						//set R/W low
	TRISB = 0;					//make D7 output
	RW_TrisBit = 0;					//make R/W output (write)
}	
	
void lcd_16number(int num)
{
	number[0]=(char)(abs(num/10000)+0x30);
	num=num-abs(num/10000)*10000;
	number[1]=(char)(abs(num/1000)+0x30);
	num=num-abs(num/1000)*1000;
	number[2]=(char)(abs(num/100)+0x30);
	num=num-abs(num/100)*100;
	number[3]=(char)(abs(num/10)+0x30);
	num=num-abs(num/10)*10;
	number[4]=(char)(num+0x30);
}

void lcd_line1(void)
{
	lcd_cmd(0x80);
}

void lcd_line2(void)
{
	lcd_cmd(0xc0);
}		

void lcd_cmd(unsigned char letter)
{
	lcd_busy();
	PORTB = letter;					//put char in PORTB
	PORTB = PORTB >> 4;				//shift over to output high 4 bits
	RS = 0;						//RS low
	e_togg();					//latch the data
	lcd_busy();
	PORTB = letter;
	RS = 0;						//RS low
	e_togg();					//latch it
}

void lcd_char(char letter)
{
	lcd_busy();
	PORTB = letter;					//put char in PORTB
	PORTB = PORTB >> 4;				//shift over to output high 4 bits
	RS = 1;						//RS high
	e_togg();					//latch the data
	lcd_busy();
	PORTB = letter;
	RS = 1;						//RS high
	e_togg();					//latch it
}

void lcd_init(void)
{
	PORTB = 0x03;					//send 3
	e_togg();
	lcd_busy();
	PORTB = 0x03;
	e_togg();
	lcd_busy();
	PORTB = 0x03;
	e_togg();
	lcd_busy();
	PORTB = 0x02;					//send 2 - set 4-bit mode
	e_togg();
	lcd_busy();
	lcd_cmd(0x28);					//set 4-bit mode and 2 lines
	lcd_busy();
	lcd_cmd(0x10);					//cursor move & shift left
	lcd_busy();
	lcd_cmd(0x06);					//entry mode = increment
	lcd_busy();
	lcd_cmd(0x0d);					//display on - cursor blink on
	lcd_busy();
	lcd_cmd(0x01);					//clear display
	lcd_busy();
}

void e_togg(void)
{
	E=1;
	E=0;
}

void delay(void)
{
	int x,y;
	for(x=0;x<1;x++)
	{
		for(y=0;y<10000;y++){}
	}
}
 
Last edited:
Pommie said:
If you have it on A0 then you need to change your code to x=read_a2d(0);

Mike.
i have done ADCON1=0 and then nothing appear on the LCD is think somee pins are floating so i changed the pins iinto ADCON1=14 then i got the reading constans as while iam moving some thing toward the sensor the reading doent changed it is equal to 17779 i dont now what is this !!!!
this is my code
Code:
#include <pic.h>
#include "lcd.h"
#include "delay.h"
#include<stdio.h>

// Setup the configuration word for use with ICD2
__CONFIG(DEBUGEN & WDTDIS & LVPDIS);


void init_a2d(void)
{
	ADCON0=0;	// select Fosc/2
	ADCON1=0;	// select left justify result. A/D port configuration 0
	ADON=1;		// turn on the A2D conversion module
}
unsigned char read_a2d(unsigned char channel)
{
	channel&=0x07;	// truncate channel to 3 bits
	ADCON0&=0xC5;	// clear current channel select
	ADCON0|=(channel<<3);	// apply the new channel select
	ADGO=1;	// initiate conversion on the selected channel
	while(ADGO)continue;
	return(ADRESH);	// return 8 MSB of the result
}



void main(void)
{
   unsigned char outString[20];
   float voltage;
   unsigned char x;
    init_a2d();	// initialise the A2D module
	GIE=0;

TRISE = 0;
TRISD = 0;
TRISB = 0;
TRISA  = 0x01;;
ADCON1 = 14;
RE2 = 0;
DelayMs(500);
lcd_init();

while(1) {
      lcd_clear();
      lcd_goto(0);
      lcd_puts("Damn!");
      x=read_a2d(0);      
      // lcd_goto(40);
      voltage=(x/255.0)*(5.0);   
     sprintf(outString,"A2D = %d volts",voltage);    
      lcd_puts(outString);


   
DelayMs(3000);
  }

}
when i run it on the board the LCD siplay the folowing: Damn! A2D=17779 vlots !!!!
what is that and why it doent not change while iam moving and object!!!!
 
engkhlaif said:
when i run it on the board the LCD siplay the folowing: Damn! A2D=17779 vlots !!!!
what is that and why it doent not change while iam moving and object!!!!

Can't help you with C at all, but the ouput of the A2D can only vary between 0 and 1023, so it sounds like your scaling routines are wrong?.

Forget about the A2D input for now, modify your code to feed a fixed number (between 0 and 1023) to the scaling routines, and confirm you get the expected value out. Do this for a range of values, and confirm it all scales correctly - then worry about the A2D reading.
 
engkhlaif said:
what is the difference between float and decimal and why is that result!!!!

When you state %d you indicate a decimal integer, voltage is a float. Just try it and see.

Mike.
 
Pommie said:
When you state %d you indicate a decimal integer, voltage is a float. Just try it and see.

Mike.
ok i will try
i want to ask also is that right to write ADCON1=14 as i just need A0 to be analog input as i think if i write ADCON1=0 i set all of them analog and i just want to use A0 !!!!!]
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top