Autor Tema: Problema de comunicación entre dos PIC  (Leído 2376 veces)

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

Desconectado sysseon

  • PIC10
  • *
  • Mensajes: 20
Problema de comunicación entre dos PIC
« en: 07 de Febrero de 2014, 14:04:12 »
Buenas! Estoy empezando con esto de los pics y me ha surgido un problema. Estoy programando con CCS, por eso meto esta duda en este subforo... aunque es posible que no tenga nada que ver.

Empiezo con la duda directamente y luego meto un rollo opcional (no puedo evitar meter rollos, lo siento) más detallado sobre el problema, por si el fallo está en la configuración de mi circuito.

Basicamente intento comunicar dos pics. Uno de ellos debe controlar el estado de una línea por un pin, y lo hace correctamente. El problema es que cuando conecto esa línea al otro pic, que debe leerla, la línea se pone en estado alto y así se queda. He comprobado el código y en ningún momento utilizo una función de output en el pic que lee, únicamente la función input(), así que no entiendo el problema. Solo con estos datos, ¿estoy haciendo alguna burrada?

========================

Ok, ahora en detalle...

Estoy intentando comunicar dos PIC12F508 (los más sencillos que he encontrado) con un protocolo que he creado en unas librerías. Es como un I2C pero más cutre, aunque personalizado a mis necesidades de muchos dispositivos comunicándose entre sí. Esto CREO que no importa para mi problema, pero lo explico rápido, por si acaso.

Utilizo dos líneas (dos pines): una de ellas para transmitir/recibir los datos, y la otra (llamémosla línea de estado) simplemente está en reposo (nivel bajo) cuando no se está transmitiendo nada, y en nivel alto cuando sí, y sirve para controlar el acceso y la lectura. La transmisión funciona perfectamente, y esto es lo que obtengo:



El problema viene al conectar el pic que hace la lectura. Al conectar la línea de estado, su nivel se hace 1 (alto), aunque este segundo pic solo configura el pin como entrada, y no escribe nada en él. Al verse la línea siempre en estado alto, no hay transmisión ninguna (porque el otro pic así lo detecta) y la línea de datos se queda a 0 siempre. Ese es el problema, y este es mi circuito (me he superado con paint):




¿Alguna idea? No sé si el error es de novato y está en la configuración o si es cosa de programación. No creo que nadie tenga ni ganas ni fuerza de ver mi código asqueroso, pero si alguien lo quiere, lo subo.

Muchas gracias y un saludo!
« Última modificación: 07 de Febrero de 2014, 14:07:45 por sysseon »

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: Problema de comunicación entre dos PIC
« Respuesta #1 en: 07 de Febrero de 2014, 14:22:58 »
intenta usar

#use fastio(x)
en x pones el puerto donde estan tus pines, para que el compilador no cambia la configuración de los pines automáticamente
"Nada es imposible, no si puedes imaginarlo"

Desconectado sysseon

  • PIC10
  • *
  • Mensajes: 20
Re: Problema de comunicación entre dos PIC
« Respuesta #2 en: 07 de Febrero de 2014, 14:42:25 »
Muchas gracias Rivale, pero parece que con

#use fast_io(B)

no hay suerte. Sigue igual la cosa...

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: Problema de comunicación entre dos PIC
« Respuesta #3 en: 07 de Febrero de 2014, 14:45:38 »
Muchas gracias Rivale, pero parece que con

#use fast_io(B)

no hay suerte. Sigue igual la cosa...

disculpa, me habia faltado poner un '_'

podrías poner tu codigo para ver como configuras tus pines
"Nada es imposible, no si puedes imaginarlo"

Desconectado sysseon

  • PIC10
  • *
  • Mensajes: 20
