I2C, 8051's and LCD2041's

LK/ELK/VK/PK/OK/MX/GLK/EGLK/GVK/GLT Series

Moderators: Henry, Mods

Post Reply
Gironic
LCD?
Posts: 5
Joined: Fri Apr 16, 2004 9:54 am

I2C, 8051's and LCD2041's

Post by Gironic »

I'm using a Cypress EZUSB FX2. It's an enhanced 8051 with a built in implementation of USB 2.0. It's a great chip, and of course is an I2C host/master. I've been using the I2C interface for some time and can talk to all of my other I2C devices, but for some reason I can't communicate with the LCD2041.

I read the posting about the read/write bit of the address scheme, and am concerned that it could break the I2C implementaiton on this chip. My base address is 0x5A to avoid conflicts with my other I2C devices. Then, shifting we get 0xB4 for a write. I've tried both addresses and can't send text. (I'll preface this by saying that I've hooked it up to the RS232 port of a PC and it displayed text fine. I haven't tried all of the commands.) The I2C protocol on the 8051 shifts all addresses up one bit as well, and I'm not sure why. I have a call into their tech support about it, as to why, but if the address were 0xB4, and we shifted up one bit, we'd have an overflow problem since this chip only allows one byte for addresses.

I'm not sure where to look next. I tried a for loop, cycling all possible address, 0-255, writing text, and got nothing at all. Any pointers here?

Also, I've tried playing with the jumpers to select RS232 vs. I2C, but that hasn't seemed to help either.

Also, using the RS232 cable, I've gotten sporadic results, for example, typing the key "1" repeatedly gives alternating 1's with a kanji symbol. ???

Thanks
Gironic
LCD?
Posts: 5
Joined: Fri Apr 16, 2004 9:54 am

Post by Gironic »

/// ALL WRONG... they are doing the same thing with the 1 or 0 shifted in
/// on the address... actually that's I2C Spec.

-----NO NO NO NO------------
I spoke with Cypress, and the address shift "I2DAT = (addr << 1) | 0x01" is for a start bit. So one bit of the "8 bit" address is getting shifted out of the frame, and lost. Since I2C spec defines 7 bit addresses, they assumed using a shift and a bit this way wouldn't have any impact. Is there a way for me to hack a lower address into the LCD? Just one bit lower would work! Something like a base address of 0x30, or lower? Is there a custom option available? Can I hack it to make sure that the problem? Is there a prom I can burn or something? Thanks

-Jared

---------------------------------

So if we're all talking about the same addressing scheme, why can't I talk to the LCD? I'm assuming I'm doing something wrong, but I can talk to all other I2C devices running at 100 kHz!
Bill_Sev
LCD!
Posts: 10
Joined: Mon Apr 12, 2004 2:31 pm

Post by Bill_Sev »

Im feeling your pain bro! I am working with a philips 87LPC764 and do not get an ack back when sending the address. Heres my code:

;****************************************************************************
; Begin Code
;****************************************************************************
; Reset and interrupt vector
;****************************************************************************
; Reset and interrupt vectors
org 0000h
ajmp Reset ; reset vector.
org 0073h ; Timer I interrupt address.
TimerI:
setb CLRTI ; Clear timer I interrupt.
clr TIRUN
acall ClrInt ; Clear interrupt pending.
mov SP,StackSave ; Restore stack for return to main.
ajmp Recover ; Attempt bus recovery.
ClrInt: reti
org 0100h
;****************************************************************************
; Main Transmit and Receive Routines
;****************************************************************************
; Send data byte(s) to slave.
; Enter with slave address in SlvAdr, data in XmtDat buffer, # of data
; bytes to send in ByteCnt.
Senddata:
clr NoAck ; clear error flags.
clr Fault
clr retry
mov StackSave,SP ; save stack address for bus fault.
mov A,SlvAdr ; get slave address.
acall SendAddr ; get bus and send slave address.
jb NoAck,SDEX ; check for missing acknowledge.
jb Fault,SDatErr ; check for bus fault.
mov R0,#XmtDat ; set start of transmit buffer.
SDLoop:
mov A,@R0 ; get data for slave.
inc R0
acall XmitByte ; send data to slave.
jb NoAck,SDEX ; check for missing acknowledge.
jb Fault,SDatErr ; check for bus fault.
djnz ByteCnt,SDLoop
SDEX:
acall SendStop ; send an I2C stop.
ret
; Handle a transmit bus fault.

SDatErr:
ajmp Recover ; attempt bus recovery.

; Receive data byte(s) from slave.
; Enter with slave address in SlvAdr, # of data bytes requested in ByteCnt.
; Data returned in RcvDat buffer.
Rcvdata:
clr NoAck ; clear error flags.
clr Fault
clr retry
mov StackSave,SP ; save stack address for bus fault.
mov A,#LCDR ; get slave address.
setb ACC.0 ; get bus read bit.
acall SendAddr ; send slave address.
jb NoAck,RDEX ; check for missing acknowledge.
jb Fault,RDatErr ; check for bus fault.
mov R0,#RcvDat ; set start of receive buffer.
djnz ByteCnt,RDLoop ; check for count = 1 byte only.
sjmp RDLast
RDLoop:
acall RDAck ; get data and send an acknowledge.
jb Fault,RDatErr ; check for bus fault.
mov @R0,A ; save data.
inc R0
djnz ByteCnt,RDLoop ; repeat until last byte.
RDLast:
acall RcvByte ; get last data byte from slave.
jb Fault,RDatErr ; check for bus fault.
mov @R0,A ; save data.
mov I2DAT,#80h ; send negative acknowledge.
jnb ATN,$ ; wait for NAK sent.
jnb DRDY,RDatErr ; check for bus fault.
RDEX:
acall SendStop ; send an I2C bus stop.
ret

; Handle a receive bus fault.

RDatErr:
ajmp Recover ; attempt bus recovery.

; Send data byte(s) to slave with subaddress.
; Enter with slave address in ACC, subaddress in SubAdr, # of bytes to
; send in ByteCnt, data in XmtDat buffer.

SendSub:
clr NoAck ; clear error flags.
clr Fault
clr retry
mov StackSave,SP ; save stack address for bus fault.
mov A,SlvAdr ; get slave address.
acall SendAddr ; get bus and send slave address.
jb NoAck,SSEX ; check for missing acknowledge.
jb Fault,SSubErr ; check for bus fault.
mov A,SubAdr ; get slave subaddress.
acall XmitByte ; send subaddress.
jb NoAck,SSEX ; check for missing acknowledge.
jb Fault,SSubErr ; check for bus fault.
mov R0,#XmtDat ; set start of transmit buffer.
SSLoop:
mov A,@R0 ; get data for slave.
inc R0
acall XmitByte ; send data to slave.
jb NoAck,SSEX ; check for missing acknowledge.
jb Fault,SSubErr ; check for bus fault.
djnz ByteCnt,SSLoop
SSEX:
acall SendStop ; send an I2C stop.
ret

; Handle a transmit bus fault.

SSubErr:
ajmp Recover ; attempt bus recovery.

; Receive data byte(s) from slave with subaddress.
; Enter with slave address in SlvAdr, subaddress in SubAdr, # of data bytes
; requested in ByteCnt. data returned in RcvDat buffer.

RcvSub:
clr NoAck ; clear error flags.
clr Fault
clr retry
mov StackSave,SP ; save stack address for bus fault.
mov A,#LCDR ; get slave address.
acall SendAddr ; send slave address.
jb NoAck,RSEX ; check for missing acknowledge.
jb Fault,RSubErr ; check for bus fault.
mov A,SubAdr ; get slave subaddress.
acall XmitByte ; send subaddress.
jb NoAck,RSEX ; check for missing acknowledge.
jb Fault,RSubErr ; check for bus fault.
acall RepStart ; send repeated start.
jb Fault,RSubErr ; check for bus fault.
mov A,SlvAdr ; get slave address.
setb ACC.0 ; get bus read bit.
acall SendAd2 ; send slave address.
jb NoAck,RSEX ; check for missing acknowledge.
jb Fault,RSubErr ; check for bus fault.
mov R0,#RcvDat ; set start of receive buffer.
djnz ByteCnt,RSLoop ; check for count = 1 byte only.
sjmp RSLast
RSLoop:
acall RDAck ; get data and send an acknowledge.
jb Fault,RSubErr ; check for bus fault.
mov @R0,A ; save data.
inc R0
djnz ByteCnt,RSLoop ; repeat until last byte.
RSLast:
acall RcvByte ; get last data byte from slave.
jb Fault,RSubErr ; check for bus fault.
mov @R0,A ; save data.
mov I2DAT,#80h ; send negative acknowledge.
jnb ATN,$ ; wait for NAK sent.
jnb DRDY,RSubErr ; check for bus fault.
RSEX:
acall SendStop ; send an I2C bus stop.
ret
; Handle a receive bus fault.
RSubErr:
ajmp Recover ; attempt bus recovery.
;****************************************************************************
; Subroutines
;****************************************************************************
; Send address byte.
; Enter with address in ACC.
SendAddr:
mov I2CFG,#BMRQ+BTIR+CTVAL ; request I2C bus.
jnb ATN,$ ; wait for bus granted.
jnb Master,SAErr ; should have become the bus master.
SendAd2:
mov I2DAT,A ; send first bit, clears DRDY.
mov I2CON,#BCARL+BCSTR+BCSTP ; clear start, releases SCL.
acall XmitAddr ; finish sending address.
ret
SAErr:
setb Fault ; return bus fault status.
ret
; Byte transmit routine.
; Enter with data in ACC.
; XmitByte : transmits 8 bits.
; XmitAddr : transmits 7 bits (for address only).
XmitAddr:
mov bitCnt,#8 ; set 8 bits of address count.
sjmp Xmbit2
XmitByte:
mov bitCnt,#8 ; set 8 bits of data count.
Xmbit:
mov I2DAT,A ; send this bit.
Xmbit2:
rl A ; get next bit.
jnb ATN,$ ; wait for bit sent.
jnb DRDY,XMErr ; should be data ready.
djnz bitCnt,Xmbit ; repeat until all bits sent.
mov I2CON,#BCDR+BCXA ; switch to receive mode.
jnb ATN,$ ; wait for acknowledge bit.
jnb RDAT,XMBX ; was there an ack?
setb NoAck ; return no acknowledge status.
XMBX:
ret
XMErr:
setb Fault ; return bus fault status.
ret
; Byte receive routines.
; RDAck: receives a byte of data, then sends an acknowledge.
; RcvByte : receives a byte of data.
; data returned in ACC.
RDAck:
acall RcvByte ; receive a data byte.
mov I2DAT,#0 ; send receive acknowledge.
jnb ATN,$ ; wait for acknowledge sent.
jnb DRDY,RdErr ; check for bus fault.
ret
RcvByte:
mov bitCnt,#8 ; set bit count.
clr A ; init received byte to 0.
Rbit:
orl A,I2DAT ; get bit, clear ATN.
rl A ; shift data.
jnb ATN,$ ; wait for next bit.
jnb DRDY,RdErr ; should be data ready.
djnz bitCnt,Rbit ; repeat until 7 bits are in.
mov C,RDAT ; get last bit, don
Bill_Sev
LCD!
Posts: 10
Joined: Mon Apr 12, 2004 2:31 pm

Post by Bill_Sev »

Sorry its so long!
Gironic
LCD?
Posts: 5
Joined: Fri Apr 16, 2004 9:54 am

Henry, how about a little attention over her bud?? :)

