Autor Tema: Ejemplo de utilizacion del Modulo I2C del 16F877a  (Leído 42729 veces)

0 Usuarios y 3 Visitantes están viendo este tema.

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re: Ejemplo de utilizacion del Modulo I2C del 16F877a
« Respuesta #30 en: 22 de Mayo de 2008, 10:28:56 »
vaya que si tenias razon,tres semanas liao por falta de tiempo.ahora seguire en el otro hilo que abri,para no saturar este.

intentare simplificarlo un poco,y poner algunas lineas de ayuda.de esta forma me ayudara a comprender mejor el I2C.y que a los demas tambien les
cueste menos su interpretacion.

saludos.

Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado pibe

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 635
Re: Ejemplo de utilizacion del Modulo I2C del 16F877a
« Respuesta #31 en: 18 de Diciembre de 2008, 12:06:14 »
Hola gente:

He ensamblado el programa y todo ok.

Ahora el problema es que aún no tengo la 24lc256 fisicamente y me he puesto a simularlo en el PROTEUS, pero  me da error.
Le he incluido unas lineas de más para saber si el error era de escritura  o lectura y para que haga un loop escribiendo y leyendo en bucle cada 1 segundo.
Lo he puesto a 20mhz, .11 en para 400khz en registro , incluso lo he modificado para 100khz pero es peor.
Me da errores erráticos, a veces de escritura (PORTA,1), a veces OK (PORTA,0) , y a veces de lectura (PORTA,2) .

Se debe esto al simulador del proteus? O hay algo que falla en el programa? Le he puesto las resistencias correspondientes de 4k7 a las lineas SDA , SCL y el WP a masa junto con los A0-A2.


Aqui os dejo el programa , a ver si veis algo anormal.

  LIST      P=16F877A
      #include   "p16F877A.INC"
         __CONFIG    _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF ;&_WRT_ENABLE_OFF   
      ERRORLEVEL   -302

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
; CONSTANTES:
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define      CLOCK         D'0'
#define      STROBE         D'2'
#define      SCL         D'3'
#define      SDA         D'4'
#define       OK         D'0'

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;Memoria EEPROM
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
; MACROS
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

BANK0      MACRO
      BCF   STATUS,RP0
      BCF   STATUS,RP1
      ENDM

BANK1      MACRO
      BSF   STATUS,RP0
      BCF   STATUS,RP1
      ENDM

BANK2      MACRO
      BSF   STATUS,RP1
      BCF   STATUS,RP0
      ENDM

BANK3      MACRO
      BSF   STATUS,RP1
      BSF   STATUS,RP0
      ENDM

;GPR: GENERAL PURPOSE REGISTERS

;0x20 -> 0x47 Reservados Memoria cartel.

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DIRL      EQU   0X20
DIRH      EQU   0X21   
DATO      EQU   0X22   ;temporar. byte a enviar/dato leido
flag      EQU   0X24
cuenta      EQU   0X25
CONTA0      EQU   0X26
CONTA1      EQU   0X27
 PDel0 equ 0x28; (registro)
 PDel1 equ 0x29 ;(registro)
PDel2 equ 0x2A; (registro)
DATASSP      EQU      0x70

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



      ORG   0X0000
      GOTO   INICIO

      ORG   0X0004
      return

      ORG   0X0020

INICIO      BANK0
      BSF   STATUS,RP0
      MOVLW   0x06       ;PINS DEL PUERTO A Y PUERTO E TODOS DIGITALES.
      MOVWF   ADCON1
      CLRW
      MOVWF TRISA

      BANK0
      CLRF   PORTA
      BSF      STATUS,RP0
      MOVLW   0X00
      MOVWF   TRISB

      BANK0
      CLRF   PORTB
      BSF      STATUS,RP0
      MOVLW   B'00011000'
      MOVWF   TRISC
   
      BANK0
      MOVLW   B'00010000'
      MOVWF   PORTC
      BSF   STATUS,RP0
      MOVLW   0X00
      MOVWF   TRISD

      BANK0
      CLRF   PORTD
      BSF      STATUS,RP0
      MOVLW   0X00
      MOVWF   TRISE
   
      BANK0
      CLRF   PORTE
      call   i2c_init   ;configurar y encender I2C


ini

CLRF PORTB
CLRF PORTA
call DEMORA1s
      clrf   DIRH      ;cargar paginas de 24LC08B en las cuales escribir
      clrf   DIRL      ;cargar direccion de 24LC08B en las cuales escribir     
      movlw   0x55
      movwf   DATASSP      ;cargar dato a escribir en la 24LC08B
      call   WriteI2CByte
      btfss   flag,0
      goto   errorescr

      call   DEMORA      ;dar 10ms a que termine la escritura
