Guten Tag,
ich habe seit längerm ein Problem.
Und zwar frage ich ein digitales Steuerkreuz ab.
Links/Rechts = auswahl des Servos (1 -18 )
Hoch/Runter = Wert um 5 verändern und über twi senden.
Diese Eingaben zeige ich auf einem Display an.

Leider hängt sich der Controller irgendwan beim senden des Werts über I2C auf.
Das hat aber funktioniert, und erst seit ich über eingabe/ausgabe via Steuerkreuz und display interagiere funktioniert das nicht mehr.

Ich habe es soweit eingegrenzt das ich mir eigentlich sicher bin, das es an der Busübertragung liegt.

So sieht der Code des Atmega644 aus(dieser sendet):
Main.c
Code:
#define F_CPU 16000000UL	//CPU Tackt

#include <avr/io.h>         // I/O Port definitions 
#include <avr/interrupt.h>   // Interrupt macros 
#include <util/twi.h>
#include <util/delay.h>
#include "lcd.h"
#include "funktionen.h"




/*----------------------------------------------------------------------------------------*/
//MAIN AUFRUF
/*----------------------------------------------------------------------------------------*/

int main(void) 
{
		
	DDRA |= (1<<PORTA0);
	PORTA |= (1<<PORTA0);

	//Init Ports Steuerkreuz (Eingänge)
	DDRD &= ~((1<<PORTD4) | (1<<PORTD5) | (1<<PORTD6) | (1<<PORTD7));
	//Pullup aktivieren
	PORTD |= (1<<PORTD4) | (1<<PORTD5) | (1<<PORTD6) | (1<<PORTD7) ;
	//D7 Rechts
	//D6 Links
	//D5 Runter
	//D4 Hoch
	twi_init();
	
	servo1 = 125;
	servo2 = 125;
	servo3 = 125;
	servo4 = 125;
	servo5 = 125;
	servo6 = 125;
	servo7 = 125;
	servo8 = 125;
	servo9 = 125;
	servo10 = 125;
	servo11 = 125;
	servo12 = 125;
	servo13 = 125;
	servo14 = 125;
	servo15 = 125;
	servo16 = 125;
	servo17 = 125;
	servo18 = 125;
	

	servochance = 1;


	//screenup();


	while(1)
	{

		if(tast(&PIND, PORTD7))
			{
				if(servochance<18)
				servochance++;
				else
				servochance = 1;
				dispz(servochance, servochance);

			}

		if(tast(&PIND, PORTD6))
			{
				if(servochance>1)
				servochance--;
				else
				servochance = 18;
				dispz(servochance, servochance);
			}

		if(tast(&PIND, PORTD4))
			{
				switch(servochance)
				{
					case 1:
					if(servo1<250)
					{
					servo1= servo1+5;
					twi_servo(SLAVE_ADRESSE1, servo1, servo2, servo3);
					dispz(servochance, servo1);
					}
					break;
/*
					case 2:
					if(servo2<250)
					{
					servo2= servo2+5;
					twi_servo(SLAVE_ADRESSE1, servo1, servo2, servo3);
					dispz(servochance, servo2);
					}
					break;

					case 3:
					if(servo3<250)
					{
					servo3= servo3+5;
					twi_servo(SLAVE_ADRESSE1, servo1, servo2, servo3);
					dispz(servochance, servo3);
					}
					break;

					case 4:
					if(servo4<250)
					{
					servo4= servo4+5;
					twi_servo(SLAVE_ADRESSE2, servo4, servo5, servo6);
					dispz(servochance, servo4);					
					}
					break;

					case 5:
					if(servo5<250)
					{
					servo5= servo5+5;
					twi_servo(SLAVE_ADRESSE2, servo4, servo5, servo6);
					dispz(servochance, servo5);
					}
					break;

					case 6:
					if(servo6<250)
					{
					servo6= servo6+5;
					twi_servo(SLAVE_ADRESSE2, servo4, servo5, servo6);
					dispz(servochance, servo6);					
					}
					break;
					
					case 7:
					if(servo7<250)
					{
					servo7= servo7+5;;
					twi_servo(SLAVE_ADRESSE3, servo7, servo8, servo9);
					dispz(servochance, servo7);
					}
					break;

					case 8:
					if(servo8<250)
					{
					servo8= servo8+5;
					twi_servo(SLAVE_ADRESSE3, servo7, servo8, servo9);
					dispz(servochance, servo8);
					}
					break;

					case 9:
					if(servo9<250)
					{
					servo9= servo9+5;
					twi_servo(SLAVE_ADRESSE3, servo7, servo8, servo9);
					dispz(servochance, servo9);
					}
					break;

					case 10:
					if(servo10<250)
					{
					servo10= servo10+5;
					twi_servo(SLAVE_ADRESSE4, servo10, servo11, servo12);
					dispz(servochance, servo10);
					}
					break;

					case 11:
					if(servo11<250)
					{
					servo11= servo11+5;
					twi_servo(SLAVE_ADRESSE4, servo10, servo11, servo12);
					dispz(servochance, servo11);
					}
					break;
					
					case 12:
					if(servo12<250)
					{
					servo12= servo12+5;
					twi_servo(SLAVE_ADRESSE4, servo10, servo11, servo12);
					dispz(servochance, servo12);
					}
					break;
					
					case 13:
					if(servo13<250)
					{
					servo13= servo13+5;
					twi_servo(SLAVE_ADRESSE5, servo13, servo14, servo15);
					dispz(servochance, servo13);
					}
					break;

					case 14:
					if(servo14<250)
					{
					servo14= servo14+5;
					twi_servo(SLAVE_ADRESSE5, servo13, servo14, servo15);
					dispz(servochance, servo14);
					}
					break;

					case 15:
					if(servo15<250)
					{
					servo15= servo15+5;
					twi_servo(SLAVE_ADRESSE5, servo13, servo14, servo15);
					dispz(servochance, servo15);
					}
					break;

					case 16:
					if(servo16<250)
					{
					servo16= servo16+5;
					twi_servo(SLAVE_ADRESSE6, servo16, servo17, servo18);
					dispz(servochance, servo16);
					}
					break;
					
					case 17:
					if(servo17<250)
					{
					servo17= servo17+5;
					twi_servo(SLAVE_ADRESSE6, servo16, servo17, servo18);
					dispz(servochance, servo17);
					}
					break;

					case 18:
					if(servo18<250)
					{
					servo18= servo18+5;
					twi_servo(SLAVE_ADRESSE6, servo16, servo17, servo18);
					dispz(servochance, servo18);
					}
					break;*/
					
				}
				
			}
		
		if(tast(&PIND, PORTD5))
			{
			switch(servochance)
				{
					case 1:
					if(servo1>1)
					{
					servo1= servo1-5;
					twi_servo(SLAVE_ADRESSE1, servo1, servo2, servo3);
					dispz(servochance, servo1);
					}
					break;
/*
					case 2:
					if(servo2>1)
					{
					servo2= servo2-5;
					twi_servo(SLAVE_ADRESSE1, servo1, servo2, servo3);
					dispz(servochance, servo2);
					}
					break;
					
					case 3:
					if(servo3>1)
					{
					servo3= servo3-5;
					twi_servo(SLAVE_ADRESSE1, servo1, servo2, servo3);
					dispz(servochance, servo3);
					}
					break;

					case 4:
					if(servo4>1)
					{
					servo4= servo4-5;
					twi_servo(SLAVE_ADRESSE2, servo4, servo5, servo6);
					dispz(servochance, servo4);
					}
					break;

					case 5:
					if(servo5>1)
					{
					servo5= servo5-5;
					twi_servo(SLAVE_ADRESSE2, servo4, servo5, servo6);
					dispz(servochance, servo5);
					}
					break;

					case 6:
					if(servo6>1)
					{
					servo6= servo6-5;
					twi_servo(SLAVE_ADRESSE2, servo4, servo5, servo6);
					dispz(servochance, servo6);
					}
					break;
					
					case 7:
					if(servo7>1)
					{
					servo7= servo7-5;
					twi_servo(SLAVE_ADRESSE3, servo7, servo8, servo9);
					dispz(servochance, servo7);
					}
					break;

					case 8:
					if(servo8>1)
					{
					servo8= servo8-5;
					twi_servo(SLAVE_ADRESSE3, servo7, servo8, servo9);
					dispz(servochance, servo8);
					}
					break;

					case 9:
					if(servo9>1)
					{
					servo9= servo9-5;
					twi_servo(SLAVE_ADRESSE3, servo7, servo8, servo9);
					dispz(servochance, servo9);
					}
					break;

					case 10:
					if(servo10>1)
					{
					servo10= servo10-5;
					twi_servo(SLAVE_ADRESSE4, servo10, servo11, servo12);
					dispz(servochance, servo10);
					}
					break;

					case 11:
					if(servo11>1)
					{
					servo11= servo11-5;
					twi_servo(SLAVE_ADRESSE4, servo10, servo11, servo12);
					dispz(servochance, servo11);
					}
					break;
					
					case 12:
					if(servo12>1)
					{
					servo12= servo12-5;
					twi_servo(SLAVE_ADRESSE4, servo10, servo11, servo12);
					dispz(servochance, servo12);
					}
					break;
					
					case 13:
					if(servo13>1)
					{
					servo13= servo13-5;
					twi_servo(SLAVE_ADRESSE5, servo13, servo14, servo15);
					dispz(servochance, servo13);
					}
					break;

					case 14:
					if(servo14>1)
					{
					servo14= servo14-5;
					twi_servo(SLAVE_ADRESSE5, servo13, servo14, servo15);
					dispz(servochance, servo14);
					}
					break;

					case 15:
					if(servo15>1)
					{
					servo15= servo15-5;
					twi_servo(SLAVE_ADRESSE5, servo13, servo14, servo15);
					dispz(servochance, servo15);
					}
					break;

					case 16:
					if(servo16>1)
					{
					servo16= servo16-5;
					twi_servo(SLAVE_ADRESSE6, servo16, servo17, servo18);
					dispz(servochance, servo16);
					}
					break;
					
					case 17:
					if(servo17>1)
					{
					servo17= servo17-5;
					twi_servo(SLAVE_ADRESSE6, servo16, servo17, servo18);
					dispz(servochance, servo17);
					}
					break;

					case 18:
					if(servo18>1)
					{
					servo18= servo18-5;
					twi_servo(SLAVE_ADRESSE6, servo16, servo17, servo18);
					dispz(servochance, servo18);
					}
					break;*/
					
				}
				
				
			}




	}

}
funktionen.c
Code:
unsigned char twi_servo(unsigned char slave_adr, unsigned char servo1,unsigned char servo2,unsigned char servo3)
{
	if(!(twi_start(slave_adr+0)))
	{
		twi_senden(0x00);
		_delay_ms(10);

		twi_senden(servo1);
		_delay_ms(10);

		twi_senden(servo2);
		_delay_ms(10);

		twi_senden(servo3);
		_delay_ms(10);

		twi_stop();
		return 1;
	}
	return 0;
}

