Newsgroup: it.hobby.elettronica.digitale
Titolo: I2c Eeprom e 16f84a

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:
http://www.microchip.com/1010/suppdoc/appnote/all/an567/index.htm
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-------------------

 collegato così i due integrati:
[CUT]
Ho risolto... l'errore era nella procedura di stop, ci entravo con SDA
ancora settato come ingresso....
Nick