Autor Tema: I2C Esclavo con un PIC16F73  (Leído 8076 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado XTOPIC

  • PIC10
  • *
  • Mensajes: 17
I2C Esclavo con un PIC16F73
« en: 18 de Noviembre de 2009, 10:55:54 »
Alguien tiene por favor un assembler para que un PIC16F73 trabaje como esclavo en una comunicación I2C?
Es muy simple lo que necesito, tengo que mandar 2 bytes desdde un PIC 16F73 Maestro (ese programa ya lo hice y funciona bien), hacia varios PIC16F73 esclavos (por ahora pruebo con uno solo pero no consigo hacerlo funcionar).
Ya me leí todo: AN734 (que tiene errores), y he buscado por todas partes pero no encontré nada que funcione y no logro que el PIC esclavo reconozca ni siquiera el bit de Start del Maestro.
El PIC16F73 no tiene módulo MSSP sino que tiene un módulo SSP para I2C pero debería funcionar igual para una recepción de 7 bits de address.
Nada ..... no lo consigo y se me están quemando todos los fusibles de la cabeza  :shock:
Agradezco cualquier ayuda al respecto .... es muy dificil trabajar solo en assembler !

Muchas Gracias

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: I2C Esclavo con un PIC16F73
« Respuesta #1 en: 18 de Noviembre de 2009, 11:00:53 »
Muéstranos el código del esclavo haber si podemos detectar algún error.


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado XTOPIC

  • PIC10
  • *
  • Mensajes: 17
Re: I2C Esclavo con un PIC16F73
« Respuesta #2 en: 18 de Noviembre de 2009, 16:48:06 »
Gracias Suki por tu tiempo,

Ahi van IC2Master es el assembler del MAster e IC2Slave
IC2Slave
;   I2C_SLAVE.ASM ----------------------------------------------------

  list      p=16F73           
 #include <p16F73.inc>       
   
 __CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
      ERRORLEVEL -302
      ERRORLEVEL -305

  #DEFINE NODE_ADDR   0x22    ; I2C address of this node
   
reset    ORG     0x000                   ; processor reset vector
         goto    inicio                  ; go to beginning of program
         ORG     0x004                   ; interrupt vector
         goto    ISR                     ;
inicio
        call    Setup
       
Main    NOP
        goto    Main       ; Loop forever.       

; ------------------------------------SUBRUTINAS ------------------------------------------
Setup   ; Initializa variables y registros
   
    banksel PORTC       
    clrf    PIR1
    clrf    SSPBUF
    clrf    PORTB
    movlw   NODE_ADDR
    banksel SSPADD
    movwf   SSPADD
    clrf    SSPSTAT
    clrf    TRISB
    MOVLW   0xFF
    movwf   TRISC                  ; ALL INPUTS (RC3 & RC4 MUST BE INPUTS)
    bsf     PIE1,SSPIE
    bsf     INTCON,PEIE            ; Enable all peripheral interrupts
    bsf     INTCON,GIE             ; Enable global interrupts
    bcf     STATUS,RP0
    movlw   0x36                   ; Setup SSP module for 7-bit, Enable Clock Start Stop Int. Enabled
    movwf   SSPCON                ; address, slave mode
    return

; ******************* INTERRUPT **********************************************
ISR
   
    banksel PIR1
    btfss   PIR1,SSPIF  ; Is this an I2C interrupt?
    goto    salida           ; No, just trap here.
   
    call    I2C_Handler  ; Yes, service I2C interrupt.
    bcf     PIR1,SSPIF
salida
    retfie              ; Return from interrupt.
I2C_Handler 
    banksel SSPSTAT
    movf    SSPSTAT,W
    banksel PORTB
    MOVWF   PORTB
   
    return

 ; INCLUDES  *****************************************************************
    ; #include  <I2C_SLAVE.inc>      ; subrutinas de manejo de BUS I2C
    #include  <RETARDOS.inc>      ; subrutinas de manejo de BUS I2C
    end

IC2Master *********************************************************************
    list      p=16F73            ; list directive to define processor
   #include <p16F73.inc>        ; processor specific variable definitions
   
   __CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
      ERRORLEVEL -302
      ERRORLEVEL -305
; las variables comienzan en 20´h *****************************************************
    CBLOCK      0X20
      
   ENDC
    #DEFINE LED     PORTA,2
    #DEFINE BEEP    PORTA,5

reset   ORG     0x000                   ; processor reset vector
        goto    inicio                  ; go to beginning of program
        ORG     0x004                   ; interrupt vector
        goto    RBI_Interrupcion ;
inicio
        ; seteo del PORTA
        banksel ADCON1      ; bank1
        movlw   0x06
        movwf   ADCON1      ; todos digitales
        clrf    TRISA       ; todas salidas
        banksel PORTA
        clrf    PORTA
        bsf       STATUS,RP0      ; select page 1 y de ahora en más queda en el BANK 1
        call    InitI2CBus_Master
        movlw   0x22        ; Slave Address
        movwf   SlaveAddr     
trigger       
        bcf       STATUS,RP0      ; select page 0
        call    beeper          ; para sincronizar el osciloscopio
      bsf       STATUS,RP0      ; select page 1
      
        call    SendStartBit
       
        call    SendSlaveAddr
        ; check for true or false
        btfsc   Bus_Status,4    ;  _Txmt_Success 
        goto    Fallo_de_TX
       
        call    SendStopBit
       
       
lazo    bcf     STATUS,RP0      ; select page 0
      bsf     LED
        call    Retardo_500ms
        bcf     LED
        call    Retardo_500ms
        goto    trigger
Fallo_de_TX
        bcf     STATUS,RP0      ; select page 0
      bsf     LED
        call    Retardo_200ms
        bcf     LED
        call    Retardo_200ms
        goto    trigger     

; aca termina el loop principal ***********************************************************

; ------------------------------------SUBRUTINAS ------------------------------------------

; BEEPER*** ******************************************************************************       
beeper
        bsf     BEEP
        call    Retardo_50ms
        bcf     BEEP
        return
; ******************* SUBRUTINA DE INTERRUPT **********************************************

RBI_Interrupcion
   clrf    INTCON          ; pare todas las interrupciones
   bsf     BEEP
    call    Retardo_1s
    bcf     BEEP
    retfie
      
 ; INCLUDES  *****************************************************************
     
    #include  <RETARDOS.inc>        ; subrutinas de retardo
    #include  <I2C_MASTER.inc>      ; subrutinas de manejo de BUS I2C
    end 
       
 Perdón porque algunos comentarios están en Inglés .
Pregunta: se puede simular I2C para el Slave en el MPLAB? existe algún simulador mejor y más práctico.

Gracias por tu ayuda


Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: I2C Esclavo con un PIC16F73
« Respuesta #3 en: 18 de Noviembre de 2009, 17:48:37 »
Buenas, un simulador más practico puede ser Proteus o el PIC Simulator. En proteus probé el código slave y funciona correctamente  :-/ Si envías correctamente la dirección setea el bit R/W donde se indica que acción se quiere realizar.
Cuando digo que se envía correctamente la dirección es, en los bits 1 a 7 va la dirección y en el bit 0 la acción, osea que si la dirección del esclavo es 0x22, para escribir en él se debe enviar 0x45, pero si se quiere leer 0x44.

Lo único que cambie fue:
Código: ASM
  1. I2C_Handler
  2.     banksel SSPBUF
  3.     movf    SSPBUF,W
  4.     banksel PORTB
  5.     MOVWF   PORTB

Porque es en SSPBUF donde se recibe el dato y es necesario leerlo para que se borre el bit BF, sino se activará el bit de sobre-escritura.

Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado XTOPIC

  • PIC10
  • *
  • Mensajes: 17
Re: I2C Esclavo con un PIC16F73
« Respuesta #4 en: 18 de Noviembre de 2009, 20:17:50 »
 :) Nuevamente Gracias Suki por probar el Slave (ahora que me fijo no te mandé el IC2_Master.INC que va con el assembler del Master), ahi va:
