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 in 8 bit mode, help please

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



Joined: 15 Nov 2004
Posts: 4

View user's profile Send private message

LCD in 8 bit mode, help please
PostPosted: Mon Nov 15, 2004 1:16 pm     Reply with quote

Hi, I´m new in programming PICs in C. It looked easy until I tried to use a LCD in 8 bit mode. I am using a 16F877A with an oscilator of 4Mhz.

I want to use the E port for enable,R/W and RS and the whole D port for data. I´ve tried to adapt the LCD.c archive which came with the compiler to satisfy my needs, but it does not result. It would be great if anyone could give me a kind of LCD.c arrchive with the LCD most common instructions, such as lcd_putc(), lcd_get_c() and so on.

Can anybody help me, please?
Mark



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

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

PostPosted: Mon Nov 15, 2004 1:20 pm     Reply with quote

Pretty easy to do. Take a look at this post where I modified CCS's code to allow different pins to be used. Give it a go and if you can't get it, let me know and I will help you more.
http://www.ccsinfo.com/forum/viewtopic.php?t=20182
masacra



Joined: 15 Nov 2004
Posts: 4

View user's profile Send private message

PostPosted: Mon Nov 15, 2004 1:30 pm     Reply with quote

Thank you for answering me so fast!! I´ve already seen and tried to get the lcdd.c to work, but I´ve trouble with it.

How can I select the pins I want to interface the LCD in this program? I´ve seen no place to do that, and I find it hard to see where can I apply the changes I need without making this program definitely fail.

In this program also the LCD is accesed in 4-bit mode, I´ve tried to change that, to make it work in 8-bit mode but it doesn´t work.

Many thanks
Mark



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

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

PostPosted: Mon Nov 15, 2004 1:38 pm     Reply with quote

Did you look at the post? It differs from CCS's code in the declaration. Here is an example on how to modify the declares to move the control lines to portE and 8bit data. You will still have to modify the code and const for 8bit mode. Give it a shot.

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;
masacra



Joined: 15 Nov 2004
Posts: 4

View user's profile Send private message

PostPosted: Tue Nov 16, 2004 11:34 am     Reply with quote

Well I´ve tried to make some changes, but the code still doesn´t work. I am using a 2x16 LCD and I don´t know where to fit that fact in the code.

Some things I´ve changed are constants such as the following:
Code:

#define LCD_READ     0xFF      // For read mode data pins are in


But I´ve no idea how to change the code to make it work, I have read it many times and still don´t understand it fully.

Another thing is that I have working routines in assembly for LCD and keypad, if I include those will they work with CCS C?

Thanks a lot, you´re so helpfull.
Mark



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

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

PostPosted: Tue Nov 16, 2004 12:42 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Nov 16, 2004 1:30 pm     Reply with quote

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

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

PostPosted: Tue Nov 16, 2004 1:34 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Nov 26, 2004 5:44 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Nov 27, 2004 12:34 pm     Reply with quote

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

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

PostPosted: Sat Nov 27, 2004 12:54 pm     Reply with quote

Compiles just fine if you change boolean to BOOLEAN
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