TODOPIC
Microcontroladores PIC => Lenguaje Basic para microcontroladores PIC => Mensaje iniciado por: DaniCNC 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:
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
' 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:
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
' 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!!!
-
hola amigo ... espero no sea muy tarde pero tengo ese codigo modificado de melas y me funiona ... hechale un ojo
ESCLAVO:
@ 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:
@ 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
-
olvide definir el i2c addres en el codigo del maestro .... es asi ,.....I2Caddress CON $04