(Si me contestas , por favor dime como poner el código en ese recuadro gris que no ocupa tanto lugar)
; ////////////////////// I2C_MASTER.INC ////////////////////////////////////////////////
; VARIABLES LOCALES ******************************************************************
    CBLOCK      0xA0    ; TODAS LAS VARIABLES DEL I2C ESTAN EN EL BANK 1 !!!!!
       Bus_Status      ; Status Reg of I2C Bus for both TXMT & RCVE
      Bus_Control      ; control Register of I2C Bus
       DataByte      ; load this reg with the data to be transmitted
      BitCount      ; The bit number (0:7) transmitted or received
      DelayCount
      SlaveAddr
   ENDC
; ******************** DEFINICIONES **************************************************
    #DEFINE     I2C_SCL     TRISA,3     ; I2C Clock
      #DEFINE     I2C_SDA     TRISA,4     ; I2C Data
      #DEFINE     _SCL        PORTA,3     ; I2C Clock Estado del Bus
      #DEFINE     _SDA        PORTA,4     ; I2C Data Estado del Bus
; NO SE TRABAJA CON BSF NI BCF SOBRE EL PORT !!!!!
; SE PONEN AMBOS PORT LATCHS EN CERO, PULLUPS EXTERNOS DE 4K7 Y SE TRABAJA CON TRIS
; Si TRIS es 0 (output) entonces pone cero (lo que tenía en el latch).
; Si TRIS es 1 (input) entonces deja que el pullup levante a 1 (el port que High Z).
;*************************************************************************************
;         I2C Bus Status Reg Bit Definitions
;*************************************************************************************
#define   _Bus_Busy       Bus_Status,0
#define   _Abort          Bus_Status,1
#define   _Txmt_Progress   Bus_Status,2
#define   _Rcv_Progress   Bus_Status,3
#define   _Txmt_Success   Bus_Status,4
#define   _Rcv_Success   Bus_Status,5
#define   _Fatal_Error   Bus_Status,6
#define   _ACK_Error       Bus_Status,7

;*************************************************************************************
;         I2C Bus Control Register
;*************************************************************************************
#define   _10BitAddr       Bus_Control,0
#define   _Slave_RW       Bus_Control,1
#define   _Last_Byte_Rcv   Bus_Control,2
#define   _SlaveActive   Bus_Control,6
#define   _TIME_OUT_       Bus_Control,7

;*************************************************************************************
;*************************************************************************************
RELEASE_BUS   MACRO    ; pone el port en Input y deja que actue el pullup externo de 4k7
   
         bsf     STATUS,RP0      ; select page 1
         bsf       I2C_SDA          ; tristate SDA
         bsf       I2C_SCL          ; tristate SCL
         ENDM                    ; fin de la Macro. OJO queda en Bank 1 !!

;**************************************************************************************
     
; EQUIVALENCIAS ***********************************************************************
TRUE   equ   1
FALSE   equ   0
;*************************************************************************************
;                   SINGLE  MASTER, MULTIPLE SLAVES
;*************************************************************************************
;            I2C Bus Initialization
;*************************************************************************************
InitI2CBus_Master
       bcf       STATUS,RP0  ; bank 0
       movf   PORTA,W
       andlw   0xE7      ; do not use BSF & BCF on Port Pins
       movwf   PORTA      ; set SDA & SCL to zero. From Now on, simply play with TRIS
        RELEASE_BUS         ; MACRO
       clrf   Bus_Status   ; reset status reg
       clrf   Bus_Control   ; clear the Bus_Control Reg, reset to 8 bit addressing
       return
;***************************************************************************************
;            Send Start Bit
;***************************************************************************************
SendStartBit
      bsf       I2C_SDA          ; set SDA high
      bsf       I2C_SCL          ; set SCL high
       call    Delay10uS       ; only necessary for setup time
        bcf       I2C_SDA          ; give a falling edge on SDA while clock is high
      call    Delay10uS       ; only necessary for START HOLD time
      bsf       _Bus_Busy       ; on a start condition bus is busy
      return

;****************************************************************************************
;            Send Stop Bit
;****************************************************************************************
SendStopBit
      bsf       STATUS,RP0   ; select page 1
      bcf       I2C_SCL      
      bcf       I2C_SDA      ; set SDA low
      bsf       I2C_SCL      ; Clock is pulled up
      call    Delay10uS
      bsf       I2C_SDA      ; give a rising edge on SDA while CLOCK is high
         bcf       _Bus_Busy   ; on a stop condition bus is considered Free
      return   

;*****************************************************************************************
;               Abort Transmission / Send STOP Bit & set Abort Flag
;*****************************************************************************************
AbortTransmission
      call   SendStopBit
      bsf       _Abort
      return   
;*****************************************************************************************
;            Transmit Address (1st Byte)& Put in Read/Write Operation
;  Transmits Slave Addr On the 1st byte and set LSB to R/W operation
;  Slave Address must be loaded into SlaveAddr reg
;  On Success, return TRUE in WREG, else FALSE in WREG
;   If desired, the failure may tested by the bits in Bus Status Reg
;*******************************************************************************************
SendSlaveAddr
       bcf       _ACK_Error          ; reset Acknowledge error bit
      movf   SlaveAddr,W
       movwf   DataByte      ; load addr to Data Byte for transmission
       call   SendData      ; send 8 bits of address