Post by Gironic »

Yeah, my code is pretty simple, and I know it works on the I2C bus as spec'd by Philips, but this LCD doesn't generate an ACK. I keep getting a "I2C_NACK" error. (No ACK received) and it hangs my I2C bus.

I read the FAQ about how the Matrix Orbital chip doesn't generate ACKs properly, and I'm 99% sure that's where my problem lies. Unfortunately my I2C support on the 8051 I'm using is native in hardware and I can't change it. If the hardware doesn't get an ACK, it doesn't return control. Surely a developer at Matrix can figure out a way to produce ACKs correctly. Maybe we should solve that problem for them?

Henry, what should I do in this situation? Thanks

-Jared
Bill_Sev
LCD!
Posts: 10
Joined: Mon Apr 12, 2004 2:31 pm

Post by Bill_Sev »

After 2 weeks of beating my head against the wall here I am just going to use the UART on the LPC764 and do rs232 to the display. and will use the I2C for other components. Has anyone gotten I2C to work with an 8051?
Gironic
LCD?
Posts: 5
Joined: Fri Apr 16, 2004 9:54 am

Yeah... just placed the header in my Layout...

Post by Gironic »

And I didn't want to do that... I wanted it to be stock out of the box, and not have to do any modifications to take 5V level signals. So now I have to drop an RS232 chip on my board and a DB9?!?!?! Grrr.... why don't they just fully implement the spec?

