en.radzio.dxp.pl

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:

st7-mcu

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:

st7-mcu

Source code of i2c_start routine
;-----------------------------------------------------------------
; 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:

st7-mcu

Source code of i2c_stop routine
;-----------------------------------------------------------------
; 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.

st7-mcu

Source code of i2c_write routine

;-----------------------------------------------------------------
; 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.

st7-mcu

Source code of i2c_read routine

;----------------------------------------------------------------
; 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

 

 
(c) Radosław Kwiecień