; if successfully transmitted, expect an ACK bit
_AddrSendTest
       btfss   _Txmt_Success      ; skip if successful
       goto   _AddrSendFail
       retlw   TRUE
_AddrSendFail
       btfss   _ACK_Error
       retlw   FALSE         ; Addr Txmt Unsuccessful, so return 0
; Address Not Acknowledged, so send STOP bit
       call   SendStopBit
       retlw   FALSE         ; Addr Txmt Unsuccessful, so return 0
;*******************************************************************************************
;            TRANSMIT A BYTE OF DATA
; The data to be transmitted must be loaded into DataByte Reg
;*******************************************************************************************
SendData                        ; send 8 bits & wait for ACK

      bsf       _Txmt_Progress   ; set Bus status for txmt progress
      bcf       _Txmt_Success   ; reset status bit
      movlw   0x08
      movwf   BitCount
      
TxmtNextBit
      bcf       I2C_SCL         ; set clock low
      rlf     DataByte, F       ; MSB first, Note DataByte Is Lost
        bcf       I2C_SDA
      btfsc   STATUS,C
      bsf       I2C_SDA
      call    Delay10uS
      bsf       I2C_SCL          ; set clock high
; check if clock is high, else clock is being stretched
      call    Delay10uS
      decfsz   BitCount, F
      goto   TxmtNextBit
; Check For Acknowledge
      bcf       I2C_SCL          ; set clock low
      bsf       I2C_SDA          ; Release SDA line for Slave to pull down
      call    Delay10uS
      bsf       I2C_SCL          ; clock for slave to ACK
      call    Delay10uS
      
      bcf       STATUS,RP0      ; select PAGE 0 to test PortA pin SDA
      btfsc   _SDA          ; SDA should be pulled low by slave if OK
        goto   _TxmtErrorAck

      bsf       STATUS,RP0      ; select page 1
      bcf   _Txmt_Progress   ; reset TXMT bit in Bus Status
      bsf   _Txmt_Success   ; transmission successful
      bcf   _ACK_Error       ; ACK OK
      return
_TxmtErrorAck
      RELEASE_BUS
      bcf   _Txmt_Progress   ; reset TXMT bit in Bus Status
      bcf   _Txmt_Success   ; transmission NOT successful
      bsf   _ACK_Error       ; No ACK From Slave
      return
;********************************************************************************************
;         General Purpose Delay Routine
;********************************************************************************************
Delay10uS       ; 2us for the Call + 8 nops + 2us for return = 10us
   NOP
   NOP
   NOP
   NOP
   NOP
   NOP
   NOP
   NOP
   return      
;********************************************************************************************

Por otra parte, no entendí bien el tema del address. Si la dirección del Slave es 0x22 , cómo es que hay que poner 0x44 para escribir un byte en él?
Saludos y  :-/ gracias

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: I2C Esclavo con un PIC16F73
« Respuesta #5 en: 18 de Noviembre de 2009, 20:52:41 »
Porque no usas el módulo para el master? Te facilita las cosas y además tendras menos código. Con respecto a la dirección lo explico en el mismo mensaje, lee detalladamente y lee por aquí un tutorial sobre el protocolo I2C


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado XTOPIC

  • PIC10
  • *
  • Mensajes: 17
Re: I2C Esclavo con un PIC16F73
« Respuesta #6 en: 19 de Noviembre de 2009, 09:35:31 »
Hola Suki
Según la hoja de datos del PIC16F73, el módulo SSP es sólo para cuando actua como Slave.
Para que funcione como Master, se debe hacer por firmware.
No lo conozco a fondo, pero creo que el 16F877 tiene módulo MSSP y ese si puede funcionar como Master.
Estoy tratando de conseguir el Proteus.

Gracias por tus comentarios.
Saludos

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: I2C Esclavo con un PIC16F73
« Respuesta #7 en: 19 de Noviembre de 2009, 09:59:43 »
 :oops: Perdón, di por hecho que se podía trabajar en modo master con el hardware, el 16F873 tiene módulo MSSP.

Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado XTOPIC

  • PIC10
  • *
  • Mensajes: 17
Re: I2C Esclavo con un PIC16F73
« Respuesta #8 en: 19 de Noviembre de 2009, 12:33:30 »
Nada de que avergonzarse, yo tengo 53 años y me reinicié en esto de los micros ahora. Cuando estudiaba ingenieria electrónica el Intel 8080 estaba en pañales , y encima necesitaba 3 tensiones de alimentación !! una locura. En fin, de a poco me voy poniendo a tono con todo esto.
A propósito, ya entendí eso de las direcciones del esclavo. Era fácil, son sólo los 7 primeros bits y luego agregar cero o uno segun quieras escribir o leer.
Traté de simular el Slave con el PICSIMulator pero no hay caso, no marca el bit de START en el SSPSTAT.
Sin embargo, si lo pude lograr en el circuito  :-) ... por fin !!  es increible, los electrónicos nos ponemos felices cuando prende un led !!  :lol:
Bueno, ahora sigo con la reedición del Master a ver que puedo lograr. El manual de lmicro dice que se puede controlar el módulo por firmware pero no aclara bien como.
Todo este firmware en realidad forma parte de un proyecto más grande en el que un Master actualiza datos en varios Slaves para que cambien sus parámetros. Los Slaves controlan motores paso a paso que a su vez cambian la velocidad de acuerdo con la posición de un joystick.
Espero terminar algún día.
Cualquier novedad te comento....
Ah! cómo hago para poner código en el rectángulo gris?

Saludos y gracias

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: I2C Esclavo con un PIC16F73
« Respuesta #9 en: 19 de Noviembre de 2009, 13:12:12 »
Probé el master y también funciona dentro de todo bien, lo único que debes cambiar es el testeo de btfsc   Bus_Status,4 a btfss   Bus_Status,4 dado que si ha ocurrido el proceso el bit se setea a 1.

Para colocar código debes ponerlo entre [ code ] Aquí código [ /code ] (Sin los espacios) y para colocarlo coloreado [ code=asm ] Aquí código [ /code ]

Saludos!!
No contesto mensajes privados, las consultas en el foro

Desconectado XTOPIC

  • PIC10
  • *
  • Mensajes: 17
Re: I2C Esclavo con un PIC16F73
« Respuesta #10 en: 20 de Noviembre de 2009, 16:40:58 »
Bueno, por fin he arribado a algo  :D
Al final te envío los assemblers del Master (Send Addres solo.asm con sus INC) y el de l Slave (TodoPIC Slave.asm).
Ahora el Master lee del PORTB la dirección del Slave (para poder ir cambiándola y ver que pasa), y la envía cíclicamente hacia el Slave.
De acuerdo con que reciba un ACK del Slave o no, enciende el LED verde (ACK recibido) o el LED rojo (ACK no recibido).
Las señales SCL y SDA salen del los pines 3 y 4 del PORT A