void twi_init(void)
{	
	DDRC &= !((1<<DD0) | (DD1));
	PORTC = (1<<DD0) | (1<<DD1);
	TWSR = 0x00;		//Prescaler 
	TWBR = 12;		//TWI 400khz

	//Hintergrundbeleuchtung on
	PORTA |= (1<<PORTA0);
	//Initialisieren des Displays, Cursor off
	lcd_init(LCD_DISP_ON);
	//Display löschen, Cursor i Zeile, 1 Spalte
	lcd_clrscr();
	//Cursor auf 1 Zeile, 3 Buchstaben
	lcd_gotoxy(0,0);
	//String ausgeben
	lcd_puts("I2C ");
	//Cursor auf 2 Zeile, 3 Buchstaben
	lcd_gotoxy  (0, 1);
	//String ausgeben
	lcd_puts("Initialisieren");
	//~3s warten
	_delay_ms(1000);
	//Display off
	lcd_init(LCD_DISP_OFF);
	//Hintergrundbeleuchtung off
	PORTA &= ~(1<<PORTA0);
}

unsigned char twi_start(unsigned char adresse)
{
	uint8_t twst;
	
	
		TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);		//TWI aktivieren und Start condition auslösen
		while(!(TWCR & (1<<TWINT))); 	//Warten auf Start condition
		twst = TW_STATUS & 0xF8;
		//if((TWSR & 0xF8) != 0x08);
		if ((twst != TW_START) && (twst != TW_REP_START))return 1;

		TWDR = adresse;		//Adresse mit Schreibbit(xxxxxxx0) in Register
		TWCR = (1<<TWINT) | (1<<TWEN);	//senden
		//if((TWSR & 0xF8) != 0x18);
		while(!(TWCR & (1<<TWINT)));	//warten auf ACK oder NACK
		twst = TW_STATUS & 0xF8;
		if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) return 1;
		return 0;
			
}