Everyone designing with a PIC can choose to ignore the ACK, but my I2C protocol (correctly implemented) is in hardware and stalls waiting for an ACK.

I guess RS232 is my only recourse.

-Jared
Miles
Matrix Orbital
Matrix Orbital
Posts: 1105
Joined: Mon Mar 04, 2002 4:00 pm

Post by Miles »

If the hardware implementation is giving you a problem why don't you try bit banging...? It's not a matter of us implementing ACK it's rather how our displays interpret data...
Miles Y.
Head of Technical Support
Product Manager
Matrix Orbital
Bill_Sev
LCD!
Posts: 10
Joined: Mon Apr 12, 2004 2:31 pm

Post by Bill_Sev »

Been there done that but didnt get the T-Shirt for it!
Gironic
LCD?
Posts: 5
Joined: Fri Apr 16, 2004 9:54 am

Waveforms...

Post by Gironic »

Does anyone have any waveforms of I2C working with the Matrix Orbital LCD's? Is there a delay from address to text that is critical, or something along those lines? I get nothing on the screen.


-Jared
Miles
Matrix Orbital
Matrix Orbital
Posts: 1105
Joined: Mon Mar 04, 2002 4:00 pm

Post by Miles »

I'll see what I can dig up...? How fast are you sending data?? We recommend 100 Kbps max...
Miles Y.
Head of Technical Support
Product Manager
Matrix Orbital
Post Reply