Mis comentarios y dudas son los siguientes:
- En el Master las señales SCL y SDA hacia el Slave hay que manejarlas cargando esos pines del port A con 0 , poner un pulll up externo y después mover la señal con BSF y BCF pero sobre el TRIS de ese pin y no BSF y BCF directamente sobre el pin . Si usas BSF o BCF directamente sobre cualquier pin de ese port (PORTA en este caso), entonces el Master deja de transmitir y quedan las señales en 1  :shock:
Si te fijas, en el caso de no recibir ACK el programa va a: Fallo_de_TX si aquí intento encender el LED directamente con bsf PORTA,0 el programa sigue corriendo (hace el loop entre vuelta .... goto vuelta), pero los pines RA3 y RA4 quedan en 1.
En cambio, mientras todo está andando bien (recibiendo el ACK del Slave), prendo el LED verde con bsf pero sobre el TRIS del PORTA,2. El programa sigue reciclando entre vuelta y goto vuelta y en cada ciclo reeenvía START ADDRESS y STOP sin problemas.
Al final, probé prendiendo el LED rojo desde otro port (el PORTC), directamente con bsf PORTC,0 y no hubo ningún problema, si el Master detecta que no le llega un ACK prende el LED rojo y sigue enviando todo cada ciclo.
 :huh: mi pregunta es ; porqué pasa esto? El PIC no sabe que está trabajando en I2C (por lo menos el Master), porqué no puedo mover los otros pines de ese port con bsf o bcf directamente sobre el pin?
Si es así, entonces tengo que cambiar todo el manejo de ese port en el progrma general ya que tengo colgado un teclado y un LCD.
Ahora seguiré trabajando sobre ambos (Master y Slave), para lograr enviar 2 bytes de datos del Master al Slave.
Aquí van los programas:
MASTER
Código: ASM
  1. list      p=16F73            ; list directive to define processor
  2.         #include <p16F73.inc>        ; processor specific variable definitions
  3.    
  4.    
  5.         __CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
  6.       ERRORLEVEL -302
  7.       ERRORLEVEL -305
  8. ; las variables comienzan en 20´h *****************************************************
  9.     CBLOCK      0X20
  10.            
  11.         ENDC
  12.     #DEFINE     RED_LED     PORTC,0
  13.     #DEFINE     GREEN_LED   TRISA,2
  14.     #DEFINE     I2C_SCL     TRISA,3     ; I2C Clock
  15.         #DEFINE     I2C_SDA     TRISA,4     ; I2C Data
  16.         #DEFINE     BEEP        TRISA,5     ; trigger del osciloscopio
  17.    
  18. reset   ORG     0x000                   ; processor reset vector
  19.                 goto    inicio                  ; go to beginning of program
  20.         ORG     0x004                   ; interrupt vector
  21.                 goto    RBI_Interrupcion ;
  22. inicio
  23.         ; seteo del PORTA
  24.         banksel ADCON1      ; bank1
  25.         movlw   0x06
  26.         movwf   ADCON1      ; todos digitales
  27.         clrf    TRISA       ; todas salidas
  28.         movlw   0xFF
  29.         movwf   TRISB       ; todas entradas para leer el SLAVE Address
  30.         clrf    TRISC       ; todas salidas
  31.         banksel PORTA
  32.         movlw   b'00100100' ; bit 5 on for osc. trigger
  33.         movwf   PORTA
  34.         clrf    PORTC
  35.         bsf         STATUS,RP0          ; select page 1 y de ahora en más queda en el BANK 1
  36.         bsf     GREEN_LED       ; pone 0 en GREEN_LED
  37.        
  38.         call    InitI2CBus_Master
  39.        
  40. vuelta        
  41.         banksel PORTB
  42.         movf    PORTB,W         ; lee PORTB
  43.         banksel  SlaveAddr
  44.         movwf   SlaveAddr       ; carga Slave Address
  45.        
  46.         bsf         STATUS,RP0          ; select page 1
  47.         call    trigger          ; para sincronizar el osciloscopio
  48.                
  49.         call    SendStartBit
  50.         call    SendSlaveAddr
  51.        
  52.         btfss   Bus_Status,4    ; check for true or false  (_Txmt_Success)
  53.         goto    Fallo_de_TX
  54.         call    SendStopBit
  55.                        
  56. lazo    
  57.                 bcf     GREEN_LED       ; pone 1 en GREEN_LED
  58.         call    Retardo_50ms
  59.         bsf     GREEN_LED       ; pone 0 en GREEN_LED
  60.         call    Retardo_50ms
  61.         goto    vuelta
  62. Fallo_de_TX
  63.                 banksel PORTC
  64.                 bsf     RED_LED
  65.         call    Retardo_50ms
  66.         bcf     RED_LED
  67.         call    Retardo_50ms
  68.         goto    vuelta    
  69.  
  70. ; aca termina el loop principal ***********************************************************
  71.  
  72. ; ------------------------------------SUBRUTINAS ------------------------------------------
  73.  
  74. ; BEEPER*** ******************************************************************************        
  75. trigger
  76.         bsf     BEEP
  77.         call    Delay10uS
  78.         bcf     BEEP
  79.         return
  80. ; ******************* SUBRUTINA DE INTERRUPT **********************************************
  81.  
  82. RBI_Interrupcion
  83.  
  84.     retfie
  85.            
  86.  ; INCLUDES  *****************************************************************
  87.      
  88.     #include  <RETARDOS.inc>        ; subrutinas de retardo
  89.     #include  <I2C_MASTER.inc>      ; subrutinas de manejo de BUS I2C
  90.     end

I2C_MASTER.INC

Código: [Seleccionar]
; ////////////////////// I2C_MASTER.INC ////////////////////////////////////////////////
; VARIABLES LOCALES ******************************************************************
    CBLOCK      0xA0    ; TODAS LAS VARIABLES DEL I2C ESTAN EN EL BANK 1 !!!!!
    Bus_Status ; Status Reg of I2C Bus for both TXMT & RCVE
DataByte ; load this reg with the data to be transmitted
BitCount ; The bit number (0:7) transmitted or received
SlaveAddr
ENDC
; ******************** DEFINICIONES **************************************************
    ; #DEFINE     I2C_SCL     TRISA,3     ; I2C Clock
    ; #DEFINE     I2C_SDA     TRISA,4     ; I2C Data
    #DEFINE     _SCL        PORTA,3     ; I2C Clock Estado del Bus
    #DEFINE     _SDA        PORTA,4     ; I2C Data Estado del Bus