unsigned char twi_rep_start(unsigned char adresse)
{
	return twi_start(adresse);
}

unsigned char twi_senden(unsigned char daten)
{
	uint8_t twst;

		TWDR = daten;					//Byte in Datenregister laden
		TWCR = (1<<TWINT) | (1<<TWEN);	//senden
		while (!(TWCR & (1<<TWINT)));	//warten auf ACK oder NACK
		twst = TW_STATUS & 0xF8;
		if(twst != TW_MT_DATA_ACK) return 1;
		return 0;
	
}

unsigned char twi_lesenAck(void)
{
	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
	while(!(TWCR & (1<<TWINT)));
	return TWDR;
}

unsigned char twi_lesenNak(void)
{
	TWCR = (1<<TWINT) | (1<<TWEN);
	while(!(TWCR & (1<<TWINT)));
	return TWDR;
}

void twi_stop(void)
{
	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
	while(TWCR & (1<<TWSTO));
}


/*----------------------------------------------------------------------------------------*/
//Display ausgaben
/*----------------------------------------------------------------------------------------*/


void dispz(const char zahl1, const char zahl2)
{
	
	char text1[17];
	char text2[17];

	itoa(zahl1, text1, 10);
	itoa(zahl2, text2, 10);

	
	//Initialisieren des Displays, Cursor off
	lcd_init(LCD_DISP_ON);
	//Display löschen, Cursor i Zeile, 1 Spalte
	lcd_clrscr();
	//Cursor auf 1 Zeile, 3 Buchstaben
	lcd_gotoxy(0,0);
	//String ausgeben
	lcd_puts(text1);
	//Cursor auf 2 Zeile, 3 Buchstaben
	lcd_gotoxy  (0, 1);
	//String ausgeben
	lcd_puts(text2);
	_delay_ms(50);
}

