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.

Pic18F452 Programming HELP!

Status
Not open for further replies.

Cheng

New Member
Hi all! Me and my group of friends have a project on hand about converting voltage input into readable data on LCD. We're still on the first phase of the programming. Any help with it would be greatly appreciated. We're using pic18F452 with the picdem 2 plus demo board. The input would be the pot connected via RA0.

Code:
#include <p18xxxx.h>
#include <delays.h>
#include "lcd.h"	
#include <string.h>


#define LCD_RS PORTAbits.RA3   
#define LCD_EN PORTAbits.RA1    
#define LCD_WR PORTAbits.RA2   

#define set_dd_line1_pos1 0x80	
#define set_dd_line2_pos1 0x80

char value1 [ ] = "0V";	 
char value2 [ ] = "5V";


void lcd_write_cmd(unsigned char cmd)
{
	unsigned char temp2;
	LCD_RS = 0;		
	Delay10TCYx(4);	
				
	temp2 = cmd;
	temp2 = temp2 >> 4;		
	PORTD = temp2 & 0x0F;	

 	Delay1KTCYx(1);	
	lcd_strobe();
	Delay1KTCYx(1);	

	temp2 = cmd;		
	PORTD = temp2 & 0x0F;	

	Delay1KTCYx(1);	
	lcd_strobe();
	Delay1KTCYx(1);	

}



void lcd_clear(void)	
{
	lcd_write_cmd(0x01);
	Delay1KTCYx(2);	
						
}



void lcd_write_data(char data)
{
	char temp1;

	LCD_RS = 1;		
	Delay10TCYx(4);	

	temp1 = data;
	temp1 = temp1 >> 4;
	PORTD = temp1 & 0x0F;

 	Delay1KTCYx(1);			
	lcd_strobe();
	Delay1KTCYx(1);

	temp1 = data;
	PORTD = temp1 & 0x0F;
		
	Delay1KTCYx(1); 
	lcd_strobe();
	Delay1KTCYx(1);
	
}



void lcd_goto(unsigned char LCD_POS)
{
	lcd_write_cmd(LCD_POS); 
	Delay1KTCYx(2);				

}



void lcd_strobe(void)	
{
 	LCD_EN = 1;
	Delay10TCYx(4);
					
	LCD_EN = 0;
	Delay10TCYx(4);	
}

void lcd_init(void)
{
	LCD_RS = 0;	
	LCD_WR = 0;	

	Delay1KTCYx(250);
	Delay1KTCYx(250);	
	Delay1KTCYx(250);	 
	Delay1KTCYx(250);	

	PORTD = 0x03;

	lcd_strobe();
	Delay1KTCYx(250);

	PORTD = 0x03;
	lcd_strobe();
	Delay1KTCYx(250);

	PORTD = 0x03;	
	lcd_strobe();
	Delay1KTCYx(250);

	PORTD = 0x02;
	lcd_strobe();
	Delay1KTCYx(250);
	Delay1KTCYx(250);


	lcd_write_cmd(0x28)
	        
	lcd_write_cmd(0x01);
	Delay1KTCYx(20);	
	Delay1KTCYx(20);	
	lcd_write_cmd(0x0F);
					
	Delay1KTCYx(20);

 	lcd_write_cmd(0x06);
					
					
	Delay1KTCYx(20);
}

