Autor Tema: PIC como esclavo como I2C  (Leído 3499 veces)

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

Desconectado DaniCNC

  • PIC12
  • **
  • Mensajes: 74
PIC como esclavo como I2C
« en: 15 de Febrero de 2009, 09:03:41 »
Hola a Todos,

Me presento, mi nombre es Daniel y trabajo con PICs hace 8 años aproximadamente. Me registre en el foro para ver si podrian darme una mano con un problemita que tengo.

Les comento, tengo dos PICs 16f88, uno maestro y otro esclavo. Estoy tratando de escribir (esto anda) y leer (esto no anda) desde un PIC a otro con el protocolo I2C.

Lei mucho sobre el tema, decenas de ejemplos en diferentes lenguajes, idiomas pero sigo sin poder leer un byte desde el PIC maestro.

El codigo maestro es bastante simple:

Código: [Seleccionar]
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
' Master
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------

@ device pic16f88, intrc_osc_noclkout ' system clock options
@ device pic16f88, wdt_on ' watchdog timer
@ device pic16f88, pwrt_on ' power-on timer
@ device pic16f88, mclr_off ' master clear options (internal)
@ device pic16f88, protect_off ' code protect off

'-------------------------------------------------------------------------------

DEFINE OSC 8
OSCCON = %01110001 '8mhz

'-------------------------------------------------------------------------------

CMCON = 7
ADCON1 = 0 ' Disable A/D converter
ADCON0 = 0
ANSEL = 0 ' all analog pins to digital

'-------------------------------------------------------------------------------


DEFINE I2C_HOLD 1
DEFINE I2C_SLOW 1

scl VAR PORTB.4 ' i2c clock input
sda VAR PORTB.1 ' i2c data input

valor VAR BYTE ' value to read
LED VAR PORTA.6

'-------------------------------------------------------------------------------

main:
        valor = 0

'        I2CWrite sda, scl, $01, [31]
'        High LED
'        Pause 100
'        I2CWrite sda, scl, $01, [30]
'        Low LED
'        Pause 100

        I2CRead sda, scl, $01, [valor]
       
        IF (valor = 24) Then
           High LED
Pause 500
             Low LED
        EndIF
 
GoTo main

'-------------------------------------------------------------------------------

End

'-------------------------------------------------------------------------------

Y codigo esclavo es el siguiente:

Código: [Seleccionar]
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
' Slave
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------

@ device pic16f88, intrc_osc_noclkout ' system clock options
@ device pic16f88, wdt_on ' watchdog timer
@ device pic16f88, pwrt_on ' power-on timer
@ device pic16f88, mclr_off ' master clear options (internal)
@ device pic16f88, protect_off ' code protect off

'-------------------------------------------------------------------------------

DEFINE OSC 8
OSCCON = %01110001 '8mhz

'-------------------------------------------------------------------------------

CMCON = 7
ADCON1 = 0 ' Disable A/D converter
ADCON0 = 0
ANSEL = 0 ' all analog pins to digital

'-------------------------------------------------------------------------------

DEFINE I2C_HOLD 1
DEFINE I2C_SLOW 1

'-------------------------------------------------------------------------------

SSPIF VAR PIR1.3 ' SSP (I2C) interrupt flag
BF VAR SSPSTAT.0 ' SSP (I2C) Buffer Full
R_W VAR SSPSTAT.2 ' SSP (I2C) Read/Write
D_A VAR SSPSTAT.5 ' SSP (I2C) Data/Address
CKP VAR SSPCON.4 ' SSP (I2C) SCK Release Control
SSPEN VAR SSPCON.5 ' SSP (I2C) Enable
SSPOV VAR SSPCON.6 ' SSP (I2C) Receive Overflow Indicator
WCOL VAR SSPCON.7 ' SSP (I2C) Write Collision Detect

'-------------------------------------------------------------------------------

I2Caddress CON 1 ' Make our address 1

'-------------------------------------------------------------------------------

SSPADD = I2Caddress ' Set our address
SSPCON = $36 ' Set to I2C slave with 7-bit address

'-------------------------------------------------------------------------------

LEDR VAR PORTA.3 ' LED 1
LEDL VAR PORTB.3 ' LED 2
BZR  VAR PORTA.7 ' Buzzer
RL6  VAR PORTB.6 ' Relay 1
RL12 VAR PORTB.5 ' Relay 2

'-------------------------------------------------------------------------------

datain VAR BYTE ' Data in
dataout VAR BYTE ' Data out

'-------------------------------------------------------------------------------

GoTo boot

'-------------------------------------------------------------------------------

