UART en modo NON INTERRUPT o INTERRUPT mientras usa VUSB

1

Estoy trabajando con la transferencia de datos UART de un ATmega8 a otro mientras el receptor ejecuta VUSB actuando como un Ratón HID a la PC.

UART aunque init con 9600, más tarde se establece en velocidad máxima - > UBRR = 0;

Problemas:

  1. VUSB no es estable en ambas comunicaciones basadas en interrupciones. o comunicación no basada en interrupciones.
  2. Tuve éxito en tenerlo estable solo una vez ... pero los datos recibidos fueron basura.

¿Cómo puedo superar estos problemas?

hizo un pequeño protocolo para datos ..

SYNC_START X Y END_SYNC

el código del transmisor:

//////////////////////////////////////////////////////////////////////////
//Defines
//////////////////////////////////////////////////////////////////////////
#define F_CPU       16000000UL
#define true        0x01
#define false       0x00
#define uchar       unsigned char
#define uint        unsigned int

#define START_SYNC_BYTE 0b10101010
#define END_SYNC_BYTE   0b01010101
//////////////////////////////////////////////////////////////////////////

#include <avr/io.h>
#include <util/delay.h>

#include "uart/UART.h"
#include "IMU.h"

//////////////////////////////////////////////////////////////////////////
//GLOBAL VARIABLES
//////////////////////////////////////////////////////////////////////////
uint X=0,Y=0;
//////////////////////////////////////////////////////////////////////////


int main(void)
{
    i2c_init();
    WakeUpIMU();

    UART_Init(9600,true,false,false);

    UBRRH = 0;
    UBRRL = 0;


    while(1)
    {
        X = Get16Bits(MPU6050_RA_ACCEL_XOUT_H);
        Y = Get16Bits(MPU6050_RA_ACCEL_YOUT_H);

        BlockingTransmitt(START_SYNC_BYTE);
        BlockingTransmitt(START_SYNC_BYTE);
        BlockingTransmitt(X);
        BlockingTransmitt(Y);
        BlockingTransmitt(END_SYNC_BYTE);

        _delay_ms(5);
    }
}

El código del receptor:

//////////////////////////////////////////////////////////////////////////
//Defines
//////////////////////////////////////////////////////////////////////////
#define F_CPU       16000000UL
#define true        0x01
#define false       0x00
#define uchar       unsigned char
#define uint        unsigned int

#define START_SYNC_BYTE 0b10101010
#define END_SYNC_BYTE   0b01010101
//////////////////////////////////////////////////////////////////////////

#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include <util/delay.h>

#include "uart/UART.h"
#include "usbdrv/usbdrv.h"

//////////////////////////////////////////////////////////////////////////
//GLOBAL VARIABLES
//////////////////////////////////////////////////////////////////////////
uint X,Y;
bool WaitingForX=false,WaitingForY=false;
bool TransmissionComplete = false;
//////////////////////////////////////////////////////////////////////////



PROGMEM const char usbHidReportDescriptor[52] =
{ /* USB report descriptor, size must match usbconfig.h */
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,                    // USAGE (Mouse)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Pointer)
    0xA1, 0x00,                    //   COLLECTION (Physical)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x01,                    //     USAGE_MINIMUM
    0x29, 0x03,                    //     USAGE_MAXIMUM
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x75, 0x05,                    //     REPORT_SIZE (5)
    0x81, 0x03,                    //     INPUT (Const,Var,Abs)
    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
    0x09, 0x30,                    //     USAGE (X)
    0x09, 0x31,                    //     USAGE (Y)
    0x09, 0x38,                    //     USAGE (Wheel)
    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
    0x25, 0x7F,                    //     LOGICAL_MAXIMUM (127)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
    0xC0,                          //   END_COLLECTION
    0xC0,                          // END COLLECTION
};

typedef struct{
    uchar   buttonMask;
    char    dx;
    char    dy;
    char    dWheel;
}report_t;


static report_t reportBuffer;
static uchar    idleRate;

usbMsgLen_t usbFunctionSetup(uchar data[8])
{
    usbRequest_t    *rq = (void *)data;

    /* The following requests are never used. But since they are required by
    * the specification, we implement them in this example.
    */
    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){    /* class request type */
        if(rq->bRequest == USBRQ_HID_GET_REPORT){  /* wValue: ReportType (highbyte), ReportID (lowbyte) */
            /* we only have one report type, so don't look at wValue */
            usbMsgPtr = (void *)&reportBuffer;
            return sizeof(reportBuffer);
            }else if(rq->bRequest == USBRQ_HID_GET_IDLE){
            usbMsgPtr = &idleRate;
            return 1;
            }else if(rq->bRequest == USBRQ_HID_SET_IDLE){
            idleRate = rq->wValue.bytes[1];
        }
    }
    else{
        /* no vendor specific requests implemented */
    }
    return 0;   /* default for not implemented requests: return no data back to host */
}



int main(void)
{
    uchar i;

    wdt_enable(WDTO_1S);

    usbInit();
    usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
    i = 0;
    while(--i){             /* fake USB disconnect for > 250 ms */
        wdt_reset();
        _delay_ms(1);
    }
    usbDeviceConnect();

    UART_Init(9600 , false , true , false);
    UBRRH = 0;
    UBRRL = 0;

    sei();

    while(1)
    {
        wdt_reset();

        usbPoll();

        RecieveUARTdata();


        if(TransmissionComplete && usbInterruptIsReady()){
            /* called after every poll of the interrupt endpoint */
            usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer));
        }

    }
    return 0;
}

void ResetValues(){
    X=0;Y=0;
    WaitingForX=false;
    WaitingForY=false;
}



void RecieveUARTdata(){
    //Get the data is available by checking the RXC in UCSRA
    if ( UCSRA & (1<<RXC) )
    {
        uint data = UDR;
        //if the data received is START SYNC DATA
        if(data==START_SYNC_BYTE){
            WaitingForX = true;return;
        }

        else {
            if(WaitingForX){
                X=data; WaitingForX=false;
                WaitingForY=true;return;
            }
            else if(WaitingForY && !WaitingForX){
                Y=data; WaitingForY=false;return;
            }
            else if(!WaitingForX && !WaitingForY && (UDR==END_SYNC_BYTE)){
                reportBuffer.dx = X;
                reportBuffer.dy = Y;
                TransmissionComplete = true;return;
            }else ResetValues();
            return;
        }
    }
}
    
pregunta Akash Gutha

1 respuesta

1

Hay un problema principal que se ha señalado en los comentarios:

if ( UCSRA & (1<<RXC) )
{
    uint data = UDR;
    ...
        else if(!WaitingForX && !WaitingForY && (UDR==END_SYNC_BYTE)){
            ...
    }
}

En esta parte, está leyendo de la UDR vacía, ya que END_SYNC_BYTE se almacenó anteriormente, por lo que esta declaración siempre será falsa.

La forma menos complicada es almacenar cada byte entrante en el búfer FIFO (o incluso usar lib que puede lidiar con v-usb) y procesar el mensaje completo en una sola ejecución.

    
respondido por el jnk0le

Lea otras preguntas en las etiquetas