call   DEMORA      ;dar 10ms a que termine la escritura
      clrf   DIRH      ;cargar paginas de 24LC08B de las cuales leer
      clrf   DIRL      ;cargar direccion de 24LC08B de las cuales leer
      call   ReadI2CByte
      btfss   flag,0
      goto   errorlect

           
;escritura y lectura OK. encender RA0, mostrar dato leido en PuertoB y loop eterno
      bsf  PORTA,0
      movf   DATO,w
      movwf   PORTB
      call DEMORA1s
      goto   ini

errorescr   bsf PORTA,1
      call DEMORA1s
      goto   ini

errorlect   bsf PORTA,2
      call DEMORA1s
      goto   ini


;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DEMORA
   movlw   .55
   movwf   CONTA0
RET1
   movlw   .181
   movwf   CONTA1
RET2
   nop
   nop
   decfsz   CONTA1,1
   goto   RET2
   decfsz   CONTA0,1
   goto   RET1
   return


;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_init

   movlw       b'00011000'
   banksel       TRISC         ;banco 1
   iorwf       TRISC,F
   movlw      .11; b'00001011'      ;.9 para 100khz a 4mhz , .11 para 400khz @ 20 mhz
   movwf       SSPADD         ;
   clrf       SSPSTAT
   movlw      b'00101000'
   bcf      STATUS,RP0      ;banco 0
   movwf       SSPCON
   CLRF      PIR1
   call      i2c_idle
   return


;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_idle

   bsf      STATUS,RP0      ;banco 1
   btfsc       SSPSTAT,R_W
   goto       $-1

   movf       SSPCON2,w
   andlw       0x1F
   btfss       STATUS,Z
   goto       $-3

   bcf      STATUS,RP0      ;banco 0
   return

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_start
   call      i2c_idle
   bsf      STATUS,RP0      ;banco 1
   bsf       SSPCON2,SEN
   btfsc       SSPCON2,SEN
   goto       $-1

   bcf      STATUS,RP0      ;banco 0
   btfss      PIR1,SSPIF
   goto      $-1

   bcf      PIR1,SSPIF
   return

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_restart

   bsf      STATUS,RP0      ;banco 1
   bsf       SSPCON2,RSEN
   btfsc       SSPCON2,RSEN
   goto       $-1

   bcf      STATUS,RP0      ;banco 0
   return

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_read

   call      i2c_idle   
   bsf      STATUS,RP0      ;banco 1   
   bsf       SSPCON2,RCEN      ;activar modo lectura
   btfsc       SSPCON2,RCEN      ;termino la recepcion?
   goto       $-1         ;no, esperar

   btfss      SSPSTAT,BF      ;dato disponible en SSPBUF para ser leidos?
   goto      $-1         ;no, esperar

   bcf      STATUS,RP0      ;banco 0
   movf      SSPBUF,W
   movwf      DATO
   return

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_write

   bcf      flag,0         ;inicializar flag como "error"
   call      i2c_idle
   movf      DATO,w         ;mover DATO a W
   movwf       SSPBUF         ;cargar dato en buffer I2C
   bsf      STATUS,RP0      ;banco 1
   btfsc       SSPSTAT,R_W      ;esperar a que termine el envio
   goto       $-1

   btfss      SSPCON2,ACKSTAT    ;checkear ack
   goto      okack
   bsf       SSPCON2,PEN      ;error ack. enviar STOP
   bcf      STATUS,RP0      ;banco 0
   return               ;volver con flag= 0 error

okack

  bcf      STATUS,RP0      ;banco 0
   btfss      PIR1,SSPIF      ;esperar finalizacion del noveno clock
   goto      $-1
   bcf      PIR1,SSPIF
   bsf      flag,0         ;volver con flag = 1 OK!
   return
   
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_sendack

   bsf      STATUS,RP0      ;banco 1
   bcf       SSPCON2,ACKDT
   bsf       SSPCON2,ACKEN
   bcf      STATUS,RP0      ;banco 0
   return

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_sendnack

   bsf      STATUS,RP0      ;banco 1
   bsf       SSPCON2,ACKDT
   bsf       SSPCON2,ACKEN
   bcf      STATUS,RP0      ;banco 0
   return

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_stop
   bsf      STATUS,RP0      ;banco 1
   bsf       SSPCON2,PEN      ;enviar STOP
   bcf      STATUS,RP0      ;banco 0
   return


;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;WriteI2CByte
;DIRH<1:0>                  ;paginas de la eeprom en las cuales grabar
;DIRL                     ;direccion baja de la posicion de eeprom en las cuales grabar
;DATASSP                  ;dato a grabar
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