main(void)
{
	
	char outchar;
	unsigned char Sizevalue1, Sizevalue2, Sizevalue3;
	unsigned char index;
	#define constant [B]0x01[/B]
	#define constant2 [B]0x05[/B]

	TRISA = 0x00;
	TRISD = 0x00;		

	PORTD = 0x00;


	ADCON0 = 0b11000001;    

	ADCON1 = 0b00001110;	

	for(;;)
	{
		ADCON0bits.GO = 1;		
	             (PIR1bits.ADIF == 0); 	   		
		PORTD = ADRESH;		
		
		if(ADRESH < constant)
		{
			Sizevalue1 = strlen(value1); // get size of array
			LCD_EN = 0;
			LCD_RS = 0;
			LCD_WR = 0;
			lcd_init();
			LCD_RS = 1;			

			lcd_goto(set_dd_line1_pos1);
			for (index = 0; index < Sizevalue1; index++)
			{
				outchar = value1[index];
				lcd_write_data(outchar);
			} 
			Delay1KTCYx(250);
			Delay1KTCYx(250);
			Delay1KTCYx(250);
			lcd_goto(set_dd_line1_pos1);
			PIR1bits.ADIF = 0;
			lcd_clear();
		}


		if(ADRESH > constant2)
		{
			Sizevalue2 = strlen(value2); 
			LCD_EN = 0;
			LCD_RS = 0;
			LCD_WR = 0;
			lcd_init();
			LCD_RS = 1;	

			lcd_goto(set_dd_line1_pos1);
			for (index = 0; index < Sizevalue1; index++)
			{
				outchar = value2[index];
				lcd_write_data(outchar); 
			} 
			Delay1KTCYx(250);
			Delay1KTCYx(250);
			Delay1KTCYx(250);
			lcd_goto(set_dd_line1_pos1);
			PIR1bits.ADIF = 0;
			lcd_clear();
		}  		 	
	}
}

I've managed to display 0V and 5V on the lcd when i turn the wiper of the pot CCW or CW completely. Now I'm trying to detect the other voltages when I adjust the wiper but there are 2 problems. Firstly, As you can see from my programming, my constant values are 0x01 and 0x05, which I assume should read analog inputs of lower than 1V and higher than 5V. (Am I right?) It works when I run the program but still would like someone's confirmation on it because I'm not so sure myself. My second problem is designing a subroutine to detect the other voltages. How should I go about it?
 
Last edited:
Hi all. We've managed to create a program that could read voltage levels up to 0.36V with steps of 0.018V. This is the program:

Code:
#include <p18f452.h>
#include <delays.h>
#include "lcd.h"	
#include <string.h>


#define LCD_RS PORTAbits.RA3    // Assigning RA3 for Register Select on LCD
#define LCD_EN PORTAbits.RA1    // Assigning RA1 for Enable on LCD controller
#define LCD_WR PORTAbits.RA2    // Assigning RA2 for Write on LCD controller

#define set_dd_line1_pos1 0x80	// The address of line 1, pos1 on the LCD module
#define set_dd_line2_pos1 0x80
#define set_dd_line3_pos1 0x80
#define set_dd_line4_pos1 0x80

char value0 [ ] = "0V";	  // Defining a char string
char value1 [ ] = "0.018V";
char value2 [ ] = "0.036V";
char value3 [ ] = "0.054V";
char value4 [ ] = "0.072V";
char value5 [ ] = "0.09V";
char value6 [ ] = "0.108V";
char value7 [ ] = "0.126V";
char value8 [ ] = "0.144V";
char value9 [ ] = "0.162V";
char value10 [ ] = "0.18V";
char value11 [ ] = "0.198V";
char value12 [ ] = "0.216V";
char value13 [ ] = "0.234V";
char value14 [ ] = "0.252V";
char value15 [ ] = "0.27V";
char value16 [ ] = "0.288V";
char value17 [ ] = "0.306V";
char value18 [ ] = "0.324V";
char value19 [ ] = "0.342V";
char value20 [ ] = "0.36V";


//--- Function for writing a command byte to the LCD in 4 bit mode -------------

void lcd_write_cmd(unsigned char cmd)
{
	unsigned char temp2;
	LCD_RS = 0;		// Select LCD for command mode
	Delay10TCYx(4);	// 40us delay for LCD to settle down
					// at command mode
	temp2 = cmd;
	temp2 = temp2 >> 4;		// Output upper 4 bits, by shifting out lower 4 bits
	PORTD = temp2 & 0x0F;	// Output to PORTD which is connected to LCD 

 	Delay1KTCYx(1);		// Delay at least 1 ms before strobing
	lcd_strobe();
	Delay1KTCYx(1);		// Delay at least 1 ms after strobing

	temp2 = cmd;			// Re-initialise temp2
	PORTD = temp2 & 0x0F;	// Mask out upper 4 bits

	Delay1KTCYx(1);		// Delay at least 1 ms before strobing
	lcd_strobe();
	Delay1KTCYx(1);		// Delay at least 1 ms before strobing

}

//----	Clear and home the LCD i.e. put the cursor at line1, pos1 ----------------

