Control mediante RS485 librería en C - Problema

Hola tengo un problema con las comunicaciones RS485 quería saber si alguien me puede orientar en el desarrollo de una librería en C por que tengo que leer y enviar 16 bytes por medio de este bus.
He traducido la librería pero no entiendo 100% su funcionamiento...si alguien la ha utilizado o puede explicarme como usarla le agracederé :apreton:

Código:
/////////////////////////////////////////////////////////////////////////
////                                                                 ////
//// Driver para implementar comunicaciones bajo el bus RS485.       ////
//// Modificación para usar solo con interrupción por el puerto B.   ////
//// Programador: Moyano Jonathan.                                   ////
//// Lineas de programa comentadas en español para mejor comprensión ////
//// por parte del programador.                                      ////
////                                                                 ////
//// int1 rs485_recibe_datos(int *datos, int espera)                 ////
////     - Toma datos del bus RS485.                                 ////
////     - La dirección puede ser 1 a 33.                            ////
////     - La función retorna 1 si hay error en la paridad de los    //// 
////       datos recibidos.                                          ////
////                                                                 ////
//// int1 rs485_envia_mensaje(int destinatario,int len, int*dato)    ////
////     - Envía un mensaje por el bus RS485.                        ////                                                   ////
////     - Destinatario : Dirección del destinatario.                ////
////     - len: Longitud del mensaje.                                ////
////     - *dato: Puntero al mensaje.                                ////
////     - Retorna TRUE si lo envió con exito, FALSE en caso de      ////
////       poder haber enviado el mensaje.                           ////
////                                                                 ////
//// void rs485_espera(int1 clrwdt)                                  ////
////     - Espera que se abra el bus RS485. Normalmente usado antes  ////
////       de efectuar un envio de mensajes para evitar colisiones   ////
////       de datos.                                                 ////
////     - Resetea al perro guardían en caso de que no responda.     ////                          ////
////     - Función no necesaria en caso de que se envíen datos       //// 
////       continuamente.                                            ////
////                                                                 ////
//// void rs485_init()                                               ////
////     - Inicia el bus RS485...se llama antes que cualquier        ////
////       función.                                                  ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////

#ifndef RS485_ID
#define RS485_ID  0x10   // Dirección del dispositivo dentro del bus por defecto.
#endif

   #define RS485_RX_PIN       PIN_B0   // PIN recepción de datos.
   #define RS485_TX_PIN       PIN_B1   // PIN transmisión de datos.
   #define RS485_ENABLE_PIN   PIN_B3   // PIN DE.  (recepción) low, (transmisión) high.
   #define RS485_RX_ENABLE    PIN_B2   // PIN RE.  Debería mantenerse en nivel bajo...

   #use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=9, long_data, errors, stream=RS485)
   #use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=9, long_data, multi_master, errors, stream=RS485_CD)

   #define RCV_OFF() {disable_interrupts(INT_EXT);} // Función para apagar recepciones de datos.

#define RS485_wait_time 20   // Periodo de espera en milisegundos.

#bit rs485_collision = rs232_errors.6 // Definimos bit indicador de colisión de datos.

#ifndef RS485_RX_BUFFER_SIZE     // Definimos tamaño del BUFFER de recepción.
#define RS485_RX_BUFFER_SIZE  20 // Por defecto 20....
#endif

int rs485_state, rs485_ni, rs485_no;
int rs485_buffer[RS485_RX_BUFFER_SIZE]; // Definimos la variable que contendrá los datos.
                                        // Su tamaño viene dado por RS485_RX_BUFFER_SIZE....


// Función: Habilitar la recepción de datos.

void RCV_ON(void) {
  clear_interrupt(INT_EXT);
  enable_interrupts(INT_EXT);
}


// Función: Iniciar el bus RS485.

void rs485_init() {
   RCV_ON(); // Habilitamos recepción de datos.
   rs485_state=0; // Ponemos variable a 0....
   rs485_ni=0;
   rs485_no=0;
   ext_int_edge(H_TO_L);        // Interrupción por flanco de bajada.
   enable_interrupts(INT_EXT);  // Habilitamos interrupción por cambio de estado PIN_RB0.
   enable_interrupts(GLOBAL);   // Habilitamos interrupciones globalmente.
   output_low(RS485_RX_ENABLE); // Escuchamos....( modo recepción ).
}


// Indice para el buffer de recepción temporal..
int8 temp_ni;

// Función: Añade un byte al buffer de recepción temporal.
void rs485_add_to_temp(int8 b) {
   // Guarda el byte.
   rs485_buffer[temp_ni] = b;

   // indexado ciclico..
   if(++temp_ni >= RS485_RX_BUFFER_SIZE)
   {
      temp_ni = 0;
   }
}


// Función: Rutina para manejar los datos entrantes...
#int_ext