WriteI2CByte
bsf PORTC,0
   call      i2c_start      ;enviar START, esperar a que se libere el BUS
   movlw      b'10100000'      ;"1010"= identificador EEPROM. "000" = numero EEPROM "0"= Write
   movwf      DATO


   call      i2c_write
   btfss      flag,OK   ;;volver. error de escritura
   return
bcf PORTC,0
   movf      DIRH,W
   andlw      b'01111111'      ;solo 7 bits de paginas admitidas para esta eeprom.
   movwf      DATO         ;cargar byte en variable a enviar(DATO)
   call      i2c_write
   btfss      flag,OK
   return                  ;volver. error de escritura

   movf      DIRL,W
   movwf      DATO
   call      i2c_write
   btfss      flag,OK
   return                  ;volver. error de escritura
   
   movf      DATASSP,W
   movwf      DATO         ;cargar en DATO
   call      i2c_write
   btfss      flag,OK
   return                  ;volver. error de escritura

   call      i2c_stop
   return                  ;flag = 1 OK!


;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;ReadI2CByte
;DIRH<1:0>               ;paginas de la eeprom de las cuales leer
;DIRL                  ;direccion baja de la posicion de eeprom de las cuales leer

;devuelve:
;DATASSP                  ;dato leido
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

ReadI2CByte
   
   call      i2c_start      ;enviar START, esperar a que se libere el BUS

   movlw      b'10100000'      ;1010=identificador EEPROM 000= numero EEPROM 0=write
   movwf      DATO         ;cargar byte en variable a enviar(DATO)
   call      i2c_write
   btfss      flag,OK
   return                  ;volver. error de escritura

   movf      DIRH,W
   andlw      b'01111111'      ;solo 7 bits admitidos para esta EEPROM
   movwf      DATO
   call      i2c_write
   btfss      flag,OK
   return

   movf      DIRL,W
   movwf      DATO
   call      i2c_write
   btfss      flag,OK
   return                  ;volver. error de escritura

   call      i2c_restart      ;enviar RESSTART

   movlw      b'10100001'      ;1010=identificador EEPROM 000= numero EEPROM 1=read
   movwf      DATO         ;cargar byte en variable a enviar(DATO)
   call      i2c_write
   btfss      flag,OK
   return                  ;volver. error de escritura

   call      i2c_read
   call      i2c_sendnack
   call      i2c_stop
   return                  ;flag = 1 OK!


;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

CurrentI2CRead

   call      i2c_start      ;enviar START, esperar a que se libere el BUS

   movlw      b'10100001'      ;1010=identificador EEPROM 000= numero EEPROM 1= read
   movwf      DATO         ;cargar byte en variable a enviar(DATO)
   call      i2c_write
   btfss      flag,OK
   return                  ;volver. error de escritura

   call      i2c_read
   call      i2c_sendnack
   call      i2c_stop
   return                  ;flag = 1 OK!


DEMORA1s  movlw     .14       ; 1 set numero de repeticion  (C)
        movwf     PDel0     ; 1 |
PLoop0  movlw     .72       ; 1 set numero de repeticion  (B)
        movwf     PDel1     ; 1 |
PLoop1  movlw     .247      ; 1 set numero de repeticion  (A)
        movwf     PDel2     ; 1 |
PLoop2  clrwdt              ; 1 clear watchdog
        decfsz    PDel2, 1  ; 1 + (1) es el tiempo 0  ? (A)
        goto      PLoop2    ; 2 no, loop
        decfsz    PDel1,  1 ; 1 + (1) es el tiempo 0  ? (B)
        goto      PLoop1    ; 2 no, loop
        decfsz    PDel0,  1 ; 1 + (1) es el tiempo 0  ? (C)
        goto      PLoop0    ; 2 no, loop
PDelL1  goto PDelL2         ; 2 ciclos delay
PDelL2  clrwdt              ; 1 ciclo delay
        return              ; 2+2 Fin.
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

         END



Mi jefe mirando el prototipo que estoy creando: "Y eso va a funcionar?"

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Ejemplo de utilizacion del Modulo I2C del 16F877a
« Respuesta #32 en: 19 de Diciembre de 2008, 17:02:10 »
Hola! Te basaste en mi programa o en el de groundman para hacerlo? Mira que si te basaste en el mio, la memoria que use yo es muchisimo mas chica y la de 256 tiene mas bits para direccionar la posicion de memoria a utilizar.

Puede que el simulador no ande bien, no sería raro. Yo no recuerdo haberlo probado. Si podés no hay nada como probarlo en la vida real.

Por lo pronto a mi me ha funcionado bien durante mucho tiempo, sin fallas. A gran demanda de velocidad. Y a groundman también le ha funcionado por lo que ha comentado.

Espero novedades.

