i2c-master.asm:
;#ASM###########################################################################################MCH#
; i2c-master.asm
; ``````````````
;
; I2C KOMUNIKACE TYPU MASTER
;
; 2.6.2018
;---------------------------------------------------------------------------------------------------
; ___|_ | |_____| | | _|________
; SDA: | \__|X|_____|X| ... |__/ |
; ___|___ | | _ | | | ___|________
; SCL: | \|_|_/ \_|_| ... |/ |
; start akcept ... stop uvolneno
;---------------------------------------------------------------------------------------------------
INCLUDE<P16F73.INC> ; definice konstant procesoru
GLOBAL r_I2C_STATUS, r_I2C_ADR_ZARIZENI
GLOBAL r_I2C_ADR_DAT_H, r_I2C_ADR_DAT_L, r_I2C_FSR_1.REG, r_I2C_POCET_BYTE
GLOBAL _I2C_EEPROM_ZAPIS, _I2C_EEPROM_CTENI
MEM_I2C_0 UDATA_SHR ; v bance 0
r_I2C_TMP RES 1 ; pomocny registr
r_I2C_STATUS RES 1 ; HLAVICKA - behem prenosu, NULOVY - po zdarnem ukonceni
r_I2C_ADR_ZARIZENI RES 1 ; 3 bitova <2~0> adresa ciloveho zarizeni napr. EEPROM
r_I2C_ADR_DAT_H RES 1 ; horni cast adresy dat napr. EEPROM
r_I2C_ADR_DAT_L RES 1 ; spodni cast adresy dat napr. EEPROM
r_I2C_FSR_1.REG RES 1 ; ukazatel na pocatecni datovy registr
r_I2C_POCET_BYTE RES 1 ; pocet byte k prenosu ! PREPISUJE SE !
#DEFINE I2C_PORT PORTC ; port pro SDA a SCL
#DEFINE b_I2C_TRIS_SCL I2C_PORT,3 ; TRIS - namapovany pin pro SCL (synchro)
#DEFINE b_I2C_PORT_SCL I2C_PORT,3 ; PORT - namapovany pin pro SCL (synchro)
#DEFINE b_I2C_TRIS_SDA I2C_PORT,4 ; TRIS - namapovany pin pro SDA (data)
#DEFINE b_I2C_PORT_SDA I2C_PORT,4 ; PORT - namapovany pin pro SDA (data)
I2C CODE
;###################################################################################################
; CTENI DAT Z I2C EEPROM PAMETI
;
; a) odeslani start bitu k zahajeni spojeni
; b) odeslani byte hlavicky s adresou EEPROM zarizeni dle (r_I2C_ADR_ZARIZENI) a atributem zapisu
; c) odeslani byte horni casti adresy dat v EEPROM (r_I2C_ADR_DAT_H)
; d) odeslani byte dolni casti adresy dat v EEPROM (r_I2C_ADR_DAT_L)
; e) odeslani start bitu k zahajeni spojeni
; f) odeslani byte hlavicky s adresou EEPROM zarizeni dle (r_I2C_ADR_ZARIZENI) a atributem cteni
; g) prijem dat z EEPROM do registru s sdresou v (r_I2C_FSR_1.REG) o poctu (r_I2C_POCET_BYTE)
; h) odeslani stop bitu k ukonceni spojeni
;
; Uspesny zapis je indikovan vynulovanym registrem (r_I2C_STATUS), pri neuspesnem obsahuje hlavicku
; Registr poctu byte ke cteni (r_I2C_POCET_BYTE) se prepisuje !
;---------------------------------------------------------------------------------------------------
_I2C_EEPROM_CTENI:
CALL _I2C_HLAVICKA ; sestaveni hlavicky
; _________________________________________________________
; ODESLANI 1 BYTE HLAVICKY: ADRESA ZARIZENI + ATRIBUT ZAPIS
CALL _I2C_START_BIT ; zahajeni spojeni, obsazeni sbernice
BCF STATUS,RP0 ; BANKA 0
MOVLW r_I2C_STATUS ; --.
MOVWF FSR ; <-' (r_I2C_STATUS) ulozena hlavicka
CALL _I2C_SDA_TX ; <-' odeslani hlavicky
DECFSZ r_I2C_TMP,f ; ?? PROBEHLO ODESLANI BYTE OK ??
GOTO _I2C_STOP_BIT ; 'NE' ukonceni spojeni, uvolneni sbernice
; ________________________________
; ODESLANI 1 BYTE HORNI ADRESY DAT
MOVLW r_I2C_ADR_DAT_H ; --.
MOVWF FSR ; <-' (r_I2C_ADR_DAT_H)
CALL _I2C_SDA_TX ; <-'
DECFSZ r_I2C_TMP,f ; ?? PROBEHLO ODESLANI BYTE OK ??
GOTO _I2C_STOP_BIT ; 'NE' ukonceni spojeni, uvolneni sbernice
; ________________________________
; ODESLANI 1 BYTE DOLNI ADRESY DAT
INCF FSR ; (r_I2C_ADR_DAT_L)
CALL _I2C_SDA_TX ; <-'
DECFSZ r_I2C_TMP,f ; ?? PROBEHLO ODESLANI BYTE OK ??
GOTO _I2C_STOP_BIT ; 'NE' ukonceni spojeni, uvolneni sbernice
; _________________________________________________________
; ODESLANI 1 BYTE HLAVICKY: ADRESA ZARIZENI + ATRIBUT CTENI
CALL _I2C_START_BIT ; zahajeni spojeni, obsazeni sbernice
MOVLW r_I2C_STATUS ; --.
MOVWF FSR ; <-' (r_I2C_STATUS) ulozena hlavicka
BSF INDF,0 ; nastavi pro cteni, bit:0
CALL _I2C_SDA_TX ; <-'
DECFSZ r_I2C_TMP,f ; ?? PROBEHLO ODESLANI BYTE OK ??
GOTO _I2C_STOP_BIT ; 'NE' ukonceni spojeni, uvolneni sbernice
; __________
; PRIJEM DAT
MOVF r_I2C_FSR_1.REG,w ; ukazatel na prvni datovy registr
MOVWF FSR ; <-'
_I2C_EEPROM_CTENI_SMYCKA:
CALL _I2C_SDA_RX ; nacteni 1 byte dat z EEPROM do registru dle FSR
INCF FSR,f ; ukazatel na nasledujici datovy registr
DECFSZ r_I2C_POCET_BYTE ; ?? PRENESEN PLNY POCET REGISTRU ??
GOTO _I2C_EEPROM_CTENI_SMYCKA ; 'NE'
CALL _I2C_STOP_BIT ; ukonceni spojeni, uvolneni sbernice
; ___________
; STATUS - OK
CLRF r_I2C_STATUS ; vynulovani statusu
RETURN
;###################################################################################################
; ZAPIS DAT DO I2C EEPROM PAMETI
;
; Data do EEPROM jdou prvne do jeho zasobniku a az ukoncenim spojeni STOP BITEM se trvale zapisi,
; po tuto dobu zapisu cca 4ms EEPROM nekomunikuje.
;
; a) odeslani start bitu k zahajeni spojeni
; b) odeslani byte hlavicky s adresou EEPROM zarizeni dle (r_I2C_ADR_ZARIZENI) a atributem zapisu
; c) odeslani byte horni casti adresy dat v EEPROM (r_I2C_ADR_DAT_H)
; d) odeslani byte dolni casti adresy dat v EEPROM (r_I2C_ADR_DAT_L)
; e) odeslani dat z registru s sdresou v (r_I2C_FSR_1.REG) a naslednych v poctu (r_I2C_POCET_BYTE)
; f) odeslani stop bitu k ukonceni spojeni a zahajeni cca 4ms interniho zapisu v EEPROM
;
; Uspesny zapis je indikovan vynulovanym registrem (r_I2C_STATUS), pri neuspesnem obsahuje hlavicku
; Registr poctu byte k zapisu (r_I2C_POCET_BYTE) se prepisuje !
;---------------------------------------------------------------------------------------------------
_I2C_EEPROM_ZAPIS:
CALL _I2C_HLAVICKA ; sestaveni hlavicky
; _________________________________________________________
; ODESLANI 1 BYTE HLAVICKY: ADRESA ZARIZENI + ATRIBUT ZAPIS
CALL _I2C_START_BIT ; zahajeni spojeni, obsazeni sbernice
MOVLW r_I2C_STATUS ; --.
MOVWF FSR ; <-' (r_I2C_STATUS) ulozena hlavicka
CALL _I2C_SDA_TX ; <-'
DECFSZ r_I2C_TMP,f ; ?? PROBEHLO ODESLANI BYTE OK ??
GOTO _I2C_STOP_BIT ; 'NE' ukonceni spojeni, uvolneni sbernice
; ________________________________
; ODESLANI 1 BYTE HORNI ADRESY DAT
MOVLW r_I2C_ADR_DAT_H ; --.
MOVWF FSR ; <-' (r_I2C_ADR_DAT_H)
CALL _I2C_SDA_TX ; <-'
DECFSZ r_I2C_TMP,f ; ?? PROBEHLO ODESLANI BYTE OK ??
GOTO _I2C_STOP_BIT ; 'NE' ukonceni spojeni, uvolneni sbernice
; ________________________________
; ODESLANI 1 BYTE DOLNI ADRESY DAT
INCF FSR ; (r_I2C_ADR_DAT_L)
CALL _I2C_SDA_TX ; <-'
DECFSZ r_I2C_TMP,f ; ?? PROBEHLO ODESLANI BYTE OK ??
GOTO _I2C_STOP_BIT ; 'NE' ukonceni spojeni, uvolneni sbernice
; ____________
; ODESLANI DAT
MOVF r_I2C_FSR_1.REG,w ; ukazatel na prvni datovy registr
MOVWF FSR ; <-'
_I2C_EEPROM_ZAPIS_SMYCKA:
CALL _I2C_SDA_TX ; zapis 1 byte dat z registru dle FSR do EEPROM
DECFSZ r_I2C_TMP,f ; ?? PROBEHLO ODESLANI BYTE OK ??
GOTO _I2C_STOP_BIT ; 'NE' ukonceni spojeni, uvolneni sbernice
INCF FSR,f ; ukazatel na nasledujici datovy registr
DECFSZ r_I2C_POCET_BYTE ; ?? PRENESEN PLNY POCET REGISTRU ??
GOTO _I2C_EEPROM_ZAPIS_SMYCKA ; 'NE'
CALL _I2C_STOP_BIT ; ukonceni spojeni, uvolneni sbernice
; ___________
; STATUS - OK
CLRF r_I2C_STATUS ; vynulovani statusu
RETURN
;###################################################################################################
; PRIJEM 1 BYTE DAT Z I2C DO (INDF)
;---------------------------------------------------------------------------------------------------
_I2C_SDA_RX:
; _________________________________________________________
; PRIJMUTI 8 BITU ZE SERIOVE LINKY SDA DO DATOVEHO REGISTRU
CLRF INDF
MOVLW 0x08
MOVWF r_I2C_TMP
_I2C_SDA_RX_SMYCKA:
CALL _I2C_PAUZA
CALL _I2C_SCL_UP ; SCL: -> 1, AKCEPTACE
CALL _I2C_PAUZA
BCF STATUS,C ; C: prednastaveni 0
BTFSC b_I2C_PORT_SDA ; ?? JE PRIJMUTY BIT Z SDA V 1 ??
BSF STATUS,C ; 'ANO' C: 1
RLF INDF ; bit:0 <- C posuvny registr
CALL _I2C_SCL_DOWN ; SCL: -> 0
DECFSZ r_I2C_TMP,f ; ?? BYLO PRENESENO 8 BITU ??
GOTO _I2C_SDA_RX_SMYCKA ; 'NE'
; _______________
; VYSLANI 9. BITU
DECF r_I2C_POCET_BYTE,w
BSF STATUS,RP0 ; BANKA 1
BTFSS STATUS,Z ; ?? JDE O POSLEDNI BYTE ??
BCF b_I2C_TRIS_SDA ; 'NE' SDA: -> 0
BCF STATUS,RP0 ; BANKA 0
BCF b_I2C_PORT_SDA ; SDA: -> 0
CALL _I2C_PAUZA
CALL _I2C_SCL_UP ; SCL: -> 1, AKCEPTACE
CALL _I2C_PAUZA
CALL _I2C_SCL_DOWN ; SCL: -> 0
BSF STATUS,RP0 ; BANKA 1
BSF b_I2C_TRIS_SDA ; SDA: -> 1, uvolneni datove linky
BCF STATUS,RP0 ; BANKA 0
CALL _I2C_PAUZA
RETURN
;###################################################################################################
; ODESLANI 1 BYTE DAT Z (INDF) DO I2C
;---------------------------------------------------------------------------------------------------
_I2C_SDA_TX:
; __________________________________________________________________
; ODESLANI 8 BIT DATOVEHO REGISTRU DO SERIOVE LINKY SDA ROTACI VLEVO
MOVLW 0x08
MOVWF r_I2C_TMP
_I2C_SDA_TX_SMYCKA:
BCF STATUS,C ; C: prednastaveni 0
BTFSC INDF,7 ; ?? JE 7 BIT DATOVEHO REGISTRU V 1 ??
BSF STATUS,C ; 'ANO' C: 1
RLF INDF,f ; C <- bit:7~0 <- C posuvny registr
;
BSF STATUS,RP0 ; BANKA 1
BTFSS STATUS,C ; ?? 0 ??
BCF b_I2C_TRIS_SDA ; SDA: -> 0
BTFSC STATUS,C ; ?? JE NACTENY BIT Z SDA V 1 ??
BSF b_I2C_TRIS_SDA ; 'ANO' SDA: -> 1
BCF STATUS,RP0 ; BANKA 0
BCF b_I2C_PORT_SDA ; SDA: -> 0
CALL _I2C_PAUZA
CALL _I2C_SCL_UP ; SCL: -> 1, AKCEPTACE
CALL _I2C_PAUZA
CALL _I2C_SCL_DOWN ; SCL: -> 0
DECFSZ r_I2C_TMP,f ; ?? BYLO PRENESENO 8 BITU ??
GOTO _I2C_SDA_TX_SMYCKA ; 'NE'
; _______________________________
; PRIJMUTI A KONTROLA 9. BITU ACK
BSF STATUS,RP0 ; BANKA 1
BSF b_I2C_TRIS_SDA ; SDA: -> 1, uvolneni datove linky
CALL _I2C_PAUZA
CALL _I2C_SCL_UP ; SCL: -> 1, AKCEPTACE
CALL _I2C_PAUZA
BTFSS b_I2C_PORT_SDA ; ?? PROBEHLO ODESLANI BYTE OK ??
INCF r_I2C_TMP,f ; 'NE' 0x01 ->(r_I2C_TMP)
CALL _I2C_SCL_DOWN ; SCL: -> 0
CALL _I2C_PAUZA
RETURN
;###################################################################################################
; SESTAVENI HLAVICKY K NAVAZANI KOMUNIKACE
;---------------------------------------------------------------------------------------------------
_I2C_HLAVICKA:
BCF STATUS,RP0 ; BANKA 0
RLF r_I2C_ADR_ZARIZENI,w ; nacteni adr zarizeni, posun o bit vlevo
ANDLW b'00001110' ; maska na 3 bitovou adresu zarizeni
IORLW b'10100000' ; pridani hlavicky pro zapis
MOVWF r_I2C_STATUS ; <-'
RETURN
;###################################################################################################
; ODESLANI START BITU PRO OBSAZENI SBERNICE A ZAHAJENI SPOJENI : PRI SCL V 1 PREJDE SDA Z 1 DO 0
;---------------------------------------------------------------------------------------------------
_I2C_START_BIT:
BSF STATUS,RP0 ; BANKA 1
BSF b_I2C_TRIS_SDA ; SDA: -> 1
CALL _I2C_PAUZA
BSF b_I2C_TRIS_SCL ; SCL: -> 1, AKCEPTACE
CALL _I2C_PAUZA
BCF b_I2C_TRIS_SDA ; SDA: -> 0
BCF STATUS,RP0 ; BANKA 0
BCF b_I2C_PORT_SDA ; SDA: -> 0
CALL _I2C_PAUZA
BSF STATUS,RP0 ; BANKA 1
BCF b_I2C_TRIS_SCL ; SCL: -> 0
BCF STATUS,RP0 ; BANKA 0
BCF b_I2C_PORT_SCL ; SCL: -> 0
CALL _I2C_PAUZA
RETURN
;###################################################################################################
; ODESLANI STOP BITU PRO UKONCENI SPOJENI A UVOLNENI SBERNICE : PRI SCL V 1 PREJDE SDA Z 0 DO 1
;---------------------------------------------------------------------------------------------------
_I2C_STOP_BIT:
BSF STATUS,RP0 ; BANKA 1
BCF b_I2C_TRIS_SCL ; SCL: -> 0
BCF STATUS,RP0 ; BANKA 0
BCF b_I2C_PORT_SCL ; SCL: -> 0
BSF STATUS,RP0 ; BANKA 1
BCF b_I2C_TRIS_SDA ; SDA: -> 0
BCF STATUS,RP0 ; BANKA 0
BCF b_I2C_PORT_SDA ; SDA: -> 0
CALL _I2C_PAUZA
BSF STATUS,RP0 ; BANKA 1
BSF b_I2C_TRIS_SCL ; SCL: -> 1, AKCEPTACE
CALL _I2C_PAUZA
BSF b_I2C_TRIS_SDA ; SDA: -> 1, uvolneni datove linky
CALL _I2C_PAUZA
BCF STATUS,RP0 ; BANKA 0
RETURN
;###################################################################################################
; SCL: 0 -> 1 PRECHOD AKCEPTACNI
;---------------------------------------------------------------------------------------------------
_I2C_SCL_UP:
BSF STATUS,RP0 ; BANKA 1
BSF b_I2C_TRIS_SCL ; SCL: 0 -> 1
BCF STATUS,RP0 ; BANKA 0
RETURN
;###################################################################################################
; SCL: 1 -> 0 PRECHOD NAVRATOVY
;---------------------------------------------------------------------------------------------------
_I2C_SCL_DOWN:
BSF STATUS,RP0 ; BANKA 1
BCF b_I2C_TRIS_SCL ; SCL: 1 -> 0
BCF STATUS,RP0 ; BANKA 0
BCF b_I2C_PORT_SCL ; SCL: -> 0
RETURN
;###################################################################################################
; PAUZA CELKEM 20 INSTRUKCNICH CYKLU, 20us PRI 4 MHz, 10us PRI 8 MHz, ...
;---------------------------------------------------------------------------------------------------
_I2C_PAUZA:
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
RETURN
;###################################################################################################
END