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 CCS Technical Support

LCD on multiple ports

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Bryan



Joined: 23 Apr 2005
Posts: 73

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

LCD on multiple ports
PostPosted: Sun May 15, 2005 7:11 pm     Reply with quote

I am attempting to modify Mark's driver that allows for data lines and control lines on different ports for LCD control but haven't been able to get it to initialize. I think my problem involves #locate and locating the tris or ports incorrectly (Mark used ports B and D while I am using A and B) but I am not sure how to do this correctly. I know the problem is not in my test program since the LCD works fine with the standard CCS driver set solely on port B. As you can see in the code I use A1-A3 for control lines and B4-B7 for data lines. Here is my code:

Code:

////////////////////////////////////////////////////////////////////////////
////                             LCDD.C                                 ////
////                 Driver for common LCD modules                      ////
////                                                                    ////
////  lcd_init()   Must be called before any other function.            ////
////                                                                    ////
////  lcd_putc(c)  Will display c on the next position of the LCD.      ////
////                     The following have special meaning:            ////
////                      \f  Clear display                             ////
////                      \n  Go to start of second line                ////
////                      \b  Move back one position                    ////
////                                                                    ////
////  lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1)     ////
////                                                                    ////
////  lcd_getc(x,y)   Returns character at position x,y on LCD          ////
////                                                                    ////
////////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,1997 Custom Computer Services            ////
//// This source code may only be used by licensed users of the CCS C   ////
//// compiler.  This source code may only be distributed to other       ////
//// licensed users of the CCS C compiler.  No other use, reproduction  ////
//// or distribution is permitted without written permission.           ////
//// Derivative programs created using this software in object code     ////
//// form are not restricted in any way.                                ////
////////////////////////////////////////////////////////////////////////////

// This structure is overlayed onto the data ports so that you may use
// whatever ports you desire
struct lcd_pin_map
{
  BOOLEAN dummy;      // PinA0 is not used
  BOOLEAN enable;     // PinA1
  BOOLEAN rw;         // PinA2
  BOOLEAN rs;         // PinA3
  int unusedA  : 4;   // The rest of portA
  int unusedB  : 4;   // upper nibble of portB is not used
  int     data : 4;   // lower nibble of portB is used for data lines
} lcd;
#if defined(__PCH__)
  #locate lcd = 0xF80
#else
  #locate lcd = 5
#endif

struct lcd_tris_map
{
  BOOLEAN dummy;      // PinA0 is not used
  int control  : 3;   // Control lines
  int unusedA  : 4;   // The rest of portA
  int unusedB  : 4;   // portB unused
  int data     : 4;   // Data lines
} 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);
}


Anyone see the error?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun May 15, 2005 8:48 pm     Reply with quote

Tell us which PIC pins that you are using for each LCD signal.
Give us the exact pins (don't just say "upper pins", etc.)
Bryan



Joined: 23 Apr 2005
Posts: 73

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

PostPosted: Sun May 15, 2005 9:45 pm     Reply with quote

A1: enable
A2: rw
A3: rs
B4: data1
B5: data2
B6: data3
B7: data4

I avoided A4 and A5 purposefully since I/O is tricky with them.
Bryan



Joined: 23 Apr 2005
Posts: 73

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

PostPosted: Sun May 15, 2005 10:06 pm     Reply with quote

I just realized that I had the pins hooked up incorrectly in my delirium (Was trying to work on it late last night on little sleep so that's what I get Very Happy ). I just redid them as described in my previous post and it works fine now. Thanks Mark for writing a great driver!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun May 15, 2005 10:24 pm     Reply with quote

Oh -- well, while you were doing that, I was typing in one million lines
of a response to your question. Should I not post it ? No, I'm going
to post it anyway. Mr. Green
---------
Quote:
A1: enable
A2: rw
A3: rs
B4: data1
B5: data2
B6: data3
B7: data4

I'm not sure where you're getting those names for the LCD data bus pins.
Here is a link to the Hantronix 16x2 LCD (without backlight) data sheet.
In this data sheet, they refer to the data bus signals as D0-D7.
http://www.hantronix.com/down/16216h5.pdf
When you use a character LCD in 4-bit mode, you always use LCD signals
D4-D7. (The 4-bit mode is commonly used in embedded applications
because it uses the minimal amount of micro-controller pins).
So your PIC to LCD connections should really look like this:
Code:
A0:  Not used
A1:  E
A2:  R/W
A3:  RS
B4:  D4
B5:  D5
B6:  D6
B7:  D7


In the pin map structures, you have to carefully enter the bits
that are going to be used within each port. Equally carefully,
you have to put in placeholders for all the bits that are not
going to be used, either in entire ports, or in portions of ports.
If you leave anything out, the addresses could be incorrect
when the code is compiled. The following code shows how to
do it. The bits used by your LCD are shown in bold.
Quote:
struct lcd_pin_map
{
BOOLEAN dummy; // PinA0 is not used
BOOLEAN enable; // PinA1
BOOLEAN rw; // PinA2
BOOLEAN rs; // PinA3

int unusedA : 4; // The rest of portA is not used.
int unusedB:4; // Lower 4 bits of portB are not used
int data:4; // Upper 4 bits of Port B are used.
int unusedC; // portC is not used
int unusedD; // portD is not used
} lcd;
#if defined(__PCH__)
#locate lcd = 0xF80
#else
#locate lcd = 5
#endif

struct lcd_tris_map
{
BOOLEAN dummy; // PinA0 is not used
int control : 3; // Bits 1,2,and 3 of PortA are used.
int unusedA : 4; // The rest of portA
int unusedB : 4; // The lower 4 bits of PortB are not used
int data : 4; // The upper 4 bits of PortB are used.
int unusedC; // PortC is not used
int unusedD : 4; // PortD is not used
} lcdtris;

#if defined(__PCH__)
#locate lcdtris = 0xF92
#else
#locate lcdtris = 0x85
#endif

#define set_tris_lcd(x) lcdtris.data = (x); lcdtris.control = 0;
Bryan



Joined: 23 Apr 2005
Posts: 73

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

PostPosted: Sun May 15, 2005 11:38 pm     Reply with quote

Thanks for posting! I realize that my designating the pins as data1-data4 could be confusing, but I was just trying to show that the data pins I was using were on pins B4-B7 since in the struct you can see that pins B0-B3 are placeholders (I did have the structs right for my PIC setup, just physically connected the pins wrong on my board). The only things I'm still curious about are how you know where to set the #locate statements for the tris and lcd structs and what the #define statements mean as shown below (What does the x mean in #define set_tris_lcd(x) lcdtris.data = (x); lcdtris.control = 0;?):
Code:

#if defined(__PCH__)
#locate lcd = 0xF80
#else
#locate lcd = 5
#endif

#if defined(__PCH__)
#locate lcdtris = 0xF92
#else
#locate lcdtris = 0x85
#endif

#define set_tris_lcd(x) lcdtris.data = (x); lcdtris.control = 0;
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Sun May 15, 2005 11:50 pm     Reply with quote

That information is in the PIC's datasheet. Look in the memory organization section. There will be a table with the "special function registers" of that particular pic. For instance, address 0xf80 is the address for port A for the 18 series. 0xf81 = port B, etc.
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

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

PostPosted: Mon May 16, 2005 5:37 am     Reply with quote

The 'x' is a variable parameter. Think of this as being a macro.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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