TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Prometeo91 en 11 de Enero de 2017, 13:21:20

Título: ModBus Problemas con interrupciones.
Publicado por: Prometeo91 en 11 de Enero de 2017, 13:21:20
Muy buenos dias a todos en el foro  :-/!!!! :-) :-) :-) :-) :-)

Verán, desde hace unos dias estoy tratando de hacer funcionar la interrupción externa del PIC16F690, con modbus, el fin de esto, es para poder sincronizar la operación del programa, con la red de CA. Hice un programa super simple, para ver si se queda muerto el micro, durante el desarrollo del programa principal, pero valla jajajaja :? no he podido pasar de ahi :? :? :? :?.

El problema radica en que tan pronto inicia el programa, la red de CA genera la interrupcion y carga los valores, despues, creo que entra el comando  modbus_init(); del void main() y bueno, hasta ahi llego la interrupción, nunca mas vuelve a cargar los valores, por lo que me imagino que lo que ha de pasar, es que ha de deshabilitar la interrupción externa o algo asi.

Lo compilo en CCS 5.25, usando la liberia del CCS 4.120, esto es porque la del 5.25 no sirve  :5]. Igual, tengo el CCS 4.120, y lo puedo compilar ahi, pero no hay ningun cambio  :(.

He revisado una sugerencia en el foro, que da pacalaconcurso en la respuestra 15, pero ya esta implícita en el codigo que proporciona CCS, asi que bueno  :(..... De todas formas adjunto la liga  http://www.todopic.com.ar/foros/index.php?topic=5807.15 (http://www.todopic.com.ar/foros/index.php?topic=5807.15)

A continuación adjunto el código del 16F690:

Código: [Seleccionar]
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//::::::::::::::::::::::Configuracion de MCU::::::::::::::::::::::::::::::::::::
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
#include <16f690.h>
#fuses HS,NOWDT,PROTECT,MCLR
#use delay(clock=20m)
#priority INT_EXT,INT_RDA

#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_TYPE MODBUS_RTU     //use MODBUS_ASCII for ASCII mode
#define MODBUS_SERIAL_RX_BUFFER_SIZE 64
#define MODBUS_SERIAL_BAUD 9600
//#define MODBUS_SERIAL_ENABLE_PIN   0   // Controls DE pin for RS485
//#define MODBUS_SERIAL_RX_ENABLE    0   // Controls RE pin for RS485
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#include <modbus_4120.c>
#define MODBUS_ADDRESS 15
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//::::::::::::::::::::::::::Variables del MCU::::::::::::::::::::::::::::::::::::
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//entradas tipicas de modbus, cualquier valor de lectura o escritura de algun
//puerto o variable debe de ser guardado en estos registros para que funcione

   int8 coils = 0b00000000; //coil 1 es LSB
   int8 inputs =0b00000000;//input 1 es LSB
   //Registro 1 es 8800, pueden ser guardados como mas convengan decimales, binarios o hexadecimales
   int16 hold_regs[] = {0x8800,64,0x6600,0x5500,0x4400,0x3300,0x2200,0x1100};
   int16 input_regs[] = {0x1100,0x2200,0x3300,0x4400,0x5500,0x6600,0x7700,0x8800};
   int16 event_count = 0;
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 
   
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//::::::::::::::::::::::::::::Interrupciones::::::::::::::::::::::::::::::::::::
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

#INT_EXT                        //Interrupción externa.
void cero()                      //Función de la interrupción externa
{

//*************************************************************************************************   
inputs = 0; // Set inicial todos a 0, solo me encargo de ponerlos en 1 en caso que sea necesario.
if(input(PIN_C1)!=1) bit_set(inputs,0);//para arreglo de resistencias pull UP
if(input(PIN_C2)!=1) bit_set(inputs,1);
if(input(PIN_B4)!=1) bit_set(inputs,2);
//**************************************************************************************************
}

//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
/*This function may come in handy for you since MODBUS uses MSB first.*/
int8 swap_bits(int8 c)
{
   return ((c&1)?128:0)|((c&2)?64:0)|((c&4)?32:0)|((c&8)?16:0)|((c&16)?8:0)
          |((c&32)?4:0)|((c&64)?2:0)|((c&128)?1:0);
}



#ZERO_RAM
void main()
{
//CONFIGURACION DE PUERTOS
   set_tris_a(0b00000100);
   output_a(0);
   
   set_tris_c(0b00000110);
   output_c(0);
   
   set_tris_b(0b01111111);
   output_b(0);
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
   setup_adc_ports(NO_ANALOGS);
/////////////////////////////////////////////////////////////////////////////////////
//CONFIGURACON DE INTERRUPCION EXTERIOR
 enable_interrupts(INT_EXT);     //Habilito interrupciones externas
 ext_int_edge(H_TO_L);           //Primera interrupción se dará en flanco de subida
 enable_interrupts(GLOBAL);      //Habilito las interrupciones generales
//////////////////////////////////////////////////////////////////////////////////////   
   modbus_init();
   
   while(TRUE){

      while(!modbus_kbhit());
     
      delay_us(50);
     
      //check address against our address, 0 is broadcast
      if((modbus_rx.address == MODBUS_ADDRESS) || modbus_rx.address == 0)
      {
         switch(modbus_rx.func)
         {
            case FUNC_READ_COILS:    //read coils
            case FUNC_READ_DISCRETE_INPUT:    //read inputs
               if(modbus_rx.data[0] || modbus_rx.data[2] ||
                  modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
                  modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
               else
               {
                  int8 data;
                 
                  if(modbus_rx.func == FUNC_READ_COILS)
                     data = coils>>(modbus_rx.data[1]);      //move to the starting coil
                  else
                     data = inputs>>(modbus_rx.data[1]);      //move to the starting input

                  data = data & (0xFF>>(8-modbus_rx.data[3]));  //0 out values after quantity

                  if(modbus_rx.func == FUNC_READ_COILS)
                     modbus_read_discrete_input_rsp(MODBUS_ADDRESS, 0x01, &data);
                  else
                     modbus_read_discrete_input_rsp(MODBUS_ADDRESS, 0x01, &data);
                     
                  event_count++;
               }
               break;
            case FUNC_READ_HOLDING_REGISTERS:
            case FUNC_READ_INPUT_REGISTERS:
               if(modbus_rx.data[0] || modbus_rx.data[2] ||
                  modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
                  modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
               else
               {
                  if(modbus_rx.func == FUNC_READ_HOLDING_REGISTERS)
                     modbus_read_holding_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),hold_regs+modbus_rx.data[1]);
                  else
                     modbus_read_input_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),input_regs+modbus_rx.data[1]);
                 
                  event_count++;
               }
               break;
            case FUNC_WRITE_SINGLE_COIL:      //write coil
               if(modbus_rx.data[0] || modbus_rx.data[3] || modbus_rx.data[1] > 8)
                  modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
               else if(modbus_rx.data[2] != 0xFF && modbus_rx.data[2] != 0x00)
                  modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_VALUE);
               else
               {
                  //coils are stored msb->lsb so we must use 7-address
                  if(modbus_rx.data[2] == 0xFF)
                     bit_set(coils,modbus_rx.data[1]);
                  else
                     bit_clear(coils,modbus_rx.data[1]);

                  modbus_write_single_coil_rsp(MODBUS_ADDRESS,modbus_rx.data[1],((int16)(modbus_rx.data[2]))<<8);
                 
                  event_count++;
               }
               break;
            case FUNC_WRITE_SINGLE_REGISTER:
               if(modbus_rx.data[0] || modbus_rx.data[1] >= 8)
                  modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
               else
               {
                  //the registers are stored in little endian format
                  hold_regs[modbus_rx.data[1]] = make16(modbus_rx.data[3],modbus_rx.data[2]);

                  modbus_write_single_register_rsp(MODBUS_ADDRESS,
                               make16(modbus_rx.data[0],modbus_rx.data[1]),
                               make16(modbus_rx.data[2],modbus_rx.data[3]));
               }
               break;
            case FUNC_WRITE_MULTIPLE_COILS:
               if(modbus_rx.data[0] || modbus_rx.data[2] ||
                  modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
                  modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
               else
               {
                  int i,j;

                  modbus_rx.data[5] = swap_bits(modbus_rx.data[5]);

                  for(i=modbus_rx.data[1],j=0; i < modbus_rx.data[1]+modbus_rx.data[3]; ++i,++j)
                  { 
                     if(bit_test(modbus_rx.data[5],j))
                        bit_set(coils,7-i);
                     else
                        bit_clear(coils,7-i);
                  }

                  modbus_write_multiple_coils_rsp(MODBUS_ADDRESS,
                                 make16(modbus_rx.data[0],modbus_rx.data[1]),
                                 make16(modbus_rx.data[2],modbus_rx.data[3]));
                 
                  event_count++;
               }
               break;
            case FUNC_WRITE_MULTIPLE_REGISTERS:
               if(modbus_rx.data[0] || modbus_rx.data[2] ||
                  modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
                  modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
               else
               {
                  int i,j;

                  for(i=0,j=5; i < modbus_rx.data[4]/2; ++i,j+=2)
                     hold_regs[i] = make16(modbus_rx.data[j+1],modbus_rx.data[j]);

                  modbus_write_multiple_registers_rsp(MODBUS_ADDRESS,
                                 make16(modbus_rx.data[0],modbus_rx.data[1]),
                                 make16(modbus_rx.data[2],modbus_rx.data[3]));
               
                  event_count++;
               }
               break;           
            default:    //We don't support the function, so return exception
               modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_FUNCTION);
         }
      }
  }
}
   