Re: Problema de comunicación entre dos PIC
« Respuesta #4 en: 07 de Febrero de 2014, 15:08:26 »
Pongo aquí un código resumido de las funciones que entran en juego e ignorando las otras para sintetizar un poco, aunque ya aviso que el código puede ser algo lioso y no es 100% definitivo. No soy de los de pensar la idea al 100% antes, sino más bien de programar sobre la marcha, así que habrá muchas cosas que se puedan hacer mejor. Además, es el primer proyecto que hago en PIC, y a poco que te pasas con el 12F508 llenas la memoria...
En fin, que el código es espeso, pero bueno, céntrate en las partes en las que se leen y escriben los pines. Ahí va, y el proyecto entero lo adjunto.

Código: [Seleccionar]
#include <12F508.h>
#use delay(clock=4M)
#use fast_io(B)
#FUSES NOMCLR    //Master Clear pin used for I/O
#FUSES INTRC

#include <wire_com.h> // Librería del protocolo de comunicación

void main()
{
   wire_initialize(0x56); // Dirección local del dispositivo
   
   while(1) {
      int8 mensaje = wire_read(10000); // Timeout de ~= 10ms
     
      if (wire_dataReceived()) { // Solo para testear que ha recibido datos
      output_high(PIN_B4);
      delay_ms( 1 );
      output_low(PIN_B4);
      delay_ms( 1 );
      }
     
   }
}

Código: [Seleccionar]
// Archivo "wire.h"

#include <manchester_tx_rx.h> // Archivo de transmisión/recepción de tramas

#define PIN_DATA PIN_B0
#define PIN_STATE PIN_B1

// Indica si el canal está libre. Se utiliza cuando se quiere iniciar
// una transmisión y para saber si se debe empezar a recibir un mensaje
int1 wire_isIdle() {
if ( input(PIN_STATE) ) {
return 0;
} else {
connected = 0;
return 1;
}
}

// Recibe la siguiente trama. Devuelve la trama si la recibe, y 0 si vence el timeout sin recibir nada.
// El timeout se expresa en milisegundos y solo es una aproximación.
frame wire_read(int16 max_timeout_us) {

if ( !wire_isIdle() )  // Si la línea está ocupada...                     
if (connected)
return manchester_receiveMessage(max_read_us); // Si existe conexión, se devuelve el siguiente dato
else
return 0; // Si no existe conexión pero la línea está ocupada, no se lee nada

// Si se llega a este punto, la línea está libre. Se espera un tiempo a que se ocupe.
setup_counters(RTCC_INTERNAL,RTCC_DIV_4); // TIMER0: Clock Interno, Prescaler 4 (Para 4MHZ -> Incrementos cada 4us)
set_rtcc(0);
while ( wire_isIdle() )
if (get_rtcc()*4 > max_timeout_us) return 0;    // Si vence el timeout, se devuelve 0

// Si se llega a este punto, la línea está ocupada. La primera trama es la de la dirección de destino,
// que debe coincidir con la local. Si no es así, la conexión no va dirigida al dispositivo local.
if (manchester_receiveMessage(max_read_us) == local_address) {
connected = 1;    // Se establece conexión con el dispositivo               
remote_address = manchester_receiveMessage(max_read_us); // La segunda trama es la dirección remota
return manchester_receiveMessage(max_read_us); // Se devuelve la tercera trama, que ya es de datos
}

return 0;
}

Código: [Seleccionar]
Archivo "manchester_tx_rx.h"

#define PIN_RX PIN_B0

void manchester_restart() {
   message = 0;
   message_count = 0;
   message_received = 0;
   next_edge = 1;
   timeout += get_rtcc(); // Se incrementa el timeout con el tiempo (us) transcurrido
   set_rtcc(0);
}

// Se introduce el bit en el mensaje y se preparan las variables
// para seguir con la adquisición. NOTA: Se transmite primero el MSB
void manchester_setNextBit() {
   message <<= 1;   
   message  |= next_edge;
   message_count++;
   next_edge = !next_edge;
   timeout = 0;
}


