TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: mauro2555 en 09 de Abril de 2011, 22:43:53

Título: Ayuda con interruciones en RB0 y RB1
Publicado por: mauro2555 en 09 de Abril de 2011, 22:43:53
Buenas a todos, haber si alguien me puede ayudar, sigo con mi proyecto USB en el 18f4550. Tengo q capturar un voltaje por RA0 y las interrupciones de un encoder por RB0 y RB1, despues enviar los valores por USB. He desarrollado el siguiente codigo, donde la comunicación USB funciona correctamente, también la captura del ADC, pero he tenido problemas con las interrupciones RB0 y RB1 ya que no me captura la cantidad de interrupciones recibidas. He programado varios PIC's y he modificado muchas veces el codigo pero nada q encuentro el fallo, entonces he programado el PIC y lo he montado en protoboard, luego he mirado los voltajes en RB0 y RB1 y resulta q me aparecen 4V en RB0 y 1,5V en RB1 y no tengo ni idea por q razon salen esos voltajes si estoy configurando RB0 y RB1 como entradas y el resto como salidas. Me gustaria q alguien probara mi código y me dijera si tambien salen esos voltajes en RB0 y RB1. El codigo es el siguiente:


#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#use fast_io(b)

#Byte PortB = 0xF81

#define USB_HID_DEVICE FALSE // deshabilitamos el uso de las directivas HID
#define USB_EP1_TX_ENABLE USB_ENABLE_BULK // turn on EP1(EndPoint1) for IN bulk/interrupt transfers
#define USB_EP1_RX_ENABLE USB_ENABLE_BULK // turn on EP1(EndPoint1) for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE 32 // size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE 32 // size to allocate for the rx endpoint 1 buffer
#include <pic18_usb.h> // Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
#include "header.h" // Configuración del USB y los descriptores para este dispositivo
#include <usb.c> // handles usb setup tokens and get descriptor reports

int16 x = 0;
int16 adc0=0;
char  voltage[9];
char  bufer[];
char  Conexion[] = "o.k";
const int8 Lenbuf = 32;
int8  recbuf[Lenbuf];

#INT_EXT
void prueba()
{     
   If (Bit_Test(PortB, 0))      // Si RB0 se ha puesto a 1 (flanco de subida),
   { 
       Ext_Int_Edge(H_TO_L);    // entonces activar la siguiente interrupción por flanco de bajada.
       If (Bit_Test(PortB, 1))  // Si RB1 está a 1,
       {
         x++;                      // entonces incrementar una unidad el valor de X.
       }
   }
   Else                         // Si RB0 se ha puesto a 0 (flanco de bajada),
   { 
       Ext_Int_Edge(L_TO_H);    // entonces activar la siguiente interrupción por flanco de subida.
       If (Bit_Test(PortB, 1))  // Si RB1 está 1,
       {
           x--;                 // entonces decrementar una unidad el valor de X.
       }
   }
}

