-         

Ergebnis 1 bis 4 von 4

Thema: Controller verhält sich merkwürdig

  1. #1
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    28.05.2007
    Ort
    Mannheim
    Alter
    30
    Beiträge
    270

    Controller verhält sich merkwürdig

    Anzeige

    Hey Jungs,

    ich habe hier ein Problem was mich seit einigen Tagen ziemlich stark verwirrt.
    Vielleicht hat jemand von euch Ideen von woher ein solches Problem kommen könnte.

    Folgendes:
    Ich habe einen ATMega88 Fuses sind auf externen Clock gestellt und der Chip hängt an einen 8MHz Quarz Oszillator.

    Der Chip fungiert als Slave am I²C Bus. Der Master ist auch ein Atmel Controller (ATMega1280, aber der ist erstmal unwichtig).
    Das Programm ist momentan noch recht einfach:


    Code:
    int main(void)
    {
        init();
    
        __RESET_LED;
        _delay_ms(100);
        __SET_LED;
        _delay_ms(100);
        __RESET_LED;
        _delay_ms(100);
        __SET_LED;
        _delay_ms(100);
        __RESET_LED;
      while(1);
    }
    
    void init(void)
    {
      //------------------------
      //Ein/Ausgänge:
      //------------------------
      DDRD |= _BV(0) | _BV(3) | _BV(1) | _BV(6) | _BV(7); //Motoren rechts/links und LED
      DDRB |= _BV(0);
    
      PORTD |= _BV(6); //vor2
      //PORTD |= _BV(7); //zurück2
    
      PORTD |= _BV(0); //vor1
      //PORTB |= _BV(0); //zurück1
    
      //------------------------
      //Timer/Counter:
      //------------------------
    
      DDRB |= _BV(3); //PWM-Pin als Output
      DDRD |= _BV(3); //PWM-Pin als Output
    
      ASSR=0;
      TCCR2A |= (1<<WGM20); //PWM-Mode
      TCCR2A |= (1<<COM2A1) | (1<<COM2B1); //Compare = Set
      TCCR2B |= (1<<CS20);  //Prescaler 64
      TCNT2=0;
      OCR2A = 0; //PWM-Wert
      OCR2B = 0; //PWM-Wert
    
      //I2C Initialisieren:
      i2c_init_slave(MY_I2C_ADR);
    
      TWAMR = 255;
    
      sei();
    }
    
    int i2c_init_slave(char address)
    {
    	TWSR = 0;
    	TWDR = 0xFF;
    	TWCR = 0b00000100;
    	TWAR = (address<<1);
    	TWCR = 0b01000101;
    
    	return 1;
    }
    
    SIGNAL (SIG_2WIRE_SERIAL)
    {
    	uint8_t status = 0;
    	uint8_t data = 0;
    	//PORTD &= ~(1<<PD2);
    	data = TWDR;
    
    	status = TWSR;
    
    	if (status_is(0xA8) || status_is(0xB8))
    	{
    
    	  if (twi_send_data[a])
    		{
            TWDR = twi_send_data[a];
    			a++;
    			if(a>3)
    				a=0;
    		}else{
    			for(a=0;a<11;a++)
    				twi_send_data[a]=0;
    
    			a=0;
    			TWDR = 0;
    		}
    
    			//TWDR = mydata;
    	}
    
    	TWCR |= 0b10000000;
    
    	if (status_is(0x80))
    	{
    		if (data == '*')
    		{
    			twi_data_received = 1;
    		}else{
    
    			if (twi_pointer < 10)
    				twi_buffer[twi_pointer++] = data;
    			//else
    				//fehler();//FEHLER!!
    		}
    	}
    }
    So viel zum Code, nur so, falls jemand was darin sieht...

    Nun zum Problem:
    Wie man sieht, müsste der Controller beim Einschalten 2x die LED blinken.

    Der Master Controller Startet regelmäßig den Bus mit der Slaveadresse, sendet 2 Bytes und stopt den Bus wieder.
    Mehr passiert da momentan nicht.

    So und nun treten bei mir immer 2 verschiedene Möglichkeiten auf:

    1) Ich starte alles und die LED blinkt 2x. Wenn der MAster den Slave aufruft, wird der Interrupt am Slave nicht aufgerufen, die Daten nicht bestätigt und somit gibt es einen Fehler auf dem Bus.

    2) Ich starte alles und die LED blinkt 1x. Wenn der Master dann den Slave aufruft, dann läuft der Datentransfer ohne jegliche Probleme, ACKs kommen zurück und alles.

    Unterm strich heißt das also:
    Wenn die LED anfangs so blinkt (2x) wie es im Code steht, dann geht der Bus nicht.
    Und wenn die LED anfangs nur einmal blinkt, was laut Code überhaupt nicht sein kann, dann geht der Bus hervorragend.

    Wann welche der Möglichkeiten auftritt habe ich noch nicht heraus gefunden. Immer nach dem Brennen tritt eine dieser beiden Möglickeiten ein. Und irgendwann später mal beim brennen mal wieder die andere.
    Ich habe da noch keinerlei Muster erkannt wann was kommt und auch keinerlei Ahnung was da los ist.
    Weil keine der beiden Möglichkeiten nach dem Code richtig läuft...

    Bin für jeden Hinweis dankbar. Egal welcher Art. Denn ich habe für dieses Verhalten keinerlei Erklärung...

    PS: Die Interruptroutine läuft 1:1 auf einem anderen Chip am selben Bus fehlerfrei.
    Wer aufhört besser zu werden, hat aufgehört gut zu sein

    Jeder I/O Port kennt drei Zustände: Input, Output, Kaputt

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    21.07.2008
    Ort
    Moosburg
    Alter
    39
    Beiträge
    49
    Hi!

    Hast Du den Bus richtig terminiert?

    Ein anderes Problem könnt die Verwendung der Timer in Verbindung mit _delay_ms() sein. _delay_ms() bentuzt einen der Timer.

    Btw: Meines Wissens ist SIGNAL veraltet und mal sollte statt dessen ISR verwenden (Vorsicht: Dann den Namen des Interrupt-Vektors angeben).
    Versuch's mal damit. Ich bin mir nämlich jetzt nicht sicher, ob das einfach das gleiche unter neuem Namen ist, oder ob sich auch was im Hintergrund geändert hat.

    Viele Grüße,

    Markus

  3. #3
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    28.05.2007
    Ort
    Mannheim
    Alter
    30
    Beiträge
    270
    Hey, also erstmal vielen Dank für deine Antwort.
    Bin für jede Idee dankbar.
    Hab mir das alles nochmal angesehen:

    Also der Bus hat auf beiden Leitungen Pull-Up Widerstände mit 4,7k Ohm.
    Und die Kommunikation zu dem anderen Slave am Bus läuft ja auch einwandfrei. Nur der eine Slave macht halt Maken...

    Die Delay Routinen habe ich mir nochmal angesehen. Diese verwenden definitiv keine Timer:
    Code:
    void
    _delay_ms(double __ms)
    {
    	uint16_t __ticks;
    	double __tmp = ((F_CPU) / 4e3) * __ms;
    	if (__tmp < 1.0)
    		__ticks = 1;
    	else if (__tmp > 65535)
    	{
    		//	__ticks = requested delay in 1/10 ms
    		__ticks = (uint16_t) (__ms * 10.0);
    		while(__ticks)
    		{
    			// wait 1/10 ms
    			_delay_loop_2(((F_CPU) / 4e3) / 10);
    			__ticks --;
    		}
    		return;
    	}
    	else
    		__ticks = (uint16_t)__tmp;
    	_delay_loop_2(__ticks);
    }
    
    void
    _delay_loop_2(uint16_t __count)
    {
    	__asm__ volatile (
    		"1: sbiw %0,1" "\n\t"
    		"brne 1b"
    		: "=w" (__count)
    		: "0" (__count)
    	);
    }
    Und die ganzen Interruptbezeichnungen sind auch alle auf die den entsprechenden Vektor definiert.
    Alle Bezeichnungen führen also zum gleichen Ergebnis:

    Code:
    /* Two-wire Serial Interface */
    #define TWI_vect			_VECTOR(24)
    #define SIG_TWI				_VECTOR(24)
    #define SIG_2WIRE_SERIAL		_VECTOR(24)
    Wer aufhört besser zu werden, hat aufgehört gut zu sein

    Jeder I/O Port kennt drei Zustände: Input, Output, Kaputt

  4. #4
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    28.05.2007
    Ort
    Mannheim
    Alter
    30
    Beiträge
    270
    Hey, also ich wollte bescheid sagen, das wir das Problem gelöst haben.

    Haben festgestellt, dass beim aufruf des Slaves nicht nur der Bus hängen bleibt, sondern der komplette Controller hängen bleibt.
    Was darauf hinweist, dass die ISR ins leere springt.

    Der Compiler hat zwar angezeigt, dass er das Programm für einen Mega88 kompiliert, aber hat es scheinbar nicht getan.
    Haben nochmal ein neues Projekt erstellt, die Dateien wieder rein kopiert und siehe da funktioniert es nun wieder
    *freu*

    Trotzdem danke für eure Bemühungen bzw. Gedanken die ihr euch eventuell darüber gemacht hat.

    Falls nochmal jemand ein solches Problem haben sollte, hat er hier die Lösung dafür...
    Wer aufhört besser zu werden, hat aufgehört gut zu sein

    Jeder I/O Port kennt drei Zustände: Input, Output, Kaputt

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •