|
|
View previous topic :: View next topic |
Author |
Message |
Foppie
Joined: 16 Sep 2005 Posts: 138 Location: The Netherlands
|
other ports with lcd.c driver? |
Posted: Mon Sep 19, 2005 1:50 am |
|
|
Hello,
I need a rewritten lcd.c display driver because I use other pins on my PIC16F877A so I was searching the board but couldn't find one. So I have rewritten my own driver but it doesn't seem to work. Can someone tell me if there are any problems in my code (and where they are offcourse )
Thanks
rewritten lcd.c driver:
[edit]see lower post[/edit]
Maincode:
[edit]see lower post[/edit]
Last edited by Foppie on Wed Sep 21, 2005 12:14 am; edited 1 time in total |
|
|
Foppie
Joined: 16 Sep 2005 Posts: 138 Location: The Netherlands
|
|
Posted: Mon Sep 19, 2005 3:37 am |
|
|
forgot to mention that I use a HD44780A00 lcd that should be compatible with the standard lcd.c driver. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
|
Guest
|
|
Posted: Mon Sep 19, 2005 11:41 am |
|
|
Hi
try to learn from this example project.
LCD Thermometer
I think you can modify that code as well. |
|
|
Foppie
Joined: 16 Sep 2005 Posts: 138 Location: The Netherlands
|
|
Posted: Tue Sep 20, 2005 1:24 am |
|
|
yes, I saw that one, but if I'm not wrong one cannot use that code when datapins are connected as following (just an example)
RD3 = DB7;
RD6 = DB6;
RD5 = DB5;
RA4 = DB4;
Can someone tell me if I am wrong or not (and why)?
P.S. I know my code can't do that to because of the set_tris_d() that got called 2 times in my code, but I'm still working on that. |
|
|
Foppie
Joined: 16 Sep 2005 Posts: 138 Location: The Netherlands
|
|
Posted: Tue Sep 20, 2005 5:59 am |
|
|
Foppie wrote: | P.S. I know my code can't do that to because of the set_tris_d() that got called 2 times in my code, but I'm still working on that. |
Worked it out. This might not be the most efficient, but according to my logics it works. The driver does still the same though. It still doesn't work.
here my new lcd.c driver:
Code: | //define pins
#define ENABLE PIN_E2
#define RS PIN_E0
#define RW PIN_E1
#define DB7 PIN_D0
#define DB6 PIN_D1
#define DB5 PIN_D2
#define DB4 PIN_D3
//TRIS registers
#define trsdb7addr 0x88
#define trsdb7bit 7
#define trsdb6addr 0x88
#define trsdb6bit 6
#define trsdb5addr 0x88
#define trsdb5bit 5
#define trsdb4addr 0x88
#define trsdb4bit 4
#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
void lcd_send_nibble(byte n)
{
if (0b00001000 & n)
{
output_high(DB7);
}
else
{
output_low(DB7);
}
if (0b00000100 & n)
{
output_high(DB6);
}
else
{
output_low(DB6);
}
if (0b00000010 & n)
{
output_high(DB5);
}
else
{
output_low(DB5);
}
if (0b00000001 & n)
{
output_high(DB4);
}
else
{
output_low(DB4);
}
delay_cycles(1);
output_high(ENABLE);
delay_us(2);
output_low(ENABLE);
}
void lcd_set_tris(short on)
{
if (on)
{
#asm
BSF trsdb7addr,trsdb7bit
BSF trsdb6addr,trsdb6bit
BSF trsdb5addr,trsdb5bit
BSF trsdb4addr,trsdb4bit
#endasm
}
else
{
#asm
BCF trsdb7addr,trsdb7bit
BCF trsdb6addr,trsdb6bit
BCF trsdb5addr,trsdb5bit
BCF trsdb4addr,trsdb4bit
#endasm
}
}
int lcd_read_nibble()
{
int result = 0;
result += (8 * input(DB7));
result += (4 * input(DB6));
result += (2 * input(DB5));
result += input(DB4);
return (result);
}
byte lcd_read_byte()
{
byte low, high;
lcd_set_tris(1);
output_high(RW);
delay_cycles(1);
output_high(ENABLE);
delay_cycles(1);
high = lcd_read_nibble();
output_low(ENABLE);
delay_cycles(1);
output_high(ENABLE);
delay_us(1);
low = lcd_read_nibble();
output_low(ENABLE);
lcd_set_tris(0);
return ((high << 4) | low);
}
void lcd_send_byte(short address, byte n)
{
output_low(RS);
while (bit_test(lcd_read_byte(), 7)) ;
if (address)
{
output_high(RS);
}
else
{
output_low(RS);
}
delay_cycles(1);
output_low(RS);
delay_cycles(1);
output_low(ENABLE);
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
void lcd_init()
{
byte i;
lcd_set_tris(0);
output_low(RS);
output_low(RW);
output_low(ENABLE);
delay_ms(15);
for(i = 1; i <= 3; ++i)
{
lcd_send_nibble(3);
delay_ms(5); //minimum waiting time 4.1 ms
}
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': //clear display
lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n': //newline
lcd_gotoxy(1,2);
break;
case '\b': //backspace
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);
output_high(RS);
value = lcd_read_byte();
output_low(RS);
return (value);
} |
|
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Tue Sep 20, 2005 6:23 am |
|
|
Foppie wrote: |
yes, I saw that one, but if I'm not wrong one cannot use that code when datapins are connected as following (just an example)
RD3 = DB7;
RD6 = DB6;
RD5 = DB5;
RA4 = DB4;
Can someone tell me if I am wrong or not (and why)?
P.S. I know my code can't do that to because of the set_tris_d() that got called 2 times in my code, but I'm still working on that. |
Why on earth would someone want to connect it that way anyways!! On a 40pin PIC I find it hard to believe that one could not put the four data pins in sequence. |
|
|
Foppie
Joined: 16 Sep 2005 Posts: 138 Location: The Netherlands
|
|
Posted: Tue Sep 20, 2005 6:40 am |
|
|
Mark wrote: | Why on earth would someone want to connect it that way anyways!! On a 40pin PIC I find it hard to believe that one could not put the four data pins in sequence. |
Very true, but I have not build nor developed the circuit. But on the board on which I'm developing they are in sequence.
But what I really want to know is if the driver I wrote should work or not, I am not able to print anything on the LCD. Not with my driver and also not with the driver of Mark. I get the same output with both drivers, all blancs. So I suspect there is somewhere else something wrong, but on a testboard that code works so it should be in the driver...
Anyway, I am very puzzled, can someone give me a tip on what I am doing wrong?
the driver I use can be found 1 posts below, and here is the other code:
[edit]see below for updated code[/edit]
Last edited by Foppie on Wed Sep 21, 2005 1:21 am; edited 1 time in total |
|
|
Foppie
Joined: 16 Sep 2005 Posts: 138 Location: The Netherlands
|
minor changes, now it's a little bit working... |
Posted: Wed Sep 21, 2005 1:18 am |
|
|
After testing and rewriting, I got the code displaying something, but it looks as if it's scrambled.
I am now using Marks lcdd.c because I thought it's safer to begin with a driver that is known working. (To many rewritten parts in my own code)
When I tested I got (finally) something on screen but now it's scrambled as following:
I send:
"Hello,"
"World!"
and I see on screen:
elo,
ord!
What am I now doing wrong?
the main code:
Code: | #device PIC16F877A *=16 ADC=8
#include <drivers/16f877.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOLVP //Low Voltage Programming on B3
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=20000000)
#use rs232(baud=9600, BRGH1OK, parity=n, bits=8, xmit=PIN_C6, rcv=PIN_C7)
#include "drivers/lcd.c"
void testLcd()
{
LCD_clear();
lcd_gotoxy(1,1);
printf(lcd_putc,"Hello,");
lcd_gotoxy(1,2);
printf(lcd_putc,"World!");
while(1) ;
}
void main()
{
lcd_init();
testLcd();
}
|
the lcd.c driver:
Code: | struct lcd_pin_map
{
int unusedA; // portA is not used
int unusedB; // portB is not used
int unusedC; // portC is not used
int data : 4; // upper nibble of portD is used for data lines
int unusedD : 4; // The rest of portD
BOOLEAN rs; // PinE0
BOOLEAN rw; // PinE1
BOOLEAN enable; // PinE2
} lcd;
#locate lcd = 5
struct lcd_tris_map
{
int unusedA; // portA is not used
int unusedB; // portB is not used
int unusedC; // portC is not used
int data : 4; // upper nibble of portD is used for data lines
int unusedD : 4; // The rest of portD
int control : 3;
} lcdtris;
#locate lcdtris = 0x85
#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);
} |
|
|
|
Foppie
Joined: 16 Sep 2005 Posts: 138 Location: The Netherlands
|
|
Posted: Wed Sep 21, 2005 4:48 am |
|
|
I fixed my problem!
There needed to be a delay in the lcd_send_byte() method. My only remaining question is: why do I need a delay when somebody else doesn't?
the modified code:
Code: | 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);
delay_ms(10); // <<=========== I have put this line in!!!
} |
|
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Sep 21, 2005 6:23 am |
|
|
You shouldn't need the delay. The code is the CCS standard LCD driver which tons of people use. I only modified the variable declarations to allow different ports to be used. |
|
|
Foppie
Joined: 16 Sep 2005 Posts: 138 Location: The Netherlands
|
|
Posted: Wed Sep 21, 2005 6:32 am |
|
|
Mark wrote: | You shouldn't need the delay. The code is the CCS standard LCD driver which tons of people use. I only modified the variable declarations to allow different ports to be used. |
Well, I need it, If there is not an delay_us(15) or larger delay, the output gets scrambled. But maybe it's a hardware problem.
There are also LEDs connected to the dataports, could that be a problem? (I don't know much about electronics , but I try to learn a bit)
In either case, it is working now, so Thanks for all your help |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Sep 21, 2005 6:37 am |
|
|
Anything connected that is affecting the signals (like rise/fall time) could certainly cause problems. However, where you inserted the delay, I would think that the problem is more likely on the control lines. |
|
|
Foppie
Joined: 16 Sep 2005 Posts: 138 Location: The Netherlands
|
|
Posted: Wed Sep 21, 2005 6:44 am |
|
|
Mark wrote: | Anything connected that is affecting the signals (like rise/fall time) could certainly cause problems. However, where you inserted the delay, I would think that the problem is more likely on the control lines. |
There is nothing connected on the control lines... The only things are those LEDs with a resistor. They are connected as following:
PIN_D1
|
|
|--------[resistor 330R]----(LED)-------GND
|
|
DB6
At first I didn't think this would be a problem, but now I think this was my problem... |
|
|
Foppie
Joined: 16 Sep 2005 Posts: 138 Location: The Netherlands
|
scrambled readings :S |
Posted: Thu Sep 22, 2005 2:57 am |
|
|
I'm running into some new trouble with the driver. As soon as I call the lcd_read_byte() or lcd_getc() method, I get scrambled data. I assume this also has something to do with the LEDs connected to the Datalines, but I don't know how to solve the problem. I tried delays (20ms) on many places in those 2 function, but it doesn't solve my problem.
Anybody any idea for how to solve the problem? |
|
|
|
|
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
|