CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

other ports with lcd.c driver?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Foppie



Joined: 16 Sep 2005
Posts: 138
Location: The Netherlands

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

other ports with lcd.c driver?
PostPosted: Mon Sep 19, 2005 1:50 am     Reply with quote

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 Wink )

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

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

PostPosted: Mon Sep 19, 2005 3:37 am     Reply with quote

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

View user's profile Send private message Send e-mail

PostPosted: Mon Sep 19, 2005 9:29 am     Reply with quote

Did you not find this one?

http://www.ccsinfo.com/forum/viewtopic.php?t=20182
Guest








PostPosted: Mon Sep 19, 2005 11:41 am     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

PostPosted: Tue Sep 20, 2005 1:24 am     Reply with quote

Mark wrote:
Did you not find this one?

http://www.ccsinfo.com/forum/viewtopic.php?t=20182


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

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

PostPosted: Tue Sep 20, 2005 5:59 am     Reply with quote

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. Sad 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

View user's profile Send private message Send e-mail

PostPosted: Tue Sep 20, 2005 6:23 am     Reply with quote

Foppie wrote:
Mark wrote:
Did you not find this one?

http://www.ccsinfo.com/forum/viewtopic.php?t=20182


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

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

PostPosted: Tue Sep 20, 2005 6:40 am     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

minor changes, now it's a little bit working...
PostPosted: Wed Sep 21, 2005 1:18 am     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

PostPosted: Wed Sep 21, 2005 4:48 am     Reply with quote

I fixed my problem! Very Happy

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

View user's profile Send private message Send e-mail

PostPosted: Wed Sep 21, 2005 6:23 am     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

PostPosted: Wed Sep 21, 2005 6:32 am     Reply with quote

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 Embarassed , 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

View user's profile Send private message Send e-mail

PostPosted: Wed Sep 21, 2005 6:37 am     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

PostPosted: Wed Sep 21, 2005 6:44 am     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

scrambled readings :S
PostPosted: Thu Sep 22, 2005 2:57 am     Reply with quote

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?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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