void incomming_rs485() {
   int16 b;
   static int8  cs,state=0,len;
   static int16 to,source;

   b=fgetc(RS485); // Toma los datos del bus y los guarda en b.
   cs^=(int8)b;    // Aplica una XOR a la variable b.

   switch(state) {
      case 0:  // Toma desde la dirección...
         temp_ni=rs485_ni;
         source=b;
         cs=b;
         rs485_add_to_temp(source);
         break;

      case 1:  // Llegar a la dirección...
         to=b;
         break;

      case 2:  // Obtiene la longitud...
         len=b;
         rs485_add_to_temp(len);
         break;

      case 255:   // Hace un checksum..para ver si los datos están correctos.
         if ((!cs)&&(bit_test(to,8))&&(bit_test(source,8))&&((int8)to==RS485_ID)) {  // Si cs==0,entonces el checksum está bien.
            rs485_ni=temp_ni;
         }
         state=0;
         return;

      default: // Obtiene los datos...
         rs485_add_to_temp(b);
         --len;
         break;
   }
   if ((state>=3) && (!len)) {
      state=255;
   }
   else {
      ++state;
   }
}


// Función: Envía datos por el bus RS485.
// Entradas:     1) La dirección del destinatario.
//               2) El número de datos a enviar.
//               3) El puntero a los datos a enviar.
// Salidas:   TRUE si puede concretar la operación.
//            FALSE si falla.
// Nota:       Formato:  fuente| destinatario | longitud de datos |datos | checksum.

int1 rs485_envia_mensaje(int destinatario,int len, int*dato) {
   int8 try, i, cs;
   int1 ret = FALSE;

   RCV_OFF(); // Desactivamos la recepción de datos.
   disable_interrupts(GLOBAL); // Desactivamos las interrupciones.
 for(try=0; try<5; ++try) {
      rs485_collision = 0; // No hay colisión de datos.
      fputc((int16)0x100|rs485_id, RS485_CD); // Transmitimos...quien envía los datos..
      fputc((int16)0x100|destinatario, RS485_CD); // elejimos un destinatario...
      fputc(len, RS485_CD); // Enviamos la longitud de datos...

      for(i=0, cs=rs485_id^to^len; i<len; ++i) {
         cs ^= *dato;
         fputc(*dato, RS485_CD); // enviamos los datos...
         ++dato;
      }

      fputc(cs, RS485_CD); // transmite checksum...
      if(!rs485_collision) { // Si no hay colisión de errores....
         ret = TRUE; // Sigue y salta...
         break;
      }
      delay_ms(RS485_ID);
   }

   RCV_ON(); // Habilitamos la recepción de datos nuevamente.
   enable_interrupts(GLOBAL); // Habilitamos las interrupciones globales.
   return(ret); // Retornamos reporte de fallas...
}


// Función: Espera a que el bus esté listo para poder enviar datos.
// Entrada: TRUE - Resetea el perro guardían para evitar el reset.
//          FALSO - El perro guardían no ha sido reseteado.
// Salidas: Ninguna.

void rs485_espera(int1 clrwdt) 
{
   int16 i;

   RCV_OFF(); // Apagamos la recepción de datos.
   for(i=0; i <= (rs485_wait_time*20); ++i)
   {
      if(!input(RS485_RX_PIN)) // Esperamos a que el PIN RX esté a 0.
         i = 0; // reseteamos el contador.
      else // sino ....
         delay_us(50);

      if(clrwdt)
         restart_wdt(); // reseteamos el perro guardían.
   }
}


// Función: Toma un dato del bus RS485 y lo guarda en un buffer.
// Entradas:   1) Puntero al buffer para guardar el mensaje.
//             2) TRUE  - En espera del mensaje.
//                FALSE - Solo comprueba si un mensaje está disponible.
// Salidas:       TRUE  - Si el mensaje fue recibido.
//                FALSE - Si espera es FALSO y ningún mensaje está disponible.
// Nota: Los datos rellenan el buffer con el siguiente orden:
//       ID del emisor | Longitud del dato | datos...

int1 rs485_recibe_datos(int *datos, int espera)
{
   while(espera && (rs485_ni == rs485_no)) {}

   if(rs485_ni == rs485_no)
      return FALSE;

   else {
      int n;
      n = rs485_buffer[(rs485_no+1)%sizeof(rs485_buffer)] + 2;

      for(; n>0; --n)
      {
         *datos = rs485_buffer[rs485_no];
         if(++rs485_no >= sizeof(rs485_buffer))
         {
            rs485_no = 0;
         }
         ++datos;
      }
      return TRUE;
   }
}
 
Gracias por tu respuesta Jonathan, te preguntaba por que tu tienes años años con este problema; yo recien he probado esta libreria y no me sale, ahora la estoy analizando.
 
Atrás
Arriba