; NO SE TRABAJA CON BSF NI BCF SOBRE EL PORT !!!!!
; SE PONEN AMBOS PORT LATCHS EN CERO, PULLUPS EXTERNOS DE 4K7 Y SE TRABAJA CON TRIS
; Si TRIS es 0 (output) entonces pone cero (lo que tenía en el latch).
; Si TRIS es 1 (input) entonces deja que el pullup levante a 1 (el port que High Z).
;*************************************************************************************
; I2C Bus Status Reg Bit Definitions
;*************************************************************************************
#define _Bus_Busy     Bus_Status,0
#define _Abort     Bus_Status,1
#define _Txmt_Progress Bus_Status,2
#define _Rcv_Progress Bus_Status,3
#define _Txmt_Success Bus_Status,4
#define _Rcv_Success Bus_Status,5
#define _Fatal_Error Bus_Status,6
#define _ACK_Error     Bus_Status,7

;*************************************************************************************
RELEASE_BUS MACRO    ; pone el port en Input y deja que actue el pullup externo de 4k7

bsf     STATUS,RP0 ; select page 1
bsf     I2C_SDA     ; tristate SDA
bsf     I2C_SCL     ; tristate SCL
ENDM                    ; fin de la Macro. OJO queda en Bank 1 !!

;**************************************************************************************
 
; EQUIVALENCIAS ***********************************************************************
TRUE equ 1
FALSE equ 0
;*************************************************************************************
;                 SINGLE  MASTER, MULTIPLE SLAVES
;*************************************************************************************
; I2C Bus Initialization
;*************************************************************************************
InitI2CBus_Master
    bcf     STATUS,RP0  ; bank 0
    movf PORTA,W
    andlw 0xE7 ; do not use BSF & BCF on Port Pins
    movwf PORTA ; set SDA & SCL to zero. From Now on, simply play with TRIS
        RELEASE_BUS         ; MACRO
    clrf Bus_Status ; reset status reg
    return
;***************************************************************************************
; Send Start Bit
;***************************************************************************************
SendStartBit
bsf     I2C_SDA     ; set SDA high
bsf     I2C_SCL     ; set SCL high
    call    Delay10uS       ; only necessary for setup time
        bcf     I2C_SDA     ; give a falling edge on SDA while clock is high
call    Delay10uS     ; only necessary for START HOLD time
bsf     _Bus_Busy       ; on a start condition bus is busy
return

;****************************************************************************************
; Send Stop Bit
;****************************************************************************************
SendStopBit
bsf     STATUS,RP0 ; select page 1
bcf     I2C_SCL
bcf     I2C_SDA ; set SDA low
bsf     I2C_SCL ; Clock is pulled up
call    Delay10uS
bsf     I2C_SDA ; give a rising edge on SDA while CLOCK is high
    bcf     _Bus_Busy ; on a stop condition bus is considered Free
return

;*****************************************************************************************
; Abort Transmission / Send STOP Bit & set Abort Flag
;*****************************************************************************************
AbortTransmission
call SendStopBit
bsf     _Abort
return
;*****************************************************************************************
; Transmit Address (1st Byte)& Put in Read/Write Operation
;  Transmits Slave Addr On the 1st byte and set LSB to R/W operation
;  Slave Address must be loaded into SlaveAddr reg
;  On Success, return TRUE in WREG, else FALSE in WREG
;   If desired, the failure may tested by the bits in Bus Status Reg
;*******************************************************************************************
SendSlaveAddr
    bcf     _ACK_Error     ; reset Acknowledge error bit
movf SlaveAddr,W
    movwf DataByte ; load addr to Data Byte for transmission
    call SendData ; send 8 bits of address
; if successfully transmitted, expect an ACK bit
_AddrSendTest
    btfss _Txmt_Success ; skip if successful
    goto _AddrSendFail
    retlw TRUE
_AddrSendFail
    btfss _ACK_Error
    retlw FALSE ; Addr Txmt Unsuccessful, so return 0
; Address Not Acknowledged, so send STOP bit
    call SendStopBit
    retlw FALSE ; Addr Txmt Unsuccessful, so return 0
;*******************************************************************************************
; TRANSMIT A BYTE OF DATA
; The data to be transmitted must be loaded into DataByte Reg
;*******************************************************************************************
SendData                        ; send 8 bits & wait for ACK

bcf     _Txmt_Success ; reset status bit
movlw 0x08
movwf BitCount

TxmtNextBit
bcf     I2C_SCL         ; set clock low
call    Delay10uS
rlf     DataByte, F     ; MSB first, Note DataByte Is Lost
        bcf     I2C_SDA
btfsc STATUS,C
bsf     I2C_SDA
call    Delay10uS
bsf     I2C_SCL     ; set clock high
; check if clock is high, else clock is being stretched
call    Delay10uS
decfsz BitCount, F
goto TxmtNextBit
; Check For Acknowledge
bcf     I2C_SCL     ; set clock low
bsf     I2C_SDA     ; Release SDA line for Slave to pull down
call    Delay10uS
bsf     I2C_SCL     ; clock for slave to ACK
call    Delay10uS

bcf     STATUS,RP0 ; select PAGE 0 to test PortA pin SDA
btfsc _SDA     ; SDA should be pulled low by slave if OK
        goto _TxmtErrorAck

bsf     STATUS,RP0      ; select page 1
bcf _Txmt_Progress ; reset TXMT bit in Bus Status
bsf _Txmt_Success ; transmission successful
bcf _ACK_Error     ; ACK OK
return
_TxmtErrorAck
RELEASE_BUS
bcf _Txmt_Progress ; reset TXMT bit in Bus Status
bcf _Txmt_Success ; transmission NOT successful
bsf _ACK_Error     ; No ACK From Slave
return
;********************************************************************************************
; General Purpose Delay Routine
;********************************************************************************************
Delay10uS       ; 2us for the Call + 8 nops + 2us for return = 10us
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
return
;********************************************************************************************


RETARDOS.INC

Código: [Seleccionar]
;**************************** Librería "RETARDOS.INC" *********************************
;
; ===================================================================
;   Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS"
;   E. Palacios, F. Remiro y L. López.
;   Editorial Ra-Ma.  www.ra-ma.es
; ===================================================================
;
; Librería con múltiples subrutinas de retardos, desde 4 microsegundos hasta 20 segundos.
; Además se pueden implementar otras subrutinas muy fácilmente.
;
; Se han calculado para un sistema microcontrolador con un PIC trabajando con un cristal
; de cuarzo a 4 MHz. Como cada ciclo máquina son 4 ciclos de reloj, resulta que cada
; ciclo máquina tarda 4 x 1/4MHz = 1 µs.
;
; En los comentarios, "cm" significa "ciclos máquina".
;
; ZONA DE DATOS *********************************************************************