void lcd_clear(void)	// Function to clear LCD display
{
	lcd_write_cmd(0x01);// LCD command of 0x01 clears the display
	Delay1KTCYx(2);		// Delay at least 2 ms after writing
						// the CLEAR LCD command
}

//---- Function to write a character data to the LCD ---------------------------

void lcd_write_data(char data)
{
	char temp1;

	LCD_RS = 1;		// Select LCD for data mode
	Delay10TCYx(4);	// 40us delay for LCD to settle down

	temp1 = data;
	temp1 = temp1 >> 4;
	PORTD = temp1 & 0x0F;

 	Delay1KTCYx(1);		//-- strobe data in	
	lcd_strobe();
	Delay1KTCYx(1);

	temp1 = data;
	PORTD = temp1 & 0x0F;
		
	Delay1KTCYx(1); 	//-- strobe data in
	lcd_strobe();
	Delay1KTCYx(1);
	
}

//-- Go to a specified position ------------------------------------------------

void lcd_goto(unsigned char LCD_POS)
{
	lcd_write_cmd(LCD_POS);  	// Set the cursor position
	Delay1KTCYx(2);				// Delay at least 2 ms after writing
								// the LCD command

}

//-- Function to generate the strobe signal -------------------------------------

void lcd_strobe(void)	// This function provides the	
						// high to low transition needed
						// to initiate the actual transfer of 
						// commands or data to the LCD module
{
 	LCD_EN = 1;
	Delay10TCYx(4);	// 40us delay for LCD_EN to settle
					// at logic "1"
	LCD_EN = 0;
	Delay10TCYx(4);	// 40us delay for LCD_EN to settle
					// at logic "0"
}

void lcd_init(void)
{
	LCD_RS = 0;		// Select LCD for command mode
	LCD_WR = 0;		// Select LCD for write mode
					// for only writing of commands
					// and data (i.e. does not read e.g. 
					// the status of the LCD)

	Delay1KTCYx(250);	// Delay a total of 1 s for LCD module to
	Delay1KTCYx(250);	// 
	Delay1KTCYx(250);	// 
	Delay1KTCYx(250);	// finish its own internal initialisation

/* The data sheets warn that the LCD module may fail to initialise properly when
   power is first applied. This is particularly likely if the Vdd 
   supply does not rise to its correct operating voltage quickly enough.

   It is recommended that after power is applied, a command sequence of 
   3 bytes of 30h be sent to the module. This will ensure that the module is in
   8-bit mode and is properly initialised. Following this, the LCD module can be
   switched to 4-bit mode.	
*/

	PORTD = 0x03;	// Note that PORTD bits 0-3 are connected
					// to the LCD data bits 4-7 (high nibble)
					// PORTD   3      2       1      0
					// 	      DB7    DB6     DB5    DB4
					// Thus, PORTD = 0x03 is 0x30 at DB7-0
	lcd_strobe();
	Delay1KTCYx(250);	// 250 ms delay

	PORTD = 0x03;
	lcd_strobe();
	Delay1KTCYx(250);	// 250 ms delay

	PORTD = 0x03;	
	lcd_strobe();
	Delay1KTCYx(250);	// 250 ms delay

	PORTD = 0x02;		// 0000001x – Cursor Home instruction
						// Returns cursor to home position
	lcd_strobe();
	Delay1KTCYx(250);	// 250 ms delay
	Delay1KTCYx(250);	// 250 ms delay


	lcd_write_cmd(0x28);// 001010xx – Function Set instruction
						// DL=0 : 4-bit interface, N=1 : 2 lines
						// F=0 : 5x7 dots 
	Delay1KTCYx(20);	// 20 ms delay
	        
	lcd_write_cmd(0x01);// 00000001 Clear Display instruction
	Delay1KTCYx(20);	// 20 ms delay
	
	Delay1KTCYx(20);	// 20 ms delay
	lcd_write_cmd(0x0F);// 00001111 – Display On/Off Control instruction
						// D=1 : Display on
						// C=1 : Cursor on
						// B=1 : Cursor Blink on
	Delay1KTCYx(20);	// 20 ms delay

 	lcd_write_cmd(0x06);// 00000110 – Entry Mode Set instruction
						// I/D=1 : Increment Cursor position
						// S=0 : No display shift
	Delay1KTCYx(20);	// 20 ms delay
}

