Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

I2C read operation failing?

Status
Not open for further replies.

shreyas.p

Newbie level 3
Joined
Oct 18, 2010
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,350
Hello

I have written a simple code to read the data present on PCF8574 pins and display it on port 2.

In my project, I have 8 switches connected to PCF8574. And I want to read the status of switches and display it on Port 2.

The following code is working perfectly for WRITE operation. When I write the data 01010101 to PCF8574, it is working (see attached image). To test the read operation, I connected the pins of PCF8574 to vcc and ground to generate a pattern (01010101). But it is not being read.

Here is the code i'm using:

;--------------------------------------
; CODE
; (address pins of PCF8574 are connected to ground)
;--------------------------------------

var1 equ r2
temp equ r4
delay equ r1


sda EQU P1.0
scl EQU P1.1


ORG 0000H
AJMP MAIN


MAIN:
setb sda
setb scl

jnb sda $
setb scl $

mov sp,#50H

acall start
mov a,#40h ; device address of PCF8574 (write operation LSB = 0)
acall send_byte
acall acknowledge

acall start
mov a,#41H ; read operation (LSB=1)
acall send_byte
acall acknowledge

acall read_byte
mov P2,A
acall stop

ret


;---------------------------------------
;SUBROUTINES:
;---------------------------------------

send_byte: mov R0,#08h ; setup count
next_bit:
acall wait_halfbit
rlc A ; rotate next bit into carry
mov SDA,C ; set IIC data to carry value
setb SCL ; set IIC clock
acall wait_halfbit ; wait
clr SCL ; drop clock. signals receiver to sample data
djnz R0,next_bit ; do next bit
setb SDA ; idle the data line
ret


read_byte: mov r0,#08H
mov a,#00h
next:
acall wait_halfbit
mov C,sda
setb scl
acall wait_halfbit
clr scl
rrc A
djnz r0, next
setb sda
acall acknowledge
ret


start:
acall wait_halfbit
clr SDA
clr SCL
ret

stop:
clr SDA
clr SDA ; stop bit

setb SCL
acall wait_halfbit
setb SDA
clr SCL
ret


acknowledge:
setb SCL
acall wait_halfbit
clr SCL
RET

wait_halfbit:
nop
nop
nop
nop
ret



delayms: ; delay of 10ms (however i hven't used it in this code)
mov var1,#230
d:
nop
nop
djnz var1,d
djnz 10,delayms
ret

end
;---------------------------------------

Also I'm getting a message saying
"Simulation is not running in real time due to excessive CPU load"

What does this mean?
I haven't executed this code on breadboard. I'm just testing it on Proteus.
 

Attachments

  • ckt.JPG
    ckt.JPG
    184.8 KB · Views: 9
  • ckt2.JPG
    ckt2.JPG
    193.3 KB · Views: 3
Last edited:

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
48,275
Helped
14,226
Reputation
28,713
Reaction score
12,920
Trophy points
1,393
Location
Bochum, Germany
Activity points
279,560
The sequence
Code:
acall acknowledge
acall start

is generating the bus sequence
clr SCL
...
clr SDA
clr SCL
which will never cause a restart. There may be other errors, too.
 

kandhu26

Member level 5
Joined
Sep 7, 2009
Messages
93
Helped
13
Reputation
26
Reaction score
12
Trophy points
1,288
Location
chennai / bangalore
Activity points
1,856
This is a 'C' coding for Read Byte [Using I2C protocol]..

unsigned char ReadByte (bit ack)
{
unsigned char lop, dta;
SCL = 0;
for(lop=0; lop<8; lop++)
{
dta <<= 1;
SCL = 1;
Delay(10);
if(SDA) dta++;
SCL = 0;
}
SDA = ack;
SCL = 1;
Delay(5);
SCL =0;
SDA = 1;
return dta;
}
 

shreyas.p

Newbie level 3
Joined
Oct 18, 2010
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,350
can you post the rest of the code ..?
It might be helpful for me.

thx
 

kandhu26

Member level 5
Joined
Sep 7, 2009
Messages
93
Helped
13
Reputation
26
Reaction score
12
Trophy points
1,288
Location
chennai / bangalore
Activity points
1,856
This is a 'C' coding for Write Byte [Using I2C protocol]

bit WriteByte (unsigned int dta)
{
unsigned char lop;
bit err;
SCL = 0;
for(lop=0; lop<8; lop++)
{
if(dta & 0x80) SDA = 1;
else SDA = 0;
SCL = 1;
Delay(10);
SCL = 0;
dta <<= 1;
}
SDA = 1;
SCL = 1;
if(SDA) err = 1;
else err = 0;
Delay(10);
SCL = 0;
return err;
}

These two things [WriteByte and ReadByte] are enough to write data to registers or read data from registers...
 

jumanji

Newbie level 6
Joined
Mar 15, 2011
Messages
13
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,395
I cannot tell for sure but it appears that you are driving the data line high during the read - you need to change the data direction bit during the read so the slave device can pull the the data low when it needs to. In fact you should set the data bit low and then toggle the data direction bit for both reads and writes.
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
48,275
Helped
14,226
Reputation
28,713
Reaction score
12,920
Trophy points
1,393
Location
Bochum, Germany
Activity points
279,560
it appears that you are driving the data line high during the read
I don't think so. The code seems to be dedicated to 8051 standard IO. It has open drain ports with weak pullup, without any data direction register. There's no risk of driving SDA high with these interfaces.
 

kandhu26

Member level 5
Joined
Sep 7, 2009
Messages
93
Helped
13
Reputation
26
Reaction score
12
Trophy points
1,288
Location
chennai / bangalore
Activity points
1,856
FVM is correct... The code which i have put meant for 8051... In 8051 there is no data direction register [Not like AVR]...
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top