Jump to content
Sign in to follow this  
mityeltu

Lcd Custom Characters

Recommended Posts

I am struggling with how to get custom lcd characters written into my code. I have read the datasheet and understand (sort of) that I need to write the data into the cgram. But looking at the datasheet also seems to suggest I need to do the following:

Clear RS & RW, set DB7 and set/clear DB6-DB0 to set the ddram address.

Then I need to clear DB7 ad set DB6 and set/clear DB5-DB0 to send the cgram address.

then I need to send the data that has my custum mapped character.

 

To compound this, I am also in 4 bit upper mode. I'm lost with this.

 

Is there anyone out there who has done this who is willing to post the code?

Share this post


Link to post
Share on other sites

Well, I can see that no one else apparently knows how to do this, or EVERYONE knows how and just doesn't care to help. I will assume the former.

So, I searched and searched some more and found the attched pdf. Page 23 of the file here: http://www.mrc.uidaho.edu/mrc/people/jff/340/341/labs/lab6/Project6.pdf gives the framework instructions and the code below will generate a single 5x8 custom charcater that is stored in cgram memory location 0. I tried to attach just page 23, but the file size limit is so small that even a single page was too large to post here (crazy). In case the link gets broken, the pdf is from Digilent and has the title "Handshaking and LCD Control with the Cerebot MX7ck".

lcd_funcmode();//command mode
lcd_write(0x40);//set cgram address to 0
lcd_datamode();//set to send character byte data
lcd_write(0x0a);//byte 0
lcd_write(0x15);//byte 1
lcd_write(0x0a);//byte 2
lcd_write(0x15);//byte 3
lcd_write(0x0a);//byte 4
lcd_write(0x15);//byte 5
lcd_write(0x0a);//byte 6
lcd_write(0x15);//byte 7
lcd_gotoxy(0,0);//leave function mode and go home

This will store the character in the LCD CGram. To display the character, simply use the lcd_write(address); command. For the above code it will be lcd_write(0x00);

 