Saludos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Ejemplo de utilizacion del Modulo I2C del 16F877a
« Respuesta #33 en: 19 de Diciembre de 2008, 17:02:50 »
P.D.

Si has leido bien el hilo, pos ya sabras entonces que con el I2C vas a tener que renegar..quieras o no...:D

;)
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado pibe

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 635
Re: Ejemplo de utilizacion del Modulo I2C del 16F877a
« Respuesta #34 en: 20 de Diciembre de 2008, 11:09:13 »
Descartado el I2c

He conseguido simular con una 25LC256 que es SPI y me va de muerte. Super rápida y mucho menos liosa.
Luego subo el código porque estoy en casa.

Ahora voy a por el DS1305 :) .
He encontrado en la página de MAXIM una aplicación para éste , pero que raro, han hecho el programa bit banging en vez de usar el SPI de hardware.
Ya os pediré ayuda seguramente :)
Mi jefe mirando el prototipo que estoy creando: "Y eso va a funcionar?"

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Ejemplo de utilizacion del Modulo I2C del 16F877a
« Respuesta #35 en: 21 de Diciembre de 2008, 03:27:06 »
Me alegro. Entonces éxito en tu nuevos rumbos.

Saludos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado pibe

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 635
Re: Ejemplo de utilizacion del Modulo I2C del 16F877a
« Respuesta #36 en: 21 de Diciembre de 2008, 07:55:01 »
Una dudita:

Cómo escribo toda la memoria?

Según entiendo la página del 25LC256 es de 64 bytes. Si le mando el comando escribir byte y no levanto el CS puedo seguir metiendo datos hasta llegar a 64, luego levanto CS y testeo el WIP del registro STATUS de la memoria para ver que finalizó la grabación de los datos.
Y luego?
Cómo salto a la próxima página? Lo hace automáticamente o debo manualmente enviarle la dirección de inicio de la próxima página?
Mi jefe mirando el prototipo que estoy creando: "Y eso va a funcionar?"

Desconectado antimason

  • PIC12
  • **
  • Mensajes: 81
Re: Ejemplo de utilizacion del Modulo I2C del 16F877a
« Respuesta #37 en: 21 de Diciembre de 2008, 16:31:21 »
Hola, saludos al foro soy nuevo por aquí. Mi pregunta es: una vez visto el asm que han presentado los compañeros para el 16f877 y para el 16f876 en el cual se escribe y representa A0  en el puerto B, ¿Como se haría para escribir y sacar por el puerto B una secuencia de 4 bytes que empezase en la dirección 00 de la primera página de memoria?. Gracias y perdonar mi ignorancia llevo poco con esto de los pics.

Desconectado pibe

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 635
Re: Ejemplo de utilizacion del Modulo I2C del 16F877a
« Respuesta #38 en: 21 de Diciembre de 2008, 17:12:46 »
Según lo que he leído simplemente activas CS, mandas palabra de comando de escritura, mandas los 2 bytes de dirección (00h ambos en tu caso), mandas el byte de datos 1 , el byte de datos 2, el byte de datos 3, el byte de datos 4, levantas CS y esperas entre 5-10 ms.
Ahora para leer : CS, comando de lectura, 2 bytes de dirección del dato 1, lees dato 1, levantas CS . Muestras en puerto B el dato que tienes en el buffer. Haces una pausa para visualizarlo.
Y repite para el resto de datos, incrementando en 1 byte de dirección baja.
Mi jefe mirando el prototipo que estoy creando: "Y eso va a funcionar?"

Desconectado antimason

  • PIC12
  • **
  • Mensajes: 81
Re: Ejemplo de utilizacion del Modulo I2C del 16F877a
« Respuesta #39 en: 21 de Diciembre de 2008, 18:30:50 »
Según lo que he leído simplemente activas CS, mandas palabra de comando de escritura, mandas los 2 bytes de dirección (00h ambos en tu caso), mandas el byte de datos 1 , el byte de datos 2, el byte de datos 3, el byte de datos 4, levantas CS y esperas entre 5-10 ms.
Ahora para leer : CS, comando de lectura, 2 bytes de dirección del dato 1, lees dato 1, levantas CS . Muestras en puerto B el dato que tienes en el buffer. Haces una pausa para visualizarlo.
Y repite para el resto de datos, incrementando en 1 byte de dirección baja.


¿No podrias poner algun ejemplo integrado en el asm de este mismo post?

Desconectado antimason

  • PIC12
  • **
  • Mensajes: 81
