CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Trouble Driving NHD LCD Display

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
OldGuy



Joined: 03 Feb 2013
Posts: 27
Location: Seattle Area

View user's profile Send private message

Trouble Driving NHD LCD Display
PostPosted: Sun Feb 03, 2013 2:08 pm     Reply with quote

Hello -

I'm trying to control an NHD-C0220 BIZ-FSW-FBW-3V3M 2x20 LCD display with a PIC 18LF1320-I/P. I've tried to recreate the code from the NHD data sheet, but it stops hand-shaking once I get to the 0x39 command during init. Not sure if its something in the hardware or the software causing the problem.

Have any of you successfully run one of these displays?

I've put my schematic and listing at www.LaineFamily.com/DisplayConnections.pdf if any of you would be so kind to lend me some ideas.

Thanks.!
Ttelmah



Joined: 11 Mar 2010
Posts: 19469

View user's profile Send private message

PostPosted: Sun Feb 03, 2013 3:57 pm     Reply with quote

Ignoring the display for a moment, 4K7, is too low a resistor value for the MCLR line. Most programmers can't pull up more than perhaps 22K to 47KR.

Then you have SCL pulled up with 4K7R, but SDA, shows no pullup. These displays are I2C, and both lines require pullups. For 3.3v I2C, 4K7R, is 'upper end' of the allowed pullup range (depending on how fast you clock the display, and the total capacitance of the wiring.

Then you need to work out how long the delays need to be. The 'example' code calls a function 'delay', but doesn't state what units the delay is in. Most displays take several _mSec_ at this point in their initialisation, so I'd suspect the delays need to be delay_ms(10). How long are you using?.

The code in the data sheet looks pretty much as is it'd almost run directly, except they don't say how fast the I2C bus can run. Assume 100KHz, unless you have data that it can run faster. Use the CCS I2C functions rather than the ones in the code. You talk about 'handshaking', but the code as supplied doesn't use handshaking at all.

Best Wishes
OldGuy



Joined: 03 Feb 2013
Posts: 27
Location: Seattle Area

View user's profile Send private message

good thoughts
PostPosted: Sun Feb 03, 2013 4:25 pm     Reply with quote

Dear Ttelmah,

Thanks for your thoughts, they are appreciated. In response...

- I used to use 47K on the MCLR line in my designs, but started to worry about noise causing MCLR to be asserted when I didn't want it. So I switched to 4.7K and the CCS ICD-U40 doesn't seem to mind

- I didn't use a pull-up on SCL since it is always driven by the PIC, so would always be in a driven state, therefore not needing a pull-up. Also, I can see on my scope that both lines are going cleanly between 0 and 3.3V. But, I'll try that - worth a shot. I saw that the NHD display can sink or source 1mA, so I figured that the 4.7K would be OK - that's 0.7 mA. But then, again, worth fiddling with. Good point about capacitance, I have some clip leads doing connections now.

- I've tried inserting delays of up to about 100uSec after each clock transition, that would get the data rate down in the low kHz range. Didn't know in the display manufacturers sample code what the delay units were in initialization (code says 'delay(10);'), but I assumed it was uSec. However, I've tried with delays up to 300mSec in the spots where they used delays.

- I initially tried the built-in I2C functions from CCS, but they didn't work so I tried the ones from the mfr to see if they might work, nice to see it all for trouble-shooting. For handshaking, I was talking about waiting for the ACK bit to be returned on the SDA line after each byte. Seems to come on the first few writes, but not after the 0x39.

Again, thanks for you thoughts, I have a few new things to try now.
Ttelmah



Joined: 11 Mar 2010
Posts: 19469

View user's profile Send private message

PostPosted: Mon Feb 04, 2013 2:01 am     Reply with quote

OK. You are preventing the I2C bus from working....

I2C, is an _open collector_ bus. Devices only pull the lines down, and rely on the resistors to pull up. The SCL line, is used bi-directionally in I2C. The slave device holds the line low, till it has completed handling the transaction. This is 'clock stretching'. The master pulls the line low, then lets go of it, and waits for it to go high (when released by the slave). This is why resistors are needed.
If you use a value as low as 4K7, even if the programmer can drive it, you risk the PIC supply rail being pulled up. Microchip give recommendations for the resistor.

I'd suggest something like:
Code:

#use i2c (MASTER, SCL=PIN_B7, SDA=PIN_A3, SLOW) //can try faster later
#define SLAVE_WRITE 0x78
#define SLAVE_READ 0x79

void init_LCD(void) {
   I2C_start();
   I2C_write(SLAVE_WRITE);
   I2C_write(0);
   I2C_write(0x38);
   delay_ms(10);
   I2C_write(0x39);
   delay_ms(10);
   I2C_write(0x14);
   I2C_write(0x78);
   I2C_write(0x5E);
   I2C_write(0x6D);
   I2C_write(0x0C);
   I2C_write(0x01);
   I2C_write(0x06);
   I2C_stop();
}

void send_string(unsigned char *text) {
   I2C_start();
   I2C_write(SLAVE_WRITE);
   I2C_write(0x40);
   do {
       I2C_write(*text);
       text++;
   } while (*text != '\0');
}


I'd wait for at least half a second in your main, before calling the init function (most LCD's take something between 250mSec, and 500mSec to actually be 'ready' after power is applied).