Y aqui esta la libreria http://www.mediafire.com/file/jepjquxjv12vnu6/modbus_4120.c (http://www.mediafire.com/file/jepjquxjv12vnu6/modbus_4120.c)

También, aunque en este momento no es muy importante, el codigo de la libreria presenta problemas en la respuesta de la lectura de las bobinas.

De ante mano les doy las gracias, me disculpo por el inmenso codigo de la libreria jejeje y les deceo un buen dia  :-/
Título: Re:ModBus Problemas con interrupciones.
Publicado por: Prometeo91 en 11 de Enero de 2017, 13:27:13
Tambien, seme paso comentar, que si cambiamos de posicion el modbus_init(); algo asi:

Código: [Seleccionar]
void main()
{
 modbus_init();
//CONFIGURACION DE PUERTOS
   set_tris_a(0b00000100);
   output_a(0);
   
   set_tris_c(0b00000110);
   output_c(0);
   
   set_tris_b(0b01111111);
   output_b(0);
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
   setup_adc_ports(NO_ANALOGS);
/////////////////////////////////////////////////////////////////////////////////////
//CONFIGURACON DE INTERRUPCION EXTERIOR
 enable_interrupts(INT_EXT);     //Habilito interrupciones externas
 ext_int_edge(H_TO_L);           //Primera interrupción se dará en flanco de bajada
 enable_interrupts(GLOBAL);      //Habilito las interrupciones generales
//////////////////////////////////////////////////////////////////////////////////////   
 
   
   while(TRUE){

No hay ninguna diferencia, esto lo comento, por lo que hace la funcion modbus_init(); en el codigo.