Go Down

Topic: LCD code help (Read 745 times) previous topic - next topic

Hello everyone, this is my first post here so I hope I'm doing things right!
I've been learning with the Arduino on and off now for a few months, but just recently started some major programming with higher functions and stuff.
I recently got a character LCD that I've connected to my board (Arduino Uno) via a parallel connection.
Being curious, I wanted to know exactly how all the pins on the LCD worked to display characters, down to the basic zero's and one's, and after a few days of research I was finally able to get it working without the LiquidCrystal library.
All that was working really well, until I decided that I wanted to try and write it in more efficient code and not take up eleven lines of code for each instruction/data i wanted to send.
What I want to be able to do is set each pin on my arduino (5-12 for Data Busses 0-7) either HIGH or LOW, depending on the status of each bit of a hexadecimal character. I hope this is making sense. :P
For example, if I wanted to display a capital A, which in ASCII is represented by 0x41 (Hexadecimal), I want a program that will break down that hexadecimal character into its binary equivalent (0 1 0 0 0 0 0 1), read each bit of that byte, and set the cooresponding pin HIGH or LOW.
This way I can just plug in the hexadecimal representation of what ever character I want to write instead of looking up the binary representation of that character and manually change each pins output.
Here's the original code I wrote with all the basic commands:
Code: [Select]

/* "Arduino pin, lcd pin - function"
   2, pin1 - RS
   3, pin2 - R/W
   4, pin3 - E
   5, pin4 - D0
   6, pin5 - D1
   7, pin6 - D2
   8, pin7 - D3
   9, pin8 - D4
   10, pin9 - D5
   11, pin10 - D6
   12, pin11 - D7
*/
int lcdPins[12] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
int x;
int RS = 2;
int RW = 3;
int E = 4;
int D7 = 5;
int D6 = 6;
int D5 = 7;
int D4 = 8;
int D3 = 9;
int D2 = 10;
int D1 = 11;
int D0 = 12;
int backlight = 13;

void setup()
{
  for(x = 0; x < 11; x++){        //Sets each pin (2-12), which coorespond to RS, RW, E, & DB7-DB0, to outputs.
  pinMode(lcdPins[x], OUTPUT);
  }
 
  pinMode(backlight, OUTPUT);      //Sets backlight as output and turns it on
  digitalWrite(backlight, HIGH);
  delay(50);
 
  /*
    The next groupings are just sending the LCD instructions to get ready to write characters to it
  */ 
 
  digitalWrite(RS, LOW);         //Clear Home
  digitalWrite(RW, LOW);
  delay(50);
  digitalWrite(E, HIGH);
  delay(50);
  digitalWrite(D0, LOW);
  digitalWrite(D1, LOW);
  digitalWrite(D2, LOW);
  digitalWrite(D3, LOW);
  digitalWrite(D4, LOW);
  digitalWrite(D5, LOW);
  digitalWrite(D6, LOW);
  digitalWrite(D7, HIGH);
  delay(50);
  digitalWrite(E, LOW);
  delay(50);
 
 
  digitalWrite(RS, LOW);         //Function set
  digitalWrite(RW, LOW);
  delay(50);
  digitalWrite(E, HIGH);
  delay(50);
  digitalWrite(D0, LOW);
  digitalWrite(D1, LOW);
  digitalWrite(D2, HIGH);
  digitalWrite(D3, HIGH);
  digitalWrite(D4, HIGH);
  digitalWrite(D5, HIGH);
  digitalWrite(D6, LOW);
  digitalWrite(D7, LOW);
  delay(50);
  digitalWrite(E, LOW);
  delay(50);
 
 
  digitalWrite(RS, LOW);         //Entry mode
  digitalWrite(RW, LOW);
  delay(50);
  digitalWrite(E, HIGH);
  delay(50);
  digitalWrite(D0, LOW);
  digitalWrite(D1, LOW);
  digitalWrite(D2, LOW);
  digitalWrite(D3, LOW);
  digitalWrite(D4, LOW);
  digitalWrite(D5, HIGH);
  digitalWrite(D6, HIGH);
  digitalWrite(D7, LOW);
  delay(50);
  digitalWrite(E, LOW);
  delay(50);
 
 
  digitalWrite(RS, LOW);         //Display Control
  digitalWrite(RW, LOW);
  delay(50);
  digitalWrite(E, HIGH);
  delay(50);
  digitalWrite(D0, LOW);
  digitalWrite(D1, LOW);
  digitalWrite(D2, LOW);
  digitalWrite(D3, LOW);
  digitalWrite(D4, HIGH);
  digitalWrite(D5, HIGH);
  digitalWrite(D6, HIGH);
  digitalWrite(D7, HIGH);
  delay(50);
  digitalWrite(E, LOW);
  delay(50);
 
 
  digitalWrite(RS, LOW);         //Set DDRAM Address
  digitalWrite(RW, LOW);
  delay(50);
  digitalWrite(E, HIGH);
  delay(50);
  digitalWrite(D0, HIGH);
  digitalWrite(D1, LOW);
  digitalWrite(D2, LOW);
  digitalWrite(D3, LOW);
  digitalWrite(D4, LOW);
  digitalWrite(D5, LOW);
  digitalWrite(D6, LOW);
  digitalWrite(D7, LOW);
  delay(50);
  digitalWrite(E, LOW);
  delay(50);
 
  /*
    Here I'm just sending the binary byte 0 1 0 0 0 0 0 1
    to the LCD on DB0 - DB7 to tell it to write a capital A
  */ 
 
  digitalWrite(RS, HIGH);         //Write capital "A"
  digitalWrite(RW, LOW);
  delay(50);
  digitalWrite(E, HIGH);
  delay(50);
  digitalWrite(D0, LOW);          // 0
  digitalWrite(D1, HIGH);         // 1
  digitalWrite(D2, LOW);          // 0
  digitalWrite(D3, LOW);          // 0
  digitalWrite(D4, LOW);          // 0
  digitalWrite(D5, LOW);          // 0
  digitalWrite(D6, LOW);          // 0
  digitalWrite(D7, HIGH);         // 1
  delay(50);
  digitalWrite(E, LOW);
  delay(50);
 
}