I hope this helps others who have been looking for a way to create custom characters in sourceboost. From the code, it should be evident how this process can be automated in a loop using an array and a pointer to the array. The address for the data is automatically incremented with each sucessive lcd_write command, so there is no need to keep up with that part of it (just like when you write characters to the display you don't have to constantly upddate the position).

 

Good luck.

Share this post


Link to post
Share on other sites

OK, more on this wierdness.

 

Apparently you can't just send the custom character to the lcd. it has to follow either the lcd_datamode() command or other formatted text. I didn't know this until after I posted the above, so please bear with me as I learn how this thing works.

 

So, if you need to send the custom character FIRST, do this:

lcd_datamode();//apparently needed so the lcd knows what to do next
lcd_write(0x00);//send custom characte to lcd
lprintf("wierd");//normal formatted text does not need the lcd_datamode() command

However, if you are sending text and THEN send the custom charcater, you do NOT need the lcd_datamode() command:

lprintf("wierd");//normal formatted text
//NOTE: No lcd_datamode command is necessary here
lcd_write(0x00);//send custom character to lcd
lprintf("still wierd)";

I have no explanation for this behavior. It is cumbersome and inconvenient and there is NO documentation on it anywhere. Either I am doing something wrong or this is a glitch in sourceboost. I suspect the latter.

 

Anyway, hope this helps.

Share this post


Link to post
Share on other sites

Here is working sample code that sets up custom characters that represent battery status and that cycles trough them. Enjoy.

Regards,
Pavel

#include <system.h>
 
// Configure LCD connections
// If using this code under SourceBoost simulator (for PIC18F97J60), configure the LCD plugin as follows:
// RS  to RH2
// R/W to RH1
// E   to RH0
// DB0 to RE0
// DB1 to RE1
// DB2 to RE2
// DB3 to RE3
// DB4 to RE4
// DB5 to RE5
// DB6 to RE6
// DB7 to RE7
//
#define LCD_ARGS 0,            /* Interface type: mode 0 = 8bit, 1 = 4bit(low nibble), 2 = 4bit(upper nibble) */ \
                 1,            /* Use busy signal: 1 = use busy, 0 = use time delays */\
                 PORTE, TRISE, /* Data port and data port tris register */ \
                 PORTH, TRISH, /* Control port and control port tris register */ \
                 2,            /* Bit number of control port is connected to RS */ \
                 1,            /* Bit number of control port is connected to RW */ \
                 0             /* Bit number of control port is connected to Enable */
 
#include <lcd_driver.h> // include the LCD template code
 
 
 
 
//Target PIC18F97J60 configuration word
#pragma config BW = 16 // 16-Bit Data Width mode
#pragma config CCP2MX = ON // ECCP2/P2A is multiplexed with RC1
#pragma config CP0 = OFF // Program memory is not code-protected
#pragma config DEBUG = OFF // Background debugger disabled; RB6 and RB7 configuredas general purpose I/O pins
#pragma config EASHFT = ON // Address shifting enabled; address on external bus is offset to start at 000000h
#pragma config ECCPMX = ON // ECCP1 outputs (P1B/P1C) are multiplexed with RE6 and RE5; ECCP3 outputs (P3B/P3C) are multiplexed with RE4 and RE3
#pragma config ETHLED = ON // RA0/RA1 are multiplexed with LEDA/LEDB when Ethernet module is enabled and function as I/O when Ethernet is disabled
#pragma config FCMEN = ON // Fail-Safe Clock Monitor enabled
#pragma config FOSC = HS // HS oscillator
#pragma config FOSC2 = ON // Clock selected by FOSC1:FOSC0 as system clock is enabled when OSCCON<1:0> = 00
#pragma config IESO = ON // Two-Speed Start-up enabled
#pragma config MODE = MM // Microcontroller mode, external bus disabled
#pragma config STVR = ON // Reset on stack overflow/underflow enabled
#pragma config WAIT = OFF // Wait states for operations on external memory bus disabled
#pragma config WDT = OFF // WDT disabled (control is placed on SWDTEN bit)
#pragma config WDTPS = 32768 // 1:32768
#pragma config XINST = OFF // Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
 
//Set clock frequency
#pragma CLOCK_FREQ 25000000
 
 
void interrupt( void )
{
    //Handle timer0 interrupt
    if( intcon & (1<<T0IF) )
    {
        clear_bit( intcon, T0IF ); //clear timer 0 interrupt bit
    }
}
 
void interrupt_low( void )
{
 
}
 
 
void main( void )
{
    //Configure port B
    trisb = 0x00;
 
    //Set Timer0 mode
    set_bit( t0con, TMR0ON ); //enable timer0
    clear_bit( t0con, T0CS ); //configure timer0 as a timer
    //Set Timer0 resolution
    set_bit( t0con, T08BIT ); //set timer0 8 bit wide
    //Set prescaler assignment
    clear_bit( t0con, PSA ); //prescaler is assigned
    //Set prescaler rate
    clear_bit( t0con, T0PS2 ); //prescaler rate 1:2
    clear_bit( t0con, T0PS1 );
    clear_bit( t0con, T0PS0 );
    //Set timer0 source edge selection
    set_bit( t0con, T0SE ); //increment on high-to-low transition on RA4/T0CKI pin
 
    // Enable priority interrupts
    rcon = (1<<IPEN);
 
    //Enable interrupts (Timer0)
    intcon = (1<<GIE) | (1<<TMR0IE);
 
    ///////////////////////////////////////////////
    //Initialize LCD
    trisg.5 = 0;
    portg.5 = 1; //lit LCD backlight
    lcd_setup();
 
    //Initialise first 3 custom characters
    lcd_funcmode();
    lcd_write( 0x40+0 );
    lcd_datamode();
    lcd_write( 0b01110 ); //empty battery character
    lcd_write( 0b11011 );
    lcd_write( 0b10001 );
    lcd_write( 0b10001 );
    lcd_write( 0b10001 );
    lcd_write( 0b10001 );
    lcd_write( 0b10001 );
    lcd_write( 0b11111 );
 
    lcd_write( 0b01110 ); //half empty battery character
    lcd_write( 0b11011 );
    lcd_write( 0b10001 );
    lcd_write( 0b10001 );
    lcd_write( 0b10001 );
    lcd_write( 0b11111 );
    lcd_write( 0b11111 );
    lcd_write( 0b11111 );
 
    lcd_write( 0b01110 ); //full battery character
    lcd_write( 0b11011 );
    lcd_write( 0b11111 );
    lcd_write( 0b11111 );
    lcd_write( 0b11111 );
    lcd_write( 0b11111 );
    lcd_write( 0b11111 );
    lcd_write( 0b11111 );
 
    ///////////////////////////////////////////////
    //Show hash pattern on LCD
    lcd_clear();
    lprintf("###");
 
    //Show changing battery status character inside an endless loop
    unsigned char ch = 0;
    while( 1 )
    {
        lcd_gotoxy( 1, 0 );
        lcd_datamode();
        lcd_write( ch++ );
        if(ch == 3) ch = 0;
        delay_ms(250);
    }
}

Share this post


Link to post
Share on other sites

Hi

 

 

I have no explanation for this behavior. It is cumbersome and inconvenient and there is NO documentation on it anywhere. Either I am doing something wrong or this is a glitch in sourceboost. I suspect the latter.

 

Anyway, hope this helps.

 

Funny.

As far as I can see your problem is understanding the protocol to communicate with the LCD, in special loading user defined characters in the CGRAM.

How can such a problem be a compiler glitch?

 

 

https://www.sparkfun.com/datasheets/LCD/HD44780.pdf

(it took almost 2 minutes to find)

 

 

Best regards

Jorge

Edited by JorgeF

Share this post


Link to post
Share on other sites

Ya know, I try my best to learn things from the net and usually come up craps. I found the same document and read through it. That's how I came up with the code I had. I appreciate what you say, and if I knew what I don't know that would make things a little easier maybe, but when I don't know what I don't know, I ask questions of people who might know - like folks on this forum. Sadly, I typically get snarky responses like yours rather than actual useful information or assistance in understanding what I don't currently understand. Thanks for sarcasm.

Share this post


Link to post
Share on other sites

Hi

 

It wasn't me that mixed subjects and try to blame the compiler for the dificulties on finding good documentation and/or samples for a given task.

On the subject of code samples, Pavel already took care of it.

As for learning by one-self, Im still there, doing it since 1980 (*).

In terms of "blamming the tool", well, already did it a few times. After being 100% sure and having collected the evidence to prove it.

 

 

 

(*) By those days we didn't had an "Internet" to bring knowledge home, but we manage to did it anyway.

 

 

Best regards

Jorge

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...