Jump to content

HD44780 LCD Library (16x2 and other models)

Recommended Posts

This is my attempt for a basic library to control an 16x2 or more LCD display using 6 PIN and controling the hd44780 in 4bit mode.


Main .c: http://dl.dropbox.com/u/13477186/MSP430 ... _example.c

Library .h: http://dl.dropbox.com/u/13477186/MSP430 ... _hd44780.h

Library .c: http://dl.dropbox.com/u/13477186/MSP430 ... _hd44780.c

Makefile : http://dl.dropbox.com/u/13477186/MSP430 ... 0/Makefile

It working great for my needs so far. Work on my 4 line display too..


My next step will be to make this library support the use of an 595 for 3 pin operation. I would also like some way to allow multiple display... But it seem doing this will require using more memory, and I'm trying to stay away from that.


I'll would love some constructive feedback...






UPDATE 22h34 4 feb 12: I've lowered the footprint from 800byte to 440 byte for the demo program using compiler optimization and code change.

Link to post
Share on other sites

Hello Moc,

A little criticism, if you don't mind:

Your functions and definitions, though descriptive, are rather long and will require lots of typing (or copy/pasting).
Instead, use abbreviations for the names, and comment the code to describe what the function performs. That way, a programmer is not obligated to type out the full title.

Also, because you have so many defines (with large titles) your code has gotten huge and difficult to sort through.

Not trying to tear you down, just trying to redirect you. icon_thumbup.gif

I've also been fiddling with LCD 4-bit mode, and this is what I have written so far:

#include "msp430g2231.h"

#define RW BIT6 // port 2

#define RS BIT4 // display RS pin connected here
#define EN BIT5 // display ENABLE

void initLCD(void);
void wrLCD(char data, bool rs);
void rdLCD(char* data, bool rs);
void wrStr(char* string);

void main(void){
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog


P1OUT = 0xDF;
P1DIR = 0xFF;
P2SEL = P2OUT = 0;
P2DIR = 0xFF;

initLCD(); // initialization
wrLCD('G',1); // write one char
char temp=0; // create temp
rdLCD(&temp,1); // read one char from the LCD, store the value in temp
wrStr("Hello 43oh!"); // write a string of chars

void initLCD(void){
for(char t=2; t; t--){

void wrLCD(char data, bool rs){
P1DIR |= 0x0F;
P2OUT &= ~RW;
rs ? (P1OUT |= RS) : (P1OUT &= ~RS);
for(char two=2; two; two--){
(data & BIT4) ? (P1OUT |= BIT0) : (P1OUT &= ~BIT0);
(data & BIT5) ? (P1OUT |= BIT1) : (P1OUT &= ~BIT1);
(data & BIT6) ? (P1OUT |= BIT2) : (P1OUT &= ~BIT2);
(data & BIT7) ? (P1OUT |= BIT3) : (P1OUT &= ~BIT3);
P1OUT |= EN;
if(!(bools & rs)) __delay_cycles(2000);
P1OUT &= ~EN;
data <<=4;

void rdLCD(char* data, bool rs){
*data = 0;
P1DIR &= ~0x0F;
P2OUT |= RW;
rs ? (P1OUT |= RS) : (P1OUT &= ~RS);
for(char two=2; two; two--){
P1OUT |= EN;
(P1IN & BIT0) ? (*data |= BIT0) : (*data &= ~BIT0);
(P1IN & BIT1) ? (*data |= BIT1) : (*data &= ~BIT1);
(P1IN & BIT2) ? (*data |= BIT2) : (*data &= ~BIT2);
(P1IN & BIT3) ? (*data |= BIT3) : (*data &= ~BIT3);
P1OUT &= ~EN;
*data <<=4;

void wrStr(char* string) {
while(*string){ // keep going until all chars are sent
for(char str = 0; (str<32) && *string; str++){
switch(str & 0x1F){
case 0x00: wrLCD(0x80, 0); break; // first line
case 0x10: wrLCD(0xC0, 0); break; // second line
wrLCD(*string, 1);
__delay_cycles(2000000); // delay between screens
This code includes reading, writing, LCD initialization, and writing whole strings.
A note on wrSTR: this function writes a string of chars to the LCD, wraps to the second line automatically, and even goes so far as to pause between screens if the string is larger than the visible portion of the LCD can handle.

I'm using IAR kicstart, with the optimizations turned all the way up. This code uses 570 bytes of flash, 51 bytes (50 for the stack, so the code really uses only one byte) of ram, and 12 byes of constants (also flash).
Link to post
Share on other sites

Your functions and definitions, though descriptive, are rather long and will require lots of typing (or copy/pasting).

Instead, use abbreviations for the names, and comment the code to describe what the function performs. That way, a programmer is not obligated to type out the full title.


Actually, I wanted it to be that way. And wont be changing it ;)


All MSP430 program are REALLY small anyway, there is really no need to shorten the name of functions and variable. I do work on million of line of code software... And in those shorter name for some stuff that come few thousand time are useful. But in this case, it doesn't. You will can run out of flash within a few minute at typing even with those long name anyway...


It actually welcome to have longer descriptive information for function name. The goal was not just to make it work, but also provide details information for all the configuration option. Even option that had was set by default, I created define name for it so it clear what information is used. It not needed to use them, but it make it clearer for people starting with it to understand what going on.


And by that, the code I made can read alot like the datasheet of HD44780. I used the same time range specified, the same name for the different function you can call... I've actually decided to write it this way because other people lcd lib were not written this way and not functional, and what they did didn't fully match the datasheet... So it was hard to understand what they did wrong.


My goal was also to keep the footprint small. So compiled with mspgcc, the size is 420byte. Lot of optimization is left to be done, but I'm ok for the moment.


It not perfect, but does the job for me and is a much better design to actually compare with the datasheet.


But what great, is everyone can provide their own flavor here ;) I did this for me and to help my dad (who had issue with current people code especially because they just seem to do something but with no flexibility / details of what they are actually doing).


There is things I don't like in my code rightnow, and the primary one is the fact you need to edit the .h to change the pin / port usage. I need to find a memory efficient way to make it configurable from the main C file, maybe by using a structure... Anyway not sure yet on how to do that part.

Link to post
Share on other sites
  • 1 year later...

Ah, I missed a line. Here is the corrected version of that command in context with this program:

rs ? (P1OUT |= RS) : (P1OUT &= ~RS);

Thanks for catching that. I'll fix it so other people don't stumble on it.


There had been several programs I was working with at the time, jumping from program to program that used almost the same functions. In one of those programs, I used a char variable as an 8-bit compact set of bool variables. A char and a bool use the same amount of ram (8 bits), but a bool is used for the least significant bit, and the rest are truncated. I had several global bools, but little ram. So I used a char to hold 8 bools, and I toggled the bit I needed, and read that bit when required, then determined whether it was true or false.


I could even use that 8 bits as 4 bools and a 4-bit counter. There are all kinds of ways to compress things.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

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.

  • Create New...