CBLOCK  0x20
R_ContA ; Contadores para los retardos.
R_ContB
R_ContC
ENDC
;
; RETARDOS de 4 hasta 10 microsegundos ---------------------------------------------------
;
; A continuación retardos pequeños teniendo en cuenta que para una frecuencia de 4 MHZ,
; la llamada a subrutina "call" tarda 2 ciclos máquina, el retorno de subrutina
; "return" toma otros 2 ciclos máquina y cada instrucción "nop" tarda 1 ciclo máquina.
;
Retardo_10micros ; La llamada "call" aporta 2 ciclos máquina.
nop ; Aporta 1 ciclo máquina.
nop ; Aporta 1 ciclo máquina.
nop ; Aporta 1 ciclo máquina.
nop ; Aporta 1 ciclo máquina.
nop ; Aporta 1 ciclo máquina.
Retardo_5micros ; La llamada "call" aporta 2 ciclos máquina.
nop ; Aporta 1 ciclo máquina.
Retardo_4micros ; La llamada "call" aporta 2 ciclos máquina.
return ; El salto del retorno aporta 2 ciclos máquina.
;
; RETARDOS de 20 hasta 500 microsegundos ------------------------------------------------
;
Retardo_500micros ; La llamada "call" aporta 2 ciclos máquina.
nop ; Aporta 1 ciclo máquina.
movlw d'164' ; Aporta 1 ciclo máquina. Este es el valor de "K".
goto RetardoMicros ; Aporta 2 ciclos máquina.
Retardo_200micros ; La llamada "call" aporta 2 ciclos máquina.
nop ; Aporta 1 ciclo máquina.
movlw d'64' ; Aporta 1 ciclo máquina. Este es el valor de "K".
goto RetardoMicros ; Aporta 2 ciclos máquina.
Retardo_100micros ; La llamada "call" aporta 2 ciclos máquina.
movlw d'31' ; Aporta 1 ciclo máquina. Este es el valor de "K".
goto RetardoMicros ; Aporta 2 ciclos máquina.
Retardo_50micros ; La llamada "call" aporta 2 ciclos máquina.
nop ; Aporta 1 ciclo máquina.
movlw d'14' ; Aporta 1 ciclo máquina. Este es el valor de "K".
goto RetardoMicros ; Aporta 2 ciclos máquina.
Retardo_20micros ; La llamada "call" aporta 2 ciclos máquina.
movlw d'5' ; Aporta 1 ciclo máquina. Este es el valor de "K".
;
; El próximo bloque "RetardoMicros" tarda:
; 1 + (K-1) + 2 + (K-1)x2 + 2 = (2 + 3K) ciclos máquina.
;
RetardoMicros
movwf R_ContA ; Aporta 1 ciclo máquina.
Rmicros_Bucle
decfsz R_ContA,F ; (K-1)x1 cm (cuando no salta) + 2 cm (al saltar).
goto Rmicros_Bucle ; Aporta (K-1)x2 ciclos máquina.
return ; El salto del retorno aporta 2 ciclos máquina.
;
;En total estas subrutinas tardan:
; - Retardo_500micros: 2 + 1 + 1 + 2 + (2 + 3K) = 500 cm = 500 µs. (para K=164 y 4 MHz).
; - Retardo_200micros: 2 + 1 + 1 + 2 + (2 + 3K) = 200 cm = 200 µs. (para K= 64 y 4 MHz).
; - Retardo_100micros: 2     + 1 + 2 + (2 + 3K) = 100 cm = 100 µs. (para K= 31 y 4 MHz).
; - Retardo_50micros : 2 + 1 + 1 + 2 + (2 + 3K) =  50 cm =  50 µs. (para K= 14 y 4 MHz).
; - Retardo_20micros : 2     + 1     + (2 + 3K) =  20 cm =  20 µs. (para K=  5 y 4 MHz).
;
; RETARDOS de 1 ms hasta 200 ms. --------------------------------------------------------
;
Retardo_200ms ; La llamada "call" aporta 2 ciclos máquina.
movlw d'200' ; Aporta 1 ciclo máquina. Este es el valor de "M".
goto Retardos_ms ; Aporta 2 ciclos máquina.
Retardo_100ms ; La llamada "call" aporta 2 ciclos máquina.
movlw d'100' ; Aporta 1 ciclo máquina. Este es el valor de "M".
goto Retardos_ms ; Aporta 2 ciclos máquina.
Retardo_50ms ; La llamada "call" aporta 2 ciclos máquina.
movlw d'50' ; Aporta 1 ciclo máquina. Este es el valor de "M".
goto Retardos_ms ; Aporta 2 ciclos máquina.
Retardo_20ms ; La llamada "call" aporta 2 ciclos máquina.
movlw d'20' ; Aporta 1 ciclo máquina. Este es el valor de "M".
goto Retardos_ms ; Aporta 2 ciclos máquina.
Retardo_10ms ; La llamada "call" aporta 2 ciclos máquina.
movlw d'10' ; Aporta 1 ciclo máquina. Este es el valor de "M".
goto Retardos_ms ; Aporta 2 ciclos máquina.
Retardo_5ms ; La llamada "call" aporta 2 ciclos máquina.
movlw d'5' ; Aporta 1 ciclo máquina. Este es el valor de "M".
goto Retardos_ms ; Aporta 2 ciclos máquina.
Retardo_2ms ; La llamada "call" aporta 2 ciclos máquina.
movlw d'2' ; Aporta 1 ciclo máquina. Este es el valor de "M".
goto Retardos_ms ; Aporta 2 ciclos máquina.
Retardo_1ms ; La llamada "call" aporta 2 ciclos máquina.
movlw d'1' ; Aporta 1 ciclo máquina. Este es el valor de "M".
;
; El próximo bloque "Retardos_ms" tarda:
; 1 + M + M + KxM + (K-1)xM + Mx2 + (K-1)Mx2 + (M-1) + 2 + (M-1)x2 + 2 =
; = (2 + 4M + 4KM) ciclos máquina. Para K=249 y M=1 supone 1002 ciclos máquina
; que a 4 MHz son 1002 µs = 1 ms.
;
Retardos_ms
movwf R_ContB ; Aporta 1 ciclo máquina.
R1ms_BucleExterno
movlw d'249' ; Aporta Mx1 ciclos máquina. Este es el valor de "K".
movwf R_ContA ; Aporta Mx1 ciclos máquina.
R1ms_BucleInterno
nop ; Aporta KxMx1 ciclos máquina.
decfsz R_ContA,F ; (K-1)xMx1 cm (cuando no salta) + Mx2 cm (al saltar).
goto R1ms_BucleInterno ; Aporta (K-1)xMx2 ciclos máquina.
decfsz R_ContB,F ; (M-1)x1 cm (cuando no salta) + 2 cm (al saltar).
goto R1ms_BucleExterno ; Aporta (M-1)x2 ciclos máquina.
return ; El salto del retorno aporta 2 ciclos máquina.
;
;En total estas subrutinas tardan:
; - Retardo_200ms: 2 + 1 + 2 + (2 + 4M + 4KM) = 200007 cm = 200 ms. (M=200 y K=249).
; - Retardo_100ms: 2 + 1 + 2 + (2 + 4M + 4KM) = 100007 cm = 100 ms. (M=100 y K=249).
; - Retardo_50ms : 2 + 1 + 2 + (2 + 4M + 4KM) =  50007 cm =  50 ms. (M= 50 y K=249).
; - Retardo_20ms : 2 + 1 + 2 + (2 + 4M + 4KM) =  20007 cm =  20 ms. (M= 20 y K=249).
; - Retardo_10ms : 2 + 1 + 2 + (2 + 4M + 4KM) =  10007 cm =  10 ms. (M= 10 y K=249).
; - Retardo_5ms  : 2 + 1 + 2 + (2 + 4M + 4KM) =   5007 cm =   5 ms. (M=  5 y K=249).
; - Retardo_2ms  : 2 + 1 + 2 + (2 + 4M + 4KM) =   2007 cm =   2 ms. (M=  2 y K=249).
; - Retardo_1ms  : 2 + 1     + (2 + 4M + 4KM) =   1005 cm =   1 ms. (M=  1 y K=249).
;
; RETARDOS de 0.5 hasta 20 segundos ---------------------------------------------------
;
Retardo_20s ; La llamada "call" aporta 2 ciclos máquina.
movlw d'200' ; Aporta 1 ciclo máquina. Este es el valor de "N".
goto Retardo_1Decima ; Aporta 2 ciclos máquina.
Retardo_10s ; La llamada "call" aporta 2 ciclos máquina.
movlw d'100' ; Aporta 1 ciclo máquina. Este es el valor de "N".
goto Retardo_1Decima ; Aporta 2 ciclos máquina.
Retardo_5s ; La llamada "call" aporta 2 ciclos máquina.
movlw d'50' ; Aporta 1 ciclo máquina. Este es el valor de "N".
goto Retardo_1Decima ; Aporta 2 ciclos máquina.
Retardo_2s ; La llamada "call" aporta 2 ciclos máquina.
movlw d'20' ; Aporta 1 ciclo máquina. Este es el valor de "N".
goto Retardo_1Decima ; Aporta 2 ciclos máquina.
Retardo_1s ; La llamada "call" aporta 2 ciclos máquina.
movlw d'10' ; Aporta 1 ciclo máquina. Este es el valor de "N".
goto Retardo_1Decima ; Aporta 2 ciclos máquina.
Retardo_500ms ; La llamada "call" aporta 2 ciclos máquina.
movlw d'5' ; Aporta 1 ciclo máquina. Este es el valor de "N".
;
; El próximo bloque "Retardo_1Decima" tarda:
; 1 + N + N + MxN + MxN + KxMxN + (K-1)xMxN + MxNx2 + (K-1)xMxNx2 +
;   + (M-1)xN + Nx2 + (M-1)xNx2 + (N-1) + 2 + (N-1)x2 + 2 =
; = (2 + 4M + 4MN + 4KM) ciclos máquina. Para K=249, M=100 y N=1 supone 100011
; ciclos máquina que a 4 MHz son 100011 µs = 100 ms = 0,1 s = 1 décima de segundo.
;
Retardo_1Decima
movwf R_ContC ; Aporta 1 ciclo máquina.
R1Decima_BucleExterno2
movlw d'100' ; Aporta Nx1 ciclos máquina. Este es el valor de "M".
movwf R_ContB ; Aporta Nx1 ciclos máquina.
R1Decima_BucleExterno
movlw d'249' ; Aporta MxNx1 ciclos máquina. Este es el valor de "K".
movwf R_ContA ; Aporta MxNx1 ciclos máquina.
R1Decima_BucleInterno         
nop ; Aporta KxMxNx1 ciclos máquina.
decfsz R_ContA,F ; (K-1)xMxNx1 cm (si no salta) + MxNx2 cm (al saltar).
goto R1Decima_BucleInterno ; Aporta (K-1)xMxNx2 ciclos máquina.
decfsz R_ContB,F ; (M-1)xNx1 cm (cuando no salta) + Nx2 cm (al saltar).
goto R1Decima_BucleExterno ; Aporta (M-1)xNx2 ciclos máquina.
decfsz R_ContC,F ; (N-1)x1 cm (cuando no salta) + 2 cm (al saltar).
goto R1Decima_BucleExterno2 ; Aporta (N-1)x2 ciclos máquina.
return ; El salto del retorno aporta 2 ciclos máquina.
;
;En total estas subrutinas tardan:
; - Retardo_20s: 2 + 1 + 2 + (2 + 4N + 4MN + 4KMN) = 20000807 cm = 20 s.
; (N=200, M=100 y K=249).
; - Retardo_10s: 2 + 1 + 2 + (2 + 4N + 4MN + 4KMN) = 10000407 cm = 10 s.
; (N=100, M=100 y K=249).
; - Retardo_5s: 2 + 1 + 2 + (2 + 4N + 4MN + 4KMN) =  5000207 cm =  5 s.
; (N= 50, M=100 y K=249).
; - Retardo_2s: 2 + 1 + 2 + (2 + 4N + 4MN + 4KMN) =  2000087 cm =  2 s.
; (N= 20, M=100 y K=249).
; - Retardo_1s: 2 + 1 + 2 + (2 + 4N + 4MN + 4KMN) =  1000047 cm =  1 s.
; (N= 10, M=100 y K=249).
; - Retardo_500ms: 2 + 1     + (2 + 4N + 4MN + 4KMN) =   500025 cm = 0,5 s.
; (N=  5, M=100 y K=249).