Re: Ejemplo de utilizacion del Modulo I2C del 16F877a
« Respuesta #40 en: 21 de Diciembre de 2008, 20:48:19 »
Me he atrevido a realizar modificaciones sobre el programa de Brunof, para que escriba en memoria AA y lo presente en puerta B,
realiza una temporización de 5s y borra puerta B, a continuación escribe en memoria (se supone que en la siguiente posición) A0
y lo presenta en puerta B, temporiza otros 5s y finalmente lo borra. ¿Que os parece?.








;programa que graba dato AA en la direccion 00h y A0 en la siguiente posición de memoria de una memoria eeprom externa
;mediante protocolo I2C pic 16f876 24LC256

           LIST      P=16F876
           #include   "p16F876.INC"
           __CONFIG    _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF ;&_WRT_ENABLE_OFF   
           ERRORLEVEL   -302

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
; CONSTANTES:
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define      CLOCK       D'0'
#define      STROBE      D'2'
#define      SCL         D'3'
#define      SDA         D'4'
#define       OK         D'0'

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;Memoria EEPROM
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
; MACROS
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

BANK0      MACRO
      BCF   STATUS,RP0
      BCF   STATUS,RP1
      ENDM

BANK1      MACRO
      BSF   STATUS,RP0
      BCF   STATUS,RP1
      ENDM

BANK2      MACRO
      BSF   STATUS,RP1
      BCF   STATUS,RP0
      ENDM

BANK3      MACRO
      BSF   STATUS,RP1
      BSF   STATUS,RP0
      ENDM

;GPR: GENERAL PURPOSE REGISTERS

;0x20 -> 0x47 Reservados Memoria cartel.

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DIRL        EQU     0X20
DIRH        EQU     0X21   
DATO        EQU     0X22          ;temporar. byte a enviar/dato leido
flag        EQU     0X24
cuenta      EQU     0X25
CONTA0      EQU     0X26
CONTA1      EQU     0X27
R_ContA     EQU     0x28
R_ContB     EQU     0x29
R_ContC     EQU     0x30
DATASSP     EQU     0x70

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



            ORG     0X0000
            GOTO    INICIO

            ORG     0X0004
            return

            ORG     0X0020

INICIO      BANK0
            BSF     STATUS,RP0
            MOVLW   0x06          ;PINS DEL PUERTO A Y PUERTO C TODOS DIGITALES.
            MOVWF   ADCON1
            CLRW
            MOVWF   TRISA

            BANK0
            CLRF    PORTA
            BSF     STATUS,RP0
            MOVLW   0X00
            MOVWF   TRISB

            BANK0
            CLRF    PORTB
            BSF     STATUS,RP0
            MOVLW   B'00011000'
            MOVWF   TRISC
   
            BANK0
            MOVLW   B'00010000'
            MOVWF   PORTC
            BSF     STATUS,RP0
   

            call    i2c_init      ;configurar y encender I2C
            clrf    DIRH          ;cargar paginas de 24LC08B en las cuales escribir
            clrf    DIRL          ;cargar direccion de 24LC08B en las cuales escribir     
            movlw   0xAA
            movwf   DATASSP       ;cargar dato a escribir en la 24LC08B
            call    WriteI2CByte

            call    DEMORA        ;dar 10ms a que termine la escritura

            clrf    DIRH          ;cargar paginas de 24LC08B de las cuales leer
            clrf    DIRL          ;cargar direccion de 24LC08B de las cuales leer
            call    ReadI2CByte

            movf    DATO,w
            movwf   PORTB
            incf    DIRL,F

            call    Retardo_5s
            clrf    PORTB


            call    i2c_init      ;configurar y encender I2C
            clrf    DIRH          ;cargar paginas de 24LC08B en las cuales escribir
            clrf    DIRL          ;cargar direccion de 24LC08B en las cuales escribir     
            movlw   0xA0
            movwf   DATASSP       ;cargar dato a escribir en la 24LC08B
            call    WriteI2CByte

            call    DEMORA        ;dar 10ms a que termine la escritura

            clrf    DIRH          ;cargar paginas de 24LC08B de las cuales leer
            clrf    DIRL          ;cargar direccion de 24LC08B de las cuales leer
            call    ReadI2CByte

            movf    DATO,w
            movwf   PORTB

           
            call    Retardo_5s
            clrf    PORTB

            nop
            goto    $-1



;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DEMORA
            movlw   .55
            movwf   CONTA0
RET1
            movlw   .181
            movwf   CONTA1
RET2
            nop
            nop
            decfsz   CONTA1,1
            goto   RET2
            decfsz   CONTA0,1
            goto   RET1
            return

;****************************************************************************************************************************

Retardo_5s                                        ;
         movlw    d'50'                           ;
         goto     Retardo_1Decima

Retardo_1Decima
         movwf    R_ContC                         ;
R1Decima_BucleExterno2
         movlw    d'100'                          ;
         movwf    R_ContB                         ;