// Se espera a conseguir una trama completa, cuyo
// resultado se almacenará en 'message' (MSB primero)
// La trama está compuesto por un bit de inicio y los
// bits de datos
msg manchester_receiveMessage(int16 max_timeout_us) {
   
   setup_counters(RTCC_INTERNAL,RTCC_DIV_4); // TIMER0: Clock Interno, Prescaler 4 (Para 4MHZ -> Incrementos cada 4us)
   manchester_restart();
timeout = 0;
   
   while (message_count < (message_length+1)) { // Se recibirá 1 bit más de la longitud de la trama (bit de start)
   
      if (input(PIN_RX) == next_edge)
      {
         int8 timer = get_rtcc();   // Se captura el valor del timer y se
         set_rtcc(0);               // resetea con cada flanco de reloj
         
         if (message == 0) {
            manchester_setNextBit(); // Se establece el primer bit a 1 (bit de start). El último bit que se reciba
// desplazará este bit fuera de la trama, haciendo que se pierda (no son datos)
         } else {
            if (abs((signed)(pulse_us/2 - timer)) < tolerance) {
               manchester_setNextBit();
            } else if (abs((signed)(pulse_us/4 - timer)) < tolerance) {
               next_edge = !next_edge;          // Como este flanco no implica nada,
               set_rtcc( timer + get_rtcc() );  // se deja el timer como estaba
            } else  {
               //timeout += timer; // Se incrementa el timeout con el tiempo (us) transcurrido
               manchester_restart();
            }
         }
      }
      if (get_rtcc() > (pulse_us/2 + tolerance)) manchester_restart();
     
      if (input_state(PIN_B1) == 0) return 0; // Esta línea es para su uso con la librería wire.h (habría que cambiarla). Hace que si el
// pin de estado está libre se deje de esperar una trama, ya que no hay conexión activa.
     
      if (timeout*4 > max_timeout_us) return 0; // Condición para el vencimiento del timeout
   }
   
   message_received = 1;
   return message;
}

Lo dicho, es lioso, pero es parte de un protocolo más o menos robusto (a falta de ACKs, que podrían hacerse por software). Si puedes sacar algo sería genial (La parte de transmisión y otras funciones van en el proyecto adjunto).

Gracias!

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Problema de comunicación entre dos PIC
« Respuesta #5 en: 07 de Febrero de 2014, 15:12:07 »
Estás trabajando sobre el PORTB, cuando ese micro sólo tiene GPIO (PORTA)?

saludos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: Problema de comunicación entre dos PIC
« Respuesta #6 en: 07 de Febrero de 2014, 15:19:48 »
Estás trabajando sobre el PORTB, cuando ese micro sólo tiene GPIO (PORTA)?

saludos.

además en ningun lado configuras tus pines con el set_tris
"Nada es imposible, no si puedes imaginarlo"

Desconectado sysseon

  • PIC10
  • *
  • Mensajes: 20
Re: Problema de comunicación entre dos PIC
« Respuesta #7 en: 07 de Febrero de 2014, 15:22:54 »
Mmm, la verdad es que no controlo mucho lo de los puertos, pero creo que no estoy haciendo ninguna locura. Puede que en CCS tengan otro nombre, ni idea.

Código: [Seleccionar]
#device PIC12F508
#nolist
//////// Program memory: 512x12  Data RAM: 25  Stack: 2
//////// I/O: 6   Analog Pins: 0
//////// C Scratch area: 07   ID Location: 0200
//////// Oscilator Calibration Address: 05
//////// Fuses: LP,XT,INTRC,RC,NOWDT,WDT,PROTECT,NOPROTECT,NOMCLR,MCLR
////////
////////////////////////////////////////////////////////////////// I/O
// Discrete I/O Functions: SET_TRIS_x(), OUTPUT_x(), INPUT_x(),
//                         PORT_x_PULLUPS(), INPUT(),
//                         OUTPUT_LOW(), OUTPUT_HIGH(),
//                         OUTPUT_FLOAT(), OUTPUT_BIT()
// Constants used to identify pins in the above are:

#define PIN_B0  48
#define PIN_B1  49
#define PIN_B2  50
#define PIN_B3  51
#define PIN_B4  52
#define PIN_B5  53

( ... )

Desconectado sysseon

  • PIC10
  • *
  • Mensajes: 20