main(void)
{         
	char outchar;	//-- character to send to the LCD
	unsigned char Sizevalue0, Sizevalue1, Sizevalue2, Sizevalue3, Sizevalue4, Sizevalue5, Sizevalue6, Sizevalue7, Sizevalue8, Sizevalue9, Sizevalue10,
				  Sizevalue11, Sizevalue12, Sizevalue13, Sizevalue14, Sizevalue15, Sizevalue16, Sizevalue17, Sizevalue18, Sizevalue19, Sizevalue20; 
	unsigned char index;
	#define constant0 0x00
	#define constant1 0x01
	#define constant2 0x02
	#define constant3 0x03
	#define constant4 0x04
	#define	constant5 0x05
	#define constant6 0x06
	#define constant7 0x07
	#define constant8 0x08
	#define constant9 0x09
	#define constant10 0x0A
	#define constant11 0x0B
	#define constant12 0x0C
	#define constant13 0x0D
	#define constant14 0x0E
	#define constant15 0x0F	
	#define constant16 0x10

	Sizevalue1 = strlen(value1); // get size of array
	Sizevalue2 = strlen(value2); // get size of array
	Sizevalue3 = strlen(value3);
	Sizevalue4 = strlen(value4);
	Sizevalue5 = strlen(value5);
	Sizevalue6 = strlen(value6);
	Sizevalue7 = strlen(value7);
	Sizevalue8 = strlen(value8);
	Sizevalue9 = strlen(value9);
	Sizevalue10 = strlen(value10);
	Sizevalue11 = strlen(value11);
	Sizevalue12 = strlen(value12);
	Sizevalue13 = strlen(value13);
	Sizevalue14 = strlen(value14);
	Sizevalue15 = strlen(value15);
	Sizevalue16 = strlen(value16);
	Sizevalue17 = strlen(value17);
	Sizevalue18 = strlen(value18);
	Sizevalue19 = strlen(value19);
	Sizevalue20 = strlen(value20);

	TRISA = 0b00000001;
	TRISD = 0x00;		

	PORTD = 0x00;


	ADCON0 = 0b11000001;    

	ADCON1 = 0b00001110;	

	for(;;)
	{
		ADCON0bits.GO = 1;		
	        
		while(PIR1bits.ADIF == 0); 	   		
			
		PORTD = ADRESH;		
		
		LCD_EN = 0;
		LCD_RS = 0;
		LCD_WR = 0;
		lcd_init();
		LCD_RS = 1;

		if(ADRESH == constant0)
		{
			
			lcd_goto(set_dd_line4_pos1);
			for (index = 0; index < Sizevalue0; index++)
			{
			outchar = value0[index];
			Delay1KTCYx(250);			// 250 ms delay
			lcd_write_data(outchar); 	// write character data to LCD
			} 
			Delay1KTCYx(250);
			Delay1KTCYx(250);
			lcd_clear();
			lcd_goto(set_dd_line4_pos1);
		}
 			

			else
			{
				if(ADRESH == constant1)
				{
				lcd_goto(set_dd_line3_pos1);
				for (index = 0; index < Sizevalue1; index++)
				{
				outchar = value1[index];
				Delay1KTCYx(250);			// 250 ms delay
				lcd_write_data(outchar); 	// write character data to LCD
				} 
				Delay1KTCYx(250);
				Delay1KTCYx(250);
				lcd_clear();
				lcd_goto(set_dd_line3_pos1);
				}
				else
				{
					if(ADRESH == constant2)
					{
					lcd_goto(set_dd_line2_pos1);
					for (index = 0; index < Sizevalue2; index++)
					{
					outchar = value2[index];
					Delay1KTCYx(250);			// 250 ms delay
					lcd_write_data(outchar); 	// write character data to LCD
					} 
					Delay1KTCYx(250);
					Delay1KTCYx(250);
					lcd_clear();
					lcd_goto(set_dd_line2_pos1);
					}			
					else
					{
						if(ADRESH == constant3)
						{
							lcd_goto(set_dd_line1_pos1);
							for (index = 0; index < Sizevalue3; index++)
						{
						outchar = value3[index];
						Delay1KTCYx(250);			// 250 ms delay
						lcd_write_data(outchar); 	// write character data to LCD
						} 
						Delay1KTCYx(250);
						Delay1KTCYx(250);
						lcd_clear();
						lcd_goto(set_dd_line1_pos1);
						}
						else
						{
							if(ADRESH == constant4)
							{
							lcd_goto(set_dd_line1_pos1);
							for (index = 0; index < Sizevalue4; index++)
							{
							outchar = value4[index];
							Delay1KTCYx(250);			// 250 ms delay
							lcd_write_data(outchar); 	// write character data to LCD
							} 
							Delay1KTCYx(250);
							Delay1KTCYx(250);
							lcd_clear();
							lcd_goto(set_dd_line1_pos1);
							}
							else
							{
								if(ADRESH == constant5)
								{	
									lcd_goto(set_dd_line1_pos1);
									for (index = 0; index < Sizevalue5; index++)
								{
								outchar = value5[index];
								Delay1KTCYx(250);			// 250 ms delay
								lcd_write_data(outchar); 	// write character data to LCD
								} 
								Delay1KTCYx(250);
								Delay1KTCYx(250);
								lcd_clear();
								lcd_goto(set_dd_line1_pos1);
								}
								else
								{
									if(ADRESH == constant6)
									{	
									lcd_goto(set_dd_line1_pos1);
									for (index = 0; index < Sizevalue6; index++)
									{
									outchar = value6[index];
									Delay1KTCYx(250);			// 2	50 ms delay
									lcd_write_data(outchar); 	// write character data to LCD
									} 
									Delay1KTCYx(250);
									Delay1KTCYx(250);
									lcd_clear();
									lcd_goto(set_dd_line1_pos1);
									}
									else
									{
										if(ADRESH == constant7)
										{	
										lcd_goto(set_dd_line1_pos1);
										for (index = 0; index < Sizevalue7; index++)
										{
										outchar = value7[index];
										Delay1KTCYx(250);			// 2	50 ms delay
										lcd_write_data(outchar); 	// write character data to LCD
										} 
										Delay1KTCYx(250);
										Delay1KTCYx(250);
										lcd_clear();
										lcd_goto(set_dd_line1_pos1);
										}
										else
										{
											if(ADRESH == constant8)
											{	
											lcd_goto(set_dd_line1_pos1);
											for (index = 0; index < Sizevalue8; index++)
											{
											outchar = value8[index];
											Delay1KTCYx(250);			// 2	50 ms delay
											lcd_write_data(outchar); 	// write character data to LCD
											} 
											Delay1KTCYx(250);
											Delay1KTCYx(250);
											lcd_clear();
											lcd_goto(set_dd_line1_pos1);
											}
											else
											{
												if(ADRESH == constant9)
												{	
												lcd_goto(set_dd_line1_pos1);
												for (index = 0; index < Sizevalue9; index++)
												{
												outchar = value9[index];
												Delay1KTCYx(250);			// 2	50 ms delay
												lcd_write_data(outchar); 	// write character data to LCD
												} 
												Delay1KTCYx(250);
												Delay1KTCYx(250);
												lcd_clear();
												lcd_goto(set_dd_line1_pos1);
												}
												else
												{
													if(ADRESH == constant10)
													{	
													lcd_goto(set_dd_line1_pos1);
													for (index = 0; index < Sizevalue10; index++)
													{
													outchar = value10[index];
													Delay1KTCYx(250);			// 2	50 ms delay
													lcd_write_data(outchar); 	// write character data to LCD
													} 
													Delay1KTCYx(250);
													Delay1KTCYx(250);
													lcd_clear();
													lcd_goto(set_dd_line1_pos1);
													}
						}
					}
				}		
	    	PIR1bits.ADIF = 0;		
		}
	}
}
}
}
}
}
}
}