int tast(volatile uint8_t *port, uint8_t pin)
{
	if(!(*port & (1<<pin)))
	{
		_delay_ms(100);
		if(!(*port & (1<<pin))) 
		{
			_delay_ms(100);
			return 1;
		}
	}
	return 0;
}
und der code des Slaves, wobei ich denke das müsste passen:
Code:
#include <avr/io.h>       		  //I/O Port definitions 
#include <avr/interrupt.h>  	 //Interrupt macros 
#include <util/twi.h>			//TWI STATUS

#define F_CPU 16000000UL		//CPU Tackt

/*----------------------------------------------------------------------------------------*/
//TWI
/*----------------------------------------------------------------------------------------*/
#define SLAVE_ADRESSE 0x60		//Slaveadresse
#define buffer_size 5			//TWI_empfangsbuffer grösse
//ACK nach empfangenen Daten senden/erwarten
#define TWCR_ACK TWCR = (1<<TWEN) | (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWWC)
//NACK nach empfangenen Daten senden/erwarten
#define TWCR_NACK TWCR =(1<<TWEN) | (1<<TWIE) | (1<<TWINT) | (0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWWC) 
//wechseln zu nicht adressiertem Slavemodus
#define TWCR_RESET TWCR = (1<<TWEN) | (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWWC)