; ===================================================================
;   Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS"
;   E. Palacios, F. Remiro y L. López.
;   Editorial Ra-Ma.  www.ra-ma.es
; ===================================================================





SLAVE

Código: [Seleccionar]
;   I2C_SLAVE.ASM ----------------------------------------------------

  list      p=16F73           
 #include <p16F73.inc>       
   
 __CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
      ERRORLEVEL -302
      ERRORLEVEL -305

  #DEFINE NODE_ADDR   0x22 ; I2C address of this node
   
reset    ORG     0x000                   ; processor reset vector
         goto    inicio                  ; go to beginning of program
         ORG     0x004                   ; interrupt vector
         goto    ISR                     ;
inicio
        call    Setup
       
Main    NOP
        goto    Main ; Loop forever.       

; ------------------------------------SUBRUTINAS ------------------------------------------
Setup   ; Initializa variables y registros
   
    banksel PORTC       
    clrf    PIR1
    clrf    SSPBUF
    clrf    PORTB
    movlw   NODE_ADDR
    banksel SSPADD
    movwf   SSPADD
    clrf    SSPSTAT
    clrf    TRISB
    MOVLW   0xFF
    movwf   TRISC                  ; ALL INPUTS (RC3 & RC4 MUST BE INPUTS)
    bsf     PIE1,SSPIE
    bsf     INTCON,PEIE            ; Enable all peripheral interrupts
    bsf     INTCON,GIE             ; Enable global interrupts
    bcf     STATUS,RP0
    movlw   0x36                   ; Setup SSP module for 7-bit
    movwf   SSPCON                ; address, slave mode
    return

