Estoy trabajando en la transferencia de datos UART de un ATmega8 a otro mientras el receptor ejecuta VUSB actuando como HID Mouse para la PC.
Aunque UART se inicia con 9600, luego se establece en velocidad máxima -> UBRR = 0;
Problemas :
Como supero estos problemas..
hizo un pequeño protocolo para datos ..
SYNC_START XY 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;
}
}
}
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 desde UDR vacío como se END_SYNC_BYTE
almacenó anteriormente, por lo que esta declaración está a punto de ser siempre falsa.
La forma menos complicada es almacenar cada byte entrante en el búfer FIFO (o incluso usar una biblioteca basada en interrupciones que pueda manejar v-usb) y procesar el mensaje completo en una sola ejecución.
brahans
tom carpintero
tom carpintero
UBR
registro una vez, no varias veces. Hay un FIFO en el bloque UART y cuando lee el registro, pasa al siguiente valor en el FIFO.tom carpintero
if(UDR==START_SYNC_BYTE){
lee el valor y luego lo olvida....X=UDR;
lo lee por segunda vez, lo que puede corromper el valor. Deberías haceruint8_t in = UDR;
y luegoif(in==START_SYNC_BYTE){...X=in;
tom carpintero
Akash Gutha
Akash Gutha
tom carpintero
Akash Gutha
jimmyb
sei()
venir antesusbPoll()
?Akash Gutha
bruce abbott
UART_Init(9600 , false , true , false)
?Akash Gutha