void loop()
  {
   
  }   


And here's where it gets funky.
I tryed to use Arrays and For Loops to perform each command in only a few lines of text.
This was the only way that seemed logical to me, but that's why I'm here, to ask you guys!
So I set up two arrays, one (A), that contained the output pins 5-12, or DB0-DB7, and the other (B), 8 elements long, where each element would be either HIGH or LOW depending on the bits of a certain byte.
So here's what I wrote:

Code: [Select]

int A[] = {5, 6, 7, 8, 9, 10, 11, 12};    //add these two arrays to all the other variables in the beginning of the sketch
int B[7];

/* Here's where all the setup commands would go, but I'm leaving them out to make it shorter.
*/

char myChar = 0x41;
int y;
for(y = 0; y < 7; y++)

{
 
if(bitRead(byte(myChar), y) == 1)    //by doing these functions I can change the character I want to write by only changing the hexadecimal character
{                                    //assigned to the variable myChar. The byte() function changes it to a byte, and then bitRead() reads each bit of
  B[y] = HIGH;                       //that byte, and if it is equal to 1 sets the cooresponding element of array B to HIGH, if its equal to 0, that element
}                                    //of array B becomes LOW.
   else
   {
    B[y] = LOW;
   }
   
}

  digitalWrite(RS, HIGH);       
  digitalWrite(RW, LOW);
  delay(50);
  digitalWrite(E, HIGH);
  delay(50);
 
  digitalWrite(A[0], B[0]);      //This is just saying that each pin 5-12 will be HIGH or LOW, depending on the cooresponding element of array B.
  digitalWrite(A[1], B[1]);
  digitalWrite(A[2], B[2]);
  digitalWrite(A[3], B[3]);
  digitalWrite(A[4], B[4]);
  digitalWrite(A[5], B[5]);
  digitalWrite(A[6], B[6]);
  digitalWrite(A[7], B[7]);

  delay(50);
  digitalWrite(E, LOW);
  delay(50);
  */


So I think something in the for loop is not working correctly. Any and all help/comments/sugestions/criticism would be appreciated!
Thank you!  XD

Marek080

#1
Apr 15, 2012, 08:50 pm Last Edit: Apr 15, 2012, 08:54 pm by Marek080 Reason: 1
Your B array has only 7 entries and not 8 but you access the 8th (B[7]) when using digitalWrite().

Code: [Select]
for(byte nBitNo= 0; nBitNo < 8; nBitNo++)
 digitalWrite(A[nBitNo], bitRead((byte)myChar, nBitNo));

This does the same without the intermediate array B. HIGH is defined as 0x01 and LOW as 0x00.

Additionally I think you have to reverse array A, because in your example D0 is the most significant bit and you set it at A[0] / bitRead(..., 0) which handles the least significant bit.
loved the 68000 assembler back then and now I have to deal with THIS 8 bit thingy

Thank you! That worked, and it's much shorter than what I originally had.
Im still wondering why my B array did not have 8 elements, because the original for loop should have started it at zero, right? and assigned either a high or low status for elements zero through seven, which is eight elements?

Marek080

You declared B[7] (running from 0 to 6) instead of B[8] (from 0 to 7). Then in your loop y started at 0 and counted to 6 (y < 7). So even if the loop would be corrected you still would access the 8th element of B which was not declared thus you would overwrite something else in memory with strange effects as a result. Hope that is somehow understandable - or in other words: do not access an array beyond its bounds.
loved the 68000 assembler back then and now I have to deal with THIS 8 bit thingy

Yes that helps a lot. Thanks again, and I was able to declare B to have eight elements and my original code worked,
but I like yours better anyway!  XD

I have a question about reading the busy flag from the LCD...