Re: Problema de comunicación entre dos PIC
« Respuesta #8 en: 07 de Febrero de 2014, 15:24:27 »
Lo del set_tris ya puede ser otro tema... creía que con las librerías de CCS no hacía falta, pero voy a probar. Puede que esté muuuy confundido.

Gracias, ahora os cuento!

(Ok, acabo de ver que lo del set_tris_b es necesario cuando se utiliza #use fast_io(B). No tenía ni idea... sigo probando)
« Última modificación: 07 de Febrero de 2014, 15:29:29 por sysseon »

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: Problema de comunicación entre dos PIC
« Respuesta #9 en: 07 de Febrero de 2014, 15:28:40 »
con el tris le especificas que pin es entrada y cual es salida, por default estan como salidas, tal vez ese es el problema. tambien incluye la instruccion de

fast_io
"Nada es imposible, no si puedes imaginarlo"

Desconectado sysseon

  • PIC10
  • *
  • Mensajes: 20
Re: Problema de comunicación entre dos PIC
« Respuesta #10 en: 07 de Febrero de 2014, 15:52:38 »
Ok, gracias de nuevo. A ver... entendiendo que el pic que transmite no tiene ningún problema (porque mientras la línea de estado no esté conectada al otro pic, funciona perfectamente), solo he modificado el puerto del pic que recibe. Debe hacerlo por el PIN_B0 y el PIN_B1, así que pongo, a parte del #use fast_io(B), lo siguiente al comienzo del main:

set_tris_b(0xEF);

Para habilitar todos los pines como entradas, excepto el PIN_B4, que lo dejo como salida para hacer cosas mías... Puede que me haya equivocado o que esté usando mal esta función, pero el problema sigue ahí...
« Última modificación: 07 de Febrero de 2014, 16:00:15 por sysseon »

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: Problema de comunicación entre dos PIC
« Respuesta #11 en: 07 de Febrero de 2014, 16:11:10 »
que pasa si pones A en lugar de B.

otra cosa, como estas midiendo si el estado del pin cambia?, si  lo haces con un multímetro puede que los pulsos sean tan rapidos que no se vea que son intermitentes

solo eso se me ocurre por ahora
"Nada es imposible, no si puedes imaginarlo"

Desconectado sysseon

  • PIC10
  • *
  • Mensajes: 20
Re: Problema de comunicación entre dos PIC
« Respuesta #12 en: 07 de Febrero de 2014, 16:21:41 »
Si pongo A tengo un fallo de compilación. Y sobre la medición... tengo un analizador lógico muy cutre que compré en una tienda de estas chinas... pero la verdad es que va muy bien, y es perfecto para estas cosas. La captura del primer post es de las señales obtenidas por el analizador (no es una simulación).

Nada, pues seguiré intentando a ratitos conseguir que esto funcione, que es lo último que me falta para montar el sistema. Si se os ocurre algo, por aquí estoy.

Gracias de nuevo!

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: Problema de comunicación entre dos PIC
« Respuesta #13 en: 07 de Febrero de 2014, 18:01:40 »
intenta con los cambios anteriores (tris, fast_io)

y cambia tu encabezado por esto

Código: C
  1. #include <12F508.h>
  2. #FUSES NOMCLR    //Master Clear pin used for I/O
  3. #FUSES INTRC_IO
  4. #use delay(clock=4M)
  5. #use fast_io(B)
"Nada es imposible, no si puedes imaginarlo"

Desconectado sysseon

  • PIC10
  • *
  • Mensajes: 20
Re: Problema de comunicación entre dos PIC
« Respuesta #14 en: 07 de Febrero de 2014, 18:28:05 »
Ok, el encabezado lo tengo así (excepto el INTRC_IO, que parece que el 12F508 no lo soporta o algo... he dejado el INTRC simple). Luego seguiré haciendo pruebas, aunque está clarísimo que el problema está en el código de las librerías que he hecho. Intentaré despiezarlas poco a poco, a ver si localizo el error.

Iré informando. Gracias!