# programacion pic en .asm para comunicacion UART y SPI



## jecyka1 (Mar 29, 2012)

Hola, estoy haciendo un proyecto en el que pretendemos comunicar 2 pc para envio y recepcion de datos por rf. Para el montaje del mismo comunico el pc por medio de RS-232 con un pic16F73 y este a su vez ira unido a un transmisor RFM12B.
La idea principal es que el pc cree unos paquetes de 8 bits los cuales enviamos por el puerto serie al pic16F73 (a través de UART) y, a su vez, este paquete de 8 bits lo enviamos al transmisor RFM12B en modo SPI.

Hasta el momento conseguimos que nuestro programa del pc cree el paquete de 8 bits y lo envie al pic sin problemas. Pero ahora se nos plantea la duda de que si podemos configurar también este mismo pic para SPI sin que afecte a las lineas UART. Estamos programando el pic con MPLAB en .asm

Espero que me puedan ayudar porque no tenemos muchos conocimientos en esta parte y la verdad es que andamos un poco perdidos.

Muchas gracias.


----------



## Romyggar (Mar 29, 2012)

Hola

A ver si te entiendo, lo que quieres hacer es usar los módulos SPI y USART del micro para enlazar 2 pc's:

PC <----> Micro(usart):Micro(SPI) <----> RF )))))))((((((( RF <---> Micro(SPI):Micro(usart) <---> PC

No es nada complicado, pienso que hay varios puntos a tener en cuenta:

- Mirar en el datasheet del micro que estas usando pic16F73 y establecer si las lineas I/O del ambos módulos (SPI y USART) no son compartidas (si lo son, se complica la cosa)

- Suponiendo que el sistema es Bidireccional, hay que establecer una especie de "sincronizacion" por comandos, es decir, que el cuando se envie un dato, se sepa si ese dato fue entregado.

- Puede ser necesario un algoritmo de deteccion de errores

Espero y te ayude un poco lo que he escrito, y si quieres, paso a paso podremos sacar tu proyecto adelante.

Salu2


----------



## jecyka1 (Mar 29, 2012)

Muchas gracias por responder.

Exacto, nuestra comunicación se basa en ese esquema:

PC <----> Micro(usart):Micro(SPI) <----> RF )))))))((((((( RF <---> Micro(SPI):Micro(usart) <---> PC

Hasta ahora conseguimos programar sin problemas la parte: PC <----> Micro(usart) tanto para transmision como para recepcion de datos. Como has comentando, si, miramos el datasheet del pic y efectivamente NO coinciden las líneas para USART con SPI asi que para configurarlas no debería dar problemas.

Ahora mismo estamos trabajando en la elaboración del código para poder añadir esa parte del modo SPI. Voy a probar a ver si consigo que transmita por SDO los datos y te comento como nos ha ido. Te agradezco cualquier ayuda que nos puedas dar porque la verdad es que andamos un poco apuradas porque, queremos entregar el proyecto en la próxima convocatoria y sobre este tema no nos dieron mucha base en su momento.

De nuevo, gracias.


----------



## Romyggar (Mar 30, 2012)

jecyka1 dijo:


> Muchas gracias por responder.
> 
> Exacto, nuestra comunicación se basa en ese esquema:
> 
> ...



Bueno *jecyka1*, creo que en la página de microchip, puedes encontrar librerias que te servirán para manejar el módulo SPI sin tener que empezar desde cero. En este caso no te podría ayudar de manera directa ya que en estos dias no poseo el tiempo para ponder a andar mi PIC.

Sin embargo te puedo ayudar con ideas o dándote alternativas. Ya tienes la comunicación Pc - USART; bueno, entonces lo que sigue es comunicar los dos PIC via SPI en modo Master-Slave(uno debe ser maestro). Internamente debes tener un área de memoria RAM en común, en donde lo que recibas por la USART sea lo que se envie por el SPI y viceversa.

También debes tener en cuenta el sincronismo, ya que la USART generalmente se usa en modo asíncrono (tu puedes configurarla en modo síncrono si quieres). A lo que me refiero es que debes cuidar que las velocidades en las transmisiones USART deben ser iguales o inferiores a las tx's SPI, ya que haciendo la traducción USART-SPI-Transmisor ))))((( Transm.-SPI-USART
consume algo de tiempo de procesamiento en cada PIC, esto puede representar un retraso considerable en la recepción de datos en ambos PC's.

Dicho de otra manera, debes de alguna forma medir cuanto tiempo le toma al pic hacer toda la transmisión y recepción desde que *empieza a recibir* datos por la USART hasta que *termina de transmitir* toda la informacion por la SPI y viceversa simultáneamente (tx y rx al tiempo). Ya con este tiempo de "retraso", puedes calibrar bien la velocidad del SPI (que debería ser la máxima que se pueda obtener sin producir tantos errores de transmisión) y también la velocidad USART (suficiente para que no se perciba el retraso)

Espero y me hayas entendido, cualquier cosa me preguntas!

Salu2


----------



## jecyka1 (Mar 31, 2012)

Hola romyggar, sí me queda mas o menos claro todo lo que se debería tener en cuenta, gracias por la explicación.

Estuve trabajando en el programa para incluir el SPI como te comenté antes, y si no te importa te pediría si podrías exarle un ojo al código para ver si crees que vamos bien encaminadas, porque hasta ahora solo hemos podido simular en MPLAB pero no hemos hecho las pruebas físicas porque aún nos falta algo del material del pedido. En ese código solo está incluida la transmisión: PC<---->Micro(usart):Micro(SPI)

Y así, si nos puedes decir si lo que tenemos hecho hasta ahora está bien planteado nos pondremos con la recepción.

Muchas gracias, saludos.


----------



## Romyggar (Abr 2, 2012)

jecyka1 dijo:


> Hola romyggar, sí me queda mas o menos claro todo lo que se debería tener en cuenta, gracias por la explicación.
> 
> Estuve trabajando en el programa para incluir el SPI como te comenté antes, y si no te importa te pediría si podrías exarle un ojo al código para ver si crees que vamos bien encaminadas, porque hasta ahora solo hemos podido simular en MPLAB pero no hemos hecho las pruebas físicas porque aún nos falta algo del material del pedido. En ese código solo está incluida la transmisión: PC<---->Micro(usart):Micro(SPI)
> 
> ...



Hola *jecyka1*

Estuve mirando tu código, lamentablemente no puedo simularlo en estos momentos, sin embargo hay algunas mejoras estratégicas que puedes hacerle para lograr que este se a mas estable:

*Estrategia de Solucion del problema* (planteamiento de la solución):

Si fuera mi proyecto, yo programaría cada micro de la siguiente manera:

1- Vector de reset, salto la configuración
*configuración*
2- Subrutinas de configuración de los Módulos USART, SPI, y cualquier otro periférico que quiera usar.
3- Etiqueta TX_RX
*programa principal*
4- Determino el estado de los Módulos UART/SPI (supongo que usaras transmisiones asíncronas con el USART)
  - *¿He recibido datos desde el PC#1?*, (esto se verifica solo mirando las banderas de estado, ene ste caso creo que es RXIF de dicho módulo...(debes verificar en cada caso).
  - *Si fue verdadero*(*Si* recibí datos desde el PC#1), Entonces envio datos por el SPI al PC#2, y verifico el estado del módulo SPI:
  - *Si fué falso* (*No* recibí datos desde el PC#1), entonces igualmente verifico el Estado del módulo SPI: 
  -*¿Recibí datos desde el PC#2?* (verificación del Módulo SPI)
  - *Si fué verdadero* (*Si* recibí datos desde el PC#2, entonces, empiezo a transmitir datos por la USART hacia el PC#1(Hago esto ultimo si *no* estoy transmitiendo algun dato todavia hacia el PC#1, en caso de que lo esté haciendo, debo tener un pequeño control que evite el inicio de transmisiones sobrepuestas).
  - *Si fué falso* (*No* recibí datos desde el PC#2, entonces vuelvo a hacer verificación inicial del módulo USART, es decir, saltar a la etiqueta TX_RX)

Como pudiste observar, no estoy usando interrupciones, pues creo que se podrían implementar cuando ya tengas funcionando todo a bajas velocidades con este método que expuse. Las interrupciones son de cuidado cuando se manejan variables asíncronas. Pude ver que tu usas interrupciones para detectar el envío/recepción de datos

*-----------------------------------------------------------------------------------*
*Estrategias de Pruebas y mantenimiento* (prevenir fallos y errores antes de que sustentes tu proyecto):

- Debes probar la transmisión y recepción simultanea de datos a diferentes velocidades para ver como se comportan los micros, y si los datos llegan bien. Asi podrás determinar cuan rápido puedes transmitir los datos sin tener demasiados errores.

- Prueba el envío/recepción de muchos datos a la vez, quizá descubras algún "Bug"...es para estar seguros.

*-----------------------------------------------------------------------------------*
*Estrategias de programación* (mejoras en el código fuente):

Debes modularizar tu programa: Esto significa que cada bloque de código debes encapsularlo como una subrutina. Aquí te propongo algunas subrutinas:

- Configuración de módulos (2 subrutinas en total)
- Cambio de velocidad de un módulo (USART y SPI, 2 sub rutinas en total)
- Envío de datos via USART/SPI (2 subrutinas)

Adicionalmente, tendrías que usar al menos 2 registros de propósito general, que sirven de puente entre lo recibido y lo enviado:

- PC12PC2: en este registro se almacena lo que se recibe desde el pc1, y es el mismo que se usa para enviar datos al pc2
- PC22PC1: similar al anterior, pero en el sentido contrario. 


*-----------------------------------------------------------------------------------*
*Tengo ciertas dudas:*
- ¿Ambos PCs deben transmitir a la misma velocidad? ¿Que tal el PC#1 sea mas lento que el PC#2 ? 
- ¿Para cambiarle la velocidad de transmisión/recepción a los micros tendrías que reporgramarlos? 
- ¿Cabe el escenario en donde no sean 2 sinó 3 los PCs a interconectar? 


*-----------------------------------------------------------------------------------*
Si tienes alguna duda, o comentario etc, no dudes en preguntarme 

PD: ¿Cuando debes presentar tu proyecto? (si es que no lo has hecho ya )

Salu2


----------



## jecyka1 (Abr 3, 2012)

Hola romyggar,

muchas gracias por toda la información, nos queda claro todos los puntos a tener cuenta. Más o menos es como nosotras habíamos planteado, pero las estrategias que nos comentas las implementaremos para mejorar el código.

No obstante, tenemos una duda en cuanto a la configuración porque compramos unos transmisores (RFM12B) para una frecuencia de 433,92Mhz, pero en la hoja del fabricante nos dice que tenemos que configurarlo para indicarle la frecuencia de trabajo, el cristal que le incorporamos, velocidad, las posibles interrupciones... ¿Aunque hallamos comprado los transmisores para una frecuencia determinada debemos configurarlo igualmente? De ser así ¿se tendría que configurar en el mismo apartado que configuramos las lineas USART y SPI? Te adjunto el datasheet del transmisor por si quieres ver la parte esa que te digo donde aparecen los bits de configuración. 

Respecto a las dudas que me comentas:
1. En principio ambos deberían transmitir a la misma velocidad, porque el objetivo del proyecto es tratar de establecer una comunicacion bidireccional y simultánea.
2. Sí, para cambiar la velocidad del pic en las pruebas tenemos que reprogramarlo.
3. También tiene que caber la posibilidad de interconectar más PCs (hasta 8 en un futuro)  Esta es una de las mejoras que se comentarán en el proyecto, pero de momento solo vamos a realizar pruebas con 2 PCs.


P.D: El proyecto tenemos que entregarlo la primera semana de mayo De ahí que esté tan apurada con esto, porque la base que tenemos no es muy buena 


Muchas gracias de nuevo. Saludos.


----------



## Romyggar (Abr 4, 2012)

jecyka1 dijo:


> Hola romyggar,
> 
> muchas gracias por toda la información, nos queda claro todos los puntos a tener cuenta. Más o menos es como nosotras habíamos planteado, pero las estrategias que nos comentas las implementaremos para mejorar el código.
> 
> ...



Hola de nuevo *jecyka1*,

Bueno, estuve mirando el pdf que adjuntaste...y me surgió una duda: ¿Porqué elegiste precisamente este módulo?...¿fué porque usa una conexión SPI?...es que alguna vez tuve que hacer un enlace inhalámbrico entre 2 micros, y los transceptores que usé eran de lo mas sencillo de utilizar....

En lo que pude detallar, a este módulo rf, se le debe programar casi todo, sin embargo al solo encenderlo el carga unos valores por defecto en los registros internos de configuracion (Pág 14).

Te recomiendo algo, Primero conecta ambos pic usando cables, luego te preocupas por hacer funcionar los módulos RF...desde que te funcione bien la comunicacion usando cables, solamente te quedarían 2 tareas: hacer funcionar los RFs, y recalibrar los tiempos de ejecucion en los micros 8ya que al parecer, hay que programar los RFs al menos 1 vez). Aqui es donde tener cada "cosita" que hace el micro como subrutinas te es de gran ayuda, porque teniendo ya todo funcionando alámbricamente, solamente sería *incluir una subrutina extra*(Ej: Configurar_rf) y ya tendrías todo andando inalámbricamente... 

Lo segundo es que no te puedo dar una respuesta exacta de que si debes programar o no los módulos antes de usarlos, pero creería que si,  aunque mirando los valores que traen por defecto, pareciera que se necesita poca programación (la mayoría de registros vienen precargados con los valores adecuados).

Sin embargo quise entrar mas en detalle en cada registro....prepárate porque estará larga la explicación (ojalá te sirva):

Asumo las siguientes cosas:
- El  RF usa la banda de 433MHz

#------- Nombre del Registro --------------------- Valor despues de un Reset de encendido(Hexa)
1 - Configuration Setting Command ------------------------------------ 8008h
2 - Power Management Command -------------------------------------- 8208h
3 - Frequency Setting Command --------------------------------------- A680h
4 - Data Rate Command ----------------------------------------------- C623h
5 - Receiver Control Command ----------------------------------------- 9080h
6 - Data Filter Command ----------------------------------------------- C22Ch
7 - FIFO and Reset Mode Command ------------------------------------ CA80h
8 - Synchron Pattern Command ---------------------------------------- CED4h
9 - Receiver FIFO Read Command 	------------------------------------ B000h
10 - AFC Command --------------------------------------------------- C4F7h
11 - TX Configuration Control Command -------------------------------- 9800h
12 - PLL Setting Command -------------------------------------------- CC77h
13 - Transmitter Register Write Command ------------------------------- B8AAh
14 - Wake-Up Timer Command ----------------------------------------- E196h
15 - Low Duty-Cycle Command ---------------------------------------- C80Eh
16 - Low Battery Detector and Microcontroller -------------------------- C000h
     Clock Divider Command					
17 - Status Read Command -------------------------------------------- 0000h


Nota: Reset de encendido es lo mismo que POR (Power On Reset)

----------------------------------------------------------------------------------------------------
*Primer registro*

Entonces, para el primer registro la forma de analizar su estado binario sería:

*Configuration Setting* => El valor 8008h se traduciría como "Cristal Load Capacitance" = 12pF
Bits 15 al 8 no se usan
Bit 7 = "el" = internal data register = 0 = Off.
Bit 6 = "ef" = FIFO mode = 0 = Off (por favor mirar en el pdf el efecto de tener este bit en 0)
Bit 5 y 4 = b1 y b0 = Banda de frecuencia = 0 , 0 = Reservada: Aqui deberías poner un valor
------------------------------------------------------------- diferente de 0, 0, por ejemplo
------------------------------------------------------------- 0, 1 = 433Mhz.

Bits 3 al 0 = Crystal Load Capacitance = 1,0,0,0 = 12pf (1000 = 8 y segun la fórmula esto equivale
a 12pf segun al tabla: 0000 = 8,5pf - 0001 = 9pf....entonces 1000b(8d) x 0.5pf + 8.0pf = 12pf
b = binario, d = decimal.

de aqui en adelante simplifcaré las explicaciones para no hacer tan largo el post. Es tu deber leer
con paciencia y entender el porque de lo que yo escriba (pude que me equivoque  )

----------------------------------------------------------------------------------------------------
*Segundo registro: Power Management = 8208h*
*Traduce*: "Enciende el cristal oscilador"
Bit 3 "ex" = 1.

----------------------------------------------------------------------------------------------------
*Tercer registro: Frequency Setting = A680h*
*Traduce*: "Frecuencia de operacion" = 10*(C2 + 680h(1664d)/4000) = 434.16Mhz (mira la fórmula y 
comprueba este resultado) Banda = 433MHz.
Bits 10,9,7 = 1

----------------------------------------------------------------------------------------------------
*Cuarto registro: Data Rate = C623*
*Traduce*: Mirar fórmula, mis cálculos dan para Tx = 9.578kbps, para Rx = 2.6h(3h)
Bits 5,4,2,1,0 = 1

----------------------------------------------------------------------------------------------------
*Quinto registro: Receiver Control = 9080*
*Traduce*: Pin 16 = Interrupt input, response = fast, Receiver baseband = 200Khz, LNA gain select = 0
RSSI detector = -103

----------------------------------------------------------------------------------------------------
*Sexto registro: Data Filter = C22C*
*Traduce*: Filter Type = Digital filter, DOD = 4d (calcular con fórmula)

----------------------------------------------------------------------------------------------------
*Séptimo registro: FIFO and Reset Mode = CA80*
*Traduce*: Numero máximo de eventos FIFO para generar una interrupcion = 8d, Synchron pattern = 2DD4h,
FIFO fill start condition = synchron pattern, FIFO fill off, Highly sensitive RESET mode = Off.

----------------------------------------------------------------------------------------------------
*Octavo registro: Synchron Pattern = CED4*
*Traduce*: Mirar comando anterior, aqui se usan los bits b7 al b0, segun la opcion "Synchron pattern"
del registro séptimo.

----------------------------------------------------------------------------------------------------
*Noveno registro: Receiver FIFO Read = B000*
*Traduce*: Mirar primer registro, en la opcion Bit 6.

----------------------------------------------------------------------------------------------------
*Decimo registro: AFC = C4F7*
*Traduce*: Operation Mode = Keep the f.offset value independently from the state of the VDI signal,
Max deviation = +3 f res to -4 f res (mirar tabla en pdf para entender lo que significa)
Strobe edge = off, Modo de veracidad fina = On (mirar que es veracidad aqui), Bit 1 y 0, activan
los registros de calibracion del PLL interno y del circuito AFC.

----------------------------------------------------------------------------------------------------
*Undecimo registro*: TX Configuration Control = 9800
Traduce: Aqui se configuran los parámetros de la modulación FSK (mirar fórmula y calcularlos),
Output power = 0 DB.

----------------------------------------------------------------------------------------------------
*Duodécimo registro*: PLL Setting = CC77
*Traduce*: Cambia la frecuencia de reloj generada desde el micro, es decir, la que viene desde el micro
y es usada por el módulo (ver el pdf si te confundes), en este caso = 5 or 10 MHz (recommended)
Retraso en el PLL = desactivado, Dithering en el PLL loop = apagado, Ancho de banda del PLL = -102DB
----------------------------------------------------------------------------------------------------
*Décimo tercer registro*: Transmitter Register Write = B8AA
*Traduce*: Despues de enviar este comando, se puede empezar a transmitir los datos. Mirar la grafica que
muetsra un ejemplo de transmision, ytambien mirar que el bit "el" del primer registro este habilitado

----------------------------------------------------------------------------------------------------
*Décimo cuarto registro*: Wake-Up Timer = E196
*Traduce*: 1.03*M*2^R + 0.5 [ms] = 1.03*(M=96h,150d)*2^(1h,1d) + 0.5 = 309ms

----------------------------------------------------------------------------------------------------
*Décimo quinto registro*: Low Duty-Cycle = C80E
*Traduce*: Ciclo util = (111b(7d)*2+1)/M*100 = 10%; M = 150 (mirar registro anterior). 

----------------------------------------------------------------------------------------------------
*Décimo sexto registro*: Low Battery Detector and Microcontroller Clock Divider = C000
*Traduce*: Maneja el detector de bateria baja y una salida de reloj parausar en un micro, en este caso
la frecuencia del reloj = 1Mhz, y los bits V1 al V0 indicarían el estado del voltaje de alimentacion
con respecto a un factor Vtb (mirar formula).

----------------------------------------------------------------------------------------------------
*Décimo séptimo registro*: Status Read = 0000
*Traduce*: Indica el estado actual del trancesptor, mirar trabla.

----------------------------------------------------------------------------------------------------


Espero y te haya sido de utilidad este post tan largo. 

PD: Sube cuando puedas alguna foto de tu montaje....


----------



## MaikahV (Abr 23, 2012)

Hola a todos, veo que están utilizando el PIC 16F73 con el modo SPI; Yo también estoy utilizando ese pic para enviar datos de 16 bits desde el PC hasta el PIC por usart y de este hasta el otro PIC por SPI. Como he visto lo que explican, almaceno los 16 bits en dos registros internos del PIC para despues enviarlos al PIC. En mi caso uno de los PIC actúa de transmisor y otro de receptor. Lo que pasa es que el receptor solo llega a recibir uno de los bytes, a pesar de que en el código del transmisor se incluye el envío de los dos bytes.

Creo que el problema está en que pongo una tras otra las instrucciones de que se manden, desde los registros internos, los 2 bytes al SSPUF, por lo que de alguna forma el receptor solo llega a leer uno y el otro se pierde. ¿Habría alguna forma de detectar esto?, es decir, podría hacer algo para que el transmisor no envíe el segundo byte hasta que el receptor le indique que ha leído el primero?

Muchas gracias de antemano y espero puedan ayudarme con el problema.

A continuación añado los códigos del transmisor y receptor 

*********************Transmisor***********************


```
LIST        P=16f73
INCLUDE        <P16F73.INC>
__CONFIG _CP_OFF &_WDT_OFF &_PWRTE_ON &_HS_OSC
 

BYTE_1        equ        20h            ;1º byte transmitido
BYTE_2        equ        21h
VALOR1            equ        24h
Guarda_W        equ        27h
Guarda_STATUS    equ        28h

; Inicio

           org            0x00
        goto        inicio
        org           0x04
        goto        inter

 

; Tranmisión en modo SPI

COM_SPI 

        bcf            STATUS,RP0        ; Banco 0
    
        bcf            STATUS,RP1  

        movf        BYTE_1,W

        movwf        SSPBUF            ; Se transmite el 1º dato
  
        bsf            PORTB,3
        
        movf        BYTE_2,W

        movwf        SSPBUF            ; Se transmite el 2º dato    

        bsf            PORTB,4
        
        nop

        nop
        
        return
    
 
; Tratamiento de interrupción

inter          
        movwf        Guarda_W         ; guardo los registros afectados por la interrupción

        swapf        STATUS,W

        movwf        Guarda_STATUS

        btfss        PIR1,RCIF        ; ¿Hay Interrupción por recepción?    

        goto        VERIFICAR

        bsf         PORTB,1            ; Encendemos 1º led para monitorizar la recepcion de dato

          bcf            PIR1,RCIF        ; reponer flag     

        movf        RCREG,W           ; Lectura del dato recibido

        btfss         VALOR1,1          ; ¿Variable AUX=1? vale 0 al comienzo

        goto        TRANSMITIR_BYTE

           movwf        BYTE_2           ; No, almacena 2º byte    
        
        bsf            VALOR1,2            ;Se activa variable que indica que se han almacenado los 2 registros    

        bcf            VALOR1,1    

        swapf        Guarda_STATUS,W

        movwf        STATUS

        swapf        Guarda_W,F

        swapf        Guarda_W,W    

        retfie
        

VERIFICAR
        movlw        b'00000000'     ; Se borran todas las interrupciones para que no hay conflicto

        movwf        PIR1

        movlw        b'00000000'     

        movwf        PIR2
        
        retfie


    
TRANSMITIR_BYTE
        movwf        BYTE_1           ; Almacena 1º byte    

        bsf            VALOR1,1

        retfie

    


; Comienzo del programa principal

inicio        
        clrf        PORTB 

        clrf        PORTC

        bcf            VALOR1,1
        
        bcf            VALOR1,2

        bsf            STATUS,RP0        ; Bank01

        bcf            STATUS,RP1

        clrf        TRISB            ; PORTB como salida

        movlw        b'10010111'       ; RC7/RX=1, RC6/TX=0, RC5/SDO=0,RC4/SDI=1,RC3/SCK=0 (el resto a 1)

        movwf        TRISC        

        movlw        b'00100100'        ; Configuración USART
    
        movwf        TXSTA            ; y activación de transmisión

        movlw        .129               ; 9600 baudios

        movwf        SPBRG

        bsf            PIE1,RCIE        ; Habilita interrupción en recepción por modo USART

        bcf            STATUS,RP0        ; Bank00

        movlw        b'10010000'        ; Configuración del USART para recepción continua

        movwf        RCSTA            ; Puesta en ON

CONF_SPI

        bsf            STATUS,RP0        ; Seleccionamos el Banco 1
    
        bcf            STATUS,RP1     
 
        movlw        b'11000000'     ; SMP=1 , CKE=1 , BF=0

        movwf        SSPSTAT

        bcf            STATUS,RP0        ;Seleccionamos el Banco 0

        bcf            STATUS,RP1

        movlw        b'00100010'        ;SSPEN=1, CKP=0 SSPM3:SSPM0=0010

        movwf        SSPCON

        bsf            STATUS,RP0        ; Seleccionamos el Banco 1

        bcf            STATUS,RP1      

        bcf            PIE1,SSPIE        ;Se inhabilita la interrupcion SPI 

        bcf            STATUS,RP0        ;Seleccionamos el Banco 0

        bcf            STATUS,RP1

        bsf            PORTB,7

        movlw        b'11000000'        ; Habilitación de las

        movwf        INTCON            ; interrupciones en general



PRINCIPAL   ; BUCLE PRINCIPAL EN EL QUE SE QUEDA A LA ESPERA DE ALMACENAR LOS DOS BYTES

        btfss        VALOR1,2          ;¿Se almacenaron los 2 registros?
        
        goto        PRINCIPAL

        bcf            VALOR1,2

        call        COM_SPI        ;Comienza comunicacion SPI

        goto         PRINCIPAL


END
```

***************************Receptor*************************


```
LIST        P=16f73
INCLUDE        <P16F73.INC>
__CONFIG _CP_OFF &_WDT_OFF &_PWRTE_ON &_HS_OSC
 
  

BYTE_1        equ        22h            ;1º byte recibido
BYTE_2        equ        23h    
VALOR2        equ        25h


; Inicio

           org            0x00
        goto        inicio
        org           0x04
        goto        inter



; Tranmisión en modo SPI

COM_USART

        bcf            STATUS,RP0        ; Banco 0
    
        bcf            STATUS,RP1

        movf        BYTE_1,W

        movwf        TXREG        ; Mueve el byte a transmitir al registro de transmision

        bsf            PORTB,3

        

COM_ESPERA       

        bsf           STATUS,RP0    ;Bank 1

        btfss        TXSTA,TRMT    ; ¿Byte transmitido?

        goto        COM_ESPERA    ; No, esperar

        bcf            TXSTA,TRMT

        bcf           STATUS,RP0    ; Si, vuelta a Bank00

        bcf            STATUS,RP1
        
        movf        BYTE_2,W

        movwf        TXREG        ; Mueve el byte a transmitir al registro de transmision
    
        bsf            PORTB,4

        return


 
; Tratamiento de interrupción

inter       

        bcf            STATUS,RP0        ;Banco 0

        btfss        PIR1,SSPIF        ; ¿Dato recibido?

         goto        VERIFICAR          ; No, falsa interrupción
        
        bcf            PIR1,SSPIF 

        bsf            PORTB,0            ; Se enciende el primer led para motorizar el programa

        movf        SSPBUF,W        ; Lectura del dato recibido

        btfss         VALOR2,1          ; ¿Variable AUX=1? vale 0 al comienzo

        goto        RECIBIR_BYTE

         movwf        BYTE_2           ; No, almacena 2º byte    
        
        bsf            VALOR2,2            ;Se activa variable que indica que se han almacenado los 2 registros    

        bsf            PORTB,2

        bcf            VALOR2,1    

        retfie

         
RECIBIR_BYTE

        movwf        BYTE_1           ; Almacena 1º byte    

        bsf            VALOR2,1

        bsf            PORTB,1

        retfie            
                


VERIFICAR

        movlw        b'00000000'
        
        movwf        PIR1        
        
        retfie
 
; Comienzo del programa principal

inicio        
        clrf        PORTB 

        clrf        PORTC

        bcf            VALOR2,1
        
        bcf            VALOR2,2

        bsf            STATUS,RP0        ; Bank01

        bcf            STATUS,RP1

        movlw        b'00000001'

        movwf        TRISB

        movlw        b'10011111'       ; RC7/RX=1, RC6/TX=0, RC5/SDO=0,RC4/SDI=1,RC3/SCK=1 (el resto a 1)

        movwf        TRISC        

        movlw        b'00100100'        ; Configuración USART
    
        movwf        TXSTA            ; y activación de transmisión

        movlw        .129               ; 9600 baudios

        movwf        SPBRG

        bcf            STATUS,RP0        ; Bank00

        movlw        b'10010000'        ; Configuración del USART para recepción continua

        movwf        RCSTA            ; Puesta en ON

CONF_SPI

        bsf            STATUS,RP0        ; Seleccionamos el Banco 1
    
        bcf            STATUS,RP1     
 
        movlw        b'01000000'     ; SMP=0 , CKE=1 , BF=0 

        movwf        SSPSTAT

        bcf            STATUS,RP0        ;Seleccionamos el Banco 0

        bcf            STATUS,RP1

        movlw        b'00100100'        ;SSPEN=1, CKP=0 SSPM3:SSPM0=0100

        movwf        SSPCON

        bsf            STATUS,RP0        ; Seleccionamos el Banco 1

        bcf            STATUS,RP1      

        movlw        b'00000000'    

        movwf        PIE1            ;Interrupcion ssp

        movlw        b'00000000'    

        movwf        PIE2            

        bcf            STATUS,RP0        ;Seleccionamos el Banco 0

        bcf            STATUS,RP1

        bsf            PORTB,7

        movlw        b'11000000'        ; Habilitación de las

        movwf        INTCON            ; interrupciones en general


PRINCIPAL

        btfss        VALOR2,2
        
        goto        PRINCIPAL

        bcf            VALOR2,2

        call        COM_USART

        goto        PRINCIPAL

END
```


----------



## Romyggar (Jul 4, 2012)

MaikahV dijo:


> Hola a todos, veo que están utilizando el PIC 16F73 con el modo SPI; Yo también estoy utilizando ese pic para enviar datos de 16 bits desde el PC hasta el PIC por usart y de este hasta el otro PIC por SPI. Como he visto lo que explican, almaceno los 16 bits en dos registros internos del PIC para despues enviarlos al PIC. En mi caso uno de los PIC actúa de transmisor y otro de receptor. Lo que pasa es que el receptor solo llega a recibir uno de los bytes, a pesar de que en el código del transmisor se incluye el envío de los dos bytes.
> 
> Creo que el problema está en que pongo una tras otra las instrucciones de que se manden, desde los registros internos, los 2 bytes al SSPUF, por lo que de alguna forma el receptor solo llega a leer uno y el otro se pierde. ¿Habría alguna forma de detectar esto?, es decir, podría hacer algo para que el transmisor no envíe el segundo byte hasta que el receptor le indique que ha leído el primero?
> 
> ...



Amigo *MaikahV*

A pesar de que hace 2 meses que no entraba al foro, me hé animado a responderte el mensaje, sin embargo e smuy engorroso leer tu código si lo pones como parte del mensaje, Es mejor si usas las herramientas del editor avanzado como por ejemplo CODE (el símbolo # en la barra de íconos):


```
*********************Transmisor******************* ****

LIST P=16f73
INCLUDE <P16F73.INC>
__CONFIG _CP_OFF &_WDT_OFF &_PWRTE_ON &_HS_OSC


BYTE_1	 equ	 20h	 ;1º byte transmitido
BYTE_2	 equ	 21h
VALOR1	 equ	 24h
Guarda_W	 equ	 27h
Guarda_STATUS	equ	 28h

; Inicio

org	 0x00
goto inicio
org 0x04
goto inter
```


Todo esto lo digo a modo de sugerencia (si es que lees alguna vez este hilo nuevamente). También podrías adjuntar el archivo .asm. Realmente ajustes sencillos como estos nos facilitan la vida y de paso nos permiten colaborar mas. En otro momento analizaré tu código.


```
Salu2
```


----------



## jmh7 (Jul 18, 2012)

hola amigos... les comento, tengo un MCU MSP430F2013 con  SPI y lo tengo que conectar a un modulo Xbee que tiene UART para enviarles datos de 16 bits . Mi consulta es : es compatible la comunicacion SPI y UART ya que las 2 son full-duplex


----------



## Romyggar (Jul 24, 2012)

jmh7 dijo:


> hola amigos... les comento, tengo un MCU MSP430F2013 con  SPI y lo tengo que conectar a un modulo Xbee que tiene UART para enviarles datos de 16 bits . Mi consulta es : es compatible la comunicacion SPI y UART ya que las 2 son full-duplex



Amigo *jmh7*

SPI y UART en mi experiencia usan 2 esquemas de comunicacion diferentes. El primero necesita de una señal de reloj que sincronice los 2 dispositivos a conectar; UART no usa señal de reloj(Si fuera USART tal vez se podría por software lograr la compatibilidad), por lo que pienso que tratar de conectar una salida Tx de SPI a una Rx de UART no es algo viable.

SPI = Serial Peripheral Interface

UART =  Universal asynchronous receiver/transmitter

Claro está que puedes tratar de implementar una UART virtual (por software, el MCU que mencionas es potente y es capaz. Estuve mirando el pdf). 

PD: En los *capítulos 15 (Pág. 421) y capítulos 16 (Pág 447) *de *éste documento* puedes econtrar mas información del USCI de tu micro (es la forma en que oficialmente se llama el "SPI" en Texas Instruments: Universal Serial Controller Interface). En *Éste otro enlace* está el pdf específico de tu MCU.


----------



## jmh7 (Jul 24, 2012)

gracias por la respuesta!!!!


----------

