desktop

Control de dispositivos a través del módulo USB del PIC18F45/2550

Muy buenas tus gráficas ! Yo todavía me estoy peleando para poder comunicarme con USB en VC# mediante Bulck, pero voy a ver como hago para hacerlo.
 
jejeje, siempre nos peleamos en algo, pero como siempre hemos hecho, no se puede decir que no sale algo hasta que lo dejes de intentar.
 
hola muchachos soy nuevo en este tema y he leido varios documentos y he visitado muchas paginas en internet. hasta el momento de encontrarme con este foro.
tengo unas dudas que no me han dejado avanzar en mi proyecto por manejar el puerto usb.Teoricamente me considero bien y entiendo el protocolo. pero mi problema es la hora de programar el pic. he mirado los post y he entendido mucho pero la cuestion que mi problema es conocer como hace el pic o el pc a nivel de lenguaje el proceso de enumeracion y como el pic deja leer los buffer descriptores. se que anivel de protocolo lo que pasa, pero cuando llego al hardware no se como entenderlo estoy trabajando sobre el pic 18f2550

Gracias por la atensión prestada, y disculpen las molestias de mi situacion
 
mmm pues ay esta el codigo de firmware del pic todavia me falta hacer el software pero queria que vieran este primero, ay me dicen como me quedo acepto criticas, por cierto sigue sin querer correr el ejemplo 1 y creo que es el cristal, y solo venden de 4 Mhz aca en mi tierra asi que me tendre que adaptar supongo, saben si funciona igual con esa condiccion?, bueno aun asi lo programe con 20Mhz, gracias por todo, se los dejo.


Código:
// programa de control de motor a pasos e interfas de datos analogos y digitales ambos de 8 canales, via USB.
// Programador: Abdul Saucedo.
// Basado en programa de Moyano Jonathan.
// Fecha: 10/05/09
//************************************************************************
#include <18F2550.h> // Definición de registros internos.
#DEVICE ADC=10 // CAD con 10 bits de resolución , justificación a la derecha.
#fuses HSPLL,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN

// Fuses utilizados:
/*
HSPLL: utilizamos un cristal HS de alta velocidad, en conjunto con el PLL para generar los 48Mhz.
NOMCLR: Utilizamos reset por software, y dejamos el pin 1 del micro como entrada/salida digital.
NOWDT: No utilizamos el perro guardían.
NOPROTECT: Desactivamos la protección de código.
NOLVP: Desactivamos la programación a bajo voltaje.
NODEBUG: No entramos al modo debug.
USBDIV: signfica que el clock del usb se tomará del PLL/2 = 96Mhz/2 = 48Mhz.
PLL5: significa que el PLL prescaler dividirá en 5 la frecuencia del cristal. para HS = 20Mhz/5 = 4Mhz.
CPUDIV1: El PLL postscaler decide la división en 2 de la frecuencia de salida del PLL de 96MHZ, si queremos 48MHZ, lo dejamos como está.
VREGEN: habilita el regulador de 3.3 volts que usa el módulo USB
NOPBADEN: Deshabilitamos el módulo de conversión ADC del puerto B.
*/

#use delay(clock=48000000) // Frecuencia máxima de trabajo 48 Mhz.
short estado_usb;   // boolean global, se debe declarar antes de llamar a usb_cdc.h
#define USB_CON_SENSE_PIN PIN_E3 // Definiendo este pin , detectamos si el host está conectado o no por hardware.
#include "usb_cdc.h" // Descripción de funciones del USB.
#include "usb_desc_cdc.h" // Descriptores del dispositivo USB.

// Declaramos las funciones utilizadas.
void config_adcon2(int num); // Función que utilizamos para configurar el registro ADCON2.
void estado_conexion_usb(short bandera); // Muestra el estado de la conexión USB.

