Autor Tema: Tarjeta de adquisición de datos. 18F4550/UBS BULK  (Leído 2276 veces)

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

Desconectado MetalKaiser

  • PIC10
  • *
  • Mensajes: 5
Tarjeta de adquisición de datos. 18F4550/UBS BULK
« en: 24 de Agosto de 2011, 21:24:01 »
Saludos a todos los foristas! Acá vengo a dejarles un pequeño proyecto en el que convierto una señal analógica a digital, y luego la mando a una PC vía USB BULK. El programa y el circuito son sumamente sencillos:

Código: C
  1. #include <18F4550.h>
  2. #device adc=8
  3. #fuses HSPLL, NOWDT, NOPROTECT, NOLVP, NODEBUG, USBDIV, PLL5, CPUDIV1, VREGEN
  4. #use delay(clock=48000000)
  5. #define usb_con_sense_pin pin_b2
  6.  
  7.  
  8. #define USB_HID_DEVICE FALSE // deshabilitamos el uso de las directivas HID
  9. #define USB_EP1_TX_ENABLE USB_ENABLE_BULK // turn on EP1(EndPoint1) for IN bulk/interrupt transfers
  10. #define USB_EP1_RX_ENABLE USB_ENABLE_BULK // turn on EP1(EndPoint1) for OUT bulk/interrupt transfers
  11. #define USB_EP1_TX_SIZE 32 // size to allocate for the tx endpoint 1 buffer
  12. #define USB_EP1_RX_SIZE 32 // size to allocate for the rx endpoint 1 buffer
  13.  
  14.  
  15. #include <pic18_usb.h> // Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
  16. #include "USB_BULK.h" // Configuración del USB y los descriptores para este dispositivo
  17. #include <usb.c> // handles usb setup tokens and get descriptor reports
  18.  
  19.  
  20. int16 adc;
  21. int16 IniciarConteoEn=65459;
  22.  
  23. float envia;
  24.  
  25. #int_TIMER3 //Interrupción timer1
  26. void temp1s(void) //función
  27. {
  28.    output_toggle(PIN_B1);
  29.    adc=read_adc();
  30.    set_timer3(IniciarConteoEn);
  31. }
  32.  
  33. void main(void) {
  34.  
  35.   setup_timer_3 (T3_INTERNAL | T3_DIV_BY_1);   ///configuro timer 1 con reloj interno y prescaler de 1
  36.    
  37.   enable_interrupts(INT_TIMER3);               //habilita interrupción timer1
  38.   enable_interrupts(global);                   //habilita interrupción general
  39.   set_timer3(IniciarConteoEn);                 //Precarga del timer1
  40.   setup_adc_ports(AN0|VSS_VDD);
  41.   setup_adc(ADC_CLOCK_DIV_64 );//|| ADC_ACQT_2TAD ); //Indica el tiempo de reloj
  42.   #asm                                               //Inicio de sentencias en lenguaje Assembler
  43.   movlw 0b10001110 ;justificacion_derecha,2Tad,Fosc/64 //Modificando el tiempo de conversión
  44.   iorwf 0xFC0,1 ; direccion de ADCON2                  //y el tiempo de adquisición
  45.   #endasm                                            //Fin de la rutina Assembler
  46.   set_adc_channel(0);
  47.   usb_init();
  48.   usb_task();
  49.   usb_wait_for_enumeration();
  50.   enable_interrupts(global);
  51.  
  52.   while (TRUE)
  53.   {
  54.     if(usb_enumerated()){
  55.  
  56.         envia=(5.0*adc)/256.0;
  57.           usb_put_packet(1,envia,1,USB_DTS_TOGGLE);
  58.    
  59.     }
  60.   }
  61. }


El único problema que no he podido solucionar es que, si aumento la precarga de TIMER1, la PC no reconoce el dispositivo USB, y con el código actual la interrupción sólo ocurre cada 28us, dando una frecuencia de muestreo de 35,71KHz.

Originalmente, pensaba que la frecuencia fuera de al menos 40KHz, ya que las señales a muestrear están en el rango de audio, pero no lo he logrado. A todas estas, el cristal utilizado es de 20MHz.

Cualquier idea vendría bien...


 

anything