R1Decima_BucleExterno
         movlw    d'249'                          ;
         movwf    R_ContA                         ;
R1Decima_BucleInterno     
         nop                                      ;
         decfsz   R_ContA,F                       ;
         goto     R1Decima_BucleInterno           ;
         decfsz   R_ContB,F                       ;
         goto     R1Decima_BucleExterno           ;
         decfsz   R_ContC,F                       ;
         goto     R1Decima_BucleExterno2          ;
         return




;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_init

   movlw       b'00011000'
   banksel       TRISC         ;banco 1
   iorwf       TRISC,F
   movlw       b'00001011'      ;.11 para 400khz @ 20 mhz
   movwf       SSPADD         ;400 khz @ 20 mhz   
   clrf       SSPSTAT
   movlw      b'00101000'
   bcf      STATUS,RP0      ;banco 0
   movwf       SSPCON
   CLRF      PIR1
   call      i2c_idle
   return


;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_idle

   bsf      STATUS,RP0      ;banco 1
   btfsc       SSPSTAT,R_W
   goto       $-1

   movf       SSPCON2,w
   andlw       0x1F
   btfss       STATUS,Z
   goto       $-3

   bcf      STATUS,RP0      ;banco 0
   return

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_start
   call      i2c_idle
   bsf      STATUS,RP0      ;banco 1
   bsf       SSPCON2,SEN
   btfsc       SSPCON2,SEN
   goto       $-1

   bcf      STATUS,RP0      ;banco 0
   btfss      PIR1,SSPIF
   goto      $-1

   bcf      PIR1,SSPIF
   return

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_restart

   bsf      STATUS,RP0      ;banco 1
   bsf       SSPCON2,RSEN
   btfsc       SSPCON2,RSEN
   goto       $-1

   bcf      STATUS,RP0      ;banco 0
   return

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_read

   call      i2c_idle   
   bsf      STATUS,RP0      ;banco 1   
   bsf       SSPCON2,RCEN      ;activar modo lectura
   btfsc       SSPCON2,RCEN      ;termino la recepcion?
   goto       $-1         ;no, esperar

   btfss      SSPSTAT,BF      ;dato disponible en SSPBUF para ser leidos?
   goto      $-1         ;no, esperar

   bcf      STATUS,RP0      ;banco 0
   movf      SSPBUF,W
   movwf      DATO
   return

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_write

   bcf      flag,0         ;inicializar flag como "error"
   call      i2c_idle
   movf      DATO,w         ;mover DATO a W
   movwf       SSPBUF         ;cargar dato en buffer I2C
   bsf      STATUS,RP0      ;banco 1
   btfsc       SSPSTAT,R_W      ;esperar a que termine el envio
   goto       $-1

   btfss      SSPCON2,ACKSTAT    ;checkear ack
   goto      okack

   bsf       SSPCON2,PEN      ;error ack. enviar STOP
   bcf      STATUS,RP0      ;banco 0
   return               ;volver con flag= 0 error

okack   bcf      STATUS,RP0      ;banco 0
   btfss      PIR1,SSPIF      ;esperar finalizacion del noveno clock
   goto      $-1

   bcf      PIR1,SSPIF
   bsf      flag,0         ;volver con flag = 1 OK!
   return
   
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_sendack

   bsf      STATUS,RP0      ;banco 1
   bcf       SSPCON2,ACKDT
   bsf       SSPCON2,ACKEN
   bcf      STATUS,RP0      ;banco 0
   return

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_sendnack

   bsf      STATUS,RP0      ;banco 1
   bsf       SSPCON2,ACKDT
   bsf       SSPCON2,ACKEN
   bcf      STATUS,RP0      ;banco 0
   return

;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

i2c_stop
   bsf      STATUS,RP0      ;banco 1
   bsf       SSPCON2,PEN      ;enviar STOP
   bcf      STATUS,RP0      ;banco 0
   return


;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;WriteI2CByte
;DIRH<1:0>                  ;paginas de la eeprom en las cuales grabar
;DIRL                     ;direccion baja de la posicion de eeprom en las cuales grabar
;DATASSP                  ;dato a grabar
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

WriteI2CByte

   call      i2c_start      ;enviar START, esperar a que se libere el BUS
   movlw      b'10100000'      ;"1010"= identificador EEPROM. "000" = numero EEPROM "0"= Write
   movwf      DATO
   call      i2c_write
   btfss      flag,OK
   return

   movf      DIRH,W
   andlw      b'01111111'      ;solo 7 bits de paginas admitidas para esta eeprom.
   movwf      DATO         ;cargar byte en variable a enviar(DATO)
   call      i2c_write
   btfss      flag,OK
   return                  ;volver. error de escritura

   movf      DIRL,W
   movwf      DATO
   call      i2c_write
   btfss      flag,OK
   return                  ;volver. error de escritura
   
   movf      DATASSP,W
   movwf      DATO         ;cargar en DATO
   call      i2c_write
   btfss      flag,OK
   return                  ;volver. error de escritura

   call      i2c_stop
   return                  ;flag = 1 OK!