i2cslave: ' I2C slave subroutine
          SSPIF = 0

          IF R_W = 1 Then i2crd ' Read data from us

          IF BF = 0 Then i2cexit ' Nothing in buffer so exit

          IF D_A = 1 Then i2cwr ' Data for us (not address)

          IF SSPBUF != I2Caddress Then i2cexit ' Clear the address from the buffer

          GoTo i2cexit

'-------------------------------------------------------------------------------

i2cwr: ' I2C write data to us

       datain = SSPBUF ' Put data into array

       GoTo i2cexit

'-------------------------------------------------------------------------------

i2crd: ' I2C read data from us

       SSPBUF = dataout ' Get data from array                 

       CKP = 1 ' Release SCL line

       GoTo i2cexit ' That's it

'-------------------------------------------------------------------------------

i2cexit:
         SSPOV = 0

         WCOL = 0

         Return

'-------------------------------------------------------------------------------

boot:

Pause 500

High RL12

High RL6

'-------------------------------------------------------------------------------

main:
      dataout = 24

      IF SSPIF = 1 Then
         GoSub i2cslave
         Toggle LEDL
      EndIF


      IF datain = 121 Then ' on 12v
        High RL12
      EndIF

      IF datain = 120 Then ' off 12v
         Low RL12
      EndIF

      IF datain = 61 Then ' on 6v
         High RL6
      EndIF

      IF datain = 60 Then ' off 6v
         Low RL6
      EndIF

      IF datain = 31 Then ' on buzer
         High BZR
      EndIF

      IF datain = 30 Then ' off buzzer
         Low BZR
      EndIF
   
      GoTo main

'-------------------------------------------------------------------------------

End

'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------

No veo porque no puedo leer un byte desde el PIC maestro, ya pase muchas horas y creo que necesito un nuevo par de ojos que miren lo que yo no encuentro.

Saludos y gracias!

Daniel.

PD: me olvidaba, antes que alguno me diga que use los ejemplos de la pagina de MeLabs, esos no andan!!!
« Última modificación: 15 de Febrero de 2009, 09:10:09 por danielhr77 »

Desconectado INGLUCHO

  • PIC10
  • *
  • Mensajes: 3
Re: PIC como esclavo como I2C
« Respuesta #1 en: 05 de Marzo de 2009, 03:24:44 »
hola amigo ... espero no sea muy tarde pero tengo ese codigo modificado de melas y me funiona ... hechale un ojo
ESCLAVO:

 
Código: [Seleccionar]
@ DEVICE pic16f877A, XT_OSC     'Reloj interno solo
@ DEVICE pic16f877A, WDT_OFF    'Watchdog Timer desconectado
@ DEVICE pic16f877A, PWRT_ON    'Power-On Timer conectado
@ DEVICE pic16f877A, BOD_OFF    'Brown-Out Detect desconectado
@ DEVICE pic16f877A, LVP_OFF    'Low-Voltage Programming desconectado
@ DEVICE pic16f877A, CPD_OFF    'Data Memory Code Protect desconectado
'*************************************************************
DEFINE   OSC   4              ' Para trabajar con un cristal de 4MHz
define I2C_SLOW 0 ' Velocidad de I2C de 400KHz


wsave VAR BYTE $20 system     ' Guarda el registro W
ssave VAR BYTE bank0 system   ' Guarda el registro STATUS
psave VAR BYTE bank0 system   ' Guarda el registro PCLATH

'************** Aqui van las demas variables a usar***********
readcnt     VAR BYTE    ' I2C read count
datain      var byte
dataout     var byte
SCL         VAR PORTC.3 ' I2C clock input
SDA         VAR PORTC.4 ' I2C data input
TRISC=      %00011000   ' RC.3 y RC.4 config como entradas
ADCON1=6 
'*******************Flags de Registro Usadas******************
SSPIF   VAR     PIR1.3       ' SSP (I2C) interrupt flag
BF      VAR     SSPSTAT.0    ' SSP (I2C) Buffer Full
R_W     VAR     SSPSTAT.2    ' SSP (I2C) Read/Write
D_A     VAR     SSPSTAT.5    ' SSP (I2C) Data/Address
CKP     VAR     SSPCON.4     ' SSP (I2C) SCK Release Control
SSPEN   VAR     SSPCON.5     ' SSP (I2C) Enable
SSPOV   VAR     SSPCON.6     ' SSP (I2C) Receive Overflow Indicator
WCOL    VAR     SSPCON.7     ' SSP (I2C) Write Collision Detect

goto inicio
'********************* Vector de Interrupcion*****************

DEFINE INTHAND Int_Vector   ' Handler de Interrupcion 
 Int_Vector   
ASM
Int_Vector
    MOVWF wsave        ; Guardamos el registro W
    MOVF STATUS,W
    CLRF STATUS        ; Guardamos el registro STATUS
    MOVWF ssave
    MOVF PCLATH,W      ; Guardamos el registro PCLATH
    MOVWF psave
    CLRF PCLATH