void main()
{
   port_b_pullups(false);
   setup_adc_ports(AN0|VSS_VDD);//para escoger el canal cero y el vss y vdd
   SETUP_ADC(ADC_CLOCK_INTERNAL);//la frecuencia de muestreo es 2-6us
   SET_ADC_CHANNEL(0);
   delay_ms(333);
   disable_interrupts(Int_Ext);
   disable_interrupts(GLOBAL);
   
   Ext_Int_Edge(L_TO_H);        // Inicialmente detectar interrupción por flanco de subida.
   Enable_Interrupts(Int_Ext);  // Activar Interrupción Externa a través de RB0.
   Enable_Interrupts(GLOBAL);   // Interrupciones Generales Activadas.
   Set_Tris_B(0b00000000);      // Puerto B todo entradas (sólo usamos las entradas RB0 y RB1).
   PortB=0;
   usb_init();
   usb_task();
   delay_ms(333);
   output_high(PIN_C2);
   
   while (TRUE)  // Si el PIC esta conectado al PC a través del USB.
   {
    while(!usb_enumerated())
    {
      output_high(PIN_B0);
      delay_ms(500);
      output_low(PIN_B0);
      output_high(PIN_B1);
      delay_ms(500);
      output_low(PIN_B1);
      output_high(PIN_B2);
      delay_ms(500);
      output_low(PIN_B2);
      output_high(PIN_B3);
      delay_ms(500);
      output_low(PIN_B3);
      output_high(PIN_B4);
      delay_ms(500);
      output_low(PIN_B4);
      output_high(PIN_B5);
      delay_ms(500);
      output_low(PIN_B5);
      output_high(PIN_B6);
      delay_ms(500);
      output_low(PIN_B6);
      output_high(PIN_B7);
      delay_ms(500);
      output_low(PIN_B7);
      }
    while(usb_enumerated())
    {
      if (usb_kbhit(1))
      {
        usb_get_packet(1, recbuf, Lenbuf);       
        if(recbuf[0]==127)
        {
           output_high(PIN_B2);
        }
        if(recbuf[0]==126)
        {
          output_low(PIN_B2);
        }
        if(recbuf[0]==125)
        {
          usb_put_packet(1,Conexion,3,USB_DTS_TOGGLE);
          output_high(PIN_B2);
        }
        if(recbuf[0]==124)
        {
          output_high(PIN_D6);
          output_low(PIN_D7);
        }
        if(recbuf[0]==123)
        {
          output_high(PIN_D7);
          output_low(PIN_D6);
        }
        if(recbuf[0]==122)
        {
          output_low(PIN_D7);
          output_low(PIN_D6);
        }
        if(recbuf[0]==121)
        {
          int16 muestra;
          int s;
          for(s=0;s<=64;s++)
          {
            muestra = read_adc();  //para leer el valor del adc0
            adc0=adc0+muestra;
            delay_ms(50);
          }
          adc0=adc0/65;
          sprintf(voltage, "%f", (float)adc0 * 0.01960784); //esta instruccion nos permite convertir  el valor del adc en un string.       
          usb_put_packet(1,voltage,4,USB_DTS_TOGGLE);//con esta instruccion mandamos el arrglo que se creo en la instruccion anterior
        }
        if(recbuf[0]==120)
        {
          char contador[6];
          sprintf(contador, "%06lu", x);
          usb_put_packet(1,contador,6,USB_DTS_TOGGLE);
        }
      }
    }
  }
}

Creo que el problema esta a la hora de configurar el ADC o depronto debido a las resistencias pull-up de RB0 y RB1, no se si tengo errores en esas partes.
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: AngelGris en 09 de Abril de 2011, 23:14:49
  Pues según tu línea "set_tris_b(0b00000000)" estás configurando todo el puerto B como salida, inclusive RB0 y RB1
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: bmb en 09 de Abril de 2011, 23:22:05
Hola mauro2555, dando un ojeada rápida a tu código veo que en los fuses te haría falta este: NOPBADEN que configura al Puerto B como E/S digitales en el Reset.

Otro problema sería que #int_ext solo te maneja la interrupción externa de RB0.  Si quisieras manejar una interrupción externa por RB1 debes usar #int_ext1.

Finalmente, otro error sería lo que te acaba de mostrar AngelGris.

Saludos!
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: mauro2555 en 09 de Abril de 2011, 23:35:33
Gracias por darle una ojeada al codigo, AngelGris tienes razon debe ser "set_tris_b(0b00000011)" asi lo tengo solo q hice una prueba antes de crear el tema y olvide arreglar eso, gracias por recordarmelo. bmb no sabia lo del NOPBADEN, tiene mucho sentido q obtenga esos voltajes si no he configurado ese fuse, voy a arreglar el codigo y probare inmediatamente, en unos minutos les cuento como me fue.
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: mauro2555 en 10 de Abril de 2011, 01:46:07
Excelente, agregue el fuse NOPBADEN y ya no tengo voltajes en RB0 y RB1, sin embargo sigo sin obtener interrupciones, no se por q razon pareciera q no entra al #INT_EXT, si alguien encuentra algun error en el codigo me informan, gracias
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: bmb en 10 de Abril de 2011, 13:09:41
Hola mauro2555, revisando más detenidamente tu código veo que estás usando a RB0 y RB1 como salidas:

