|
|
View previous topic :: View next topic |
Author |
Message |
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Tue Nov 16, 2004 12:42 pm |
|
|
This works for me:
Code: |
// This structure is overlayed onto the data ports so that you may use
// whatever ports you desire
struct lcd_pin_map
{
int unusedA; // portA is not used
int unusedB; // portB is not used
int unusedC; // portC is not used
int data; // portD is used for data lines
BOOLEAN enable; // PinE0
BOOLEAN rw; // PinE1
BOOLEAN rs; // PinE2
int unusedE : 5; // The rest of portE
} lcd;
#if defined(__PCH__)
#locate lcd = 0xF80
#else
#locate lcd = 5
#endif
struct lcd_tris_map
{
int unusedA; // The rest of portA
int unusedB; // portB is not used
int unusedC; // portC is not used
int data; // portD is used for data lines
int control : 3; // portE for control
int unusedE : 5; // The rest of portE
} lcdtris;
#if defined(__PCH__)
#locate lcdtris = 0xF92
#else
#locate lcdtris = 0x85
#endif
#define set_tris_lcd(x) lcdtris.data = (x); lcdtris.control = 0;
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the second line
BYTE const LCD_INIT_STRING[4] = {8, 0xc, 1, 6};
// These bytes need to be sent to the LCD
// to start it up.
// The following are used for setting
// the I/O port direction register.
#define LCD_WRITE 0 // For write mode all pins are out
#define LCD_READ 0xFF // For read mode data pins are in
BYTE lcd_read_byte() {
BYTE data;
set_tris_lcd(LCD_READ);
lcd.rw = 1;
delay_cycles(1);
lcd.enable = 1;
delay_cycles(1);
data = lcd.data;
lcd.enable = 0;
set_tris_lcd(LCD_WRITE);
return( data );
}
void lcd_send_nibble( BYTE n ) {
lcd.data = n;
delay_cycles(1);
lcd.enable = 1;
delay_us(2);
lcd.enable = 0;
}
void lcd_send_byte( BYTE address, BYTE n ) {
lcd.rs = 0;
while ( bit_test(lcd_read_byte(),7) ) ;
lcd.rs = address;
delay_cycles(1);
lcd.rw = 0;
delay_cycles(1);
lcd.enable = 0;
lcd.data = n;
delay_cycles(1);
lcd.enable = 1;
delay_us(2);
lcd.enable = 0;
}
void lcd_init() {
BYTE i;
set_tris_lcd(LCD_WRITE);
lcd.rs = 0;
lcd.rw = 0;
lcd.enable = 0;
delay_ms(15);
for(i=1;i<=3;++i) {
lcd_send_byte(0, 0x38);
delay_ms(5);
}
for(i=0;i<=3;++i)
lcd_send_byte(0,LCD_INIT_STRING[i]);
}
void lcd_gotoxy( BYTE x, BYTE y) {
BYTE 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;
}
}
char lcd_getc( BYTE x, BYTE y) {
char value;
lcd_gotoxy(x,y);
lcd.rs=1;
value = lcd_read_byte();
lcd.rs=0;
return(value);
}
|
and a test program:
Code: |
#include <16F876.h>
#device *=16
#case
#use delay(clock=20000000)
#fuses HS,NOWDT,NOPROTECT,NOLVP
#ZERO_RAM
#include "lcdd.c"
//======================= MAIN ============================//
void main(void)
{
lcd_init();
printf(lcd_putc,"Hello World");
printf(lcd_putc,"\nSecond Line");
while(1)
{
}
} |
|
|
|
masacra
Joined: 15 Nov 2004 Posts: 4
|
|
Posted: Tue Nov 16, 2004 1:30 pm |
|
|
Thanks a lot! You have saved me a lot of work. I had to change some of your code to make it run, just a couple of litle things, nothing reliable.
I needed this because I am going to start working with more powerfull MCUs oriented to interfacing LCDs. I am interested in scrolls (specially vertical, the horizontal ones I already know) and in anything related to using LCDs, how can I program the lcd to make vertical scrolls or other kind of efects?(Also Iwould like to enter new characters in the LCD´s RAM).
I have done almost everything above in assembly, but I find myself quite lost in C. Thanks again! |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Tue Nov 16, 2004 1:34 pm |
|
|
If you can do it in asm then you can do it in C. Most of the stuff in asm is just setting the registers to certain values. The same holds true for C. The same LCD code could have been written using bit_set and bit_clear on the port registers. The C Struct just kind of "hides" it. Note you can also embed asm code in a C routine with the #asm. |
|
|
Boyko
Joined: 11 Oct 2004 Posts: 13 Location: Sofia
|
|
Posted: Fri Nov 26, 2004 5:44 am |
|
|
Could you please help me. I'd like to use my LCD like this:
PortD.4-7 : data lnes
PortE.0 : rs
PortE.1 : enable
PortE.2 : rw
I tried to modify the Mark's lcdd.c file, but when I compile the test program I get an error message, in the lcdd.c file, saying "Illegal C character in input file 0xA0". Here is the lcdd.c file I modified:
Code: |
// This structure is overlayed onto the data ports so that you may use
// whatever ports you desire
struct lcd_pin_map
{
int unusedA; // portA is not used
int unusedB; // portB is not used
int unusedC; // portC is not used
int unusedD : 4; // lower nibble of portD unused
int data : 4; // high nibble of portD for data
boolean rs; // pin E0
booelan enable; // pin E1
boolean rw; // pin E2
int unusedE : 5; // rest unused
} lcd;
#if defined(__PCH__)
#locate lcd = 0xF80
#else
#locate lcd = 5
#endif
struct lcd_tris_map
{
int unusedA; // The rest of portA
int unusedB; // portB is not used
int unusedC; // portC is not used
int unusedD : 4; // lower nibble of portD is unused
int data : 4; // data lines
int control : 3; //
int unusedE : 5; // unused
} lcdtris;
#if defined(__PCH__)
#locate lcdtris = 0xF92
#else
#locate lcdtris = 0x85
#endif
#define set_tris_lcd(x) lcdtris.data = (x); lcdtris.control = 0;
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the second line
BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
// These bytes need to be sent to the LCD
// to start it up.
// The following are used for setting
// the I/O port direction register.
#define LCD_WRITE 0 // For write mode all pins are out
#define LCD_READ 15 // For read mode data pins are in
BYTE lcd_read_byte() {
BYTE low,high;
set_tris_lcd(LCD_READ);
lcd.rw = 1;
delay_cycles(1);
lcd.enable = 1;
delay_cycles(1);
high = lcd.data;
lcd.enable = 0;
delay_cycles(1);
lcd.enable = 1;
delay_us(1);
low = lcd.data;
lcd.enable = 0;
set_tris_lcd(LCD_WRITE);
return( (high<<4) | low);
}
void lcd_send_nibble( BYTE n ) {
lcd.data = n;
delay_cycles(1);
lcd.enable = 1;
delay_us(2);
lcd.enable = 0;
}
void lcd_send_byte( BYTE address, BYTE n ) {
lcd.rs = 0;
while ( bit_test(lcd_read_byte(),7) ) ;
lcd.rs = address;
delay_cycles(1);
lcd.rw = 0;
delay_cycles(1);
lcd.enable = 0;
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
void lcd_init() {
BYTE i;
set_tris_lcd(LCD_WRITE);
lcd.rs = 0;
lcd.rw = 0;
lcd.enable = 0;
delay_ms(15);
for(i=1;i<=3;++i) {
lcd_send_nibble(3);
delay_ms(5);
}
lcd_send_nibble(2);
for(i=0;i<=3;++i)
lcd_send_byte(0,LCD_INIT_STRING[i]);
}
void lcd_gotoxy( BYTE x, BYTE y) {
BYTE 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;
}
}
char lcd_getc( BYTE x, BYTE y) {
char value;
lcd_gotoxy(x,y);
lcd.rs=1;
value = lcd_read_byte();
lcd.rs=0;
return(value);
}
|
And the test program:
Code: |
#include <18F452.h>
#use delay(clock=4000000)
#fuses HS,NOWDT,NOPROTECT,NOLVP
#include "lcdd.c"
//======================= MAIN ============================//
void main(void)
{
lcd_init();
printf(lcd_putc,"Hello World");
printf(lcd_putc,"\nSecond Line");
while(1)
{
}
}
|
What am I doing wrong? _________________ Regards
Boyko |
|
|
Boyko
Joined: 11 Oct 2004 Posts: 13 Location: Sofia
|
|
Posted: Sat Nov 27, 2004 12:34 pm |
|
|
Come on friends. I need help. I'm a novice with the CCS PIC C. I have got the LAB-X1 development system where the LCD is connected:
PortD.4 - data
PortD.5 - data
PortD.6 - data
PortD.7 - data
PortE.0 - rs
PortE.1 - enable
PortE.2 - rw
I can't manage to run it. The original lcd.c file is for PortA or PortB. What modification I've to do? Till now I used Proton+. _________________ Regards
Boyko |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Sat Nov 27, 2004 12:54 pm |
|
|
Compiles just fine if you change boolean to BOOLEAN |
|
|
|
|
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
|