void main() { // Comienza el programa principal.
// Variables utilizadas en el programa.
int i;//variable de incremento
long valorA,valorB,valorC,valorD,valorE,valorF,valorG,valorH;//variables de valor analogico
// Configuramos los puertos del PIC.
    set_tris_a(63); // RA0 a RA5, como entrada
    set_tris_b(152); // RB1,RB2,RB3,RB4,RB7 como entrada
    set_tris_c(199);// RC0,RC1,RC2,RC6,RC7 como entrada
// Otras configuraciones.
   disable_interrupts(global);
   disable_interrupts(int_timer1);
   disable_interrupts(int_rda);
   disable_interrupts(int_ext);
   disable_interrupts(int_ext1);
   disable_interrupts(int_ext2);
   setup_spi(FALSE);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   port_b_pullups(FALSE);    
   setup_adc_ports(AN0 || VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_64);
/*************************************************************************************/
   estado_usb=false; // No se ha conectado al HOST.
   usb_cdc_init(); // llamadas necesarias para iniciar el módulo USB.
   usb_init_cs();    // inicia el USB y sale. Va de la mano con usb_task().
/******************************Empieza bucle infinito*********************************/   
   while(true){
    usb_task(); // configura el USB.
     estado_conexion_usb(estado_usb); // Se fija en el estado de la conexión usb.
     for(i=0;i<=7;i++){//  ciclo de adquicicion de datos analogicos
     config_adcon2(i); // Configuramos el conversor analógico digital.
     delay_ms(10); // Espera 10 mseg a que la convercion acabe.
     switch (i)//guarda cada convercion en una variable diferente.
       {
       case 1:
       valorA = read_adc(); // El resultado de la conversión lo guarda en la variable valorA.
       break;
       case 2:
     valorB = read_adc(); // El resultado de la conversión lo guarda en la variable valorB.
       break;
       case 3:
        valorC = read_adc(); // El resultado de la conversión lo guarda en la variable valorC.
       break;
       case 4:
        valorD = read_adc(); // El resultado de la conversión lo guarda en la variable valorD.
       break;
       case 5:
        valorE = read_adc(); // El resultado de la conversión lo guarda en la variable valorE.
       break;
       case 6:
        valorF = read_adc(); // El resultado de la conversión lo guarda en la variable valorF.
       break;
       case 7:
        valorG = read_adc(); // El resultado de la conversión lo guarda en la variable valorG.
       break;
       case 8:
        valorH = read_adc(); // El resultado de la conversión lo guarda en la variable valorH.
       break;
       default:
       break;
       }
     }
     
     if(usb_cdc_connected()){ // Si está conectado entonces....
   // Espera a detectar una transmisión de la PC (Set_Line_Coding).
       if (usb_enumerated()){ // aquí se enumera el dispositivo por el host y despúes sale.
        // En espera de nuevos caracteres en el buffer de recepción.
          switch (usb_cdc_kbhit())//dependiendo de la peticion del host es la accion que realizara.
       {
       case 'a'://¿lo que llegó fué el caracter a?
            printf(usb_cdc_putc,"%Lx", valorA); // envia el ADRESH:ADRESL al HOST
       break;
       case 'b'://¿lo que llegó fué el caracter b?
            printf(usb_cdc_putc,"%Lx", valorB); // envia el ADRESH:ADRESL al HOST
       break;
       case 'c'://¿lo que llegó fué el caracter c?
            printf(usb_cdc_putc,"%Lx", valorC); // envia el ADRESH:ADRESL al HOST
       break;
       case 'd'://¿lo que llegó fué el caracter d?
            printf(usb_cdc_putc,"%Lx", valorD); // envia el ADRESH:ADRESL al HOST
       break;
       case 'e': //¿lo que llegó fué el caracter e?
            printf(usb_cdc_putc,"%Lx", valorE); // envia el ADRESH:ADRESL al HOST
       break;
       case 'f': //¿lo que llegó fué el caracter f?
            printf(usb_cdc_putc,"%Lx", valorF); // envia el ADRESH:ADRESL al HOST
       break;
       case 'g': //¿lo que llegó fué el caracter g?
            printf(usb_cdc_putc,"%Lx", valorG); // envia el ADRESH:ADRESL al HOST
       break;
       case 'h'://¿lo que llegó fué el caracter h?
       printf(usb_cdc_putc,"%Lx", valorH); // envia el ADRESH:ADRESL al HOST
       break;
       case 'A'://¿lo que llegó fué el caracter A?
       printf(usb_cdc_putc,"%d",PIN_A4);// envia el VALOR DEL PIN_A4 al HOST
       break;
       case 'B'://¿lo que llegó fué el caracter B?
       printf(usb_cdc_putc,"%d",PIN_C0);// envia el VALOR DEL PIN_C0 al HOST
       break;
       case 'C'://¿lo que llegó fué el caracter C?
       printf(usb_cdc_putc,"%d",PIN_C0);// envia el VALOR DEL PIN_C0 al HOST
       break;
       case 'D'://¿lo que llegó fué el caracter D?
       printf(usb_cdc_putc,"%d",PIN_C1);// envia el VALOR DEL PIN_C1 al HOST
       break;
        case 'E'://¿lo que llegó fué el caracter E?
       printf(usb_cdc_putc,"%d",PIN_C2);// envia el VALOR DEL PIN_C2 al HOST
       break;  
              case 'F'://¿lo que llegó fué el caracter F?
       printf(usb_cdc_putc,"%d",PIN_B4);// envia el VALOR DEL PIN_B4 al HOST
       break;
              case 'G'://¿lo que llegó fué el caracter G?
       printf(usb_cdc_putc,"%d",PIN_B7);// envia el VALOR DEL PIN_B7 al HOST
       break;
              case 'H'://¿lo que llegó fué el caracter H?
       printf(usb_cdc_putc,"%d",PIN_C0);// envia el VALOR DEL PIN_C0 al HOST
       break;
       case 'L'://¿lo que llegó fué el caracter L?paso a la izquierda
       output_low(PIN_B5); // bit de sentido de giro, conectado al pin RB6.
       delay_ms(100); // Espera 100 mseg.
       output_low(PIN_B6); // desenergiza bobina, conectado al pin RB6.
       delay_ms(100); // Espera 100 mseg.
       output_high(PIN_B6); // energiza bobina , conectado al pin RB6.
       delay_ms(100); // Espera 100 mseg.
       output_low(PIN_B6); // completa el paso, conectado al pin RB6.
       delay_ms(100); // Espera 100 mseg.
       break;
       case 'R'://¿lo que llegó fué el caracter R?paso a la derecha
       output_high(PIN_B5); // bit de sentido de giro, conectado al pin RB6.
       delay_ms(100); // Espera 100 mseg.
       output_low(PIN_B6); //desenergiza bobina, conectada al pin RB6.
       delay_ms(100); // Espera 100 mseg.
       output_high(PIN_B6); // energiza bobina , conectada al pin RB6.
       delay_ms(100); // Espera 100 mseg.
       output_low(PIN_B6); // completa el paso, conectado al pin RB6.
       delay_ms(100); // Espera 100 mseg.
       break;
   default:
       break;
         }
      }         
   }
}
}

