snažím se připojit paměť Atmel 24C16A k PIC 16F628A, abych do ní mohl ukládat nápisy na displej. Nefunguje mi ale I2C komunikace. Rutinu pro I2C jsem použil od tmm http://www.ebastlirna.cz/modules.php?na ... 686#222686 , ale něco dělám špatně.
Můžete se někdo na to kouknout a vysvětlit mi, kde dělám chybu.
PIC16F628, vnitřní osc 4,00MHz, 24C16A na RA1-0, pull-up odpory 10k na SDA a SCL. Snažím se pro začátek jen zapisovat a číst první byte v paměti.
Kód: Vybrat vše
; PIC16F628, vnitřní osc 4,00MHz, 24C16A na RA1-0, pull-up odpory 10k na SDA a SCL
;
;**************************************************************************
;* PIC16F628 *
;* --------\/-------- *
;* -|RA2 RA1|- SCL *
;* -|RA3 RA0|- SDA *
;* -|RA4ck osc1|- *
;* -|MCLR osc2|- *
;* 0V -|Vss Vdd|- +5V *
;* LCD RS -|RB0/INT PGD/RB7|- LCD data bit 7 *
;* -|RB1 PGC/RB6|- LCD data bit 6 *
;* -|RB2 RB5|- LCD data bit 5 *
;* LCD E -|RB3 RB4|- LCD data bit 4 *
;* ------------------ *
;* *
;**************************************************************************
list p=16f628A, R=DEC
include "p16f628A.inc"
org 0x2007 ; adresa konfigurace PIC16F627 a 628
dw _BODEN_OFF & _CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF & _MCLRE_OFF & _INTRC_OSC_NOCLKOUT
;- Proměnné ----------------------------------------------------
;
RAM equ 20h
TMP0 equ RAM+4 ; cekaci smycka
TMP1 equ RAM+5 ; cekaci smycka
TMP2 equ RAM+6 ; cekaci smycka
TMP3 equ RAM+7 ; cekaci smycka
ADRESA equ RAM+8 ; inicializace cestiny, adresa pro misto znaku
ZNAK equ RAM+9 ; zobrazeni znaku na LCD
EVAL equ 70h
EADR equ 71h ; Adresa v EEPROM při čtení
EBYTE equ 72h
rot equ 73h ; rotace bytu
EE_ADR equ 7Eh ; !!! 70h - 7Fh pro vsechny banky !!!
#define E PORTB,3 ; E - LCD displej
#define RS PORTB,0 ; RS - LCD displej
#define SDA PORTA,0 ; I2C data
#define SCL PORTA,1 ; I2C Hodiny
#define SDADIR TRISA,0
#define SCLDIR TRISA,1
;
;************************ Nastavení dat v EEPROM **************************
;
org 0x2100 ; tabulka v pameti EEPROM (128 bytu)
/// tady mám české znaky pro LCD
;
;---------------------------------------------------------------
;
org 0x0000 ; zacatek programu
goto INIT ; skok na počáteční inicalizaci
;
;- Nastavení V/V -----------------------------------------------
;
INIT movlw b'00000111' ; digitalni vstupy na PORTu A (PIC16F627 a 628)
movwf CMCON
bsf STATUS,RP0 ; přesun do banky 1
movlw b'00000011' ; RA7-2 výstupy RA1-0 vstup
movwf TRISA
movlw b'00000000' ; RB7-0 výstupy
movwf TRISB
bcf STATUS,RP0 ; přesun zpět do banky 0
movlw b'00000011'
movwf PORTA
movlw b'00000000'
movwf PORTB
call INI_LCD ; inicializace LCD
call CESTINA
clrf EVAL
;
;- Vlastní program ---------------------------------------------
HLAVNI call DISPLEJ1 ; zobrazení textu a znaku v registru EVAL - b'00000000'
call CEK2s
call @eeprom_read ; na zkoušku přečtu hodnotu v prázDné EEPROM
call DISPLEJ1 ; zobrazení textu a znaku v registru EVAL (FF)
call CEK2s
call @eeprom_write ; chci zapsat na 1. pozici - b'00100100' (na dipleji to je $)
call CEK100m
call @eeprom_read ; chci přečíst 1. pozici v paměti - b'00100100' (na dipleji to je $)
call DISPLEJ1 ; zobrazení textu a znaku v registru EVAL
call CEK2s
goto HLAVNI ; znovu, ikdyž bude v EVAL stále - b'00100100' (na dipleji to je $)
;**************************************************************************
; PODPROGRAM eeprom_read
; Přečte EEPROM na zadané adrese a hodnotu uloží do registru EVAL
;
; Vstupní registry:
; EADR - adresa
;
; Výstupní registry:
; EVAL - hodnota
;
; -------------------------------------------------------------
@eeprom_read
CALL @i2c_start
; Device Address
MOVLW B'10100000'
CALL @i2c_write
; Word Address
MOVLW H'00'
CALL @i2c_write
CALL @i2c_start
; Device Address
MOVLW B'10100001'
CALL @i2c_write
CALL @i2c_read
MOVF EBYTE,W
MOVWF EVAL
CALL @i2c_stop
RETURN
; -------------------------------------------------------------
; PODPROGRAM eeprom_write
; -------------------------------------------------------------
@eeprom_write
CALL @i2c_start
; Device Address
MOVLW B'10100000'
CALL @i2c_write
; Word Address
MOVLW H'00'
CALL @i2c_write
; Zápis dat do EEPROM
MOVLW b'00100100'
CALL @i2c_write
CALL @i2c_stop
RETURN
; -------------------------------------------------------------
; I2C
; -------------------------------------------------------------
@i2c_read
MOVLW 8
MOVWF rot ; Počet rotací
BSF STATUS,RP0
BSF SDADIR ; SDA vstup
BCF STATUS,RP0
i2c_read_rot
CALL @delay_10us ; Pauza cca 10us
BSF SCL ; SCL = 1
CALL @delay_10us ; Pauza cca 10us
BCF STATUS,C ; Vynulujeme C
BTFSC SDA ; Otestujeme SDA
BSF STATUS,C ; Pokud SDA == 1, nastavíme C
CALL @delay_10us ; Pauza cca 10us
BCF SCL ; SCL = 0
RLF EBYTE,1 ; Rotace EBYTE přes C doleva
DECFSZ rot,1
GOTO i2c_read_rot ; Cyklus
CALL @delay_10us ; Pauza cca 10us
BCF SDA ; SDA = 0
BSF STATUS,RP0
BCF SDADIR ; SDA výstup
BCF STATUS,RP0
RETURN
@i2c_send_ack
BCF SDA ; SDA = 0
CALL @delay_10us ; Pauza cca 10us
BSF SCL ; SCL = 1
CALL @delay_10us ; Pauza cca 10us
BCF SCL ; SCL = 0
RETURN
@i2c_write
MOVWF EBYTE ; W do EBYTE
MOVLW 8
MOVWF rot ; Počet rotací
i2c_write_rot
RLF EBYTE,1 ; Rotace EBYTE o 1 bit doleva přes C
BTFSS STATUS,C ; Otestujeme C a nastavíme SDA
GOTO $+3
BSF SDA ; SDA = 1
GOTO $+2
BCF SDA ; SDA = 0
CALL @delay_10us ; Pauza cca 10us
BSF SCL ; SCL = 1
CALL @delay_10us ; Pauza cca 10us
BCF SCL ; SCL = 0;
DECFSZ rot,1
GOTO i2c_write_rot ; Cyklus
CALL @delay_10us ; Pauza cca 10us
CALL @i2c_ack ; ACK
RETURN
@i2c_start
BSF SDA ; SDA = 1
BSF STATUS,RP0
BCF SDADIR ; SDA výstup
BCF STATUS,RP0
BSF SCL ; SCL = 1
CALL @delay_10us ; Pauza cca 10us
BCF SDA ; SDA = 0
CALL @delay_10us ; Pauza cca 10us
BCF SCL ; SCL = 0
RETURN
@i2c_stop
CALL @delay_10us ; Pauza cca 10us
BCF SDA ; SDA = 0
CALL @delay_10us ; Pauza cca 10us
BSF SCL ; SCL = 1
CALL @delay_10us ; Pauza cca 10us
BSF SDA ; SDA = 1
BSF STATUS,RP0
BCF SDADIR ; SDA vstup
BCF STATUS,RP0
RETURN
@i2c_ack
BSF STATUS,RP0
BSF SDADIR ; SDA vstup
BCF STATUS,RP0
CALL @delay_10us ; Pauza cca 10us
BSF SCL ; SCL = 1
CALL @delay_10us ; Pauza cca 10us
BTFSC SDA
GOTO $-1
CALL @delay_10us ; Pauza cca 10us
BCF SCL ; SCL = 0
CALL @delay_10us ; Pauza cca 10us
BCF SDA
BSF STATUS,RP0
BCF SDADIR ; SDA výstup
BCF STATUS,RP0
RETURN
@delay_10us
GOTO $+1
GOTO $+1
RETURN
;**************************************************************************
;**************************************************************************
; čtení z EEPROM v PIC
/// čtu české znaky
;**************************************************************************
; obsluha LCD
/// rutiny pro LCD
;**************************************************************************
/// čekací smyčky
;**************************************************************************
END ;konec programu