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 CCS Technical Support

I2C LCD MC21605A6WD-BNMLW-V2 problem

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



Joined: 28 May 2017
Posts: 80

View user's profile Send private message

I2C LCD MC21605A6WD-BNMLW-V2 problem
PostPosted: Sun Mar 13, 2022 7:50 am     Reply with quote

Hey, I have a problem in I2C LCD. I am a new LCD I2C user.

I use CCS V5.092.

The datasheet is here

https://www.farnell.com/datasheets/2825693.pdf


The LCD address is 0x78, which I have checked in my program

http://remotesmart.wikidot.com/i2c-converter.


I checked that the device is I2C type

http://remotesmart.wikidot.com/lcd-i2c.
It is 5V device.
The CSB bit is in the ground.

I used this test code
Code:

/ I2CLCD.c test program
// made by Pekka Ritamaki, Finland email: oh3gdo@gmail.com
// date 2.2.2022
// proram: ccs c-cpmpiler v5.092
// for MIDAS I2C LCD MC2165A6WD-BNMLW-V2
// what: It does though PIC18F27K40 prosessor to LCD
// It does some simple tests to the I2C LCD
// Memory usage: ROM=1% RAM=1%
// I2C program for LCD MC1605A6WD-BNMLW-V2
#include <18F27K40.h> // define PIC type
#device ADC=10 // define ADC type, although it not here needed
#fuses RSTOSC_HFINTRC_64MHZ, NOXINST, NOMCLR, NOLVP, STVREN, NOFCMEN // setup
#fuses NOPUT, NODEBUG, NOPROTECT, NOWDT // setup for the processor
#fuses NOCPD, NOWRTD, NOWRTC, NOWRTB // setup for the processor
// if you use watchdog, use #fuses WDT512 or #fuses WDT4194304
#use delay(internal=32MHz,restart_wdt) // use internal oscillator
#pin_select U1TX=PIN_C6 // select UART TX pin
#pin_select U1RX=PIN_C7 // select UART RX pin

#use rs232(UART1,baud=9600) //Text through the UART

//The following define sets the I2C clock divisor, can be set to 4 or 5.
#define I2C_CLOCK_DIVISOR 4

// define how I2C is used in master mode
#use i2c(MASTER, scl=PIN_C3, sda=PIN_C4, CLOCK_DIVISOR=I2C_CLOCK_DIVISOR)

//The following define sets the I2C LCD slave address that will be used
#define I2C_SLAVE_ADDRESS 0x78

The following define sets the MAX buffer size used with this device,
i.e. it controls the max number of bytes that can be written to or read from slave device.
#define MAX_BUFFER_SIZE 127

#define I2C_READ_DO_RESTART

The following is used to setup Timer 2, when USE_I2C_CLOCK_SOURCE is defined
as 2, so that it's setup to correctly generate the I2C clock for the specified
system clock, I2C_CLOCK_DIVISOR, and I2C_BAUD_RATE. If not specified the
I2C_BAUD_RATE is set for 400kHz.
#define LENGOFROW 16
#define I2C_BAUD_RATE 400000
#define TIMER_PERIOD 1
#define TIMER_SETTINGS (T2_DIV_BY_128 | T2_CLK_INTERNAL)

#define one 0x80 // define command data for goto row 1
#define two 0xc0 // define command data for goto row 2
#define addr_row_one 0x00 //LCDN RAM address to row 1
#define addr_row_two 0x40 //LCDN RAM address to row 2
#define addr_row_three 0x14 //LCDN address to row 3
#define addr_row_four 0x54 //LCDN address to row 4
#define lcd_total_rows 2
#define lcd_total_columns 16
#include <stdlib.h>
#INCLUDE <STDLIB.H>
#include <input.c>

// the data to LCD comes to here
void writeI2C ( unsigned int8 command, unsigned int8 data)
{
// 0x00 is command and 0x40 is data to command
// Data is the parameter for this command

i2c_start(); // Issues a start I2C
delay_us(10) ; // a small delay
i2c_write(command); // 0x00 = command , 0x40 = data
delay_us(10) ; // a small delay
i2c_write(data); // Sends a single byte over i2c
delay_us(10) ; // a small delay
i2c_stop(); // stops i2c

}
// goto row x and postion y
void lcd_gotoxy( byte x, byte y) //goto row x and its place y
{
byte row,column,row_addr,lcd_address;

if (y>lcd_total_rows) row=lcd_total_rows; else row=y;

switch(row)
{
case 1: row_addr=addr_row_one; break;
case 2: row_addr=addr_row_two; break;
case 3: row_addr=addr_row_three; break;
case 4: row_addr=addr_row_four; break;
default: row_addr=addr_row_one; break;
}

if (x>lcd_total_columns) column=lcd_total_columns; else column=x;
lcd_address=(row_addr+(column-1));
writeI2C (0,0x80|lcd_address); // write command 0 ,address
}