//***********************************************
// Esta función, nos indica mediante 1 diodo LED conectados al 
// puerto RB0. El estado de conexión del puerto usb.
// Conectado: Enciende el LED VERDE.
//Desconectado: de apaga el LED VERDE.
//***********************************************
void estado_conexion_usb(short bandera){
 if(bandera){
 output_high(PIN_B0); // Enciende LED VERDE.
 }else{
 output_low(PIN_B0);  // Apaga LED VERDE.
 }
}
// Esta función configura el registro ADCON2.
void config_adcon2(int num) {
if(num>=5){//necesidad de implementacion por vercion del pic ya que se salta algunos puetos analogos
num=num+3;
}
   #asm
   movlw 0b10111110 ;justificacion_derecha,20Tad,Fosc/64
   iorwf 0xFC0,1    ; direccion de ADCON2
   #endasm
   set_adc_channel(num); // Selecciono el canal de conversión.
}
 
hola alfangel:

1.- Si defines HSPLL entoces deberas usar osciladores mayores de 4MHZ , pero si usas el de 4MHz define XTPLL
2.-Si usas un oscilador de 4Mhz el PLL que defines debe ser PLL1 , y no PLL5 .
3.- Supongo que conectas dos resistencias de 100k para detectar por harware al declara el con_sense_pin
4.-¿usas solo un canal o multiplexas otros canales ? esto por q veo : setup_adc_ports(AN0 || VSS_VDD) con esta directiva solo estas configurando elcanal "RA0" como entrada analogica pero lineas abajo veo:
config_adcon2(i); // Configuramos el conversor analógico digital.
// Esta función configura el registro ADCON2.
void config_adcon2(int num) {
if(num>=5){//necesidad de implementacion por vercion del pic ya que se salta algunos puetos analogos
num=num+3;


? :rolleyes: :rolleyes: no tiene mucho sentido tus declaraciones

5.- lo anterior te pregunto debido a que haces on bucle for que realizara siete veces configurando siete canales y enviando orden al void config_adcon2 ...
6.- una recomendacion : PRUEBA POR SEPARADO CADA MODULO, primero el modulo ADC si usas un solo canal o multiplexas, luego prueba el modulo USB y finalmente el envio-recpcion de datos del USB
saludos ...
 
Este foro está muy bueno pero yo no necesito emular el puerto, yo lo que necesito es usar la comunicación USB tipo Isochronous puesto que tengo que tomar datos en tiempo real de un proceso, me ayudarían mucho si me dijeran donde hay información de este tipo de comunicación; o ustedes creen que sería igual de bueno emular el puerto serial?
De antemano muchas gracias, y estoy a su disposición para lo que necesiten y yo pueda ayudar.
 
hola. para los que hayan trabajado con el pic18f4550, como se configura el ADC y que quieren decir estos bits:
#define ADC_ADFM_RIGHT 0x80
#define ADC_ACQT_2TAD 0x38
Me refiero a porque le ponen 0x80 y 0x38, que sentido tiene esto, la verdad no le veo ninguna utilidad,
y otra cosa, si le ponemos 20TAD en lugar de 2TAD en que afecta? si algo aqui esta el codigo completo:
#include <18F4550.h>

#device adc=10
#define ADC_ADFM_RIGHT 0x80
#define ADC_ACQT_20TAD 0x38
#define AN0

#include <string.h>
#include <stdlib.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL3,CPUDIV1,VREGEN
#use delay(clock=48000000)
#USE RS232(BAUD=19200, XMIT=PIN_A4, RCV=PIN_A5, stream=RF)


#include <usb_cdc.h> //Siempre va antes del include usb_desc_cdc.h
#include <usb_desc_cdc.h>
#define emergencia PIN_B0
#define bombillo PIN_B1
#define on output_high
#define off output_low



char c,d;


char cad[5];
int l=0,i;
void main(){
long dato;

//off(emergencia);
//off(bombillo);

usb_cdc_init();
usb_init(); //inicializamos el USB

while (!usb_cdc_connected()) {}
while (true)
{
usb_task();
if(usb_enumerated()){
if(usb_cdc_kbhit())
{c=usb_cdc_getc();
putc(c,RF);}
}



if(c=='n'){
setup_adc_ports( AN0_ANALOG||VSS_VDD);
setup_adc(ADC_CLOCK_DIV_64 || ADC_ACQT_20TAD || ADC_ADFM_RIGHT );
set_adc_channel(0);
delay_ms(1000);
dato= read_adc();

itoa(dato,10,cad);// dato pasa a ser una cadena
l=strlen(cad);// longitud de la cadena
i=0;
for(i;i<l;i++){
usb_task();//Establecer comunicacion
if(usb_enumerated()) // Estamos correctamente conectados
{

d=cad;
usb_cdc_putc(d);// enviar caracter d
}
}
}

usb_task();
if(usb_enumerated()){
if(usb_cdc_kbhit())
{c=usb_cdc_getc();
putc(c,RF);}
}


setup_ccp2(CCP_PWM); // Configure CCP1 as a PWM






switch(c){
case 'b':
off(emergencia);
on(bombillo);
setup_timer_2(T2_DIV_BY_4||0x01, 200,1);
set_pwm2_duty(25);
break;

case 'm':
off(emergencia);
on(bombillo);
setup_timer_2(T2_DIV_BY_1||0x01, 200,1);
set_pwm2_duty(75);
break;

case 'k':
on(emergencia);
off(bombillo);
setup_timer_2(T2_DIV_BY_1||0x01, 255,1);
set_pwm2_duty(210);
break;

case 'f':
off(emergencia);
off(bombillo);
setup_timer_2(T2_DIV_BY_1||0x01, 255,1);
set_pwm2_duty(10);
break;

}

if(c=='b'||c=='m'||c=='k'){
setup_adc_ports( AN0_ANALOG||VSS_VDD);
setup_adc(ADC_CLOCK_DIV_64 || ADC_ACQT_20TAD || ADC_ADFM_RIGHT );
set_adc_channel(0);
delay_ms(1000);
dato= read_adc();
itoa(dato,10,cad);// dato pasa a ser una cadena
l=strlen(cad);// longitud de la cadena
i=0;
for(i;i<l;i++){
usb_task();//Establecer comunicacion
if(usb_enumerated()) // Estamso correctamente conectados
{

d=cad;
usb_cdc_putc(d);// enviar caracter d
}
}
} } }
 
Hola: Disculpad que me una al hilo estando tan avanzado y con tanto nivel.
He estrenado hoy un portátil y al empezar a leer este tema e intentar probar el primer ejemplo
me asalta la primera duda, porque no me abre el ejecutable en Vista.
¿Tengo que tener VB instalado ?
La dll de Microchip sirve para Vista Home Basic?

Llevo un día con Vista y ya echo de menos el XP

Saludos[/quote]
 
chipichape dijo:
hola. para los que hayan trabajado con el pic18f4550, como se configura el ADC y que quieren decir estos bits:
#define ADC_ADFM_RIGHT 0x80
#define ADC_ACQT_2TAD 0x38
Me refiero a porque le ponen 0x80 y 0x38, que sentido tiene esto, la verdad no le veo ninguna utilidad,
y otra cosa, si le ponemos 20TAD en lugar de 2TAD en que afecta?

Hola chipichape.
No programo en ese compilador de C, pero si te puedo orientar con que es lo que definen esos parámetros.

#define ADC_ADFM_RIGHT 0x80 : esto define como se va a alinear el resultado que arroja el conversor AD en ADRES. Este registro tiene 16 bits, y el resultado del conversor es de 10 bits. Entonces hay dos posibilidades, que el conversor AD escriba los 10 bits más significativos de ADRES (alineación a la izquierda) o que escriba los 10 menos significativos (alineación a la derecha).
La sentencia #define define una constante, es decir, cada vez que en el código aparezca ADC_ADFM_RIGHT el compilador (mejor dicho, el pre-procesador del compilador) lo va a reemplazar por 0x80.
Debe tener ese valor para que la rutina
setup_adc(ADC_CLOCK_DIV_64 || ADC_ACQT_20TAD || ADC_ADFM_RIGHT );
configure al conversor AD para que el resultado se alinee a la derecha.

#define ADC_ACQT_2TAD 0x38 : el tiempo de adquisición ACQT es un tiempo que espera el conversor AD antes de iniciar la conversión. Es decir, si yo hago que comience la conversión ahora mismo, no se va a iniciar ahora mismo sino dentro de un tiempo ACQT.
¿Para que está ésta funcionalidad?: bueno, hay que hablar de como funciona el conversor. Uno primero tiene conectada la entrada analógica a un capacitor interno, el capacitor de muestreo. Cuando ordeno que comience la conversión del AD el PIC abre la conexión del capacitor de muestreo con el circuito externo, y el capacitor de muestreo que antes estaba conectado al circuito externo ahora ya no lo está, solo queda conectado al conversor AD del PIC.
Entonces el capacitor mantiene ese valor de tensión (se descarga pero muy lentamente) mientras el modulo AD realiza la conversión.
Finalizada la conversión el módulo AD se encarga de volver a conectar el capacitor de muestreo al circuito externo.
Ahora, que pasa si yo inicio otra conversión ahí mismo? (es decir, si hubiera fijado ACQT el tiempo de adquisición como 0). Pasa que no le dí tiempo al capacitor de muestreo de cargarse al valor de tensión que quiero medir (del circuito externo). Entonces estaría obteniendo una medición que no es el valor real que está en el circuito externo, sino uno muy cercano al que medí anteriormente.
Por eso ACQT se suele fijar con un valor que de tiempo suficiente al capacitor de volver a cargarse al nivel de tensión presente en el circuito externo.
Los detalles para calcular el valor de ACQT están en la hoja de datos, su valor depende del valor de tensión a medir, de la resistencia de la fuente de señal, y de parámetros internos del PIC.
¿Cuando puedo poner ACQT=0?, cuando estoy seguro que mi programa nunca va a iniciar una conversión sin que le de tiempo a que el capacitor se cargue luego de la anterior conversión (o luego de cambiar de canal analógico, de AN0 a AN3 por ejemplo).

Bueno, ojalá te sea de utilidad, saludos.
 
cordial saludo señores: moyano y Meta

he leido detenidamente el foro y de como puedo conectar el microcontrolador 18f2550 al puerto usb y mediante una interfaz grafica puedo yo controlar 8 reles por el puerto B del micro. hasta ahi todo esta bien, yo personalmente no se mucho sobre el tema de comunicacion usb ni el protocolo que se utiliza , hago una pequeña reseña . tengo mi programador de micros e programado el 16f84 el 16f877 es mas por medio del puerto paralelo y v. b. e controlado 8 reles para controlar unos dispositivos a 115v ac. pero a raiz que mi nueva computadora no tiene el puerto paralelo sino puros usb e desidido comprar el 18f2550 y ya tengo el circuito montado en baquelita o fibra de vidio , yo lo conecto al pc pr el puerto usb y me reconoce el micro. pero ahora quisiera saber si ustedes me pueden ayudar con el programa ya compiladoosea el .hex o si lo tienben en asembler muchisimo mejor
y un ejecutable que este funcionando , la verdad no se mucho de programacion en visual. asi me si me pueden ayudar con el ejecutable seria muchisimo mejor
gracias se despide de ustedes su nuevo amigo del foro
 
Estoy esperando que saque algo de la Interfaz de USB sea en el lenguaje que sea para poder hacerlo yo lo mismo con Visual C#, y más adelante con VC++ y VB .net
 
Atrás
Arriba