|
|
View previous topic :: View next topic |
Author |
Message |
Guest
|
EXTERNAL LCD |
Posted: Tue Dec 04, 2007 1:24 am |
|
|
I wish to display the measured temperature on a external lcd screen but i am unsure.
I know i need to use setup_lcd and lcd_load functions to activate the lcd.
but i m not sure how to use it.
Please advise.
By the way, I'm using
- Alphanumeric dot matrix LCD module
(+5Vdc), format: 16 characters lines
for lcd.
& LM35DZ for temperature sensor.
thanks.
Quote: | #include <16f887.h>
#fuses hs, nowdt, nolvp, noprotect, noput, nobrownout,nocpd, nodebug
#device adc=10
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, parity=n, bits=8)
char test;
float temp,volt,temperature;
void main()
{
set_tris_a(0xff);
set_tris_e(0xff);
setup_adc_ports(all_analog);
setup_adc(adc_clock_div_32);
do
{
set_adc_channel(5);
delay_us(40);
temp = read_adc();
volt = (temp*5)/1023;
temperature = 20*volt;
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
xbt87
Joined: 04 Dec 2007 Posts: 11
|
|
Posted: Tue Dec 04, 2007 9:30 am |
|
|
oki thanks, i will try it out thanks for the guide! |
|
|
xbt87
Joined: 04 Dec 2007 Posts: 11
|
|
Posted: Sun Dec 09, 2007 11:06 am |
|
|
Hi there,
i tried the above method and it kinda have some problems.
Nothing is shown on the lcd.
i am not sure if it's the lcd or the demo board is faulty.
or something i have miss out.
i am using 44pin demo board with pic16f887.
please advice.
Thanks.
Quote: | #include <16F887.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)
#include "flex_lcd.c"
//==========================
void main()
{
lcd_init(); // Always call this first.
lcd_putc("\fHi, i am a lcd\n");
lcd_putc("Please light up");
while(1);
} |
&
Quote: | // flex_lcd.c
// These pins are for the Microchip PicDem2-Plus board,
// which is what I used to test the driver. Change these
// pins to fit your own board.
#define LCD_DB4 PIN_A0
#define LCD_DB5 PIN_A1
#define LCD_DB6 PIN_A2
#define LCD_DB7 PIN_A3
#define LCD_E PIN_B1
#define LCD_RS PIN_B3
#define LCD_RW PIN_B2
// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.
#define USE_LCD_RW 1
//========================================
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line
int8 const LCD_INIT_STRING[4] =
{
0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
0xc, // Display on
1, // Clear display
6 // Increment cursor
};
//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
// Note: !! converts an integer expression
// to a boolean (1 or 0).
output_bit(LCD_DB4, !!(nibble & 1));
output_bit(LCD_DB5, !!(nibble & 2));
output_bit(LCD_DB6, !!(nibble & 4));
output_bit(LCD_DB7, !!(nibble & 8));
delay_cycles(1);
output_high(LCD_E);
delay_us(2);
output_low(LCD_E);
}
//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine. For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.
#ifdef USE_LCD_RW
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3
retval = 0;
output_high(LCD_E);
delay_cycles(1);
retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);
output_low(LCD_E);
return(retval);
}
#endif
//---------------------------------------
// Read a byte from the LCD and return it.
#ifdef USE_LCD_RW
int8 lcd_read_byte(void)
{
int8 low;
int8 high;
output_high(LCD_RW);
delay_cycles(1);
high = lcd_read_nibble();
low = lcd_read_nibble();
return( (high<<4) | low);
}
#endif
//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);
#ifdef USE_LCD_RW
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60);
#endif
if(address)
output_high(LCD_RS);
else
output_low(LCD_RS);
delay_cycles(1);
#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif
output_low(LCD_E);
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
//----------------------------
void lcd_init(void)
{
int8 i;
output_low(LCD_RS);
#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif
output_low(LCD_E);
delay_ms(15);
for(i=0 ;i < 3; i++)
{
lcd_send_nibble(0x03);
delay_ms(5);
}
lcd_send_nibble(0x02);
for(i=0; i < sizeof(LCD_INIT_STRING); i++)
{
lcd_send_byte(0, LCD_INIT_STRING[i]);
// If the R/W signal is not used, then
// the busy bit can't be polled. One of
// the init commands takes longer than
// the hard-coded delay of 60 us, so in
// that case, lets just do a 5 ms delay
// after all four of them.
#ifndef USE_LCD_RW
delay_ms(5);
#endif
}
}
//----------------------------
void lcd_gotoxy(int8 x, int8 y)
{
int8 address;
if(y != 1)
address = lcd_line_two;
else
address=0;
address += x-1;
lcd_send_byte(0, 0x80 | address);
}
//-----------------------------
void lcd_putc(char c)
{
switch(c)
{
case '\f':
lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n':
lcd_gotoxy(1,2);
break;
case '\b':
lcd_send_byte(0,0x10);
break;
default:
lcd_send_byte(1,c);
break;
}
}
//------------------------------
#ifdef USE_LCD_RW
char lcd_getc(int8 x, int8 y)
{
char value;
lcd_gotoxy(x,y);
// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));
output_high(LCD_RS);
value = lcd_read_byte();
output_low(lcd_RS);
return(value);
}
#endif |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Dec 09, 2007 11:33 am |
|
|
Quote: | I am using 44pin demo board with pic16f887. |
Post the manufacturer and the name of the board.
Also post your compiler version. It's a 4-digit number in this format:
You can find it at the start of the .LST file. The file will be in your project
directory after you do a successful compilation. |
|
|
xbt87
Joined: 04 Dec 2007 Posts: 11
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Dec 09, 2007 2:25 pm |
|
|
Your version of the compiler has a bug in the start-up code for the
16F887. It's not initializing the comparator registers correctly.
This will cause problems with pins on Port A if you try to use them
for digital i/o. However, the setup_comparator() function does work
OK on that version, so you can use it to disable the comparators.
Add the line shown in bold below:
Quote: | void main()
{
setup_comparator(NC_NC_NC_NC);
lcd_init(); // Always call this first.
lcd_putc("\fHi, i am a lcd\n");
lcd_putc("Please light up");
while(1);
} |
|
|
|
xbt87
Joined: 04 Dec 2007 Posts: 11
|
|
Posted: Mon Dec 17, 2007 12:17 am |
|
|
Thanks PCM Programmer.
i ran into another problem thou.
Code: | #include <16f887.h>
#fuses HS,NOWDT,NOPUT,NOPROTECT,NODEBUG,BROWNOUT,NOLVP,NOCPD,NOWDT
#device adc=10
#use delay(clock=4000000)
#include <flex_lcd.c>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, parity=n, bits=8)
void main()
{
float voltage,tempdeg, temp;
setup_comparator(NC_NC_NC_NC);
set_tris_a(0xff);
set_tris_e(0xff);
setup_adc_ports(all_analog);
setup_adc(adc_clock_div_32);
lcd_init(); // always call this 1st
lcd_putc("voltage:");
lcd_putc("temperature:");
do
{
set_adc_channel(5); //re0/an5
delay_us(40); //delay
temp = read_adc(); // starts the conversion/read the rsult
voltage = (temp*5)/1023;
tempdeg = 20*voltage;
printf(lcd_putc,"%2.2f",voltage);
lcd_gotoxy(0,2);
printf(lcd_putc,"%2.2f",tempdeg);
delay_ms(1000);
}while (true);
do
{
getch();
printf("%2.2f",voltage);
getch();
printf("%2.2f",tempdeg);
}while (true);
} |
i run the above code and there is no display at the lcd.
i checked the vout of the lm35dz and there is voltage.
http://users.tpg.com.au/gramo/Site/lm35dz.htm
i set up the lm35dz using the above schematic.
just that the vout is an5/re0.
may i know what went wrong?
pls advice. thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 17, 2007 12:36 am |
|
|
Quote: |
printf(lcd_putc,"%2.2f",voltage);
lcd_gotoxy(0,2);
printf(lcd_putc,"%2.2f",tempdeg);
delay_ms(1000);
}while (true);
|
You have an incorrect parameter for the lcd_gotoxy() function.
Look at the explanation of the function in the CCS LCD.c file:
Quote: |
lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1)
|
You can't use 0 as a parameter.
Also, you should add a "\f" to your first printf() function, so it will
clear the LCD before you start to display the new data.
See this sample program. Notice how it has "\f" in the printf() to
clear the screen.
http://www.ccsinfo.com/forum/viewtopic.php?t=32168&start=1 |
|
|
xbt87
Joined: 04 Dec 2007 Posts: 11
|
|
Posted: Mon Dec 17, 2007 12:58 am |
|
|
Hi pcm programmer,
i tried and it kinnda dont work
i was wondering is the adc conversion went wrong?
because when i commented the adc part away, the lcd is working.
pls advice. thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 17, 2007 1:18 am |
|
|
The LCD formatting needs more changes. I shortened the labels to
"volts:" and "temp:", so they would fit on a 16x2 LCD. Also, notice
that I put a newline "\n" after the "volts:". This puts the "temp:"
on the 2nd line of the LCD.
Also notice that I changed the lcd_gotoxy() statements so they start
displaying the numbers at column 8 on the LCD. Also, I added a
space at the end of the printf format string for each statement.
That way, if there is overflow into the next column, it will be cleared
in the next display cycle, if the result is smaller. This is really only
needed for the 2nd line, where the result can extend out to "100.00".
See the changes marked in bold:
Quote: |
lcd_putc("volts:\n");
lcd_putc("temp:");
do
{
set_adc_channel(5); //re0/an5
delay_us(40); //delay
temp = read_adc(); // starts the conversion/read the rsult
voltage = (temp*5)/1023;
tempdeg = 20*voltage;
lcd_gotoxy(8,1);
printf(lcd_putc,"%2.2f ",voltage);
lcd_gotoxy(8,2);
printf(lcd_putc,"%2.2f ",tempdeg);
delay_ms(1000);
}while (true); |
|
|
|
xbt87
Joined: 04 Dec 2007 Posts: 11
|
|
Posted: Mon Dec 17, 2007 1:41 am |
|
|
just to check with you incase i make a mistake.
the vout of the lm35dz should be RE0
and ground should be RE1 right?
Code: |
set_tris_e(0xff);
setup_adc_ports(all_analog);
setup_adc(adc_clock_div_32);
lcd_init(); // always call this 1st
lcd_putc("voltage:");
lcd_putc("temperature:");
do
{
set_adc_channel(5); //re0/an5
delay_us(40); //delay
temp = read_adc(); // starts the conversion/read the rsult |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 17, 2007 2:04 am |
|
|
I have not used the LM35DZ so I can't help too much on it.
Probably somebody else will come along and help you
on it in this thread. |
|
|
xbt87
Joined: 04 Dec 2007 Posts: 11
|
|
Posted: Mon Dec 17, 2007 3:15 am |
|
|
ok thanks
i got another question to ask..
i can only set adc port to all analog but not others...
Code: | setup_adc_ports(all_analog); |
example...
Code: | setup_adc_ports(RE0_RE1_ANALOG); |
giving this error : Line 17(17,31): Undefined identifier RE0_RE1_ANALOG
hmmm... |
|
|
Gerhard
Joined: 30 Aug 2007 Posts: 144 Location: South Africa
|
|
Posted: Mon Dec 17, 2007 3:47 am |
|
|
Try the following way to set up adc ports.
Code: |
setup_adc_ports(sAN1|sAN2|sAN3); |
Just set it up for the correct port.
In the header file there is the description of how to set it up[/code] |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|