I've modified the output function to use C strings (so it keeps sending till it finds the null terminator), where the example only sends 20 characters.

Best Wishes
OldGuy



Joined: 03 Feb 2013
Posts: 27
Location: Seattle Area

View user's profile Send private message

Got it!
PostPosted: Mon Feb 04, 2013 12:22 pm     Reply with quote

Dear Ttelmah -

Thanks for your suggestions, I took some of them and made changes based on that.

What the problem turned out to be was that I had left the display RST line floating. When I pulled that up to VCC I had the much waited HELLO show up on the display.

Thanks for taking the time to lend some suggestions - much appreciated. I've learned from them.

- Brian
ccowley



Joined: 12 Sep 2009
Posts: 19

View user's profile Send private message

Could you post your successful code?
PostPosted: Fri May 01, 2015 3:13 pm     Reply with quote

Hi Brian,

I see in your post that you were able to get this display working! I and another guy have been playing around with the unit, but it seems to lock up after it sets table 1 (0x39). Did you use Ttelmah's suggestion to go with the CCS compilers #use I2C or did you stay with the bit banged method in New Haven's example?

The routines I currently have are adapted from a couple of sources including yours and assembly code from the driver chips data sheet. I have stuck with the bit banged process so far.

Any help would be greatly appreciated!

Carl

BTW - Here is my current version of the driver code, it does not include the main or .h file where the details of the chip are defined:

Code:

void DSP_LED_off()
{
   output_high(DSP_LED);
}

// LED on - turn on the LED
void DSP_LED_on()
{
   output_low(DSP_LED);
}

// send a byte to the display
void DSP_i2c_write (unsigned char j)
{
   int n;
   unsigned char d;
   d = j;
   for (n=0; n<8; n++)
   {
      if ((d&0x80)==0x80)
         output_high(SDA);
      else
         output_low(SDA);
         d=(d<<1);
         output_low(SCL);
         output_high(SCL);
         output_low(SCL);
   }
   output_high(SCL);
   while (input(SDA))
   {
      output_low (SCL);
      output_high (SCL);
   }
output_low(SCL);
}

// set i2c start condition
void DSP_i2c_start()
{
   output_high (SCL);
   output_high (SDA);
   output_low (SDA);
   output_low (SCL);
}

// set i2c stop condition
void DSP_i2c_stop()
{
   output_low (SDA);
   output_low (SCL);
   output_high (SCL);
   output_high (SDA);
}

// initialize the display
void init_display()
{
   delay_ms (100);
   DSP_i2c_start ();
   DSP_i2c_write (0x78); // slave   
   DSP_i2c_write (0x00); // Command send
   DSP_i2c_write (0x38); // Set table 0
   delay_us (30);
   DSP_i2c_write (0x39); // Set table 1
   delay_us (30);
   DSP_i2c_write (0x14); // Set bias - 1/5
   delay_us (30);
   DSP_i2c_write (0x78); // Set contrast C3 on
   delay_us (30);
   DSP_i2c_write (0x5E); // Icon on, Booster on, C5 on
   delay_us (30);
   DSP_i2c_write (0x6D); // follower on, follower amp ratio 5
   delay_ms(200);
   DSP_i2c_write (0x0C); // display on
   delay_us (30);
   DSP_i2c_write (0x01); // clear display
   delay_ms (2);
   DSP_i2c_write (0x06); // entry mode set to increment
   delay_us (30);
   DSP_i2c_stop ();
}

