You are on page 1of 2

; ***************************************************************

; This collection of routines allows an 80x51 microcontroller


; to read and write the I2C devices
; FOSC = 24MHz.
; ***************************************************************
_R EQU 0
SDA EQU P3.1
SCL EQU P3.7

RSEG RCODE

PUBLIC I2C_Start
; void I2C_Start (void);
; Send START, defined as high-to-low SDA with SCL high
; Input: None
; Output: None
; Registers destroyed: A, PSW, R1
I2C_Start:
setb SDA
mov A, #5 ; wait Tr + Tsu:dat, prevent "STOP"
mov R1, #7
setb SCL ; release bus
djnz R1, $ ; wait Tr + Tsu:sta (> 5.7us)
clr SDA ; high-to-low SDA with SCL high
mov R1, A
djnz R1, $ ; wait Tf + Thd:sta (> 4.3us)
clr SCL ; SCL low, enable data change
djnz ACC, $ ; wait Tf + Tlow (> 5us)
ret

PUBLIC I2C_Stop
; void I2C_Stop (void);
; Send STOP, defined as low-to-high SDA with SCL high
; Input: None
; Output: None
; Registers destroyed: R1
; SCL expected low on entry. Return with SCL, SDA high
I2C_Stop:
clr SDA
nop ; wait Tf + Tsu:dat, prevent "START"
mov R1, #7
setb SCL ; prepare for "STOP"
djnz R1, $ ; wait Tr + Tsu:sto (> 5.7us)
setb SDA ; low-to-high SDA with SCL high
ret
PUBLIC I2C_OUTB
; bit I2C_OUTB (data BYTE b);
; Shift out a byte to the device, most significant bit first.
; Read ACK or NAK from the device.
; Input: R4 - Byte to be shifted out
; Output: Carry flag - Clear if there is not acknowledge
; Registers destroyed: A, PSW, R1, R4
; SCL expected low on entry. Return with SCL low
I2C_OUTB:
setb C ; CY = 1, get ACK bit
mov A, R4 ; byte to be shifted in A
sjmp I2C_Shift

PUBLIC I2C_INB
; BYTE I2C_INB (data BYTE SendACK);
; Shift in a byte from the device, most significant bit first.
; Send ACK or NAK to the device.
; Input: R4 - 0 - Send NAK to device
; else - Send ACK to device
; Output: R4 - Received data byte from device
; Registers destroyed: A, PSW, R1
; SCL expected low on entry. Return with SCL low
I2C_INB:
mov A, R4
add A, #0FFh ; move ACK bit into CY
cpl C
mov A, #0FFh ; SDA high
I2C_Shift:
mov R1, #9 ; bit counter, 8 bits + ACK
L_Next_Bit:
rlc A ; move bit7 into CY
mov SDA, C ; output bit
mov R4, #2
djnz R4, $ ; wait Tr + Tsu:dat + more (3us)
setb SCL ; raise clock
mov R4, #4
djnz R4, $ ; wait Tr + Thigh (5us)
mov C, SDA ; input bit
clr SCL ; drop clock
djnz R1, L_Next_Bit ; now wait Tf + Tlow (> 5us)
cpl C ; ACK bit
mov R4, A
ret

END

You might also like