endasm
;*****************Codigo de interrupcion**********************     
SSPIF = 0     ' Borra la bandera de interrupcion
IF R_W  = 1 Then i2crd      ' Leen la informacion de èl
IF BF   = 0 Then End_Int    ' Nada en el bufer entonces sale
IF D_A  = 1 Then i2cwr      ' Data for us (not address)
IF SSPBUF != $04 Then End_Int     ' Borra la direccion del buffer
goto    End_Int
'*****************leer********
i2cwr: ' I2C write data to us
datain = SSPBUF      ' Put data into array
GoTo End_Int
'*****************escribir****
i2crd: ' I2C read data from us
SSPBUF = datain
CKP = 1                  ' Release SCL line

End_Int 
SSPOV = 0
WCOL = 0
asm
        CLRF STATUS
        MOVF psave,W
        MOVWF PCLATH      ; Restauramos el registro PCLATH
        MOVF ssave,W
        MOVWF STATUS      ; Restauramos el registro STATUS
        SWAPF wsave,F
        SWAPF wsave,W     ; Restauramos el registro W
        RETFIE
eNDASM

'************************Inicio del Programa*************************
Inicio:
ADCON1=6
TRISB=0
TRISC=%00011000     ' RC.3 y RC.4 config como entradas

'****************** Inicializamos el modo I2C slave*******************
SSPADD = $04          ' Cargamos la direccion(0x04) del Slave
SSPCON2 = 0         ' Reseteamos el registro de control del I2C
SSPCON = %00110110  ' Configuramos en modo Slave
PIE1 = %00001000    ' Habilitamos la interrupcion por I2C
PIR1=0              ' Limpiamos los flags de interrupcion
INTCON = %11000000  ' Configuramos las Interrupciones por I2C
datain=0

inicio2:

goto inicio2

end   


Maestro:
Código: [Seleccionar]
@ DEVICE pic16f877A, XT_OSC     'Reloj interno solo
@ DEVICE pic16f877A, WDT_OFF    'Watchdog Timer desconectado
@ DEVICE pic16f877A, PWRT_ON    'Power-On Timer conectado
@ DEVICE pic16f877A, BOD_OFF    'Brown-Out Detect desconectado
@ DEVICE pic16f877A, LVP_OFF    'Low-Voltage Programming desconectado
@ DEVICE pic16f877A, CPD_OFF    'Data Memory Code Protect desconectado
'****************************************************************
'CONFIGURACION DEL LCD           
'****************************************************************
Define osc 4
define I2C_SLOW 0 ' Velocidad de I2C de 400KHz
Define LCD_DREG PORTB ' direcciona el bus de dato para el puerto B
DEFINE LCD_DBIT 4 'le indica con que pin del puerto comienza
DEFINE LCD_RSREG PORTA 'le indica que la escritura y lectura se define por el puerto A
DEFINE LCD_RSBIT 0 'le indica por cual pin, se va selecionar escritura o lectura
DEFINE LCD_EREG PORTA 'indica por cual puerto se va selecciona el enabled
DEFINE LCD_EBIT 1 'indica que pin va selecionar ENABLED del puerto A
DEFINE LCD_BITS 4 'tamaño del bus de datos 4 o 8
DEFINE LCD_LINES 4
'****************************************************************
ADCON1   = 6 'TODOS LOS DEL A COMO DIGITALES 
'****************************************************************
'CONFIGURACION DE ENTRADAS Y SALIDAS DE LOS PUERTOS             
'****************************************************************

'****************************************************************
'CONFIGURACION PINES DEL I2C           
'****************************************************************
SCL VAR PORTA.2 ' Clock
SDA VAR PORTA.3 ' Data
'****************************************************************
'CONFIGURACION DE VARIABLES GENERALES           
'****************************************************************

I2Caddress  CON $04 ' Direccion del esclavo es 0x04
g     VAR byte
x     VAR byte
'****************************************************************

inicio:   
for x = 0 to 255
I2CWrite SDA,SCL,I2Caddress,[x]
pause 200
I2CRead SDA,SCL,I2Caddress,[g]
pause 200
LCDOut $fe,$C0+8,#g
pause 1000
next x

goto inicio


este es un ejemplo sencillo ... lo que hace es mandar un dato con un contador al pic esclavo , despues leerlo del mismo y sacarlo por el lcd para verificar que esta bien

Desconectado INGLUCHO

  • PIC10
  • *
  • Mensajes: 3
Re: PIC como esclavo como I2C
« Respuesta #2 en: 05 de Marzo de 2009, 03:28:36 »
olvide definir el i2c addres en el codigo del maestro .... es asi ,.....I2Caddress  CON $04
 


 

anything