Jump to content
43oh

Using 3 wires to control parallel LCD display


Recommended Posts

  • Replies 47
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

I have seen this done other ways, but I didn't want to deal with 7 pins, or 4 bits, etc., so I did it my way. You send 8 bits to shift register, then set data out to whatever RS should be, and finall

If anyone is interested, I found this display that uses 3 volts for both the display and backlight http://www.newhavendisplay.com/index.ph ... cts_id=282   onlinecomponents.com has them for $7.00 +

So Ive managed to get RobG's code to work on the Wintek 1 x 24 Character LCD Display Module that I got awhile ago from Electronic Goldmine for $1.99.   Here's the link: http://www.goldmine-elec

Posted Images

Since we started talking about connecting a keypad and we have another thread talking about building a calculator, I decided to expand this post and... add a keypad. I bought mine from futurlec for <$5 when I was thinking of building DTMF generator and now it will make a perfect calculator pad.

 

Here's my backpack with new keypad header:

 

post-197-135135496954_thumb.jpg

 

And the complete setup showing 4 wires from LP to keypad, 4 wires from keypad to backpack, and 5 wires from backpack to LP. We still have 3 pins unused on our LP!

 

post-197-135135497217_thumb.jpg

 

Code to follow.

Link to post
Share on other sites

Here's the code to read the keypad and then display 2 characters. Each key represents a bit, 1 is bit0, A bit4, D bit15, and by pressing multiple keys, you can display appropriate characters.

