Hallo

ich habe ein Problem beim Senden von Daten vom PC an einen Atmega168.
Ich verwende WinAVR 20081205.
Das board ist ein RN-Mini-Control von Robotikhardware.de (Fertig gekauft)
An dieses möchte ich vom PC den Wert einer "Trackbar" (0 bis 255) senden um die geschwindigkeit eines Motors zu einzustellen.
Dazu sollen zwei Byte übertragen werden: Als erstes eine Befehlsnummer, in diesem Fall eine 1 die dem Controller mitteilen soll das nun der Wert für die PWM des Motors kommt. Und als zweites Byte der Wert selbst.

Vom PC werden die zwei Bytes auch korrekt gesendet. Ich habe das mit hilfe eines Nullmodemkabels überprüft. Der PC kann von COM4 zu COM1 soviele Bytes senden wie er will es kommen immer alle korrekt an.
Bei der Kommunikation mit dem Controller kommt es allerdings sporadisch zu Fehlern! Zwischendurch springt der Motor einfach auf volle Geschwindigkeit und beim nächsten Wert ist wieder alles normal.

Hier ist der komplette Code:
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <util/delay.h>

#define BAUD 9600UL
#define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)

#define UART_SEND_READY 	(UCSR0A & (1<<UDRE0))  // UDRE in UCSRA gesetzt
#define UART_RECEIVED 		(UCSR0A & (1<<RXC0))
#define ADC_START_CONV		(ADCSRA |= (1<<ADSC)) 
#define DATAOVERRUN 		(UCSR0A & (1<<DOR0)) 
#define FRAMEERROR			(UCSR0A & (1<<FE0))


#define PWM_VALUE OCR2A

#define nop() asm volatile ("nop")


#define SENDENSIZE 		9
#define EMPFANGENSIZE 	2

#define DATENAUSLESEN 	1
#define RESET 			2
#define PWM_SETZEN		1
#define DATENSENDEN		1

volatile uint8_t senden[SENDENSIZE];					// volatile ist wichtig damit die 
volatile uint8_t empfangen[EMPFANGENSIZE];				// variable auch in der ISR verwendet werden kann
volatile uint8_t empfangbyte=0;
volatile uint8_t ADC_channel=0;
volatile uint8_t ADC_byte=1;
volatile uint8_t empfangsbefehl=0;

void Uart_Init(void)
{

	
	UBRR0 = UBRR_BAUD;
	
	//Enable receiver and transmitter
	UCSR0B = (1<<RXEN0)|(1<<TXEN0) | (1<<RXCIE0);
	
	// Set frame format: 8data, 1stop bit 
	UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);

}


void PWM_Init(void)
{
	TCCR2A = (1<<COM2A1) | (1<<WGM20);
	TCCR2B = (1<<CS22);
	DDRB |= (1<<3);
	PWM_VALUE=0;
	
}


void Input_Capture_Init(void)
{
	//ICNC1 = Noise Filter , CS10-12 Vorteiler auswählen
	TCCR1B = (1<<CS10) | (1<<CS12) | (1<<ICNC1);
	
	//ICIE1 = Interrupt enable , TOIE = Interrupt bei überlauf
	TIMSK1 = (1<<ICIE1) | (1<<TOIE1);
	
	DDRB &= ~(1<<0);		// Pin B0 als eingang
	PORTB |= (1<<0);		// Pullup an Pin B0 einschalten
}


void ADC_channel_select(uint8_t channel)
{
		
	ADMUX = channel;		//ADC port auswählen
	
	//Referenzspannung AVCC
	ADMUX |= (1<<REFS0); 

	// ADEN = ADC-Enable ; ADSP0-2 = Vorteiler auf 128 setzen
	ADCSRA = (1<<ADEN) | (1<<ADIE) | (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2);

}


void Senden(uint8_t anzahlbytes, volatile uint8_t data[])
{
	uint8_t byte;	

	for(byte=0 ; byte<anzahlbytes ; byte++)		//für alle bytes
	{
		while(!UART_SEND_READY) { nop(); }		//Solange noch gesendet wird warten
		UDR0 = data[byte];	//Byte aus dem Sendearray senden
	}
}

void pin_init(void)
{
	DDRD |=(1<<6);
	DDRD |=(1<<7);
	DDRB |=(1<<5);
	PORTB |=(1<<5);
	PORTD |=(1<<6);
	PORTD &=~(1<<7);

}


void anmelden(void)          // Sendet eine 63 bis diese vom PC entdeckt und mit einer 42 beantwortet wird
{								// der pc weiß dann an welchen COM-port der Controller angeschlossen ist
	while(UDR0!=42)
	{
		while(!UART_SEND_READY) { nop(); }		//Solange noch gesendet wird warten
		UDR0=63;
		_delay_ms(100);
	}
}

void empty_buffer(void)
{
	uint8_t buffer;
	// Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte) 
    do 
    { 
        buffer = UDR0; 
    } 
    while (UART_RECEIVED); 
}

int main(void)
{

	Uart_Init();
	ADC_channel_select(0);
	Input_Capture_Init();
	PWM_Init();
	pin_init();
	
	anmelden();			//am pc anmelden
	
	sei();
	
	while (1) {		
		_delay_ms(100);
		
		if (DATAOVERRUN | FRAMEERROR) empty_buffer();    
		
		if (empfangen[0]==PWM_SETZEN && !DATAOVERRUN && !FRAMEERROR) PWM_VALUE = empfangen[1]; 
		
		if (ADC_channel == 0) 
		{
			senden[0]=DATENSENDEN;			//erstes byte gibt an was der controller vom pc möchte
			Senden(SENDENSIZE, senden);		//alle daten senden
			ADC_START_CONV;					//adc's neu auslesen
		}
	}
}


ISR (TIMER1_CAPT_vect)
{
	TCNT1=0;							// Timer1 zurücksetzten
	senden[7]=ICR1L;					//icr low byte
	senden[8]=ICR1H;					//icr high byte
}

ISR (USART_RX_vect)
{
	empfangen[empfangbyte]=UDR0;		//empfangenes byte ins empfangsarray schreiben
	empfangbyte++;						// index raufzählen
	if (empfangbyte == EMPFANGENSIZE) 	// wenn alles empfangen wurde 
	{
		empfangbyte=0;					// index zurücksetzen
	}	
}


ISR (ADC_vect)
{
	senden[ADC_byte]=ADCL;			//Lowbyte des ADCs ins Sendearray schreiben
	senden[ADC_byte+1]=ADCH;		//Highbyte des ADCs ins Sendearray schreiben
	ADC_byte +=2;					//Bytenr für die nächste wandlung um 2 erhöhen
	ADC_channel++;					//channel nr erhöhen
	ADC_channel_select(ADC_channel);	//channel auswählen
	if (ADC_channel < 3) ADCSRA |= (1<<ADSC);	//ADSC = ADC Start Conversion 
	else	//wenn alle channel durch sind
	{
		ADC_channel=0;   //wieder bei 0 beginnen
		ADC_byte=1;
		ADC_channel_select(ADC_channel); //channel 0 auswählen
	}
}

ISR (TIMER1_OVF_vect)		//Wenn der Timer überlauft wird er auf 60000 zurückgesetzt
{							//Wenn der Intervall zu groß ist pendelt der Timer immer zwischen 60000 und 65536 
	TCNT1=60000;		
}
Jemand ne Ahnung woran das liegen könnte ?
Jede Idee könnte helfen

MfG
Jens