Código: C
  1. while(!usb_enumerated())
  2.     {
  3.       output_high(PIN_B0);
  4.       delay_ms(500);
  5.       output_low(PIN_B0);
  6.       output_high(PIN_B1);
  7.       delay_ms(500);
  8.       output_low(PIN_B1);
  9.       .
  10.       .
  11.       .

Como no tengo todas las librerías que usas para USB, hice un pequeño código para prender y apagar un LED usando exactamente el mismo encabezado y configuración que usas y eliminando todo tu código, la interrupción funciona bien:

Código: C
  1. #include <18F4550.h>
  2. #device adc=10
  3. #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,NOPBADEN,USBDIV,PLL5,CPUDIV1,VREGEN
  4. #use delay(clock=48000000)
  5. #use fast_io(b)
  6.  
  7. #Byte PortB = 0xF81
  8.  
  9. int1 x = false;
  10.  
  11. #INT_EXT
  12. void prueba()
  13. {    
  14.    x++;
  15. }
  16.  
  17. void main()
  18. {
  19.    port_b_pullups(false);
  20.    setup_adc_ports(AN0|VSS_VDD);//para escoger el canal cero y el vss y vdd
  21.    SETUP_ADC(ADC_CLOCK_INTERNAL);//la frecuencia de muestreo es 2-6us
  22.    SET_ADC_CHANNEL(0);
  23.    delay_ms(333);
  24.    disable_interrupts(Int_Ext);
  25.    disable_interrupts(GLOBAL);
  26.    
  27.    Ext_Int_Edge(L_TO_H);        // Inicialmente detectar interrupcion por flanco de subida.
  28.    Enable_Interrupts(Int_Ext);  // Activar Interrupción Externa a traves de RB0.
  29.    Enable_Interrupts(GLOBAL);   // Interrupciones Generales Activadas.
  30.    Set_Tris_B(0b00000011);      // Puerto B todo entradas (sólo usamos las entradas RB0 y RB1).
  31.  
  32.    while(true)
  33.    {
  34.       if(x)
  35.          output_high(PIN_C2);
  36.       else
  37.          output_low(PIN_C2);
  38.    }
  39. }

Como ves, solo le he adicionado la directiva #device adc=10 para que la captura ADC sea de 10 bits.  Te anexo el código y la prueba en proteus.

Saludos!
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: mauro2555 en 10 de Abril de 2011, 21:20:25
bmb ya corregi los errores, he probado tu codigo y no responde la interrupcion, es muy extraño por q es un codigo sencillo pero nada. Quisiera saber q version utilizas de Proteus y CCS. Yo estoy trabajando en CCS 4.104 y Proteus 7.6, las pruebas USB las realizo en XP debido a la libreria JpicUsb de java, pero las pruebas de ADC e interrupciones las realizo en Windows 7 de 64x. Saludos.
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: mauro2555 en 10 de Abril de 2011, 23:38:47
bmb gracias por tu aporte!!! despues de varias pruebas he conseguido q me funcionen las interrupciones en RB0 y RB1, hice los arreglos q ustedes me aconsejaron al codigo, luego he conectado resistencias pullups externas al micro en las entradas a RB0 y RB1 y me ha detectado las interrupciones. Me base en el esquema de protesus q subiste, gracias por quitarme un dolor de cabeza jeje. Exitos a todos..
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: bmb en 11 de Abril de 2011, 08:29:13
Hola mauro2555, me alegra mucho que puedas seguir avanzando con tu proyecto!

Saludos!
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: mauro2555 en 13 de Abril de 2011, 22:09:37
hola a todos, he seguido con mi proyecto, pero ahora se me ha presentado otro inconveniente. Necesito guardar la cantidad de interrupciones del encoder en la eeprom externa, el inconveniente es q necesito almacenar el dato cada vez q se realice la interrupcion. Entonces lo q hice fue incluir en la funcion de la interrupcion el comando para guardar el dato en la eeprom, pero al programar el pic y probarlo me doy cuenta q no inicia, encontre q cuando compilo el CCS con el codigo aparece un warning de escritura en la eeprom, el codigo de la interrupcion es el siguiente:

#INT_EXT
void prueba()
{     
   If (Bit_Test(PortB, 0))      // Si RB0 se ha puesto a 1 (flanco de subida),
   {
       Ext_Int_Edge(H_TO_L);    // entonces activar la siguiente interrupción por flanco de bajada.
       If (Bit_Test(PortB, 1))  // Si RB1 está a 1,
       {
         x++;                      // entonces incrementar una unidad el valor de X.
       }
   }
   Else                         // Si RB0 se ha puesto a 0 (flanco de bajada),
   {
       Ext_Int_Edge(L_TO_H);    // entonces activar la siguiente interrupción por flanco de subida.
       If (Bit_Test(PortB, 1))  // Si RB1 está 1,
       {
           x--;                 // entonces decrementar una unidad el valor de X.
       }
   }
   write_int16_ext_eeprom(0,x);//guardo el valor de X en la eeprom
}

He intentado de muchas formas pero no hallo la manera de guardar en la eeprom el valor de X cada vez q se incremente o decremente. q me pueden aconsejar, donde puedo poner la linea de escritura en la eeprom teniendo en cuenta q haya cambiado el valor de X???

Helppp...
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: bmb en 13 de Abril de 2011, 22:56:20
Hola mauro1555, cual eeprom estás usando?

Saludos!
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: mauro2555 en 13 de Abril de 2011, 23:37:21
Hola bmb, la eeprom es un FM24C512, ahi te envio la pag del fabricante donde se encuentra el datasheet.

http://www.ramtron.com/products/nonvolatile-memory/serial-product.aspx?id=5
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: bmb en 14 de Abril de 2011, 09:07:52
Hola mauro2555 , le tienes las resistencias pullup en los pines SDA y SCL?  En que pines los definiste? Tienes en el encabezado esto?

Citar
#include <24512.C>
#include <external_eeprom.c>

Saludos!
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: mauro2555 en 14 de Abril de 2011, 17:49:51
si tengo las resistencias y los include, estoy trabajando SDA=D0 y SCL=D1. He hecho pruebas con la eeprom y la escritura y lectura es exitosa, el problema es q necesito escribir un dato cada vez q el encoder me active la interrupcion. Otra cosa es q estoy enviando desde java 5 caracteres por ejemplo "43500" y consigo q lleguen al pic, el problema es q quiero almacenar ese valor en la eeprom pero como int16 y no he conseguido convertir esos 5 char en int16, sabes como hacerlo??

gracias por la ayuda...
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: Suky en 14 de Abril de 2011, 18:22:30
Utiliza atoi, atol algo por el estilo. Usa la ayuda para informarte cual corresponde, dado que por lo visto los 43500 van en ascii.


Saludos!
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: mauro2555 en 14 de Abril de 2011, 19:23:40
Suky tienes razon la funcion atoi me sirve, pero aun asi no pasa nada. Resulta q para enviar los datos de java al PIC por USB lo q hago es convertir ese "43500" a un byte[] y en vio los bytes asi: byte[0],byte[1],byte[2],byte[3]. Es decir cuando llegan al PIC llegan bytes y es ahi donde necesito convertir de nuevo todos los bytes a Int16 para almacenarlos en la eeprom.
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: Suky en 14 de Abril de 2011, 23:13:09
Suky tienes razon la funcion atoi me sirve, pero aun asi no pasa nada. Resulta q para enviar los datos de java al PIC por USB lo q hago es convertir ese "43500" a un byte[] y en vio los bytes asi: byte[0],byte[1],byte[2],byte[3]. Es decir cuando llegan al PIC llegan bytes y es ahi donde necesito convertir de nuevo todos los bytes a Int16 para almacenarlos en la eeprom.

Guárdalos en un buffer para formar la cadena de caracteres ascii y luego usas atoi.


Saludos!
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: COARITES en 07 de Febrero de 2012, 18:24:26
Hola compañeros yo igual estoy chocando con el mismo problema que pasaste, no se si ya le diste solucion; mi codigo compila y run en proteus, pero no registra nada en la memoria eeprom.

Mi codigo es el siguiente haber si pueden echarme una ayudita.
_____________
#include <18f4550.h>
#include <24256.c>
#include <external_eeprom.c>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#use i2c(Master,sda=PIN_B0,scl=PIN_B1)       
void main(void)
{
   byte i;
   for(i=0;i<=12;i++)
   write_int16_ext_eeprom(i,i);
}
_______________________
Compilado en ccs v4.128 y proteus 7.8
Título: Re: Ayuda con interruciones en RB0 y RB1
Publicado por: mauro2555 en 31 de Marzo de 2012, 23:20:07
Hola perdon por no responder antes, pense q nadie habia solucionado el problema. Despues de hacer muchos arreglos hice funcionar mi codigo el cual posteo acá. Esta configuracion me permite manejar el adc y tambien las interrupciones RB0 y RB1, ademas tambien me almacena las interrupciones en un espacio en memoria eeprom externa y funciona a la perfeccion la comunicacion USB, para quien tenga algun problema similar puede utilizar esta configuracion, ya he probado con el 18f4550 y actualmente esta en funcionamiento en un dispositivo q diseñe e instale, espero sirva de ayuda a alguien. Exitos!!

#include <18F4550.h>
#device adc=10
#include <24512.c> //libreria eeprom 24LC512
#include <external_eeprom.c>
#include <stdlib.h>

#fuses HSPLL,NOWDT,PROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOBROWNOUT,NOPBADEN
#use delay(clock=48000000)

#use fast_io(B)
#use fast_io(D)
#byte ADCON2=0xFC0
#byte PortB = 0xF81            // Dirección del puerto B para la familia 18Fxx5x
#byte PortD = 0xF83            // Dirección del puerto D para la familia 18Fxx5x

#define USB_HID_DEVICE FALSE // deshabilitamos el uso de las directivas HID
#define USB_EP1_TX_ENABLE USB_ENABLE_BULK // turn on EP1(EndPoint1) for IN bulk/interrupt transfers
#define USB_EP1_RX_ENABLE USB_ENABLE_BULK // turn on EP1(EndPoint1) for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE 32 // size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE 32 // size to allocate for the rx endpoint 1 buffer

#include <pic18_usb.h> // Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
#include "header.h" // Configuración del USB y los descriptores para este dispositivo
#include <usb.c> // handles usb setup tokens and get descriptor reports

int16 x = 0, y=0, limS=0, limI=0;
int16 adc0;
char  voltage[10];
char  Conexion[] = "o.k";
const int8 Lenbuf = 32;
int8  recbuf[Lenbuf];       

#INT_EXT                        // Interrupción Externa por RB0: Decodificación de Encoder.
Void IntRB0()
{
   // CCS se encarga de desactiva automáticamente cualquier interrupción.
   // No hace falta guardar contextos de registros.

   If (!Bit_Test(PortB, 0))      // Si RB0 se ha puesto a 1 (flanco de subida),
   { 
       Ext_Int_Edge(L_TO_H);    // entonces activar la siguiente interrupción por flanco de bajada.
       If (!Bit_Test(PortB, 1))  // Si RB1 está a 1,
       {
           x--;                 // entonces incrementar una unidad el valor de X.
       }
   }
   Else                         // Si RB0 se ha puesto a 0 (flanco de bajada),
   { 
       Ext_Int_Edge(H_TO_L);    // entonces activar la siguiente interrupción por flanco de subida.
       If (!Bit_Test(PortB, 1))  // Si RB1 está 1,
       {
           x++;                 // entonces decrementar una unidad el valor de X.
       }
   }
   // Al finalizar la interrupción CCS se encarga de volver a poner automáticamente
   // la badera INTF = 0 ---> borra la interrupción para poder permitir la siguiente;
   // no hemos de hacer nada por nuestra parte.
   y=1;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//
//                            M A I N
//
///////////////////////////////////////////////////////////////////////////////////////////////////
void main()
{
  Port_B_Pullups(FALSE);       // Configuración para el PIC 18F4550.
  set_tris_a(0x03); //Entrada an0 y an1
  setup_adc_ports(AN0_TO_AN1|VSS_VDD);//para escoger el canal cero y el vss y vdd
  setup_adc(ADC_CLOCK_INTERNAL);//la frecuencia de muestreo es 2-6us
  ADCON2= ADCON2 | 0b00111000;
  set_adc_channel(1);
  Setup_vref(FALSE);
  clear_interrupt(INT_EXT);
  delay_ms(333);
  //////////////////INICIO Y HABILITACION DE LO QUE NECESITO/////////////////////////////////////////
  init_ext_eeprom();
  Enable_Interrupts(int_ext);  // Activar Interrupción Externa a través de RB0.
  Ext_Int_Edge(H_TO_L);        // Inicialmente detectar interrupción por flanco de bajada.
  enable_interrupts(global);   // Activo interruciones globales
  bit_clear(PortB,0);
  Set_Tris_B(0b11111111);
  usb_init();
  usb_task();
  delay_ms(333);

while (TRUE)
  {
  }