|
|
View previous topic :: View next topic |
Author |
Message |
OldGuy
Joined: 03 Feb 2013 Posts: 27 Location: Seattle Area
|
Trouble Driving NHD LCD Display |
Posted: Sun Feb 03, 2013 2:08 pm |
|
|
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: 19499
|
|
Posted: Sun Feb 03, 2013 3:57 pm |
|
|
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
|
good thoughts |
Posted: Sun Feb 03, 2013 4:25 pm |
|
|
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: 19499
|
|
Posted: Mon Feb 04, 2013 2:01 am |
|
|
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
|
Got it! |
Posted: Mon Feb 04, 2013 12:22 pm |
|
|
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
|
Could you post your successful code? |
Posted: Fri May 01, 2015 3:13 pm |
|
|
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
|
|
Posted: Fri May 01, 2015 5:06 pm |
|
|
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
|
Some good test code. |
Posted: Tue May 12, 2015 9:17 am |
|
|
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();
}
|
|
|
|
|
|
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
|