;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;ReadI2CByte
;DIRH<1:0>               ;paginas de la eeprom de las cuales leer
;DIRL                  ;direccion baja de la posicion de eeprom de las cuales leer

;devuelve:
;DATASSP                  ;dato leido
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

ReadI2CByte
   
   call      i2c_start      ;enviar START, esperar a que se libere el BUS

   movlw      b'10100000'      ;1010=identificador EEPROM 000= numero EEPROM 0=write
   movwf      DATO         ;cargar byte en variable a enviar(DATO)
   call      i2c_write
   btfss      flag,OK
   return                  ;volver. error de escritura

   movf      DIRH,W
   andlw      b'01111111'      ;solo 7 bits admitidos para esta EEPROM
   movwf      DATO
   call      i2c_write
   btfss      flag,OK
   return

   movf      DIRL,W
   movwf      DATO
   call      i2c_write
   btfss      flag,OK
   return                  ;volver. error de escritura

   call      i2c_restart      ;enviar RESSTART

   movlw      b'10100001'      ;1010=identificador EEPROM 000= numero EEPROM 1=read
   movwf      DATO         ;cargar byte en variable a enviar(DATO)
   call      i2c_write
   btfss      flag,OK
   return                  ;volver. error de escritura

   call      i2c_read
   call      i2c_sendnack
   call      i2c_stop
   return                  ;flag = 1 OK!


;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

CurrentI2CRead

   call      i2c_start      ;enviar START, esperar a que se libere el BUS

   movlw      b'10100001'      ;1010=identificador EEPROM 000= numero EEPROM 1= read
   movwf      DATO         ;cargar byte en variable a enviar(DATO)
   call      i2c_write
   btfss      flag,OK
   return                  ;volver. error de escritura

   call      i2c_read
   call      i2c_sendnack
   call      i2c_stop
   return                  ;flag = 1 OK!
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   
   END

Desconectado pibe

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 635
Re: Ejemplo de utilizacion del Modulo I2C del 16F877a
« Respuesta #41 en: 22 de Diciembre de 2008, 05:47:03 »
Perdona pero es que no tenía el programa en casa.

Muy buen trabajo. Lo has probado si funciona?
Mi jefe mirando el prototipo que estoy creando: "Y eso va a funcionar?"

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Ejemplo de utilizacion del Modulo I2C del 16F877a
« Respuesta #42 en: 22 de Diciembre de 2008, 06:17:43 »
e he atrevido a realizar modificaciones sobre el programa de Brunof...

Hola!

Bueno, la subrutina i2c_init debería ser llamada sólo la primera vez. Volver a llamarla puede provocar efectos indeseados.

...a continuación escribe en memoria (se supone que en la siguiente posición) A0
y lo presenta en puerta B, temporiza otros 5s y finalmente lo borra. ¿Que os parece?.

Lamentablemente supones mal. Y con esto voy a responderte a ti y a pibe.

Estas memorias pueden ser leidas de 3 maneras: Random Read, Current Access Read y  Sequential Read. La Random Read implica que uno le pasa como parametros también la dirección que se desea leer, pudiendo elegir entre cualquiera presente en la memoria. Current Read implica que se leerá la posición de memoria a la cual apunte su puntero interno. ¿Que valor posee el puntero interno?

Luego de realizar una Random Read, el valor del puntero interno es el valor de la posición que se acaba de leer + 1. Es decir que el puntero se autoincrementa según la última posición a la cual se ha accedido.

Ejemplos:

Si realizo primero un Random Read de la posición 125 y luego realizo un Current Access Read, la memoria leerá el valor de la posición 126. Si realizo otro Current Access  Read, leerá la posición 127.

Sequential Read sirve para leer muchas posiciones de memoria CONSECUTIVAS. Podés leer toda la memoria si querés. La diferencia es que leer de esta manera es muchísimo más rápido que en los otros dos modos.

Para escribir, hay dos modos: Byte Write(el que usan en mi ejemplo) y Block Write(que creo que no he publicado el algoritmo).

El byte write que es el que se usa para escribir un byte en la RAM, siempre exige que se defina la posición a escribir. Por lo que es necesario que se le pase la posición a la cual se desea acceder. Todas las operaciones afectan al puntero interno que es el que indica cual es la posicion actual a leer/escribir.

Ejemplo:

