TODOPIC
Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: ales en 27 de Marzo de 2008, 14:15:58
-
Hola a todos y gracias por leer mis dudas
Estoy haciendo el Proyecto Final en Ingeniería Automática en donde por cierto no tuve un plan docente sobre PIC solo sobre 8051 y 8086, solo he programado en PIC de forma autodidacta por los conocimientos que tenía en C y los micros antes mencionados. Estoy programando con el CCS y sería bueno que cualquier respuesta me la hagan llegar a través de este compilador o con una explicación.
Entrando en detalles:
Necesito conectar un PIC 16F877A como Master a 16 PIC 16F877A como esclavos, además conectaré un banco de 8 memorias 24LC512 y todo por el bus I2C.
Tengo varios problemas:
1 - Ya logro escribir en todas las memorias pero se lee de ellas cualquier dato menos el que escribo, estuve viendo alguna información en el foro sobre conectar resistencias PULL-UP a Vcc por lo que las probaré a ver si funcionan, aunque no vi nada respecto a la conexión de más de una memoria y la librería que me proporciona el CCS está configurada para 1 sola memoria y tuve que reprogramarla. Si han visto algo al respecto y me lo hacen llegar se los agradeceré así puedo comparar mis ideas.
2 - El otro problema y no menos importante es que logré enviar información a los esclavos, pero No logró enviar información de los esclavos al Master (Me refiero a las PIC esclavas. Con respecto a esto mis PIC esclavas tendrán el mismo código fuente por lo que su identifiación para el Master será por Hardware, o sea el mismo programa de los esclavos leerá en su inicialización su identificación, creo que es bueno aclarar esto porque he visto que siempre se habla del protocolo de I2C de un bit R/W para leer o escribir en los esclavos y no se como encajarlo con mis esclavos. La idea de mis esclavos es algo así como las patas A2, A1 y A0 de las memorias 24LC512 donde a través de estas se pone la identificación de cada memoria y ellas por supuestos mantienen un mismo programa.
Resumiendo el punto 2: Necesito establecer comunicación con varios esclavos PIC (16) poniéndoles identificación por Hardware a través del puerto I2C.
Si los agobie un poco con tanta explicación les pido disculpa es que consideraba necesaria toda la información para que les fuera más fácil poder ayudarme.
También me pueden escribir a: ales_rf@yahoo.es
Y les recuerdo que cualquier información que me hagan llegar me será de mucha utilidad.
Gracias nuevamente, se que utilizan su tiempo para hacer del mio más productivo.
-
Qeu tal ales,
Bienvenido al foro y solo te recuerdo que te pases a leer las reglas del foro para que en un futuro no te llamen la atencion los amigos moderadores. ESto es claro para mantener el mejor orden en el mismo, se que comprenderas el punto.
Con respecto a tus dudas.
El bus I2C es un bus de open drain por lo que si no pones las resistencias de pull-up el bus no trabajara adecuadamente, necesitas colocarlas y el valor de las mismas es de unos 4.7 Kohm.
Ahora bien el protocolo I2C es protocolo serial sincrono mestro-esclavo. Esto que quiere decir que necesitas una senail de clock para sincronizar los datos, la cual es generada por el modulo mestro. Los esclavos no pueden enviar informacion a menos que el maestro los solicite, ya que el maestro es quien genera la senial de clock. Por lo tanto si quieres enviar informacion de alguno de los esclavos, el maestro comienza la comunicacion y le solicita los datos a los esclavos.
Saludos y espero haberte ayudado a despejar las dudas.
Elreypic.
-
El CCS trae ejemplos de como implementar un maestro y un esclavo, estúdiatelo por que es muy didáctico y esta perfectamente explicado.
Un saludo
-
Lo de la identificacion por hardware no es mas que una "ayuda" para que el usuario pueda elegir la direccion de la memo, pues sabemos que no podemos elegir "libremente" la direccion de ellas dado que no son micros como para ser reprogramados 100% en su esencia.
Pero en un micro eso cambia. Si tu aplicacion exige que se pueda cambiar la direccion de un micro "on the fly" (osea sin tener que reprogramar el micro), entonces adelante con la identificacion por hardware. De lo contrario, es absurdo, pues desde el mismo programa puedes asignar una direccion a tu micro. No he andado con tu micro (ese modelo exacto) pero todos son parecidos, y supongo que si miras en el datasheet encontraras un registro de 8 bits donde puedes poner la direccion de tu pic como I2C esclavo. Escribe en ese registro antes de cualquier transaccion I2C, y adelante.
La identificacion por hardware va por el mismo hilo: Al principio del programa lees unos determinados pines, y de acuerdo a su estado (1 o 0) cambias los bits de la direccion, la cual luego escribiras, antes de cualquier transaccion I2C, en el registro de direccion I2C esclavo.
Un saludo.
-
Gracias por responderme, pero tuve un fin de semana muy bueno y ya logré la comunicación I2C con las 8 memorias y con los Esclavos que puedo poner hasta 120, aunque solo por ahora hallan 4.
Necesito identificación de dirección por HW ya que mis esclavos tendrán el mismo programa y necesitaba conocer cual era cada cual.
Aqui les adjunto mis software y el hardware del Proteus por si les sirve de algo.
Gracias por todo.
-
Quemas ales
Es para comentarle que estoy intentando hacer la comunicacion I2C entre un maestro y varios esclavos, y mi problema es que solo me acepta la comunicacion con el primer esclavo que me comunico y al querer comunicarme con otro esclavo se pierde el maestro y creo que es la sincronizacion del SCL.
Pero estuve leyendo en este foro y usted logro comunicarse con varios microcontroladores 16F877A, sera posible que me colabore con este problema o que me oriente con esta comunicacion I2C.
Le recuerdo enviandole este mensaje a su correo, de todas maneras dejo mi direccion de correo para podernos comunicar.
oschupocar@yahoo.es
le agradeceria si me colabora, porque es de suma importancia
-
Hola Oschupocar, me gustaría ayudarte pero necesito que seas un poco más específico, o al menos, pon el codigo del programa para darle una hojeada y sacar conclusiones, además en esto de la I2C es importante saber con que programa estás corriendo el HW y con cual el SW, yo por ejemplo trabajo con Proteus 7.2 y CCS, y con el proteus es un dolor de cabeza muchas cosas por eso te digo de saber si es éste o no.
Saludos.
-
Bueno Ales Gracias por la pronta respuesta, Yo estoy trabajando en MPLAB v8 y proteus 7,2. No se si el codigo tenga problema debido a que esta comunicacion funciona bien con el maestro y un solo esclavo, sin importar la direccion del Slave.
;Slave
list p=16F877A
include "P16F877A.INC"
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _WRT_OFF & _LVP_ON & _CPD_OFF
errorlevel 1,-301
;Definición de constantes
#define DirNodo b'00001000' ;Dirección I2C de este esclavo
;Definición de variables
cblock 0x20
MensajeIn ;Contendrá el dato recibido por I2C del master
MensajeOut ;Contendrá el dato a enviar por I2C al master
BkStatus ;Backup del registro STATUS
BkW ;Backup W
Temp ;Variable Temporal usada para evaluación de eventos I2C
endc ;Fin de definiciones
org 0x00
goto INICIO
org 0x04
;-------------------------------------------------------------------------------
Interrupcion ;RUTINA DE INTERRUPCIÓN. Se ocupa de los eventos I2C
;-------------------------------------------------------------------------------
;Guardamos copia de algunos registros
movwf BkW ;Hace copia de W
movf STATUS,W ;Hace copia de registro de estado
banksel PORTA
movwf BkStatus
;Chequeamos si la interrupción es por evento I2C. En caso positivo llamamos
;a la rutina de proceso del evento
banksel PIR1
btfss PIR1,SSPIF ;Ha ocurrido un evento SSP? (I2C)
goto IntNoSSP ;No. entonces será por otra cosa. Saltamos.
call SSP_Handler ;Si. Procesamos el evento. Si se reciben ordenes, quedarán
;registradas en "MensajeIn". Se enviarán las ordenes
;guardadas en "MensajeOut".
banksel PIR1
bcf PIR1,SSPIF ;Limpiamos el flag
goto Rest
IntNoSSP ;Aquí se gestionan interrupciones que no son por SSP
;..........
; En caso de necesitarse, poner aquí la rutina de gestión de interrupciones
; que no sean por bus I2C
;..........
Rest ;Restauramos las copias de los registros
movf BkStatus,W ;Restaura las copias de registros
movwf STATUS ;registro de estado
movf BkW,W ;registro W
retfie
;-------------------------------------------------------------------------------
INICIO ;Inicio del cuerpo del programa
banksel TRISB ;Apunta a banco 1
clrf TRISB ;Salida (Leds)
banksel PORTB ;Apunta a banco 0
clrf PORTB ;Limpia puerto B
call init_i2c_Slave ;Configuración para uso de i2c
banksel INTCON
bsf INTCON,GIE ;Activamos las interrupciones
banksel MensajeIn
clrf MensajeIn
clrf MensajeOut
MLoop
movlw 0xF0 ;dato cualquiera por I2C que metemos en
movwf MensajeOut ;"MensajeOut" para cuando el Master se lo pida
movf MensajeIn,W ;Muestra por port B (leds)...
movwf PORTB ;...el ultimo valor enviado por el Master
goto MLoop
;*********************************************************************************
; SUBRUTINAS
;*********************************************************************************
;-------------------------------------------------------------------------------
init_i2c_Slave ;Inicializa valores para uso de I2C en Slave
;Ha de ser llamado tras definir TRISC y un valor para
;ClockValue. Para frecuencia SCL=Fosc/(4x(ClockValue+1))
;-------------------------------------------------------------------------------
;Guardamos copia de algunos registros
movwf BkW ;Hace copia de W
movf STATUS,W ;Hace copia de registro de estado
banksel PORTA
movwf BkStatus
;Configuramos I2C
banksel TRISC ; Pasamos a direccionar Banco 1
movlw b'00011000' ; Establece líneas SDA y SCL como entradas...
iorwf TRISC,f ;..respetando los valores para otras líneas.
bcf SSPSTAT,CKE ; Establece I2C input levels
bcf SSPSTAT,SMP ; Habilita slew rate
bsf SSPCON2,GCEN ; Habilita direccionamiento global
movlw DirNodo ; Dirección esclavo
movwf SSPADD ;
banksel SSPCON ; Pasamos a direccionar Banco 0
movlw b'00110110' ; Slave mode, SSP enable, velocidad segun...
movwf SSPCON ; ... Fosc/(4x(SSPADD+1))
bcf PIR1,SSPIF ; Limpia flag de eventos SSP
bcf PIR1,7 ; Limpia bit. Mandatorio por Datasheet
;Configuración para interrupciones por evento I2C
banksel PIE1
bsf PIE1,SSPIE
bsf INTCON,PEIE
;Restauramos las copias de los registros
movf BkStatus,W ;Restaura las copias de registros
movwf STATUS ;registro de estado
movf BkW,W ;registro W
return
; --------------------------------------------------------------------------------------
SSP_Handler ; Este manejador controla cada evento SSP (I2C) acontecido.
; El código que se muestra abajo chequea 5 posibles estados.
; Cada uno de los 5 estados SSP son identificados haciendo
; XOR de los bits del registro SSPSTAT con mascaras de bits
; predeterminadas. Una vez que el estado ha sido identificado
; se llevan a cabo las acciones pertinentes. Los estados
; indefinidos son considerados como estados de error.
; State 1: Operación de escritura I2C, ultimo byte era de dirección.
; SSPSTAT bits: S = 1, D_A = 0, R_W = 0, BF = 1
; State 2: Operación de escritura I2C, ultimo byte era de datos.
; SSPSTAT bits: S = 1, D_A = 1, R_W = 0, BF = 1
; State 3: Operación de lectura I2C, ultimo byte era de dirección.
; SSPSTAT bits: S = 1, D_A = 0, R_W = 1, BF = 0
; State 4: Operación de lectura I2C, ultimo byte era de datos.
; SSPSTAT bits: S = 1, D_A = 1, R_W = 1, BF = 0
; State 5: Reset lógico del Slave I2C por NACK del master.
; SSPSTAT bits: S = 1, D_A = 1, R_W = 0, BF = 0
; --------------------------------------------------------------------------------------
banksel SSPSTAT
movf SSPSTAT,W ; Obtiene el valor de SSPSTAT
andlw b'00101101' ; elimina los bits no importantes SSPSTAT.
banksel Temp
movwf Temp ; para chequeo posterior.
State1: ; Operación de escritura, ultimo byte ha sido
movlw b'00001001' ; de dirección, el buffer está lleno.
banksel Temp
xorwf Temp,W ;
btfss STATUS,Z ; Estamos en el primer estado?
goto State2 ; No, checkeamos siguiente estado
call ReadI2C ; SI. Hacemos un read SSPBUF (para vaciar buffer).
; El Hardware se ocupa de mandar Ack
return
State2: ; Operación de escritura, ultimo byte ha sido
movlw b'00101001' ; de datos, el buffer está lleno.
banksel Temp
xorwf Temp,W
btfss STATUS,Z ; Estamos en el segundo estado?
goto State3 ; NO, checkeamos siguiente estado
call ReadI2C ; SI, Tomamos el byte del SSP.
;Aquí tenemos en W el valor del dato recibido
movwf MensajeIn
return
State3: ; Operación de lectura, ultimo byte ha sido
movlw b'00001100' ; de dirección, el buffer está vacío
banksel Temp
xorwf Temp,W
btfss STATUS,Z ; Estamos en el tercer estado?
goto State4 ; NO, checkeamos siguiente estado
;Aquí debemos poner en W el valor del dato a enviar (solicitado por el master)
movf MensajeOut,W
call WriteI2C ; SI, escribimos el byte en SSPBUF
return
State4: ; Operación de lectura, ultimo byte ha sido
movlw b'00101100' ; de datos, el buffer está vacío
banksel Temp
xorwf Temp,W
btfss STATUS,Z ; Estamos en el cuarto estado?
goto State5 ; NO, checkeamos siguiente estado
;Aquí debemos poner en W el valor del dato a enviar (solicitado por el master)
movf MensajeOut,W
call WriteI2C ; SI, escribimos el byte en SSPBUF
return
State5:
movlw b'00101000' ; Se ha recibido un NACK mientras se transmitían...
banksel Temp
xorwf Temp,W ; ..datos al master. Lo lógica del Slave..
btfss STATUS,Z ; ..se resetea en este caso. R_W = 0, D_A = 1
goto I2CErr ; y BF = 0
return ; Si no estamos en State5, entonces es
I2CErr ; que algo fue mal
nop ; Algo fue mal
return
;---------------------------------------------------------------------
WriteI2C ;Usada por SSP_Handler para escribir datos en bus I2C
;---------------------------------------------------------------------
banksel SSPCON
movwf SSPBUF ; Escribe el dato en W
bsf SSPCON,CKP ; Libera el reloj
return
;---------------------------------------------------------------------
ReadI2C ;Usada por SSP_Handler para escribir datos en bus I2C
;---------------------------------------------------------------------
banksel SSPBUF
movf SSPBUF,W ; Toma el byte y lo guarda en W
return
;********************************************* FIN *****************************************************
END
-
;Master
LIST p=16F877A
INCLUDE "P16F877A.INC"
errorlevel 1,-301
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _WRT_OFF & _LVP_ON & _CPD_OFF
;Definición de constantes
#define ClockValue d'49' ;(100khz) valor para cálculo de vel. I2C que pasará a SSPADD
;Definición de variables
cblock 0x20
MensajeIn ;Contendrá el dato recibido por I2C del slave
MensajeOut ;Contendrá el dato a enviar por I2C al slave
DirSlave ;Dirección del Slave para escritura
BkStatus ;Backup del registro STATUS
BkW ;Backup W
BDel0 ;Usada en retardos. Usada por subr "HacerTiempo"
BDel1 ;Usada en retardos. Usada por subr "HacerTiempo"
BDel2 ;Usada en retardos. Usada por subr "HacerTiempo"
Pausa ;Pausa en centesima de sg. Usada por subr "HacerTiempo"
endc ;Fin de definiciones
org 0x00
goto INICIO
org 0x04
;-------------------------------------------------------------------------------
INICIO ;Inicio del cuerpo del programa
banksel PORTA
CLRF PORTA
banksel TRISB ;Apunta a banco 1
clrf TRISE ; Prende led para saber si Tx o Rx
bsf TRISA,0
bsf TRISA,1
clrf TRISD
movlw 0x06 ;Pone el puerto A digital
movwf ADCON1 ;
movlw b'00000000' ;Salida (Leds)
movwf TRISB ;
banksel PORTB ;Apunta a banco 0
clrf PORTA ;Limpia puerto A
clrf PORTB ;Limpia puerto B
clrf PORTE ;Limpia puerto E
clrf PORTD
call init_i2c_Master ;Configuración para uso de i2c
clrf MensajeIn
clrf MensajeOut
movlw d'10' ;Pausa de 10 centésimas de segundo para que en...
movwf Pausa ;...el arranque de tiempo a los slaves a quedar...
call HacerTiempo ;..configurados adecuadamente.
MLoop
;ENVIO DE UN BYTE AL SLAVE
;Se ha de guardar el byte que se quiere transmitir en "MensajeOut" y
;la dirección del Slave en "DirSlave". Tras esto solo hay que llamar
;a la subrutina "Enviar"
;***********************
btfsc PORTA,0 ;***
goto $-1 ;***
;***********************
movlw 0x0A ;dato cualquiera por I2C que metemos en
movwf MensajeOut ;"MensajeOut" para envío por I2C
movlw b'00001000' ;Establece dirección de envío y escritura.
Movwf DirSlave ;..es decir, dirección del slave
call Enviar ;Envía el dato de "MensajeOut" al Slave
;***********************
btfss PORTA,0 ;***
goto $-1 ;***
;***********************
;PETICION DE UN BYTE DE DATOS AL SLAVE
;Se ha de la dirección del Slave en "DirSlave". Tras esto solo hay que llamar
;a la subrutina "Recibir" y se obtendrá el dato en "MensajeIn"
;***********************
btfsc PORTA,0 ;***
goto $-1 ;***
;***********************
movlw b'00001000' ;Establece dirección de solicitud..
Movwf DirSlave ;..es decir, dirección del slave
call Recibir ;Toma dato del Slave...
movf MensajeIn,W ;... a través de "MensajeIn"...
movwf PORTB ;...y lo muestra por PORTB (Leds)
;***********************
btfss PORTA,0 ;***
goto $-1 ;***
bsf PORTE,0 ;***
;***********************
;***********************
btfsc PORTA,1 ;***
goto $-1 ;***
;***********************
movlw 0x0A ;dato cualquiera por I2C que metemos en
movwf MensajeOut ;"MensajeOut" para envío por I2C
movlw b'00011000' ;Establece dirección de envío y escritura.
Movwf DirSlave ;..es decir, dirección del slave
call Enviar ;Envía el dato de "MensajeOut" al Slave
;***********************
btfss PORTA,1 ;***
goto $-1 ;***
;***********************
;PETICION DE UN BYTE DE DATOS AL SLAVE
;Se ha de la dirección del Slave en "DirSlave". Tras esto solo hay que llamar
;a la subrutina "Recibir" y se obtendrá el dato en "MensajeIn"
;***********************
btfsc PORTA,1 ;***
goto $-1 ;***
;***********************
movlw b'00011000' ;Establece dirección de solicitud..
Movwf DirSlave ;..es decir, dirección del slave
call Recibir ;Toma dato del Slave...
movf MensajeIn,W ;... a través de "MensajeIn"...
movwf PORTB ;...y lo muestra por PORTB (Leds)
;***********************
btfss PORTA,1 ;***
goto $-1 ;***
bsf PORTE,1 ;***
;***********************
goto MLoop
;*********************************************************************************
; SUBRUTINAS
;*********************************************************************************
;-------------------------------------------------------------------------------
init_i2c_Master ;Inicializa valores para uso de I2C en Master
;Ha de ser llamado tras definir TRISC y un valor para
;ClockValue. Para frecuencia SCL=Fosc/(4x(ClockValue+1))
;-------------------------------------------------------------------------------
;Guardamos copia de algunos registros
movwf BkW ;Hace copia de W
movf STATUS,W ;Hace copia de registro de estado
banksel PORTA
movwf BkStatus
;Configuramos I2C
banksel TRISC ; Pasamos a direccionar Banco 1
movlw b'00011000' ; Establece líneas SDA y SCL como entradas...
iorwf TRISC,f ;..respetando los valores para otras líneas.
movlw ClockValue ; Establece velocidad I2C segun...
movwf SSPADD ; ...valor de ClockValue
bcf SSPSTAT,6 ; Establece I2C input levels
bcf SSPSTAT,7 ; Habilita slew rate
banksel SSPCON ; Pasamos a direccionar Banco 0
movlw b'00111000' ; Master mode, SSP enable, velocidad segun...
movwf SSPCON ; ... Fosc/(4x(SSPADD+1))
bcf PIR1,SSPIF ; Limpia flag de eventos SSP
bcf PIR1,7 ; Limpia bit. Mandatorio por Datasheet
bcf PORTC,0
bcf PORTC,1
bcf PORTC,2
;Restauramos las copias de los registros
movf BkStatus,W ;Restaura las copias de registros
movwf STATUS ;registro de estado
movf BkW,W ;registro W
return
; --------------------------------------------------------------------------------------
Enviar ;Envía un mensaje (comando) almacenado en "MensajeOut" al Slave cuya dirección
;se ha de encontrarse en la variable "DirSlave"
;---------------------------------------------------------------------------------------
;Guardamos copia de algunos registros
movwf BkW ;Hace copia de W
movf STATUS,W ;Hace copia de registro de estado
banksel PORTA
movwf BkStatus
StEnv
call Send_Start ;Envía condición de inicio
;***************************************
btfsc PORTE,0
goto apagar
goto prender
apagar
bcf PORTE,0
goto continuar
prender
bsf PORTE,0
continuar
;***************************************
call CheckIdle ;Espera fin evento
bsf PORTE,1
banksel DirSlave
movf DirSlave,W ;Dirección esclavo
call Send_Byte ;Envía dirección y orden de escritura
call CheckIdle ;Espera fin evento
call WrtAckTest ;Verifica llegada ACK
banksel SSPCON2
bcf SSPCON2,ACKSTAT ;limpia flag ACK
xorlw .1
btfsc STATUS,Z ;Chequea si llegó ACK
goto StEnv ;No. Reintentamos envío
banksel MensajeOut ;Si. Seguimos con envío dato
movf MensajeOut,W ;Lo deja en W para que la subrutina Send_Byte lo envíe
call Send_Byte ;envía por i2c
call CheckIdle ;Espera fin evento
call Send_Stop ;Envia condición de parada
call CheckIdle ;Espera fin evento
;Restauramos las copias de los registros
movf BkStatus,W ;Restaura las copias de registros
movwf STATUS ;registro de estado
movf BkW,W ;registro W
return
; --------------------------------------------------------------------------------------
Recibir ;Solicita dato al Slave cuya dirección ha de encontrarse en la variable
;"DirSlave" y lo mete en "MensajeIn".
;---------------------------------------------------------------------------------------
;Guardamos copia de algunos registros
movwf BkW ;Hace copia de W
movf STATUS,W ;Hace copia de registro de estado
banksel PORTA
movwf BkStatus
StRec call Send_Start ;Envía condición de inicio
call CheckIdle ;Espera fin evento
banksel DirSlave
movf DirSlave,W ;Dirección esclavo
iorlw b'00000001' ;con orden de lectura
call Send_Byte ;Envía dirección y orden de lectura
call CheckIdle ;Espera fin evento
call WrtAckTest ;Verifica llegada ACK
banksel SSPCON2
bcf SSPCON2,ACKSTAT ;limpia flag ACK
xorlw .1
btfsc STATUS,Z ;Chequea si llegó ACK
goto StRec ;No. Reintentamos envío
;Si. Leemos dato
call Rec_Byte ;Recibe dato por i2c y lo mete en "MensajeIn"
call CheckIdle ;Espera fin evento
call Send_Nack ;Envía Nack para finalizar recepción
call CheckIdle ;Espera fin evento
call Send_Stop ;Envía condición de stop
call CheckIdle ;Espera fin evento
;Restauramos las copias de los registros
movf BkStatus,W ;Restaura las copias de registros
movwf STATUS ;registro de estado
movf BkW,W ;registro W
return
; --------------------------------------------------------------------------------------
Send_Start ;Envía condición de start
;---------------------------------------------------------------------------------------
banksel SSPCON2
bsf SSPCON2,SEN ; Envía Start
return
; --------------------------------------------------------------------------------------
Send_Ack ;Envía Ack
;---------------------------------------------------------------------------------------
banksel SSPCON2
bcf SSPCON2,ACKDT ; acknowledge bit state to send (ack)
bsf SSPCON2,ACKEN ; Inicia secuencia de ack
return
; --------------------------------------------------------------------------------------
Send_Nack ;Envía Nack para finalizar recepción
;---------------------------------------------------------------------------------------
banksel SSPCON2
bsf SSPCON2,ACKDT ; acknowledge bit state to send (not ack)
bsf SSPCON2,ACKEN ; Inicia secuencia de nack
return
; --------------------------------------------------------------------------------------
Send_Stop ;Envía condición de stop
;---------------------------------------------------------------------------------------
banksel SSPCON2
bsf SSPCON2,PEN ;Activa secuencia de stop
return
; --------------------------------------------------------------------------------------
Send_Byte ;Envía el contenido de W por i2c
;---------------------------------------------------------------------------------------
banksel SSPBUF ; Cambia a banco 0
movwf SSPBUF ; inicia condicion de escritura
return
; --------------------------------------------------------------------------------------
Rec_Byte ;Recibe dato por i2c y lo mete en "MensajeIn"
;---------------------------------------------------------------------------------------
banksel SSPCON2 ; Cambia a banco 1
bsf SSPCON2,RCEN ; genera receive condition
btfsc SSPCON2,RCEN ; espera a que llegue el dato
goto $-1
banksel SSPBUF ; Cambia a banco 0
movf SSPBUF,w ; Mueve el dato recibido ...
movwf MensajeIn ; ... a MensajeIn
return
; --------------------------------------------------------------------------------------
CheckIdle ;Chequea que la operación anterior termino y se puede proceder con
;el siguiente evento SSP
;---------------------------------------------------------------------------------------
banksel SSPSTAT ; Cambia a banco 1
btfsc SSPSTAT, R_W ; Transmisión en progreso?
goto $-1
movf SSPCON2,W
andlw 0x1F ; Chequeamos con mascara para ver si evento en progreso
btfss STATUS, Z
goto $-3 ; Sigue en progreso o bus ocupado. esperamos
banksel PIR1 ; Cambia a banco 0
bcf PIR1,SSPIF ; Limpiamos flag
return
;---------------------------------------------------------------------------------------
WrtAckTest ;Chequea ack tras envío de dirección o dato
;Devuelve en W 0 o 1 dependiendo de si llegó (0) o no (1) ACK
;---------------------------------------------------------------------------------------
banksel SSPCON2 ; Cambia a banco 1
btfss SSPCON2,ACKSTAT ;Chequea llegada ACK desde slave
retlw .0 ;llegó ACK
retlw .1 ;no llegó ACK
;---------------------------------------------------------------------------------------
HacerTiempo ;realiza una pausa del numero de centesimas de segundo especificadas en "Pausa"
;---------------------------------------------------------------------------------------
movf Pausa,W ;Coloca el valor de pausa en BDel2...
movwf BDel2 ;...para no alterar su contenido
;............................................................
; Generado con PDEL ver SP r 1.0 el 24/02/03 Hs 18:31:22
; Descripcion: Delay 10000 ciclos (1 centésima de segundo)
;............................................................
BCiclo movlw .8 ; 1 set numero de repeticion (B)
movwf BDel0 ; 1 |
BLoop1 movlw .249 ; 1 set numero de repeticion (A)
movwf BDel1 ; 1 |
BLoop2 nop ; 1 nop
nop ; 1 ciclo delay
decfsz BDel1, 1 ; 1 + (1) es el tiempo 0 ? (A)
goto BLoop2 ; 2 no, loop
decfsz BDel0, 1 ; 1 + (1) es el tiempo 0 ? (B)
goto BLoop1 ; 2 no, loop
BDelL1 goto BDelL2 ; 2 ciclos delay
BDelL2 nop ; 1 ciclo delay
;............................................................
decfsz BDel2,F ;Repite tantas veces el ciclo de una decima de segundo...
goto BCiclo ;..como se lo indique ADel2
return ; 2+2 Fin.
;******************************************************************************
END
-
Bueno Ales le explico con detalles, El maestro tiene dos pulsadores que los pusimos para que realizara las tareas de Tx Y Rx detalladamente para guiarnos y saber y que lo estaba haciendo bien, el RA0 es el pulsador que realiza la comunicacion con el esclavo 1 y la bandera que indica que si lo hizo bien es el LED en RE0, de la misma manera con el esclavo 2 y el pulsador en RA1 y el led en RE1. Los esclavos tienen el mismo codigo lo único que los diferencia es la dirección y el dato que le envian al maestro.Lo que hemos hecho es..... Nos comunicamos con el esclavo 1 enviandole un dato cualquiera que lo visualiza por el puerto B de este mismo y a su vez envia un dato al maestro que lo visualiza tambien en el puerto B del Maestro, lo siguiente es enviar un dato al esclavo 2 para visualizarlo en el puerto B y este tambien debe enviar un dato diferente al maestro para visualizar por el puerto B del maestro.
La comunicacion con el esclavo 1 funciona muy bien, pero cuando le doy pulso a RA1 para que realice la conumicacion con el esclavo 2 creemos que pierde la sincronización por lo que nos muestra la simulacion en proteus 7.2 y nunca enciende el led (bandera) que nos dice si terminó o no la comunicación.
Le envio a su correo el pantallazo que utilizamos en proteus además del archivo.
Gracias espero su respuesta.
-
Hola, bueno le envíe un correo explicándole algunos detalles del I2C, pero de todas formas le comunico por aqui que cada esclavo tiene que tener obligatoriamente una dirección única, y que si los esclavos tienen el mismo programa entonces la identificación (ID) tienes que ponersela por hardware, o sea, para dos esclavos en principio necesitas 1 solo bit porque sería 0 o 1 cada esclavo, pero la comunicación I2C que de hecho es un estándar de Phillips utiliza la dirección 0 para enviar información a todos los esclavos a la vez, por lo que necesitarás 2 pines del micro para la ID de cada esclavo. Pones una sencilla lógica en el mismo puerto de cada esclavos que represente un número y al principio del programa lo lees y entonces ya cada programa tendrá de diferente ese número que le pasas a la I2C como identificación del esclavo.
Saludos. :-)
-
Hola a todos,
Veo que pudieron conectar varios pic por i2c. Yo tengo el problema de que no puedo hacer funcionar el pic como esclavo, tengo las configuraciones hechas en ccs y simulo en proteus 7.1 (en hardware sucede lo mismo q en proteus), he hecho el seguimiento de las variables y al parecer el problema está en la función i2c_isr_state();, veo el valor que lee esta función con unos led en el puerto b y siempre es cero, por lo que no puedo llamar al pic esclavo con el maestro. Recordemos que cuando el maestro llama al esclavo la función i2c_isr_state(); es 0x80 y aumenta cada vez que se solicita un nuevo dato. En fin, si alguien ha podido solucionar este problema se lo agradeceria.
adjunto los archivos utilizados en ccs, no varian mucho de los ejemplo. He buscado información por varios lugares y no he podido dar solucion a este problema. si se fijan el esclavo es sólo una memoria con valores asignadas por una función y el maestro solo lee al esclavo, no es gran cosa pero me tiene cmplicado.
Si alguien puede ayudarme gracias!!!
Gracias
-
Disculpa amigo, anteriormente dices que dejas el software y hardware para proteus pero no veo el adjunto , lo podrias recargar.
Gracias