// write the data to the display
void Display_Data()
{
   int n;
   char test_data[6];
   strcpy (test_data, "Hello");
   DSP_i2c_start ();
   DSP_i2c_write (0x78); // slave address
   DSP_i2c_write (0x40); // data send
   for (n=0; n<5; n++)
   {
      DSP_i2c_write (test_data[n]);
   }
DSP_i2c_stop ();
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri May 01, 2015 5:06 pm     Reply with quote

Why don't you use the CCS i2c library ?

This guy has done low level routines for i2c for the MSP430, because he
doesn't have the CCS compiler with its built-in i2c library. You will notice
that he manipulates the data direction register (TRIS in PICs). He doesn't
set the i/o pins to a hard high level as you are doing. He lets the i2c
pullup resistors take the lines to a high level (when required), which is
how i2c is supposed to work.
http://dbindner.freeshell.org/msp430/lcd_i2c.html

I suggest, get rid of your code. Do a complete re-write using CCS
routines. Make sure you have pullup resistors on SDA and SCL (3.3K).
Also, make sure you have the 1 uF capactor across LCD pins 7 and 8.
Make sure RST on the LCD is not floating (unconnected) or held at a
low level. A low level will hold the LCD in reset. Also, put in a delay
at the start of main() of about 500 ms for the LCD to do a self-init.

Also, you didn't post your PIC or the i/o pins that you're using on the PIC.
The LCD runs at 3.3 volts. There are some voltage level issues that need
to be checked. This can only be done if you post your PIC. Also be sure
to tell us if it's an "F" or an "LF" PIC.
ccowley



Joined: 12 Sep 2009
Posts: 19

View user's profile Send private message

Some good test code.
PostPosted: Tue May 12, 2015 9:17 am     Reply with quote

Thanks for the reply, sorry I haven't gotten back to this sooner. I did end up going with the built in I2C and it worked well. Below is some working test code for anyone else that might be trying to see if this display is working for them.

Code:

/* This is code to test the operation of a New Haven Display,
NHD-C0220B9Z-FS(RGB)-FBW-3MV.
We used a Microchip Explorer 16 Development board with a 24FJ128GA010
plugged into the processsor socket.
The program will display "Hello World" on the first line of the display for
five seconds, then it will write it again in another 5 seconds, etc.
I hope it helps someone else trying to see if their display works!
Carl Cowley
*/


#include <24FJ128GA010.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOJTAG                   //JTAG disabled
#FUSES CKSFSM                   //Clock Switching is enabled, fail Safe clock monitor is enabled

#device ICSP=1
#use delay(crystal=8000000)

#use FIXED_IO( D_outputs=PIN_D3,PIN_D6 )

#define RST   PIN_D3
#define DSP_LED   PIN_D6
#use I2C (MASTER, SCL=PIN_D4, SDA=PIN_D5, FAST) //Fast worked fine for me.
                                               // but try SLOW if it gives you
                                               // problems.
#define SLAVE_WRITE 0x78
#define SLAVE_READ 0x79

//*************  Declarations  *********************

void DSP_LED_off(void);
void DSP_LED_on(void;
void init_LCD(void);

// **************  Main Program ***********************

void main()
{
   unsigned char mytxt[] = {"Hello World"};
   delay_ms(500);
   output_high(RST);
   Init_LCD();
   DSP_LED_on();
   delay_ms(1000);

while (TRUE)
   {
     int i = 0;
     I2C_start();
     I2C_write(SLAVE_WRITE);
     I2C_write(0x40);
     do
     {
         I2C_write(mytxt[i]);
         i++;
     } while (mytxt[i] != '\0');
     
     delay_ms(5000);
   }
}

//******************  FUNCTIONS  ****************************

void DSP_LED_off(void)
{
   output_high(DSP_LED);
}

// LED on - turn on the LED
void DSP_LED_on(void)
{
   output_low(DSP_LED);
}

void init_LCD(void)
{
   I2C_start();
   I2C_write(SLAVE_WRITE);
   I2C_write(0);
   I2C_write(0x38);
   delay_ms(10);
   I2C_write(0x39);
   delay_ms(10);
   I2C_write(0x14);
   I2C_write(0x78);
   I2C_write(0x5E);
   I2C_write(0x6D);
   I2C_write(0x0C);
   I2C_write(0x01);
   I2C_write(0x06);
   I2C_stop();
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group