Ich arbeite an der UART-Datenübertragung von einem ATmega8 zum anderen, während der Empfänger VUSB ausführt, das als HID-Maus zum PC fungiert.
UART obwohl init mit 9600 , wird später auf maximale Geschwindigkeit gesetzt -> UBRR = 0;
Probleme :
Wie überwinde ich diese Probleme ..
machte ein kleines Protokoll für Daten ..
SYNC_START XY END_SYNC
der Sendercode:
//////////////////////////////////////////////////////////////////////////
//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);
}
}
Der Empfängercode:
//////////////////////////////////////////////////////////////////////////
//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;
}
}
}
Es gibt ein Hauptproblem, auf das in den Kommentaren hingewiesen wurde:
if ( UCSRA & (1<<RXC) )
{
uint data = UDR;
...
else if(!WaitingForX && !WaitingForY && (UDR==END_SYNC_BYTE)){
...
}
}
In diesem Teil lesen Sie von einer leeren UDR, da die END_SYNC_BYTE
zuvor gespeichert wurde, sodass diese Aussage immer falsch sein wird.
Der weniger komplizierte Weg besteht darin, jedes eingehende Byte im FIFO-Puffer zu speichern (oder sogar eine Interrupt-basierte Bibliothek zu verwenden , die mit v-usb umgehen kann) und die gesamte Nachricht in einem Durchgang zu verarbeiten.
brhans
Tom Tischler
Tom Tischler
UBR
Register nur einmal lesen, nicht mehrmals. Es gibt einen FIFO auf dem UART-Block und wenn Sie das Register lesen, geht es weiter zum nächsten Wert im FIFO.Tom Tischler
if(UDR==START_SYNC_BYTE){
liest den Wert und vergisst ihn....X=UDR;
liest es ein zweites Mal, was den Wert verfälschen kann. Sie sollten tunuint8_t in = UDR;
und dannif(in==START_SYNC_BYTE){...X=in;
Tom Tischler
Akash Gutha
Akash Gutha
Tom Tischler
Akash Gutha
JimmyB
sei()
kommen ?usbPoll()
Akash Gutha
Bruce Abbott
UART_Init(9600 , false , true , false)
?Akash Gutha