As you can see, we've practically assigned every single step of 0.018V to a variable. As the variable continues, we got an error stating that the program is too long or it's overloaded. Is there another way to program it so that we could output 0-5V from the pot connected via RA0 with steps of 0.018V? Any suggestions would be greatly appreciated. Thank you in advance!
 
Don't define them as strings (which is just a lookup table anyway), read the value (0 - 1023) and process it mathmatically to give the range you want (multiply/divide).
 
Thanks for the reply! Anyway now we're utilizing sprintf to try and get things done.. Problem is we don't know whether cstdio.h or stdio.h is required..?
 
Ok we solved that problem too. Has anyone tried sprintf-ing data onto LCD before? We couldn't get anything to show other than a couple of blinking cursors at most. Any help would be most appreciated.
 
Ok we solved that problem too. Has anyone tried sprintf-ing data onto LCD before? We couldn't get anything to show other than a couple of blinking cursors at most. Any help would be most appreciated.

Yes. It looks like you are using the Microchip C18 compiler.

All you have to do is redirect the sprintf output to the LCD. By default it goes to the UART. See 4.7 CHARACTER OUTPUT FUNCTIONS of MPLAB® C18 in the document C COMPILER LIBRARIES has what you need. Look at output streams.

You can find the document on the Microchip C18 page. It is either called MPLAB_C18_Libraries_51297f.pdf or just 51297f.pdf

