| ??? 04/04/07 15:37 Read: times |
#136607 - Working code... Responding to: ???'s previous message |
Hello Asif,
Here is a piece of working code which was used along with C, hope it solves your problem.This was used with an AT89C51 and AT24C04. If I can recall correctly, I put this together from Philips and Atmel application notes. You can you use the assembler portion alone with modificaton.
$NOMOD51
$INCLUDE (REG515.INC)
NAME I2C ;name of the program module
;FILE NAME - I2C.A51
;-----------------------------------------------------------------------------
; THIS MODULE CONTAINS THE I2C DRIVER ROUTINES
; 27/08/98,07/12/98
;-----------------------------------------------------------------------------
?PR?ReadWriteI2c?I2C SEGMENT CODE ;segment for program code
?DT?ReadWriteI2c?I2C SEGMENT DATA OVERLAYABLE ;segment for local variables
?BI?ReadWriteI2c?I2C SEGMENT BIT OVERLAYABLE ;segment for local bit var
PUBLIC _ReadWriteI2c ;public symbols
PUBLIC ?_ReadWriteI2c?BYTE ;for 'C'
PUBLIC ?_ReadWriteI2c?BIT ;function calls
RSEG ?DT?ReadWriteI2c?I2C ;segment for local variables
?_ReadWriteI2c?BYTE: ;start of parameter passing
;segment
i2c_slave_address: ds 1
i2c_register_address: ds 1
write_i2c_data: ds 1
RSEG ?BI?ReadWriteI2c?I2C ;segment for local bit var
?_ReadWriteI2c?BIT: ;start of parameter passing
;segment
read_write_flag: dbit 1
;----------------------------------------------------------------------------
; I2C PORT PIN DEFINITIONS
;----------------------------------------------------------------------------
SDA EQU P3.6
SCL EQU P3.7
RSEG ?PR?ReadWriteI2c?I2C
USING 0
_ReadWriteI2c:
;----------------------------------------------------------------------------
; 08/12/98
; CHECK WHETHER READ OR WRITE
; IF CY = 1 THEN IT IS READ, IF CY = 0 THEN IT IS WRITE
;----------------------------------------------------------------------------
JB CY, READ_I2C_REGISTER
JMP WRITE_I2C_REGISTER
;----------------------------------------------------------------------------
; LOW LEVEL I2C MACROS
;----------------------------------------------------------------------------
SET_SCL MACRO
SETB SCL
JNB SCL,$
BIT_DELAY
ENDM
CLEAR_SCL MACRO
CLR SCL
BIT_DELAY
ENDM
EMIT_CLOCK MACRO
SET_SCL
CLEAR_SCL
ENDM
START MACRO
SETB SDA
SET_SCL
CLR SDA
BIT_DELAY
CLEAR_SCL
ENDM
STOP MACRO
CLR SDA
SET_SCL
SETB SDA
BIT_DELAY
ENDM
BIT_DELAY MACRO
NOP
NOP
;NOP ;04/02/2003 for 24Mhz
ENDM
;----------------------------------------------------------------------------
; I2C SUBROUTINES
;----------------------------------------------------------------------------
XMIT_BYTE:
;ACC CONTAINS BYTE TO TRANSMIT
;CY= 0 IF SEQUENCE COMPLETES
;CY= 1 IF UNABLE TO TRANSMIT
MOV R1,#8 ;8 BITS TO SEND
XB1:
RLC A
MOV SDA, C ;PUT BIT ON PIN
EMIT_CLOCK ;EMIT CLOCK PULSE
DJNZ R1,XB1 ;LOOP UNTIL DONE
;SETUP TO ACK FROM SLAVE DEVICE
SETB SDA ;RELEASE DATA PIN
SET_SCL ;SCL HIGH
JNB SDA,XB2 ;JUMP IF ACK SEEN
CLEAR_SCL ;DROP SCL
SETB C ;SET ERROR CODE
RET
XB2:
CLEAR_SCL ;DROP SCL
CLR C ;SET COMPLETION CODE
RET
;----------------------------------------------------------------------------
REC_BYTE:
;RECEIVE A BYTE OVER THE I2C BUS
;ACC CONTAINS RECEIVED BYTE
;CY IS DUMMIED UP WITH A 0
MOV R1,#8 ;8 BITS TO RECEIVE
RB1:
SET_SCL ;SCL HIGH
MOV C,SDA ;PICK BIT OFF A PIN
RLC A
CLEAR_SCL ;SCL LOW
DJNZ R1,RB1 ;MORE BITS TO RECEIVE?
CLR C ;MUST COMPLETE OK
RET
;----------------------------------------------------------------------------
; TRANMIT ADDRESS AND DATA REGISTERED BYTE OVER I2C BUS
; R7 CONTAINS SLAVE ADDRESS
; R5 CONTAINS REGISTER ADDRESS
; R3 CONTAINS DATA BYTE
; CY = 0 IF SEQUENCE COMPLETES
; CY = 1 IF UNABLE TO TRANSMIT
;----------------------------------------------------------------------------
XD_FAULT: ;BUS FAULTL
SETB C ;SET ERROR CODE
RET
WRITE_I2C_REGISTER:
JNB SCL,XD_FAULT
JNB SDA,XD_FAULT ;JUMP IF BUS FAULT
MOV A,R7 ;SETUP SLAVE ADDRESS
CLR ACC.0 ;INDICATE WRITE OPERATION
START ;SET START CONDITION
ACALL XMIT_BYTE ;SEND SLAVE ADDRESS
JC XD2 ;JUMP ON ERROR
MOV A,R5 ;SETUP REGISTER ADDRESS
ACALL XMIT_BYTE ;SEND REGISTER ADDRESS
JC XD2 ;JUMP ON ERROR
MOV A,R3 ;SETUP DATA BYTE
ACALL XMIT_BYTE ;GO SEND
; SET STOP CONDITION, RETURN CODE IS ALREADY IN CY
XD2:
STOP ;SET STOP CONDITION
RET
;----------------------------------------------------------------------------
; TRANSMIT ADDRESS AND RECEIVE REGISTERED DATA BYTE OVER I2C BUS
; R7 CONTAINS SLAVE ADDRESS
; R5 CONTAINS REGISTER ADDRESS
; CY = 0 IF SEQUENCE COMPLETES
; CY = 1 IF UNABLE TO RECEIVE
; R3 CONTAINS RECEIVED BYTE IF CY = 0
;----------------------------------------------------------------------------
RD_FAULT:
SETB C ;SET ERROR CONDITION
RET
READ_I2C_REGISTER:
JNB SCL,RD_FAULT
JNB SDA,RD_FAULT ;JUMP IF BUS FAULT
MOV A,R7 ;SETUP SLAVE ADDRESS
CLR ACC.0 ;INDICATE READ OPERATION
START
PUSH ACC
ACALL XMIT_BYTE ;SEND SLAVE ADDRESS
POP ACC
JC RD3 ;JUMP ON ERROR
XCH A,R5 ;SET UP REGISTER ADDRESS
ACALL XMIT_BYTE ;SEND REGISTER ADDRESS
JC RD3 ;JUMP ON ERROR
START ;SET REPEATED START
MOV A,R7 ;SETUP SLAVE ADDRESS
SETB ACC.0 ;INDICATE READ OPERATION
ACALL XMIT_BYTE ;SEND SLAVE ADDRESS AGAIN
JC RD3 ;JUMP ON ERROR
RD1:
ACALL REC_BYTE ;GO RECEIVE
MOV R7,A ;STORE DATE BYTE
;SEQUENCE COMPLETE, RETURN CODE IS ALREADY IN CY
RD2:
SETB SDA ;SET SDA IDLE
EMIT_CLOCK ;EMIT CLOCK PULSE
RD3:
STOP ;SET STOP CONDITION
RET
END
John. |