Is there a way to read the busy flag continuously, and when it is on pause the program, and then wait to continue until it is off?

Here is my code I have now:
Code: [Select]


int lcdPins[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
int A[] = {5, 6, 7, 8, 9, 10 ,11, 12};
int B[] = {2, 3, 4};
char command;
char myChar;
int x;
int backlight = 13;
int E = 4;

void setup()
{
  for(x = 0; x < 11; x++){        //Sets each pin (2-12),
  pinMode(lcdPins[x], OUTPUT);    //which coorespond to
  }                               //RS, RW, E, & DB7-DB0,
                                  //to outputs.
                                 
  pinMode(backlight, OUTPUT);      //Sets backlight as output
  digitalWrite(backlight, HIGH);   //and turns it on
  delay(50);

command = 0x00;            //Clear Home
myChar = 0x01;
 
  for(x = 0; x < 1; x++)
  digitalWrite(B[x], bitRead((byte)command, x));
   
  delay(50);
  digitalWrite(E, HIGH);
  delay(50);

  for(byte nBitNo = 0; nBitNo < 8; nBitNo++)
  digitalWrite(A[nBitNo], bitRead((byte)myChar, nBitNo));
 
  delay(50);
  digitalWrite(E, LOW);
  delay(50);
 
 
command = 0x00;
myChar = 0x3C;               //Function Set
 
    for(x = 0; x < 1; x++){
    digitalWrite(B[x], bitRead((byte)command, x));
    }

  delay(50);
  digitalWrite(E, HIGH);
  delay(50);

  for(byte nBitNo = 0; nBitNo < 8; nBitNo++)
  digitalWrite(A[nBitNo], bitRead((byte)myChar, nBitNo));
 
  delay(50);
  digitalWrite(E, LOW);
  delay(50);
 
command = 0x00;
myChar = 0x06;                //Entry Mode
 
    for(x = 0; x < 1; x++){
    digitalWrite(B[x], bitRead((byte)command, x));
    }

  delay(50);
  digitalWrite(E, HIGH);
  delay(50);

  for(byte nBitNo = 0; nBitNo < 8; nBitNo++)
  digitalWrite(A[nBitNo], bitRead((byte)myChar, nBitNo));
 
  delay(50);
  digitalWrite(E, LOW);
  delay(50);
 
command = 0x00;
myChar = 0x0F;           //Display Control
 
    for(x = 0; x < 1; x++){
    digitalWrite(B[x], bitRead((byte)command, x));
    }

  delay(50);
  digitalWrite(E, HIGH);
  delay(50);

  for(byte nBitNo = 0; nBitNo < 8; nBitNo++)
  digitalWrite(A[nBitNo], bitRead((byte)myChar, nBitNo));
 
  delay(50);
  digitalWrite(E, LOW);
  delay(50);
 
command = 0x00;
myChar = 0x80;            //Set DDRAM Address
 
    for(x = 0; x < 1; x++){
    digitalWrite(B[x], bitRead((byte)command, x));
    }

  delay(50);
  digitalWrite(E, HIGH);
  delay(50);

  for(byte nBitNo = 0; nBitNo < 8; nBitNo++)
  digitalWrite(A[nBitNo], bitRead((byte)myChar, nBitNo));
 
  delay(50);
  digitalWrite(E, LOW);
  delay(50);
 
command = 0x01;
myChar = 0x41;           //Write Capital "A"
 
    for(x = 0; x < 1; x++){
    digitalWrite(B[x], bitRead((byte)command, x));
    }

  delay(50);
  digitalWrite(E, HIGH);
  delay(50);

  for(byte nBitNo = 0; nBitNo < 8; nBitNo++)
  digitalWrite(A[nBitNo], bitRead((byte)myChar, nBitNo));
 
  delay(50);
  digitalWrite(E, LOW);
  delay(50);
 
command = 0x01;
myChar = 0x42;           //Write Capital "B"
 
    for(x = 0; x < 1; x++){
    digitalWrite(B[x], bitRead((byte)command, x));
    }

  delay(50);
  digitalWrite(E, HIGH);
  delay(50);

  for(byte nBitNo = 0; nBitNo < 8; nBitNo++)
  digitalWrite(A[nBitNo], bitRead((byte)myChar, nBitNo));
 
  delay(50);
  digitalWrite(E, LOW);
  delay(50);
   
}


void loop()
{}


So essentially I could have the one function that reads the BF and get rid of all the delay(50) commands.

PaulS

Quote
Is there a way to read the busy flag continuously, and when it is on pause the program, and then wait to continue until it is off?

Yes. Use a while loop(). Won't be any faster.

Code: [Select]
  for(x = 0; x < 1; x++)
  digitalWrite(B[x], bitRead((byte)command, x));

Why are you using a for loop to loop once?

Code: [Select]
    for(x = 0; x < 1; x++){
    digitalWrite(B[x], bitRead((byte)command, x));
    }

Why are you doing it more than once?


Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy