Autor Tema: Problema comunicación serie. Transmito un dato y recibo otro  (Leído 2034 veces)

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

Desconectado MasterTemplar

  • PIC10
  • *
  • Mensajes: 2
Problema comunicación serie. Transmito un dato y recibo otro
« en: 10 de Julio de 2017, 20:03:05 »
Buenas tardes a todos:
Hace un tiempo que estoy aprendiendo sobre PICs y Assembler. Me embarqué en un proyecto, y está prácticamente listo, menos la comunicación. Les explico:
Tengo un marcador de 24 segundos, de esos que se utilizan para los juegos de basketball. El programa que contabiliza el tiempo, y que recibe las órdenes de la botonera, se almacena en un PIC16F886. Esto irá en una caja que tendrá el operador del marcador.
En el gimnasio, arriba de los tableros, irán dos paneles LED de cierto tamaño, los que serán simplemente un esclavo de la caja central. En estos marcadores irá un PIC16F628A, el que recibirá mediante comunicación serie (RS-485) el valor de las variables unidad y decena que representan el tiempo mientras es contabilizado por la caja central. El esclavo debe recibir el valor de cada variable, y con ellas generar la representación numérica en los paneles LED.
Lo que ocurre es que cuando transmito el primer valor (un 3 para ser preciso), el esclavo recibe un -2 en el RCREG, y después de eso no recibe nada más, o al menos eso parece.
Envío los archivos de Proteus donde está simulado lo que menciono arriba.
Saludos, y gracias de antemano por la ayuda.

Nota: No se si es indispensable para que se establezca una comunicación serie asíncrona como corresponde, utilizar osciladores externos en cada uno de los PICs. La verdad es que yo sólo estoy utilizando los osciladores internos.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema comunicación serie. Transmito un dato y recibo otro
« Respuesta #1 en: 10 de Julio de 2017, 20:56:26 »
Transmisor

1-
Te recomiendo que leas el codigo que provee el datasheet acerca de guardar/restorar el contexto, veras que usa instrucciones como SWAPF porque estas instrucciones no modifican las variables. Algo que estas haciendo mal en tu codigo, Simplmente es copiar y pegar.

Con lo cual vas a terminar con una funcion de Salir_interrupcion y cuando tengas que salir simplemente vas a hacer un GOTO a la misma.

2-

Código: ASM
  1. MOVF            UNIDAD,W
  2.                 SUBLW           D'0'
  3.                 BTFSC           STATUS,Z

El SUBLW no es necesario, el MOVF actualiza la bandera Z por si solo.

3-

Código: ASM
  1. waittx  BTFSS           TXSTA,TRMT
  2.                 GOTO            waittx

Un loop que depende de otra cosa dentro de una interrupcion es malo, ya que si esta dentro de una interrupcion y ocurre otra no va a poder atenderlo. Lo mejor tal ves sea acomodar el valor y activar un flag, para que el loop principal luego lo envie.

4-

Código: ASM
  1. Inicio_pausa    ; Inicia o pausa el contador
  2.                 BTFSC   INTCON,T0IE

Un error, ya que el Timer0 sigue corriendo, eso quiere decir que por mas que pares , apenas arranques vas a tener el flag en 1, y no lo estas limpiando antes de activarlo. O usar un timer que si pueda detenerse como el Timer1

5-

Código: ASM
  1. MuestraDigito
  2.     movwf   Digito      ;Carga el valor de W en Dígito
  3.     movlw   .0          ;Compara con 0
  4.     xorwf   Digito,W
  5.     btfsc   STATUS,Z    ;Cuenta = 0?
  6.     goto    Envia0      ;Sí: Envia Dígito
  7.     movlw   .1          ;No: Compara con 1
  8.     xorwf   Digito,W
  9.     btfsc   STATUS,Z    ;Cuenta = 1?
  10.     goto    Envia1      ;Sí: Envia Dígito
  11.     movlw   .2          ;No: Compara con 2
  12.     xorwf   Digito,W
  13.     btfsc   STATUS,Z    ;Cuenta = 2?
  14.     goto    Envia2      ;Sí: Envia Dígito
  15.     movlw   .3          ;No: Compara con 3
  16.     xorwf   Digito,W
  17.     btfsc   STATUS,Z    ;Cuenta = 3?
  18.     goto    Envia3      ;Sí: Envia Dígito
  19.     movlw   .4          ;No: Compara con 4
  20.     xorwf   Digito,W
  21.     btfsc   STATUS,Z    ;Cuenta = 4?
  22.     goto    Envia4      ;Sí: Envia Dígito
  23.     movlw   .5          ;No: Compara con 5
  24.     xorwf   Digito,W
  25.     btfsc   STATUS,Z    ;Cuenta = 5?
  26.     goto    Envia5      ;Sí: Envia Dígito
  27.     movlw   .6          ;No: Compara con 6
  28.     xorwf   Digito,W
  29.     btfsc   STATUS,Z    ;Cuenta = 6?
  30.     goto    Envia6      ;Sí: Envia Dígito
  31.     movlw   .7          ;No: Compara con 7
  32.     xorwf   Digito,W
  33.     btfsc   STATUS,Z    ;Cuenta = 7?
  34.     goto    Envia7      ;Sí: Envia Dígito
  35.     movlw   .8          ;No: Compara con 8
  36.     xorwf   Digito,W
  37.     btfsc   STATUS,Z    ;Cuenta = 8?
  38.     goto    Envia8      ;Sí: Envia Dígito
  39.     movlw   .9          ;No: Compara con 9
  40.     xorwf   Digito,W
  41.     btfsc   STATUS,Z    ;Cuenta = 9?
  42.     goto    Envia9      ;Sí: Envia Dígito
  43.  
  44. Envia0
  45.     movlw   b'10000001'
  46.     movwf   PORTA
  47.     return
  48. Envia1
  49.     movlw   b'11110011'
  50.     movwf   PORTA
  51.     return
  52. Envia2
  53.     movlw   b'01001001'
  54.     movwf   PORTA
  55.     return
  56. Envia3
  57.     movlw   b'01100001'
  58.     movwf   PORTA
  59.     return
  60. Envia4
  61.     movlw   b'00110011'
  62.     movwf   PORTA
  63.     return
  64. Envia5
  65.     movlw   b'00100101'
  66.     movwf   PORTA
  67.     return
  68. Envia6
  69.     movlw   b'00000101'
  70.     movwf   PORTA
  71.     return
  72. Envia7
  73.     movlw   b'11110001'
  74.     movwf   PORTA
  75.     return
  76. Envia8
  77.     movlw   b'00000001'
  78.     movwf   PORTA
  79.     return
  80. Envia9
  81.     movlw   b'00100001'
  82.     movwf   PORTA
  83.     return