There is a lot of good info on functions for using the hardware and software only routines in this doc.

4.7.1 Output Streams
Output is based on the use of a destination stream. A stream can be a peripheral,
memory buffer, or any other consumer of data and is denoted by a pointer to an object
of FILE type. MPLAB C18 defines two streams in the standard library:
_H_USER output via the user-defined output function _user_putc.
_H_USART output via the library output function _usart_putc.
The current version of the library supports only these two output streams. Both streams
are always considered to be open and do not require use of functions such as fopen,
fclose, etc.
The global variables stdout and stderr are defined by the library and have default
value of _H_USART. To change the destination to be _H_USER, assign that value to the
variable. For example, to change standard output to use the user defined output
function:
stdout = _H_USER;
In short you name your LCD putc function _user_putc and set stdout = _H_USER;

You may want to check that it is about 4AM here and I need to get back to bed.
 
Hi. We tried to run the program using the code below:

Code:
#include <p18xxxx.h>
#include <delays.h>
#include "lcd.h"	
#include <string.h>
#include <stdio.h>

char outstring []="                ";	  // Defining a char string
float fVolts;	/* floating pt */

main(void)
{
	
	int voltage;

	LCD_EN = 0;
	LCD_RS = 0;
	LCD_WR = 0;
	lcd_init();
	LCD_RS = 1;

	TRISA = 0x01;
	TRISD = 0x00;		

	PORTD = 0x00;


	ADCON0 = 0b11000001;    

	ADCON1 = 0b00001110;	

	for(;;)
	{
		lcd_init();

		ADCON0bits.GO = 1;		
	    
		while(PIR1bits.ADIF == 0); 	   		
		PORTD = ADRESH;
		lcd_goto(set_dd_line1_pos1);
		[B]voltage = ADRESH * 19.0;
		fVolts= voltage/1000.0;
                sprintf(outstring,"Volt %1.3f", fVolts);[/B]	
(breakpoint)	lcd_write_data(outstring); 	
		    		 	
	    PIR1bits.ADIF = 0;		
	}
}

We added a breakpoint at the "lcd_write_data(outstring)" sentence, (to see if the computation was done) and didn't went on to display at LCD. When we highlighted the sentence "fVolts = voltage/1000.0;" we got "fVolts = 1.710000" but when we highlighted sprintf it showed "outstring = Volt", with no values shown. Why is this so?
 
Last edited:
Hi again. I read from the forums at the microchip website that sprintf in c18 compiler (which we're using) does not support the %f ONLY. And dhenry also mentioned a solution which is "Print the integer part and the fractional part separately using the conversion specifiers that your compiler does support." Is this true? And if it is, how do we go about using dhenry's method?
 
Here's a program I wrote for the picdemo2 a couple of years ago that does what you want. It also lights the 4 leds in sequence as the voltage changes.
 

Attachments

  • 2007.03.12a.pdf
    385.8 KB · Views: 407
Thanks Analog! We're gonna try out your program but seems like you were using pic18f4520 while we're using pic18f452 so there's a little difference in the coding. Will get back to you after we've tried it out. =)
 
Hi all. We have managed to display the voltage on the pot using simple programming. Currently we're just detecting the voltage and displaying it as both voltage and current, and squaring it to produce the power. Now our problem comes in when we have to include another pot. We used another 5k pot. How do we program it to read two pot inputs simultaneously? Do we program ADCON0 and ADCON1 two times, to initialise each pot one at a time?
 