=================================
INITIALIZE LCD writeI2C (command= 0x00, then data how command is done)
//==============================================
void Initial_I2C(){
delay_ms(100); //a small delay
writeI2C(0x00,0x38); //SET 2 LINE,5*8 FONT
delay_ms(100); //a small delay
writeI2C(0x00,0x0c); //Display off
delay_ms(100); //a small delay
writeI2C(0x00,0x06); //Entry mode set
delay_ms(100); //a small delay
writeI2C(0x00,0x01); //CLEAR DISPLAY
delay_ms(100); //a small delay
writeI2C(0x00,0x0c); //DISPLAY ON,Cursor OFF,Cursor Blink OFF

}

#define CHARSINROW 16 // how menu characters in one row?
void LCD_PUTC(char in_data)
{
writeI2C(0x40, in_data); // command =0x40 i.e data, and in_data is data character

}
// main program starts

void main ()
{

setup_timer_2(TIMER_SETTINGS, TIMER_PERIOD, 1);

Initial_I2C(); // initialize LCD to right mode
while(1)
{
printf(LCD_PUTC,"Testing…."); // send data to I2C LCD
printf( "\rTesting…."); // send data to serial port
delay_ms(100);
}
}


I shows only one row like any other LCD without initial code.
The serial code works fine.
I wonder what could be wrong?
I have checked I2C wires with the oscilloscope and they seem to be working normally.
I have not found any working program for CCS in the internet for this LCD.
Can anybody help me?
temtronic



Joined: 01 Jul 2010
Posts: 9224
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Mar 13, 2022 7:55 am     Reply with quote

For starters, go to the code library forum and download PCMP's I2C scanner program. Copy/modify for your PIC, compile and run it.
It will confirm what address the LCD is set for.

Some use 7 bit I2C addressing, other 8 bit, so always best to run the 'scanner' program !

also , do you have proper pullup resistors installed.

also I looked at datasheet but didn't see how the 0x78 address was made.
pekka1234



Joined: 28 May 2017
Posts: 80

View user's profile Send private message

PostPosted: Sun Mar 13, 2022 9:41 am     Reply with quote

Temtronic

Thank you for your fast advice, but I have already done this.
I found the LCD address 0x78. like it should be.

It give a good answer, but not any marks on LCD.
There is only one row to seen. like without the prosessor.

Look
http://remotesmart.wikidot.com/i2c-converter.
Here is the address search program.


Pekka
temtronic



Joined: 01 Jul 2010
Posts: 9224
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Mar 13, 2022 12:26 pm     Reply with quote

I've never used this setup..
Quote:
// define how I2C is used in master mode
#use i2c(MASTER, scl=PIN_C3, sda=PIN_C4, CLOCK_DIVISOR=I2C_CLOCK_DIVISOR)

I've always used the speed= ...option so I don't KNOW what actual speed the I2C bus is running in this program.

The scanner test program (in the link) uses an 8 MHz clock, your program runs at 32MHz.

Since the 'scanner' program works, I'd lower the clock to 8 MHz.

Also run the I2Cscanner program to confirm the other program is running properly.

As well, remove/disable the WDT feature. It could be causing some problem and not needed until 100% of the code is running right.
pekka1234



Joined: 28 May 2017
Posts: 80

View user's profile Send private message

PostPosted: Sun Mar 13, 2022 12:41 pm     Reply with quote

Temtronic

I have put 8MHz, so that everything were slow enough.

Nice that you show some faults in my code,
What you suggest?

On the end of http://remotesmart.wikidot.com/lcd-i2c
There is oscilloscopes picture from the clock and the data.

What do you say about these pictures?

Pekka
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 13, 2022 9:27 pm     Reply with quote

pekka1234 wrote:

#include <18F27K40.h>

#use i2c(MASTER, scl=PIN_C3, sda=PIN_C4, CLOCK_DIVISOR=I2C_CLOCK_DIVISOR)

The CCS manual says the "CLOCK_DIVISOR" is only used with
PIC's that have an "i2c module", such as the 18F27K42.
From the CCS manual (page 188):
Quote:

PIC18 devices that have a separate I2C peripheral instead
of a combined SSP peripheral allow the following:
CLOCK_SOURCE=x
CLOCK_DIVISOR=x

Your 18F27K40 does not have an I2C Module. It has an MSSP module.
I suggest that you put in the keyword 'SLOW' instead of
CLOCK_DIVISOR=I2C_CLOCK_DIVISOR. This will make it run
at 100 KHz for SCL.
pekka1234



Joined: 28 May 2017
Posts: 80

View user's profile Send private message

PostPosted: Mon Mar 14, 2022 3:05 am     Reply with quote

PCM programmer

Very nice to find this!
I have never even think of about this.

I did as you suggest, but it not helped.
Is there some other faults?

I take a picture with two probes at the end of http://remotesmart.wikidot.com/lcd-i2c

How the cpu already gave a normal I2C signals, even it should not work?

He is my last setup code
Code:

#include <18F27K40.h>           // define PIC type
#device ADC=10                  // define ADC type, althoug it not here needed
#fuses RSTOSC_HFINTRC_64MHZ,  NOXINST, NOMCLR, NOLVP, STVREN, NOFCMEN // setup
#fuses  NOPUT, NODEBUG, NOPROTECT, NOWDT // setup for the processor
#fuses  NOCPD, NOWRTD, NOWRTC, NOWRTB    // setup for the processor
// if you use watchdog, use   #fuses WDT512 or #fuses WDT4194304
#use delay(internal=32MHz,restart_wdt)  // use internal oscillator
#pin_select U1TX=PIN_C6        // select UART  TX pin   
#pin_select U1RX=PIN_C7        // select UART  RX pin   

#use rs232(UART1,baud=9600)    //Text through the UART

//The following define sets the I2C clock divisor, can be set to 4 or 5.
#define I2C_CLOCK_DIVISOR     4

// define how I2C is used in master mode
#use i2c(MASTER, scl=PIN_C3, sda=PIN_C4, SLOW)

//The following define sets the I2C LCD slave address that will be used 
#define I2C_SLAVE_ADDRESS     0x78

//The following define sets the MAX buffer size used with this device,
//i.e. it controls the max number of bytes that can be written to or read from slave device.
#define MAX_BUFFER_SIZE       127   

 
#define I2C_READ_DO_RESTART

It doesn't show any mark in the LCD.

Pekka
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Mon Mar 14, 2022 4:35 am     Reply with quote

Two basic questions.

How have you got the backlight connected (You won't see much unless
this is driven correctly).

How have you got Vo connected?.
I think you are talking about Vo, when you refer to CR. The contrast ratio
is controlled by Vo, but I can't see anywhere that this unit says it supports
0v for Vo, Many of these white/blue displays will show nothing unless this is
correctly driven.....
pekka1234



Joined: 28 May 2017
Posts: 80

View user's profile Send private message

PostPosted: Mon Mar 14, 2022 6:18 am     Reply with quote

Ttelmah

I can control the picture in the LCD with potentiometer,
It works fine.

Look the end of http://remotesmart.wikidot.com/lcd-i2c

In same address there are also picture of LCD.
I have use LCD more than 40 years, but this is my first I2C device.

Thanks for the help.

Pekka
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Mon Mar 14, 2022 6:45 am     Reply with quote

Looking at this, you do realise your commands are wrong..... Sad

The sequence on I2C, is that the start must always be followed by the
device address. So your WRITE_I2C command needs to be:
Code:

// the data to LCD comes to here
void writeI2C ( unsigned int8 command, unsigned int8 data)
{
// 0x00 is command and 0x40 is data to command
// Data is the parameter for this command

   i2c_start(); // Issues a start I2C
   I2c_write(2C_SLAVE_ADDRESS); //address the device
   i2c_write(command); // 0x00 = command , 0x40 = data
   i2c_write(data); // Sends a single byte over i2c 
   I2c_stop(); // stops i2c
}


You are not addressing the device, so it won't take the data you are
sending...
You have to address the device for every transfer. You are not doing it at all.
Look at figure 9.6. Note the 'slave address' byte before anything else is
sent....

I'd slightly increase the initial delay on your init. The LCD is ready to
accept data 40mSec after the supply reaches 4.5v, but the PIC will
start running when the supply gets to just 2.3v. Depending on the rise
time of your supply, several extra mSec may be needed. Alternatively just
enable PUT on the PIC, which will slow it's start up.
pekka1234



Joined: 28 May 2017
Posts: 80

View user's profile Send private message

PostPosted: Mon Mar 14, 2022 7:10 am     Reply with quote

Ttelmah
What a great success!
Now it works.
I will take the delays off.

Very much thanks!
It will take four days.

Regards
Pekka
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Mon Mar 14, 2022 8:26 am     Reply with quote

The good thing was the link you gave showed everything. Including the
I2C waveforms circuit etc..
A look then showed what was missing. Very Happy
temtronic



Joined: 01 Jul 2010
Posts: 9224
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Mar 14, 2022 9:58 am     Reply with quote

glad it's 'up and running' !!!
Since day one, some 2+ decades ago, I've always had a delay_ms(100) just before setting up( 1st access) of all LCD modules. They are sloooow compared to PICs when powered up. Really the 1/10th of a second is not a lot of time...maybe a sip of coffee.....
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Mon Mar 14, 2022 10:30 am     Reply with quote

The original standard Hitachi text LCD controller required a minimum of
90mSec after boot. Many of the 'third party' ones require a little more.
Separately though there is the issue of 'when' boot actually is. More and
more on the recent PIC's that wake up at lower voltages, the PIC will wake
before the boot actually starts on the LCD. This particular one has a very
high wake up voltage, so it is well worth increasing the time a little.
He had already got 100mSec at the start of the init code.
pekka1234



Joined: 28 May 2017
Posts: 80

View user's profile Send private message

PostPosted: Mon Mar 14, 2022 12:37 pm     Reply with quote

I had a similar problem when I tried to use my first LCD about 1993.
The LCD started only the second time.

I was wondering what was a problem.
Then I went to Helsinki to electronic fair.
I explained my problem to LCD seller.

He did not understand anything programming, but he took ten switches and LCD. Then he turned all the switched on and off and LCD started every time.
From there I understand that the LCD need some delay, before it starts.

Pekka
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