uint8_t adresse; 				//Slaveadresse
volatile uint8_t buffer_adr;	//Speicherposition
volatile uint8_t rxbuffer[buffer_size] = {1,1,1,1,1};	//TWI_empfangsbuffer
volatile uint8_t txbuffer[buffer_size] = {1,1,1,1,1};	//TWI_sendenbuffer	


/*----------------------------------------------------------------------------------------*/
//PWM
/*----------------------------------------------------------------------------------------*/

//1000 = 1ms(links), 1500 = 1,5ms(mitte), 2000 = 2ms(rechts)
volatile int schulter= 1500;		
volatile int huefte = 1500;			
volatile int knie = 1500;	

void twi_slave(uint8_t adresse);					//TWI_Init funktion
void pwm_init(int schulter, int huefte, int knie);	//PWM_init Funktion		
void pwm_chance(int schulter, int huefte, int knie);//Anpassen der PWM grössen

/*----------------------------------------------------------------------------------------*/
//MAIN AUFRUF
/*----------------------------------------------------------------------------------------*/

int main(void) 
{
	adresse = SLAVE_ADRESSE;											//Slave 1
	DDRB = 0xFF;											//B... AUSGANG
	PORTB &= ~((1<<PORTB1) | (1<<PORTB2) | (1<<PORTB3));	//B.. Low
	sei();												//Globale Interupts zulassen
	pwm_init(schulter, huefte, knie);						//PWM initialisieren
	twi_slave(adresse);										//TWI initialisieren


	while(1)
	{
	

		
	}

}

ISR(TWI_vect)						//TWI Interupt (Ausgelöst bei Bus Ereignis)
{
	uint8_t daten = 0;
	
	switch(TW_STATUS)					//TWI-Statusregister prüfen und agieren
	{
		
		case TW_SR_SLA_ACK:					//0x60, Slave Receiver wurde adressiert
		
			TWCR_ACK;
			buffer_adr = 0xFF;					
			break;

		case TW_SR_DATA_ACK:				//0x80, Slave Receiver Daten empfangen
		
			daten = TWDR;						//Daten auslesen
	
			if (buffer_adr == 0xFF)
			{
				if(daten<=buffer_size)
					{
						buffer_adr = daten;				
					}
				else
					{
						buffer_adr=0;
					}

				TWCR_ACK;
			}
			else
			{
				rxbuffer[buffer_adr] = daten;
				buffer_adr++;
				
				//Zuweisen der neuen PWM werte
				schulter = ((rxbuffer[0]*4)+1000);
				huefte = ((rxbuffer[1]*4)+1000);
				knie = ((rxbuffer[2]*4)+1000);
	
				pwm_chance(schulter, huefte, knie);	//PWM grössen anpassen
				
				if (buffer_adr<(buffer_size-1))
					{
						TWCR_ACK;
					}
				else
					{
						TWCR_NACK;
					}
			}


		
		
		break;

		case TW_ST_DATA_ACK:			//0xB8, Slave Transmitter Daten angefordert
		
			if(buffer_adr == 0xFF)
				{
					buffer_adr = 0;
				}
			TWDR = txbuffer[buffer_adr];
			buffer_adr++;
		
			if(buffer_adr<(buffer_size-1))
				{
					TWCR_ACK;
				}
			else
				{
					TWCR_NACK;
				}
		break;


		case TW_SR_STOP:
		
		default:	
		TWCR_RESET;

		break;

		//Ende
	}

	


}
Ich hoffe das reicht an Code, es fehlen Teile wie Headerfiles und funktionen die nichts mit dem Problem zu tun haben.
Ein Grossteil ist bewusst auskommentiert um den Fehler näher einzugrenzen.

Nochmal um das Problem näher zu umschreiben:
Das auswählen des Servos klappt super, auch das erhöhen des Wert wen ich die Twiübertragung ausklammere.
Ist diese aber drin funktioniert es, aber meisst nur kurz. Sprich 1 -3 Werte können übertragen werden dann hängt sich der Atmega644 auf.
Manchmal sind es auch mehrere Übertragungen. Dies aber eher selten.
Mir gehen echt die Ideen aus.

Besten dank fürs lesen und jeglichen Tipp