Sign in to follow this  
Followers 0
oPossum

2 wire Nokia 5110 interface

9 posts in this topic

This is a way to use the Nokia 5110 LCD with only 2 GPIO pins. Software SPI allows any 2 pins to be used. In some cases the data line may be shared with another external peripheral such as an output shift register or an other 5110.

 

The D/C and Reset lines are controlled by stretching the clock pulse. R/C values must be calculated for the specific clock frequency that the MSP430 will run at. A variety of Schmitt trigger gates could be used, such as MC14584, CD40106, 74HC14, 74HC132, etc...

 

Wiring...

post-2341-135135525263_thumb.png

 

The clock pulse for D0 is stretched when a command byte is sent. The PCD8544 controller latches the D/C line during the rising edge of the clock during the D0 period.

A reset pulse uses an even longer clock pulse.

post-2341-135135525273_thumb.jpg

 

Software SPI for 2 wire scheme

typedef enum {
   lcd_command = 0,        // Array of one or more commands
   lcd_data = 1,           // Array of one or more bytes of data
   lcd_data_repeat = 2     // One byte of data repeated
} lcd_cmd_type;

void lcd_send(const unsigned char *cmd, unsigned len, lcd_cmd_type type)
{
   register unsigned mask;
                                                           // CLK high upon entry and exit 
   do {                                                    // Send bits 7 to 1
       mask = 0x0080;                                      // msb first
       do {                                                //
           if(*cmd & mask) {                               // Test bit
               P1OUT |= LCD_DATA;                          // 1 bit, data high
               P1OUT &= ~LCD_CLK;                          // Clock low
           } else {                                        //
               P1OUT &= ~(LCD_CLK | LCD_DATA);             // 0 bit, data & clock low
           }                                               //
           P1OUT |= LCD_CLK;                               // Clock high
           mask >>= 1;                                     // Next bit
       } while(!(mask & 1));                               // Check if bit 0, loop if not
                                                           // Send bit 0
       if(*cmd & mask) {                                   // Test bit
           P1OUT |= LCD_DATA;                              // 1 bit, data high
           P1OUT &= ~LCD_CLK;                              // Clock low
       } else {                                            //
           P1OUT &= ~(LCD_CLK | LCD_DATA);                 // 0 bit, data & clock low
       }                                                   //
       if(!type) __delay_cycles(10);                       // Stretch clock if command - DC will go low                                                                
       P1OUT |= LCD_CLK;                                   // Clock high
       if(!(type & 2)) ++cmd;                              // Inc buf pointer if not repeat
   } while(--len);                                         // Decrement byte count, next byte if not zero...
}

void lcd_reset(void)
{
   P1OUT &= ~LCD_CLK;
   __delay_cycles(10000);
   P1OUT |= LCD_CLK;
   __delay_cycles(10000);
}

RobG, larsie, roadrunner84 and 3 others like this

Share this post


Link to post
Share on other sites

This is very nice. You could also (or should) use hardware SPI and just change to slower speed when sending command, for example 4MHz data, 1MHz command. You would then avoid any problems when using interrupts.

I would also suggest using little/tiny logic like 2G14 (plus 1G14 if reset is needed.) At one point, I wanted to do something similar for my serial LCD pack, use missing pulse detector to trigger enable pin, but I figured that inflexibility (and extra parts) is not worth it. Any ideas?

roadrunner84 likes this

Share this post


Link to post
Share on other sites

I chose to use software SPI so the code could work with any MSP430 and any two pins (of the same port). Interrupts can be disabled at the bit, byte or function level as appropriate. Hardware SPI is obviously much faster, but chip and pin selection is limited and there are 2 different hardware SPI peripherals that need to be supported.

 

Software control of the 5110 reset is essential to allow debugging and also improves reliability in a finished product. I would not recommend removing this feature - use a 74LVC3G14. Explicit reset and initialization of all peripherals is generally good design and coding practice.

 

Many ways to detect absence of clock. I think this will work...

post-2341-135135525953_thumb.png

Share this post


Link to post
Share on other sites
Software control of the 5110 reset is essential to allow debugging and also improves reliability in a finished product. I would not recommend removing this feature - use a 74LVC3G14. Explicit reset and initialization of all peripherals is generally good design and coding practice.

I agree, though I prefer hardware reset with a simple RC (shared or separate in cases when in-circuit debugging is required.)

Many ways to detect absence of clock. I think this will work...

Thanks! That put me on the right track, I was looking at a more complex solution.

I think this simple one, which uses LVC3G17, will do the trick for me.

 

post-197-135135526226_thumb.png

Share this post


Link to post
Share on other sites

I assumed the HD44780 latches on rising edge (like the shift register), but it latches on falling edge. So I think you could eliminate the last stage of your circuit or flip the diode in the circuit I posted.

post-2341-135135526231_thumb.png

 

Data has to be valid for 80 ns before (tDSW) and 10 ns after (tH) the falling clock edge. Outside of those times the data lines may change.

post-2341-135135526238_thumb.png

Share this post


Link to post
Share on other sites

hello, oPossum. i've got most of the things i need to hook up this nokia LCD screen to just two pins. it's quite awesome. but there's only one thing i don't understand. with the lcd_send funtion in your code.. namely, this:

 

void lcd_send(const unsigned char *cmd, unsigned len, lcd_cmd_type type)

 

how would i send a command like

 

display.setTextSize(1);

display.setTextColor(BLACK);
display.setCursor((display.width()/2)-25,(display.height()/2)-3);

display.print("hello, world");

 

to the LCD screen?

 

if it helps any, to know what library i'm using for this

 

#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

Adafruit_PCD8544 display = Adafruit_PCD8544(9, 8, 7, 6, 5);

 

it's the adafruit nokia screen library

Share this post


Link to post
Share on other sites

Thanks for the post oPossum!

 

I've been struggling with this just a bit. I picked up a MC14584 and opted for R1/C1 at 10ohm and 100nf (calculated for ~8mhz) and substituted a 1k and 100nf for R2/C2. According to my MSO i'm only signaling for about 5us and your trace shows about 20us. I assume my scaling of R1/C1 and or R2/C2 is off. Any help greatly appreciated.

 

Thanks!

Share this post


Link to post
Share on other sites

The resistance should be at least several hundred ohms - 1k to 10k is a good range to stay within. The MSP430 can only supply limited current on outputs pins, and low value resistors make the circuit require more than what can be supplied to work properly (have expected timing).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0