Ciao a tutti, sto provando ad interfacciare una eeprom 24C02B con un PIC16f84A, cercando di implementare il protocollo I2C in ASM. Ho guardato questo documento di microchip:
e ho basato il mio codice su di esso, cambiando un pochino di cose, per adattarlo al codice che avevo già iniziato a scrivere. Io devo scrivere un unico byte, prefissato, all'indirizzo 0 dell'eeprom. Ho collegato così i due integrati:
PIC: RB0 --> SDA, Linea dati EEPROM (con resistore di pull up da 10k) PIC: RB1 --> SCL, Clock EEPROM
Poi ho messo due led, uno verde ed uno rosso, per "debug": PIC: RB3 --> led verde = TUTTO ok PIC: RB4 --> led ROSSO = errore (non ho ricevuto l'ack sostanzialmente...)
Ora... quando alimento il circuito, ottengo come risultato che il programma arriva alla fine correttamente, ed il led verde (che indica appunto l'arrivo della fine del programma), si accende. Vado a leggere l'eeprom sul PC con il multipippo ma.. nulla è stato scritto... Il led rosso, che indicherebbe la non corretta ricezione del ack e la terminazione immediata del programma, non si accende, e ho verificato che l'ack viene ricevuto correttamente... provo a postare il codice, anche se è un po lungo... spero qualcuno mi possa aiutare lo stesso! Sono un principiante, quindi non "spaventavi" per il codice... ho cercato di mettere qualche commento per rendere le cose un po' più chiare.
Grazie! Nick
;-----------------BOF---------------------
PROCESSOR 16F84 RADIX DEC INCLUDE "P16F84.INC" ERRORLEVEL -302
;Setup of PIC configuration flags ;XT oscillator ;Disable watch dog timer ;Enable power up timer ;Disable code protect ;
__CONFIG 0x3FF1
SDA EQU 0 ;RB0 = SDA linea DATI SCL EQU 1 ;RB1 = sCL linea CLOCK LEDr EQU 4 ;led rosso errore = RB4 LEDv EQU 3 ; led verde: tutto ok = RB3
ORG 0X0C
DATABYTE RES 1 ; memorizzo byte da spedire COUNTER RES 1 ; contatore per la spedizone di 8 bit BUFF RES 1 ; buffer di output temporaneo INBUFF RES 1 ; buffer di input temporaneo
ORG 0X00
bsf STATUS, RP0 ;Setto RB0, RB1, RB3 e RB4 come uscite movlw B'11100100' movwf TRISB bCf STATUS,RP0
MainLoop
Call START ;Procedura di Start I2C movlw B'10100000' ; carico stringa di init scrittura movwf DATABYTE call tx ; trasmetto la stringa di inizializzazione
movlw B'0000000' ; carico indirizzo di prova movwf DATABYTE call tx ; trasmetto indirizzo dove scrivere
movlw B'10101010'; carico byte di prova da spedire movwf DATABYTE call tx Call stop
goto OK ; se tutto fila liscio si accende il led verde
START bsf PORTB,SDA ; data alta nop nop bcf PORTB,SCL ;ck basso nop ; bsf PORTB,SCL ;CK alto nop nop nop nop nop
bcf PORTB,SDA ; Ecco che inizia lo start... SCL=1, porto giù SDA nop nop nop nop nop
bcf PORTB,SCL ; Ck basso nop nop return
STOP
bcf PORTB, SDA ; SDA basso... condizione iniziale
nop nop nop ;Quanti NOP a 4 MHZ? da calcolare.... bsf PORTB,SCL ;CK alto
nop nop nop ; ma non sarebbe meglio una wait? Direi di si...
bsf PORTB, SDA ; Ecco che inizia lo stop... SCL=1, porto su SDA nop nop
bcf PORTB, SCL; nop nop nop
return
BITOUT movlw b'11100100' ; set data,clock as outputs tris portb btfss buff,7; Confronto sempre il bit più significativo goto bitlow ; bsf portb,sda ; set data line high goto clkout ; go toggle the clock
bitlow bcf portb,sda ; output a low bit
clkout bsf portb,scl ; set clock line high nop nop nop nop bcf portb,scl ; return clock line low return
BITIN bsf inbuff,0 ; assume input bit is high movlw b'11100101' ; make sdata an input line tris portb bsf portb,sda ; set sdata line for input bsf portb,scl ; set clock line high nop nop nop btfss portb,sda ; read the data bit bcf inbuff,0; input bit was low bcf portb,scl ; set clock line low return
TX ; trasmissione di un byte contenuto in databyte movlw .8 movwf counter ; set the #bits to 8
TXLP bcf buff,7 ; assume bit out is low btfsc databyte,7 ; is bit out really low? bsf buff, 7 ; otherwise data bit =1 call BITOUT ; serial data out rlf databyte,f ; rotate txbuf left decfsz counter,f ; 8 bits done? goto TXLP ;no - go again call BITIN ; read ack bit btfsc INBUFF,0 ; check ack bit
goto fine; se l'ack è a 1 allora errore: finisco e accendo il led rosso
return ; altrimenti ritorno e tutto ok!
Fine bsf PORTB, LEDr ; FINE con ERRORE, led rosso acceso goto fine;
OK bsf PORTB, LEDv ; Fine .. TUTTO ok led verde acceso. goto ok;
;---EOF-------------------