|
|
View previous topic :: View next topic |
Author |
Message |
pekka1234
Joined: 28 May 2017 Posts: 80
|
I2C LCD MC21605A6WD-BNMLW-V2 problem |
Posted: Sun Mar 13, 2022 7:50 am |
|
|
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
|
|
Posted: Sun Mar 13, 2022 7:55 am |
|
|
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
|
|
Posted: Sun Mar 13, 2022 9:41 am |
|
|
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
|
|
Posted: Sun Mar 13, 2022 12:26 pm |
|
|
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
|
|
Posted: Sun Mar 13, 2022 12:41 pm |
|
|
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
|
|
Posted: Sun Mar 13, 2022 9:27 pm |
|
|
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
|
|
Posted: Mon Mar 14, 2022 3:05 am |
|
|
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
|
|
Posted: Mon Mar 14, 2022 4:35 am |
|
|
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
|
|
Posted: Mon Mar 14, 2022 6:18 am |
|
|
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
|
|
Posted: Mon Mar 14, 2022 6:45 am |
|
|
Looking at this, you do realise your commands are wrong.....
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
|
|
Posted: Mon Mar 14, 2022 7:10 am |
|
|
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
|
|
Posted: Mon Mar 14, 2022 8:26 am |
|
|
The good thing was the link you gave showed everything. Including the
I2C waveforms circuit etc..
A look then showed what was missing. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9224 Location: Greensville,Ontario
|
|
Posted: Mon Mar 14, 2022 9:58 am |
|
|
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
|
|
Posted: Mon Mar 14, 2022 10:30 am |
|
|
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
|
|
Posted: Mon Mar 14, 2022 12:37 pm |
|
|
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 |
|
|
|
|
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
|