How do we program it to read two pot inputs simultaneously? Do we program ADCON0 and ADCON1 two times, to initialise each pot one at a time?

After reading the first pot you need to change ADCON0 to read the second pot. You must allow enough time for the sample and hold capacitor to charge between switching channels and starting the conversion. Check the data sheet for the acquisition time.

Mike.
 
Thanks for the reply Pommie. We added delays but only got numerical displays for the first pot. Below is our code:

Code:
#include <p18f452.h>
#include <delays.h>
#include "lcd.h"	
#include <string.h>


#define LCD_RS PORTAbits.RA3    // Assigning RA3 for Register Select on LCD
#define LCD_EN PORTAbits.RA1    // Assigning RA1 for Enable on LCD controller
#define LCD_WR PORTAbits.RA2    // Assigning RA2 for Write on LCD controller
	
char outchar;	//-- character to send to the LCD

unsigned float A,B,C;	



//--- Function for writing a command byte to the LCD in 4 bit mode -------------

void lcd_write_cmd(unsigned char cmd)
{
	unsigned char temp2;
	LCD_RS = 0;		// Select LCD for command mode
	Delay10TCYx(4);	// 40us delay for LCD to settle down
					// at command mode
	temp2 = cmd;
	temp2 = temp2 >> 4;		// Output upper 4 bits, by shifting out lower 4 bits
	PORTD = temp2 & 0x0F;	// Output to PORTD which is connected to LCD 

 	Delay1KTCYx(1);		// Delay at least 1 ms before strobing
	lcd_strobe();
	Delay1KTCYx(1);		// Delay at least 1 ms after strobing

	temp2 = cmd;			// Re-initialise temp2
	PORTD = temp2 & 0x0F;	// Mask out upper 4 bits

	Delay1KTCYx(1);		// Delay at least 1 ms before strobing
	lcd_strobe();
	Delay1KTCYx(1);		// Delay at least 1 ms before strobing

}

//----	Clear and home the LCD i.e. put the cursor at line1, pos1 ----------------

void lcd_clear(void)	// Function to clear LCD display
{
	lcd_write_cmd(0x01);// LCD command of 0x01 clears the display
	Delay1KTCYx(2);		// Delay at least 2 ms after writing
						// the CLEAR LCD command
}

//---- Function to write a character data to the LCD ---------------------------

void lcd_write_data(char data)
{
	char temp1;

	LCD_RS = 1;		// Select LCD for data mode
	Delay10TCYx(4);	// 40us delay for LCD to settle down

	temp1 = data;
	temp1 = temp1 >> 4;
	PORTD = temp1 & 0x0F;

 	Delay1KTCYx(1);		//-- strobe data in	
	lcd_strobe();
	Delay1KTCYx(1);

	temp1 = data;
	PORTD = temp1 & 0x0F;
		
	Delay1KTCYx(1); 	//-- strobe data in
	lcd_strobe();
	Delay1KTCYx(1);
	
}

//-- Go to a specified position ------------------------------------------------

void lcd_goto(unsigned char LCD_POS)
{
	lcd_write_cmd(LCD_POS);  	// Set the cursor position
	Delay1KTCYx(2);				// Delay at least 2 ms after writing
								// the LCD command

}

//-- Function to generate the strobe signal -------------------------------------

void lcd_strobe(void)	// This function provides the	
						// high to low transition needed
						// to initiate the actual transfer of 
						// commands or data to the LCD module
{
 	LCD_EN = 1;
	Delay10TCYx(4);	// 40us delay for LCD_EN to settle
					// at logic "1"
	LCD_EN = 0;
	Delay10TCYx(4);	// 40us delay for LCD_EN to settle
					// at logic "0"
}