More to come, maybe RPN calculator? Programmable power supply (I still have 3 inputs to measure voltage and current and I didn't get to ADC yet.)

 

#include "msp430g2231.h"

#define sendData(data) send(data, 1)
#define sendInstruction(data) send(data, 0)
#define initDisplay() sendInstruction(0x3C); sendInstruction(0x0C); clearDisplay(); sendInstruction(0x06)
#define clearDisplay() sendInstruction(0x01); _delay_cycles(2000)
#define DATAPIN BIT6
#define CLOCKPIN BIT5
#define ENABLEPIN BIT4
#define BIT0_3 0x0F

void send(char data, char registerSelect);
void sendDataArray(char data[], char length);

char charIndex = 0;
char bitCounter = 0;
char charsToSend[2] = {0,0};

int keypadPrevState = 0;
int keypadCurrState = 0;
int keypadPress = 0;

void main(void)
{
WDTCTL = WDTPW + WDTHOLD;

BCSCTL1 = CALBC1_1MHZ;
   DCOCTL = CALDCO_1MHZ;

_delay_cycles(100000);

P1OUT &= ~(CLOCKPIN + DATAPIN);
P1OUT |= ENABLEPIN;
P1DIR |= ENABLEPIN + CLOCKPIN + DATAPIN;

initDisplay();

P1REN |= BIT0_3;
P1OUT |= BIT0_3;

CCTL0 = CCIE;
CCR0 = 6250;
TACTL = TASSEL_2 + MC_1 + ID_3;

_bis_SR_register(LPM0_bits + GIE);

}

// Timer A0 interrupt service routine
#pragma vector = TIMERA0_VECTOR
__interrupt void Timer_A (void)
{	
keypadCurrState = 0;

bitCounter = 0;
P1OUT |= DATAPIN;
while(bitCounter < 4) {
	P1OUT |= CLOCKPIN;
 		P1OUT &= ~CLOCKPIN;
 		bitCounter++;
}

bitCounter = 0;
while(bitCounter < 4) {
 		(bitCounter == 0) ? (P1OUT &= ~DATAPIN) : (P1OUT |= DATAPIN);
 		P1OUT |= CLOCKPIN;
 		P1OUT &= ~CLOCKPIN;
 		bitCounter++;
 		keypadCurrState <<= 4;
 		keypadCurrState |= (0x000F & P1IN);
 	}

if(keypadCurrState != keypadPrevState) {
	clearDisplay();
	charsToSend[0] = keypadCurrState & 0x00FF;
	charsToSend[1] = (keypadCurrState >> 8) & 0x00FF;
	sendDataArray(charsToSend, 2);
}
keypadPrevState = keypadCurrState;
}

void sendDataArray(char data[], char length) {
charIndex = 0;
 	while(charIndex < length) {
 		sendData(data[charIndex]);
 		charIndex++;
 	}
}

void send(char data, char registerSelect) {
//TODO may need to disable interrupt
bitCounter = 0;
while(bitCounter < 8) {
 		(data & BIT7) ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
 		data <<= 1;
 		P1OUT |= CLOCKPIN;
 		P1OUT &= ~CLOCKPIN;
 		bitCounter++;
 	}
 	registerSelect ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
 	P1OUT &= ~ENABLEPIN;
 	P1OUT |= ENABLEPIN;
 	//TODO may need to enable interrupt
}

Link to post
Share on other sites

I was going to do write a little program to convert decimal/hex/bin to dec/hex/bin, but then I realized my keypad doesn't have E or F.

I guess I could allow just dec and bin input and hex as output only, but for now, here's a code to input numbers and A-D. * clears display, # switches between rows.

 

 

#include "msp430g2231.h"

#define sendData(data) send(data, 1)
#define sendInstruction(data) send(data, 0)
#define initDisplay() sendInstruction(0x3C); sendInstruction(0x0C); clearDisplay(); sendInstruction(0x06)
#define clearDisplay() sendInstruction(0x01); _delay_cycles(2000)
#define DATAPIN BIT6
#define CLOCKPIN BIT5
#define ENABLEPIN BIT4
#define BIT0_3 0x0F

const char charMap[16] = {
                            0x31,0x32,0x33,0x41,0x34,0x35,0x36,0x42,0x37,0x38,0x39,0x43,0x00,0x30,0x00,0x44
                        };

void send(char data, char registerSelect);
void sendDataArray(char data[], char length);

char charIndex = 0;
char bitCounter = 0;
char line = 0;

int keypadPrevState = 0;
int keypadCurrState = 0;
int keypadPress = 0;

void main(void) {
   WDTCTL = WDTPW + WDTHOLD;

   BCSCTL1 = CALBC1_1MHZ;
   DCOCTL = CALDCO_1MHZ;

   _delay_cycles(100000);

   P1OUT &= ~(CLOCKPIN + DATAPIN);
   P1OUT |= ENABLEPIN;
   P1DIR |= ENABLEPIN + CLOCKPIN + DATAPIN;

   initDisplay();

   P1REN |= BIT0_3;
   P1OUT |= BIT0_3;

   CCTL0 = CCIE;
   CCR0 = 6250;
   TACTL = TASSEL_2 + MC_1 + ID_3;

   _bis_SR_register(LPM0_bits + GIE);

}

// Timer A0 interrupt service routine
#pragma vector = TIMERA0_VECTOR
__interrupt void Timer_A (void) {
   keypadCurrState = 0;

   bitCounter = 0;
   P1OUT |= DATAPIN;
   while(bitCounter < 4) {
       P1OUT |= CLOCKPIN;
       P1OUT &= ~CLOCKPIN;
       bitCounter++;
   }

   bitCounter = 0;
   while(bitCounter < 4) {
       (bitCounter == 0) ? (P1OUT &= ~DATAPIN) : (P1OUT |= DATAPIN);
       P1OUT |= CLOCKPIN;
       P1OUT &= ~CLOCKPIN;
       bitCounter++;
       keypadCurrState <<= 4;
       keypadCurrState |= (0x000F & P1IN);
   }

   keypadPress = keypadCurrState ^ keypadPrevState;
   keypadPress &= ~keypadCurrState;
   keypadPrevState = keypadCurrState;

   if(keypadPress) {
       if(keypadPress & BITC) {
           clearDisplay();
           line = 0;
       } else if(keypadPress & BITE) {
           sendInstruction(line ? 0x80 : 0xC0);
           line ^= 1;
       } else {
           char bit = 0;
           while(bit < 16) {
               if(keypadPress & BIT0) {
                   sendData(charMap[bit]);
               }
               keypadPress >>= 1;
               bit++;
           }
       }
   }
}

void sendDataArray(char data[], char length) {
   charIndex = 0;
   while(charIndex < length) {
       sendData(data[charIndex]);
       charIndex++;
   }
}

void send(char data, char registerSelect) {
   bitCounter = 0;
   while(bitCounter < 8) {
       (data & BIT7) ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
       data <<= 1;
       P1OUT |= CLOCKPIN;
       P1OUT &= ~CLOCKPIN;
       bitCounter++;
   }
   registerSelect ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
   P1OUT &= ~ENABLEPIN;
   P1OUT |= ENABLEPIN;
}

Link to post
Share on other sites

So Ive managed to get RobG's code to work on the Wintek 1 x 24 Character LCD Display Module that I got awhile ago from

Electronic Goldmine for $1.99.

 

Here's the link: http://www.goldmine-elec-products.com/p ... ber=G15318

 

There are only 2 cons so far:

1 It takes 5v to power the display.

2 It takes 4 wires instead of 3. ( you have to toggle the reset pin on the display.)

 

logic seems to work fine at the 3.6v the msp430 puts out.

 

 

here's the code:

 

/*
  hex instructions for display setup
  0x1C == LCD power control         PW
  0x14 == Display on/off            DO
  0x28 == Display Control sets lines ect.   DC
  0x4F == Contrast Set              CN
  0xE0 == DDRAM address set         DA

*/  
   #include "msp430g2452.h"

   #define sendData(data) send(data, 1)
   #define sendInstruction(data) send(data, 0)
   #define clearDisplay() sendInstruction(0x01); _delay_cycles(2000)
   #define DATAPIN BIT6
   #define CLOCKPIN BIT5
   #define ENABLEPIN BIT4
   #define RESETPIN BIT7

   void send(char data, char registerSelect);
   void sendDataArray(char data[], char length);
   //void resetPin(unsigned int bit);
   void initDisplay(void);

   char charIndex = 0;
   char bitCounter = 0;

   const char message1[8] = {0x34,0x33,0x6F,0x68,0x2E,0x63,0x6F,0x6D};
   char message2[11] = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0xA4};
   const char message3[16] = {0x34,0x2D,0x70,0x69,0x6E,0x20,0x73,0x65,0x72,0x69,0x61,0x6C,0x20,0x4C,0x43,0x44};
   char message4[12] = {0x54,0x68,0x61,0x6E,0x6B,0x73,0x20,0xAE,0x6F,0x62,0x47,0x21};
   void main(void)
   {
      WDTCTL = WDTPW + WDTHOLD;

      _delay_cycles(100000);
      P1DIR |= ENABLEPIN + CLOCKPIN + DATAPIN + RESETPIN; // sets ENABLEPIN,CLOCKPIN,DATAPIN and RESETPIN to outputs
      P1OUT &= ~(CLOCKPIN + DATAPIN + RESETPIN);        // sets CLOCKPIN,RESETPIN and DATAPIN low
      P1OUT |= ENABLEPIN;                               // sets ENABLEPIN high

      initDisplay();                              // initiate display

      while(1) {
           // send const message using sendDataArray
         clearDisplay();
         sendDataArray((char *)message1, 8);

         _delay_cycles(3000000);

         // send message using sendDataArray
         clearDisplay();
         sendDataArray(message2, 11);

           _delay_cycles(3000000);

         // send message one char at the time
           clearDisplay();
           charIndex = 0;
           while(charIndex < 16) {
              sendData(message3[charIndex]);
              charIndex++;
           }

         _delay_cycles(3000000);

           // send message using sendDataArray
         clearDisplay();
         sendDataArray(message4, 12);

           _delay_cycles(3000000);
        }
   }

   void sendDataArray(char data[], char length) {
      charIndex = 0;
        while(charIndex < length) {
           sendData(data[charIndex]);
           charIndex++;
        }
   }

   void send(char data, char registerSelect) {
      bitCounter = 0;
      while(bitCounter < 8) {
           (data & BIT7) ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
           data <<= 1;
           P1OUT |= CLOCKPIN;
           P1OUT &= ~CLOCKPIN;
           bitCounter++;
        }
        registerSelect ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
        P1OUT &= ~ENABLEPIN;
        _delay_cycles(3000);
        P1OUT |= ENABLEPIN;
        _delay_cycles(10000);
        P1OUT &= ~ENABLEPIN;
   }

   void initDisplay(void) {
   	P1OUT &= ~RESETPIN;                     // RESETPIN low
       _delay_cycles(10000);
       P1OUT |= RESETPIN;                      //RESETPIN high
   	sendInstruction(0x1C);             //PW
   	sendInstruction(0x14);             //DO   0x14
   	sendInstruction(0x28);             //DC   0x28
   	sendInstruction(0x4F);             //CN   0x4F
   	sendInstruction(0xE0);             //DA
   	//sendInstruction(0x72);             //SC
   	//sendInstruction(0xC);              //CR
   }

Link to post
Share on other sites
So Ive managed to get RobG's code to work on the Wintek 1 x 24 Character LCD Display Module that I got awhile ago from Electronic Goldmine for $1.99.

 

Nicely done Tim. That looks like a very nice display.

 

If anyone is interested, I found some additional info' on it, including a link to a data sheet for it, here.

 

Cheerful regards, Mike

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.

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.


×
×
  • Create New...