Todo eso es demasiado codigo para solo una tabla el cual te llevaria unas 12 lineas.


Receptor

1-

Mismo problema con el guardado/restaurado de contexto que el transmisor en las interrupciones

2-

Código: ASM
  1. interrupciones          ; CONTROLA INTERRUPCIÓN DE PERIFÉRICOS, ESPECÍFICAMENTE DE USART
  2.                 MOVWF           WTEMP
  3.                 MOVF            STATUS,W
  4.                 MOVWF           STATUSTEMP
  5.                 ; RUTINA RECEPCIÓN
  6.                 BTFSS           PIR1,RCIF
  7.                 GOTO            interrupciones

Loop posiblemente infinito dentro de una interrupcion, no debe haber loops asi, ademas si ya entro a la interrupcion es porque llego algo, asi que o no tiene sentido tener eso, o puede traerte problemas, en resumen quitarlo.

3-

Nuevamente lo de la tabla..

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

Solucionando eso creo que podriamos empezar a pensar en que esta mal acerca de la comunicacion Serial

Y uan cosa que no entiendo, si utilizas decimal no se porque lo escribis en binario. Y tambien veo que estas enviando un solo valor ( UNIDAD ) pero en el transmisor usas DECENA. Lo cual pienso que no estas enviando los 2 digitos en un byte ( packet-BCD )
« Última modificación: 10 de Julio de 2017, 21:20:59 por KILLERJC »

Desconectado MasterTemplar

  • PIC10
  • *
  • Mensajes: 2
Re:Problema comunicación serie. Transmito un dato y recibo otro
« Respuesta #2 en: 10 de Julio de 2017, 21:30:54 »
Gracias KILLERJC. Voy a implementar los cambios y enviaré luego la simulación. La duda que tenía del oscilador... ¿es indispensable tener osciladores externos para tener un baudrate estable entre todos los PICs?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema comunicación serie. Transmito un dato y recibo otro
« Respuesta #3 en: 10 de Julio de 2017, 21:36:35 »
Como la UART es asincrona ambos PIC deberian tener al menos una frecuencia similar, si hay un poco de diferencia y solo envias un dato no es demasiado problema, pero si vas a enviar algo mucho mas largo,imagino que podrias llegar a perder datos.

Ademas no entiendo cual es el problema si el PIC16F628A si o si tenes que ponerle cristal externo, y un cristal no ocupa demasiado lugar como para que te afecte con el PIC16F886, es decir estamos hablando de ponerle o no cristal al PIC16F886, Otra cosa mas, el PIC16F886 va a ser el encargado de contar segundos, por lo tanto su oscilador si debe ser dentro de todo mas exacto.

La otra es poner un Cristal de 32Khz en el Timer1, y que te sirva para 2 cosas:

- Usarlo para contar los segundos, ya que es es multiplo de 2.
- En caso de querer que el oscilador interno se aproxime lo mas posible a cierta frecuencia, podrias usar este cristal para calibrar el oscilador interno ( OSCTUNE )

Con un cristal matarias 2 pajaros de 1 tiro. Por supuesto, complica un poco mas el programa en la parte de la calibracion, pero generar la interrupcion en cada segundo se vuelve mucho mas facil si es que usas el modulo CCP.

PD: Son opciones que te dejo, y que vos veras con cual lo haces, tal ves en 24 segundos no se note, pero el error acumulado puede llegar a ser una buena diferencia.
« Última modificación: 10 de Julio de 2017, 21:41:15 por KILLERJC »