; ******************* INTERRUPT **********************************************
ISR
    banksel PIR1
    btfss   PIR1,SSPIF      ; Is this an I2C interrupt?
    goto    salida          ; No, salga.
    call    I2C_Handler     ; Yes, service I2C interrupt.
    banksel PIR1
    bcf     PIR1,SSPIF
salida
    retfie                  ; Return from interrupt.

I2C_Handler 
    banksel SSPBUF
    movf    SSPBUF,W
    movwf   PORTB
    bcf     SSPCON,SSPOV ; SSPCON<6> =0 ----> No Overflow
    banksel SSPSTAT         ; Bank 1
    bcf     SSPSTAT,BF ; SSPSTAT<0> Buffer Full
    return

 ; INCLUDES  *****************************************************************
    ; #include  <I2C_SLAVE.inc>      ; subrutinas de manejo de BUS I2C
   
    end

Espero haber aprendido como se mandan los archivos dentro de esa cajita gris

Saludos y gracias por tu ayuda :-)

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: I2C Esclavo con un PIC16F73
« Respuesta #11 en: 20 de Noviembre de 2009, 21:59:52 »
 :shock: Por lo visto al actuar sobre cualquier pin se debe modificar (En hardware) el valor del pin que en ese momento esta como entrada (I2C inactivo), Quedaría actualizar a 0 los bits del PORTA utilizados por I2C antes de comenzar algún proceso en él  :?


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado XTOPIC

  • PIC10
  • *
  • Mensajes: 17
Re: I2C Esclavo con un PIC16F73
« Respuesta #12 en: 24 de Noviembre de 2009, 14:22:01 »
Hola Suki.
Bueno parece que tenías razón  :-/ antes de mover algún pin del PORT A, primero tuve que mandar los que usaba para SDA y SCL a 1 y el TRISA 3 y 4 como salidas. Luego de eso te permite comandar las salidas de los pines del port con BSF y BCF directamente sobre el pin y sigue funcionando todo normal.
 :shock: :shock: :shock:  :?: :?: :?:sigo sin entender porqué pasa esto pero: creer o reventar :D
Achiqué bastante las rutinas para lograr algo más compacto y que no ocupe tanto espacio (  8) soy viejo y ahorro bytes de programa  :lol: ).
Ah, antes que me olvide, si pones en el Slave un dirección en el SSPADD (x ej: 0x22), hay que transmitirle exactamente ese valor para que reconozca la transmisión, o sea 0x22  y no 0x44 como pensábamos.
Ya terminé los dos programas (Master y Slave), y se comunican muy bien. Le envío el address y dos bytes de datos sin ningún problema. Y si cambio el address en el Master o en el Slave no hay comunicación.
Si a alguien le interesan los programas los puedo postear.
Lo único que no funcionaría en un entrorno I2C Bus sería la llamada general (se supone que si mandas Address = 00, todos los Slave tienen que "escuchar" la transmisión como si fuera para ellos.
Bien, de nuevo Suki, muchas gracias por tu ayuda y hasta pronto  :-) :-) :-) :-/

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: I2C Esclavo con un PIC16F73
« Respuesta #13 en: 24 de Noviembre de 2009, 15:02:08 »
Hola Suki.
Bueno parece que tenías razón  :-/ antes de mover algún pin del PORT A, primero tuve que mandar los que usaba para SDA y SCL a 1 y el TRISA 3 y 4 como salidas. Luego de eso te permite comandar las salidas de los pines del port con BSF y BCF directamente sobre el pin y sigue funcionando todo normal.
 :shock: :shock: :shock:  :?: :?: :?:sigo sin entender porqué pasa esto pero: creer o reventar :D

Debe ser como trabaja el hardware, y como los pines están como entradas se actualizan  ;-)

Ah, antes que me olvide, si pones en el Slave un dirección en el SSPADD (x ej: 0x22), hay que transmitirle exactamente ese valor para que reconozca la transmisión, o sea 0x22  y no 0x44 como pensábamos.

Seguro? mira que enviando 0x22 no sabes que operación quieres hacer en el slave, por eso en el protocolo I2C se estable la dirección en los 7 bits mas significativos y el bit LSb (0) para indicar la operación. Fue exactamente lo que comprobé en la prueba anterior, donde al enviar 0x44 o 0x45 se setea el bit R/W del registro SSPSTAT. En el slave, al recibir el primer byte se debe rotar a la derecha con carry 0 y comprobar la dirección, luego leer el bit R/W para saber que operación se solicita.

Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado XTOPIC

  • PIC10
  • *
  • Mensajes: 17
Re: I2C Esclavo con un PIC16F73
« Respuesta #14 en: 24 de Noviembre de 2009, 15:30:47 »
Estoy seguro. Cuando el SSP del Slave recibe 0x22 lo compara con lo que ya tiene almacenado en SSPADD y si los 7 bits más significativos coinciden, entonces - si está habilitado - genera un interrupt. En ese momento es que hay que decidir que es lo que quiere el  MASTER porque si llegó 0x22 (último bit 3n cero), entonces quiere decir que el Master quiere escribir datos en el Salve (prepararse para recibir datos hasta que llegue un Stop).
Si en cambio, el Slave recibe un 0x23, entonces el SSP del Slave también genera un interrupt (los 7 bits más significativos también coinciden), pero en éste caso el Master está queriendo leer datos del Salve y el programa debe cargar SSPBUF y esperar que el Master lo lea.
Las direcciones pares son para escribir en el Slave y las direcciones impares son para leer del Salve. Por eso es que sólo hay 127 direcciones posibles (en realidad según la Norma de I2C bus hay sólo 112 direcciones posibles porque algunas están reservadas, como por ejemplo: 0x00 que es la llamada general).
En mi caso por ahora, no estoy leyendo del Slave pero la escritura funciona bien de esta forma.
Si hay otra explicación estoy abierto a escucharla (la información siempre enriquece  :) )
Saludos :-/ :-/ :-/