void lcd_init(void)
{
	LCD_RS = 0;		// Select LCD for command mode
	LCD_WR = 0;		// Select LCD for write mode
					// for only writing of commands
					// and data (i.e. does not read e.g. 
					// the status of the LCD)

	Delay1KTCYx(250);	// Delay a total of 1 s for LCD module to
	Delay1KTCYx(250);	// 
	Delay1KTCYx(250);	// 
	Delay1KTCYx(250);	// finish its own internal initialisation



	PORTD = 0x03;	// Note that PORTD bits 0-3 are connected
					// to the LCD data bits 4-7 (high nibble)
					// PORTD   3      2       1      0
					// 	      DB7    DB6     DB5    DB4
					// Thus, PORTD = 0x03 is 0x30 at DB7-0
	lcd_strobe();
	Delay1KTCYx(250);	// 250 ms delay

	PORTD = 0x03;
	lcd_strobe();
	Delay1KTCYx(250);	// 250 ms delay

	PORTD = 0x03;	
	lcd_strobe();
	Delay1KTCYx(250);	// 250 ms delay

	PORTD = 0x02;		// 0000001x – Cursor Home instruction
						// Returns cursor to home position
	lcd_strobe();
	Delay1KTCYx(250);	// 250 ms delay
	Delay1KTCYx(250);	// 250 ms delay


	lcd_write_cmd(0x28);// 001010xx – Function Set instruction
						// DL=0 : 4-bit interface, N=1 : 2 lines
						// F=0 : 5x7 dots 
	Delay1KTCYx(20);	// 20 ms delay
	        
	lcd_write_cmd(0x01);// 00000001 Clear Display instruction
	Delay1KTCYx(20);	// 20 ms delay
	
	Delay1KTCYx(20);	// 20 ms delay
	lcd_write_cmd(0x0F);// 00001111 – Display On/Off Control instruction
						// D=1 : Display on
						// C=1 : Cursor on
						// B=1 : Cursor Blink on
	Delay1KTCYx(20);	// 20 ms delay

 	lcd_write_cmd(0x06);// 00000110 – Entry Mode Set instruction
						// I/D=1 : Increment Cursor position
						// S=0 : No display shift
	Delay1KTCYx(20);	// 20 ms delay
}

void display(void)
{
	for(;;)
	{	
		
		ADCON0bits.GO = 1;		// This is bit2 of ADCON0, START CONVERSION NOW
	        
		while(PIR1bits.ADIF == 0);
		
		A = ADRESH * 0.01859375 ;

		if(A < 1)
		{
			lcd_goto(0x80);
			lcd_write_data('0'); 	// write character data to LCD
			Delay1KTCYx(1);	
		
		}

		else
		{
			if (A <2)
			{
				lcd_goto(0x80);
				lcd_write_data('1'); 	// write character data to LCD
				Delay1KTCYx(1);
								
			}
			else
			{
				if (A <3)
				{
					lcd_goto(0x80);
					lcd_write_data('2'); 	// write character data to LCD
					Delay1KTCYx(1);
				
				}
		    	else
				{
					if (A <4)
					{
						lcd_goto(0x80);
						lcd_write_data('3'); 	// write character data to LCD
						Delay1KTCYx(1);
						
					}
					else
					{
						if (A <5)
						{
							lcd_goto(0x80);
							lcd_write_data('4'); 	// write character data to LCD
							Delay1KTCYx(1);
							
						}	 	
						else
						{
							lcd_goto(0x80);
							lcd_write_data('5'); 	// write character data to LCD
							Delay1KTCYx(1);
						}
					}
				}
			}
		}
	    PIR1bits.ADIF = 0;	
	}
}
					
void main(void)
{
	

	ADCON0 = 0b11000001;
	ADCON1 = 0x0E;		// configure PORTA to be digital I/O
	TRISA = 0x01;	
	TRISD = 0x00;	
		
	LCD_EN = 0;
	LCD_RS = 0;
	LCD_WR = 0;

	PORTD = 0x00;
	Delay1KTCYx(1);		// 1 ms delay
	lcd_init();

	LCD_RS = 1;			// Select LCD for data mode
	Delay1KTCYx(1);	

	display();
	Delay1KTCYx(1);
	Delay1KTCYx(1);
	
	ADCON0 = 0b11100001;
	ADCON1 = 0x0E;		// configure PORTA to be digital I/O
	TRISA = 0b00100000;	
	TRISD = 0x00;	
	
	lcd_init();

	LCD_RS = 1;			// Select LCD for data mode
	Delay1KTCYx(1);	
	display();
}

Are we doing something wrong or have we missed out anything? Any help would be greatly appreciated.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top