Comunicación USB CDC PIC18F4550 se detiene al enviar una cadena de caracteres

#1
Buenas tardes.

Mi duda es que conecto mi microcontrolador a la PC y se conecta como puerto COM, hasta ahí ningún problema, pero al enviar una cadena de caracteres de la PC al micro, se detiene la transmisión de datos y ya no me permite hacer nada.

A continuación pongo el código y espero su respuesta.
PHP:
#include <18f4550.h> //microcontrolador utilizado
#device adc=10 //convertidor
#fuses HSPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN //configuración para el uso de microcontrolador
#USE delay(clock=48000000) //configuracion de la frecuencia del reloj 
#define USB_CON_SENSE_PIN PIN_B2
#include <usb_cdc.h>//libreria para controlar el puerto usb cdc
#include <usb_desc_cdc.h>//configuracion de la direccion de microchip
#include <math.h> // libreria matematica
#include <stdlib.h>
#include <stdio.h>  
#include <usb.c>
char buffer[20];
float setpoint=0; 
double kp,kv,kpmax; 
float qtilde; 
float qpunto; 
float tau,tau0; 
int8 lectura,lanterior; 
signed int16 posicion; 
float pos,posi,grados; 
float vel; 
int16 t; 
// variables que se utilizan en el cuerpo del programa
int8 contador=0,numero=0;
//int c;
int8 recibe1[3];
int16 conversion=0;

#INT_TIMER1
void TIMER1_isr (void) 
{ 
    lectura = input_b()<<6; 
    lectura = lectura>>6; 
    if(lectura==0&&lanterior==1) 
    { 
        posicion++; 
    }
    if(lectura==0&&lanterior==2) 
    { 
        posicion--; 
    } 
    if(lectura==1&&lanterior==3) 
    { 
        posicion++; 
    } 
    if(lectura==1&&lanterior==0)
    { 
        posicion--; 
    } 
    if(lectura==3&&lanterior==2)
    { 
        posicion++; 
    }
    if(lectura==3&&lanterior==1) 
    {
        posicion--; 
    } 
    if(lectura==2&&lanterior==0) 
    {
        posicion++; 
    } 
    if(lectura==2&&lanterior==3) 
    {
        posicion--; 
    } 
    lanterior = lectura;
    ////////****************Hasta aquí se obtiene la posicion****************//////// 
    t=t+1; 
    //Se incrementa el contador de temporizador interno 
    if(t==625) //Si el temporizador interno ha llegado a 625 o sea 0.025s 
    {
        vel=(posicion-posi)*2*pi/(0.025*8400.0); 
        // estima velocidad mediante formula de Euler
        // convirtiendo pulsos en grados y h=0.025 
        posi=posicion; 
        //Asigna qinicial a qactual 
        qtilde=setpoint-(posicion*2*pi)/(8400.0);
        qpunto=vel;
        if(tau>332.0)
        {
            tau=332.0;
        }

        if(tau<-332.0)
        {
            tau=-332.0;
        }
        if(tau<0.0)
        {
            set_pwm2_duty((int16)0);//3720hz
            set_pwm1_duty((int16)tau*(-1));//3720hz
        }
        if(tau>0.0)
        {
            set_pwm1_duty((int16)0);//166 50%//332-100%
            set_pwm2_duty((int16)tau);//166 50%//332-100%
        }
        t=0; // Inicializa la variable del contador interno
    }
    set_timer1(65489); //Recarga el timer en 0.00004 s
}

//programa principal
void main()
{
    set_tris_d(0x00);
    output_d(0x00);
    //set_tris_d(0x00);//configuracion del puerto de salida
    //output_d(0x00);
    usb_cdc_init();//inicializacion del comunicacion cdc
    usb_init();//inicializacion usb
    while(!usb_cdc_connected()){}//mientras la conexion usb no este conectado
    
    do {//ciclo do while
        grados=posicion*360/8400;
        sprintf(buffer,"%03f",grados);
        printf(usb_cdc_putc,"grados:%s\n",buffer);//envia datos al puerto serial
        delay_ms(100);//da un espacio entre dato y dato
        usb_task();//prepara o resetea el periferico usb
        if(usb_enumerated()){//condicion para enumerar el hardware
            output_high(pin_d3);//muestra el encendido de un led para saber que ya esta conectado a la pc
            conversion=read_adc();//lee el adc del pic
            if (usb_cdc_kbhit())//condicion para demostrar si se estan recibiendo datos en buffer
            {
                for (char contador=0;contador<4;contador++){//ciclo para obtener datos del puerto serial
                recibe1[contador]=usb_cdc_getc();//obtencion de los caracteres
                //conversion de caracter a decimal
                }
                numero=atoi(recibe1);
            if (numero==90)//condicion de que dato se recibe
            {
                output_high(pin_d4);
                int16 kg;
                posi=0; 
                posicion=0; 
                pos=0; 
                vel=0; 
                t=0; 
                //setpoint=pi/2; 
                kpmax=53.06;
                kp=kpmax; 
                set_tris_a(0b00000011); 
                set_tris_b(0xff); 
                kv=0.0009*kp;
                kg=400;
                setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);  
                //setup_timer_2(T2_DIV_BY_1,249,1);
                setup_timer_2(T2_DIV_BY_1,0,1);      //819 us overflow, 819 us interrupt83
                setup_ccp1(CCP_PWM|CCP_SHUTDOWN_AC_L|CCP_SHUTDOWN_BD_L);
                setup_ccp2(CCP_PWM);
                set_pwm1_duty((int16)0);//3720hz
                set_pwm2_duty((int16)0);//166 50%//332-100%
                enable_interrupts(INT_TIMER1);
                enable_interrupts(GLOBAL); 
                set_timer1(65489);
                lanterior = input_b()<<6;
                lanterior = lanterior>>6; 
                while(TRUE)
                {
                    tau0=kp*(1/(sinh(qtilde)))-kv*(1/(sinh(qpunto)))+kg*sin(2*pi*posicion/8400.0);
                    //tau0=kp*cosh(qtilde)*sinh(qtilde)/(1+cosh(qtilde)*cosh(qtilde))-kv*cosh(qpunto)*sinh(qpunto)/(1+cosh(qpunto)*cosh(qpunto))+kg*sin(2*pi*posicion/8400.0);
                    if(tau0>0.0) 
                    { 
                        tau=tau0+5.0;
                    } 
                    if(tau0<0.0)
                    { 
                        tau=tau0-5.0;
                    }
                }
            }
            if (numero==10)
            {
                output_low(pin_d4);
            }
        }
    }
    } while(true);
}
 
Última edición por un moderador:
#2
Si vas a recibir una cadena, es mejor que uses usb_gets (endpoint, ptr, max, timeout);
Es igual a gets (string); del RS-232, pero para protocolos USB. (Incluyendo el CDC)

Con esa instrucción recibes la cadena completa de una sola vez y evitas los problemas de hacerlo con un bucle for.

Ejemplo de uso:
usb_gets (2, datos_usb, sizeof (datos_usb), 100); // Recibir la cadena de datos.

Donde, el 2 será el endpoint, datos_usb es el arreglo de x tamaño, P.E: int8 datos_usb[30];
sizeof (datos_usb) determina el tamaño del arreglo y 100 será el tiempo máximo de espera en mS.

Si con ese cambio no resuelves el problema, prueba desactivando alguna o varias de las interrupciones que uses.
(P.E: La interrupción por desborde del Timer 1)
Esto lo debes hacer antes de recibir datos y posteriormente volverla/s a activar.
 
Arriba