What is I2C bus?
I2C is a serial two wire bus used in microcontrollers systems to
communication with devices such as EEPROM memories, digital
potentiometers, LCD controllers, RTCs and other. I2C bus uses only
two bidirectional open-drain lines : Serial Data (SDA) and Serial
Clock (SCL). This lines are pulled up with resistors (usually
4,7kOhms). For more details about I2C bus see : I2C on Wikipedia
Basics of I2C bus
Generally, SDA state can change only if SCL is low. When SCL is
high SDA state can NOT change, except START and STOP signals. See
below picture:
START signal
Start signal begins all transmission via I2C bus. Start
condition occurs when SDA line goes low (falling edge) when SCL line
is high. See below picture:
;-----------------------------------------------------------------
; START routine
;-----------------------------------------------------------------
.i2c_start
BRES I2C_DIR, #SDA ; set SDA
BRES I2C_DIR, #SCL ; set SCL
BSET I2C_DIR, #SDA ; falling
edge on SDA
CALL i2c_delay
; wait some microseconds
BSET I2C_DIR, #SCL ; reset SCL
RET |
STOP signal
Stop signal ends all transmission via I2C bus. Stop condition
occurs when SDA line goes high (rising edge) when SCL line is high.
See below picture:
;-----------------------------------------------------------------
; STOP routine
;-----------------------------------------------------------------
.i2c_stop
BRES I2C_DIR, #SCL ; set SCL
CALL i2c_delay
; wait some microseconds
BRES I2C_DIR, #SDA ; rising
edge on SDA
RET |
Master sends byte to slave device
Master generate SCL signal, write eight data bits, from MSB to
LSB and read an ACK from Slave device.
;-----------------------------------------------------------------
; Write byte to I2C bus
; ACK bit is return in C flag
; Byte to send must be into A register before call this
routine
;-----------------------------------------------------------------
.i2c_write
PUSH A
LD i2c_data, A
; store A into i2c_data
LD A, #8
;
LD i2c_counter, A ;
loop counter
i2cw1
BSET I2C_DIR, #SCL ;
BSET I2C_DIR, #SDA ;
LD A, i2c_data
; restore data
RLC A
; rotate left through C flag
LD i2c_data, A
; store data
JRNC i2cw2
; branch if not carry
BRES I2C_DIR, #SDA ; else
SDA go high
i2cw2
BRES I2C_DIR, #SCL ; set
SCL
DEC i2c_counter
; decrease loop counter
JRNE i2cw1
; jump if greater than 0
BSET I2C_DIR, #SCL ;
clear SCL
BRES I2C_DIR, #SDA ;
set SDA
BRES I2C_DIR, #SCL ; set
SCL
BTJT I2C_DAT, #SDA, i2cw3 ; copy SDA into C (read ACK bit)
i2cw3
BSET I2C_DIR, #SDA ;
clear SDA
BSET I2C_DIR, #SCL ;
clear SCL
POP A
RET |
Master receives byte from slave device
Master generate SCL signal, read eight data bits from slave
device and send ACK bit to slave device.
;----------------------------------------------------------------
; Read byte from I2C bus
; ACK bit must be written into C flag before call this
routine
; Read byte is return in A register
;-----------------------------------------------------------------
.i2c_read
RLC A
; store C flag
LD i2c_data, A
;
LD A,#8
;
LD i2c_counter, A ; loop
counter
BRES I2C_DIR, #SDA ; set SDA
i2cr1
CALL i2c_delay
; wait some microseconds
BRES I2C_DIR, #SCL ; set SCL
BTJT I2C_DAT, #SDA, i2cr2 ; copy SDA into C (read data bit)
i2cr2
LD A, i2c_data
; restore data
RLC A
; store new bit
LD i2c_data, A
; store data
BSET I2C_DIR, #SCL ; clear SCL
DEC i2c_counter
; decrease loop counter
JRNE i2cr1
; jump, if greater than zero
BSET I2C_DIR, #SDA ; clear SDA
JRNC i2cr3
; jump, if C flag (ACK bit) is clear
BRES I2C_DIR, #SDA ; set SDA
i2cr3
BRES I2C_DIR, #SCL ; set SCL
BSET I2C_DIR, #SCL ; clear SCL
BSET I2C_DIR, #SDA ; clear SDA
LD A, i2c_data
; move read byte to A register
RET |
Download
Source file for ST7FLITE19 MCU :
File i2c.asm
|