Escribo posición 0. (Luego de eso, el puntero interno valdrá 1)
Leo posición 0. Debo hacerlo usando el Random Read indicandole que quiero leer la posición 0.(si usase en su lugar el Current Access Read o Block Read, el primer byte leido seria el de la posicion 1).

Escribo posición 1. (Luego de eso, el puntero interno valdrá 2)
Leo posición 1. Nuevamente debo hacerlo usando el Random Read indicandole que quiero leer la posición 1.(si usase en su lugar el Current Access Read o Block Read, el primer byte leido seria el de la posicion 2).

Si se fijan bien en el protocolo, el Random Read comienza exáctamente igual que un Byte Write. Esto es porque de esta manera se logra modificar el puntero interno. Luego en la lectura se interrumpe la escritura y se procede a leer.

Se entendió?
Saludos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado pibe

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 635
Re: Ejemplo de utilizacion del Modulo I2C del 16F877a
« Respuesta #43 en: 22 de Diciembre de 2008, 07:12:29 »
Gracias Bruno por la aclaración.
Una pregunta: En el secuencial byte read, puedo leer toda la memoria con una sola instrucción mientras le sigo mandando reloj y CS? O sólo los primeros 64 bytes de la página?
Mi jefe mirando el prototipo que estoy creando: "Y eso va a funcionar?"

Desconectado antimason

  • PIC12
  • **
  • Mensajes: 81
Re: Ejemplo de utilizacion del Modulo I2C del 16F877a
« Respuesta #44 en: 22 de Diciembre de 2008, 15:33:43 »
Perdona pero es que no tenía el programa en casa.

Muy buen trabajo. Lo has probado si funciona?


En el Proteus funciona, aun así he seguido el consejo de Brunof de solo hacer una llamada  "call    i2c_init", que tambien he probado y funciona. Ahora solo queda asegurar que lo que se escribe y se lee es desde una posición conocida y esa información sale linea tras linea desde esa posición de memoria..............bufffffff, que entretenido es esto, por cierto la intrucción "goto    $-1" es salto incondicional a.......¿$-1?, que es...es que he pasado de un pic 16f84a a este otro pic y no estoy muy suelto. El código ahora queda así:



ORG     0X0000
            GOTO    INICIO

            ORG     0X0004
            return

            ORG     0X0020

INICIO      BANK0
            BSF     STATUS,RP0
            MOVLW   0x06          ;PINS DEL PUERTO A Y PUERTO C TODOS DIGITALES.
            MOVWF   ADCON1
            CLRW
            MOVWF   TRISA

            BANK0
            CLRF    PORTA
            BSF     STATUS,RP0
            MOVLW   0X00
            MOVWF   TRISB

            BANK0
            CLRF    PORTB
            BSF     STATUS,RP0
            MOVLW   B'00011000'
            MOVWF   TRISC
   
            BANK0
            MOVLW   B'00010000'
            MOVWF   PORTC
            BSF     STATUS,RP0
   

            call    i2c_init                  ;configurar y encender I2C
            clrf    DIRH                     ;cargar paginas de 24LC08B en las cuales escribir
            clrf    DIRL                     ;cargar direccion de 24LC08B en las cuales escribir     
            movlw   0xAA
            movwf   DATASSP          ;cargar dato a escribir en la 24LC08B
            call    WriteI2CByte

            call    DEMORA               ;dar 10ms a que termine la escritura

            clrf    DIRH                    ;cargar paginas de 24LC08B de las cuales leer
            clrf    DIRL                     ;cargar direccion de 24LC08B de las cuales leer
            call    ReadI2CByte

            movf    DATO,w
            movwf   PORTB
            incf    DIRL,F

            call    Retardo_5s
            clrf    PORTB


           
            clrf    DIRH                      ;cargar paginas de 24LC08B en las cuales escribir
            clrf    DIRL                      ;cargar direccion de 24LC08B en las cuales escribir     
            movlw   0xA0
            movwf   DATASSP           ;cargar dato a escribir en la 24LC08B
            call    WriteI2CByte

            call    DEMORA                ;dar 10ms a que termine la escritura

            clrf    DIRH                     ;cargar paginas de 24LC08B de las cuales leer
            clrf    DIRL                      ;cargar direccion de 24LC08B de las cuales leer
            call    ReadI2CByte

            movf    DATO,w
            movwf   PORTB

           
            call    Retardo_5s
            clrf    PORTB

            nop
            goto    $-1



Solo pongo la parte del programa sobre la que estoy trabajando porque supongo que el resto sufrira pocos cambios o ninguno (creo yo, a lo mejor me equivoco, je, je, je).
« Última modificación: 22 de Diciembre de 2008, 15:36:36 por antimason »


 

anything