-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 18

Thema: Disign Frage (Interrupt oder Main)

  1. #1
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    31.01.2004
    Ort
    36399
    Alter
    43
    Beiträge
    1.517

    Disign Frage (Interrupt oder Main)

    Anzeige

    Ich gebe zu so viel habe ich noch nicht in c für den AVR geschrieben.
    Aber ich möchte hinterher nicht alles neu machen weil ich eine dumme gebaut habe.

    Zu meiner Frage:
    Zur Zeit arbeitet ich so das in den Interrupt Routinen nur das wichtigste gemacht wird und die eingleiche arbeit finden im Main statt.
    Das mache ich so damit die Interrupts sich nicht gegenseitig unter Brechen.

    Wenn ich mir jetzt andere Software so angucken gibt es welche die haben überhaupt kein Main (spich da steht nur wihle) und wieder ander arbeiten komplett ohen interupts bzw. mit nur sehr wenig.

    Code:
    /**************************************
     mains.c
     Autor: Numberfive
     versuchen das ganze mal zu verstehen.
     Alle die im Netzt beispiel code habe
     sei an dieser stelle gedankt
     man komme nie auf die Idee irgend wo
     Interupts zu enablen wenn dafür keine
     signal procedure hat dann springt
     der AVR wieder in die main routine
     Danke an Picknick für das Seriale Protokoll
    *************************************/
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <inttypes.h>
    //#include <stdlib.h>
    
    //#define F_CPU 16000000   // 16 MHz jetzt im Makefile
    #define UART_BAUD_RATE 19200      // 19200 Baud
    
    #define UART_BAUD_SELECT (F_CPU/(UART_BAUD_RATE*16l)-1)
    #define SCLOCK 16;
    
    // _BV = BitValue
    #define SETBIT(ADDRESS,BIT)(ADDRESS |=(1<<BIT))
    #define CLEARBIT(ADDRESS,BIT)(ADDRESS &= ~(1<<BIT));
    
    typedef unsigned char BYTE;
    typedef unsigned short WORD;
    
    //MN Funktions
    void WDT_off(void);
    void InitCom(void);
    void InitTimer1(void);
    void InitAD(void);
    void SendAlive(void);
    
    //RS232 Protokoll funktionen
    #define CTL_M_MASK   0xF8
    #define CTL_M_ADON   0x08
    #define CTL_C_BASE   0xA8
    #define CTL_C_STX   CTL_C_BASE + 1
    #define CTL_C_ETX   CTL_C_BASE + 2
    #define CTL_C_PFX   CTL_C_BASE + 3
    void TxSendStuffByte (BYTE bTxChar);
    void TxSendFrameByte (BYTE bTxChar);
    void TxStartFrame ( void );
    void TxCloseFrame ( void );
    void SendChar(BYTE Zeichen);
    void SendADValue(BYTE nToClass,BYTE nToIdent,BYTE nPort);
    
    // Public Vars
    
    volatile BYTE IsHardBeat = 0;
    volatile BYTE IsPCData = 0;
    volatile BYTE HardBeatCount = 0;
    volatile BYTE bTxBcc;            // Checksum für BCC
    
    volatile BYTE bSerialInBuffer[128];
    volatile BYTE bBefehlbuffer[128];
    volatile BYTE bInBufferPos = 0;
    volatile BYTE waitforad = 1;
    
    //Interupts
    
    SIGNAL(SIG_OVERFLOW1)
    {
    	IsHardBeat = 1;
    	TCNT1 = 49910;//Reload Timer
    }
    
    SIGNAL(SIG_UART_RECV)
    {
    	BYTE Zeichen = UDR;
    	if(bInBufferPos == 0)
    	{
    		if(Zeichen == CTL_C_STX)
    		{
    			bSerialInBuffer[0] = CTL_C_STX;
    			bInBufferPos++;
    		}
    	}
    	else
    	{
    		if(Zeichen == CTL_C_ETX)
    		{
    			bSerialInBuffer[bInBufferPos] = CTL_C_ETX;
    			//Copy Buffer resetInbuffer
    			for(BYTE nSize=0;nSize<=bInBufferPos;nSize++)
    			{
    				bBefehlbuffer[nSize] = bSerialInBuffer[nSize];
    			}
    			bInBufferPos = 0;
    			IsPCData = 1;
    		}
    		else
    		{
    			bSerialInBuffer[bInBufferPos] = Zeichen;
    			bInBufferPos++;
    			if(bInBufferPos == 128)
    			{
    				//Übergelaufen
    				bInBufferPos = 0;
    
    			}
    		}
    	}
    }
    
    SIGNAL(SIG_UART_TRANS)
    {
    	// nix machen aber sonst komme ich immer wider forne an
    }
    
    SIGNAL(SIG_UART_DATA)
    {
    	// nix machen aber sonst komme ich immer wider forne an
    }
    
    SIGNAL(SIG_ADC)
    {
    	//Mal sehen der ad wander ist fertig
    	waitforad = 0;
    }
    //Interupts ende
    
    int main (void)
    {
    	//hauptprg hier geht der controler immer als erstes hin
    	InitCom();
    	WDT_off();
    	InitAD();
    
    	SETBIT(DDRD,PD7); // Das ist der lautsprecher
    
    	bSerialInBuffer[0] = 0X00;
    	bSerialInBuffer[1] = 0X00;
    	bSerialInBuffer[2] = 0X00;
    	bSerialInBuffer[3] = 0X00;
    	bSerialInBuffer[4] = 0X00;
    
    	InitTimer1();//Timer 1 auf 1 sec
    	sei();//interupt enable
    
    	for(;;)
    	{
    		if(IsHardBeat == 1)
    		{
    			IsHardBeat = 0;
    			HardBeatCount++;
    			if(HardBeatCount == 5)
    			{
    				HardBeatCount=0;
    				SendAlive();
    			}
    		}
    		if(IsPCData == 1)
    		{
    			IsPCData = 0;
    			BYTE nPos = 1;
    			BYTE nCheckSum = 0;
    			// Das geht schief wenn das BCC maskiert ist
    			while(bBefehlbuffer[nPos+1] != CTL_C_ETX)
    			{
    				if(bBefehlbuffer[nPos] != CTL_C_PFX)
    				{
    					nCheckSum ^= bBefehlbuffer[nPos];
    				}
    				else
    				{
    					nPos++;
    					nCheckSum ^= bBefehlbuffer[nPos]-CTL_M_ADON;
    				}
    				nPos++;
    			}
    			if(nCheckSum == bBefehlbuffer[nPos])
    			{
    				//BCC OK
    				if(bBefehlbuffer[1] == 0x05)
    				{
    					//NXT Bekommen
    					if(bBefehlbuffer[5] == 0x00)
    					{
    						//Erste Gerät auf diesem Roboter ist ein ADWandler mit der Adresse 0x25
    						TxStartFrame();
    						TxSendFrameByte(0x09);
    						TxSendFrameByte(0x00);
    						TxSendFrameByte(0x25);
    						TxSendFrameByte(0x00);
    						TxSendFrameByte(0x01);
    						TxSendFrameByte(0x82);
    						TxSendFrameByte(0x00);
    						TxCloseFrame();
    					}
    					if(bBefehlbuffer[5] == 0x01)
    					{
    						//.. ist ein ADWandler mit der Adresse 0x29
    						TxStartFrame();
    						TxSendFrameByte(0x09);
    						TxSendFrameByte(0x00);
    						TxSendFrameByte(0x25);
    						TxSendFrameByte(0x01);
    						TxSendFrameByte(0x02);
    						TxSendFrameByte(0x82);
    						TxSendFrameByte(0x01);
    						TxCloseFrame();
    					}
    					if(bBefehlbuffer[5] == 0x02)
    					{
    						// Ich bin das Letzt und ein RN-Control
    						TxStartFrame();
    						TxSendFrameByte(0x09);
    						TxSendFrameByte(0x00);
    						TxSendFrameByte(0x2D);
    						TxSendFrameByte(0x00);
    						TxSendFrameByte(0xFF);
    						TxSendFrameByte(0x62);
    						TxSendFrameByte(0x00);
    						TxCloseFrame();
    					}
    
    				}
    				else if(bBefehlbuffer[1] == 0x25)
    				{
    					if(bBefehlbuffer[2] == 0x00)
    					{
    						SendADValue(bBefehlbuffer[3],bBefehlbuffer[4],0);
    					}
    				}
    			}
    		}
    	} //Ende MainLoop
    }
    
    void InitCom(void)
    {
    	/* Set baud rate */
    	/* wenn wir in das h register schreiben wollen muß da ein 0 drin sein */
    	UCSRC = (0<<URSEL);
    	UBRRH = (UART_BAUD_SELECT>>8);
    	UBRRL = UART_BAUD_SELECT;
    	/* Enable receiver and transmitter und die Interupts*/
    	UCSRB = _BV(RXEN)|_BV(RXCIE);//|_BV(TXCIE);
    	/* Set frame format: 8data, 1stop bit */
    	UCSRC = (1<<URSEL)|(0<<USBS)|(0<<UCSZ2)|_BV(UCSZ1)|_BV(UCSZ0);
    	// Braucht man nicht aber das ist dir register umschaltung ob man
    	// das hight byte des UBRR sieht oder UCSRC
    	UCSRC != _BV(URSEL);
    }
    
    void WDT_off(void)
    {
    	//WDR();
    	WDTCR |=(1<<WDTOE) | (1<<WDE);
    	WDTCR = 0x00;
    }
    
    void InitTimer1(void)
    {
    	SETBIT(TCCR1B,CS10);
    	SETBIT(TCCR1B,CS11);
    	//SETBIT(TCCR1B,CS12);
    
    	//enable interrupt timer
    	SETBIT(TIMSK,TOIE1);
    
    	// 1 sec bei Teiler 1024
    	TCNT1 = 49910;
    
    	TCNT1 = 100;//<- Für SIM
    }
    
    void InitAD(void)
    {
    	//Init ADwandler
    	ADCSRA = (1<<ADEN)|(1<<ADSC)|(0<<ADATE)|(0<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
    	//CLEARBIT(ADCSRA,ADFR); // Kein Freilauf
    	CLEARBIT(ADMUX,REFS1);
    	SETBIT(ADMUX,REFS0); // externe vergleichs Quelle
    	SETBIT(ADCSRA,ADIE);
    }
    
    void SendAlive(void)
    {
    	TxStartFrame();
    	TxSendFrameByte(0x01);
    	TxSendFrameByte(0x00);
    	TxSendFrameByte(0x00);
    	TxSendFrameByte(0x00);
    	TxCloseFrame();
    }
    
    void SendADValue(BYTE nToClass,BYTE nToIdent,BYTE nPort)
    {
    	CLEARBIT(ADCSRA,ADEN); // aus schlaten damit ich den port wechseln kann
    	//ADMUX = nPort; geht nicht da sind noch 2 bit's
    	if(nPort == 0)
    	{
    		CLEARBIT(ADMUX,MUX4);
    		CLEARBIT(ADMUX,MUX3);
    		CLEARBIT(ADMUX,MUX2);
    		CLEARBIT(ADMUX,MUX1);
    		CLEARBIT(ADMUX,MUX0);
    	}
    	else if(nPort == 1)
    	{
    		CLEARBIT(ADMUX,MUX4);
    		CLEARBIT(ADMUX,MUX3);
    		CLEARBIT(ADMUX,MUX2);
    		CLEARBIT(ADMUX,MUX1);
    		SETBIT(ADMUX,MUX0);
    
    	}
    	// Bit invertieren messung starten
    	ADCSRA |=_BV(ADSC);
    	waitforad = 1;
    	// warten bis messung abgesclossen ist und wert gültig
    	while(waitforad != 0)
    	{
    		//warten auf den adwandler;
    	};
    	// den wert aus dem register holen
    	if(nPort == 0)
    	{
    		TxStartFrame();
    		TxSendFrameByte(nToClass);
    		TxSendFrameByte(nToIdent);
    		TxSendFrameByte(0x25);
    		TxSendFrameByte(0x00);
    		TxSendFrameByte(ADCL);
    		TxSendFrameByte(ADCH);
    		TxCloseFrame();
    		/*
    			pBuffer[0] = nToClass;
    			pBuffer[1] = nToIdent;
    			pBuffer[2] = 0x25;
    			pBuffer[3] = 0x00;
    			pBuffer[4] = LOBYTE(nValue);
    			pBuffer[5] = HIBYTE(nValue);*/
    
    	}
    	//Result = ADCH*256 + ADCL;
    }
    
    void SendChar(BYTE Zeichen)
    {
        SETBIT(UCSRB,TXEN);
    	//Warten bis schnittstelle bereit
    	loop_until_bit_is_set(UCSRA,UDRE);
    
    	// Zeichen ins register schreiben
    	UDR = Zeichen;
    
    	CLEARBIT(UCSRB,TXEN);
    }
    
    // --------------------------------------------------------------
    void TxStartFrame ( void )
    {
      bTxBcc = 0;
      SendChar ( CTL_C_STX );
    }
    // --------------------------------------------------------------
    void TxCloseFrame ( void )
    {
      TxSendStuffByte ( bTxBcc );// auch das BCC mit ev. prefixed werden
      SendChar ( CTL_C_ETX );
    }
    // --------------------------------------------------------------
    void TxSendFrameByte (BYTE bTxChar)
    {
         bTxBcc ^= bTxChar;
         TxSendStuffByte( bTxChar );
    }
    // --------------------------------------------------------------
    void TxSendStuffByte (BYTE bTxChar)
    {
        if((bTxChar & CTL_M_MASK) == CTL_C_BASE)
        {
    		SendChar( CTL_C_PFX );
    		SendChar( bTxChar + CTL_M_ADON );
        }
        else
        {
    		SendChar( bTxChar );
        }
    }
    Das ist das was ich gestern verbrochen habe. Im Simulator tut es.
    Home
    P: Meine Tochter (06.11.07) und Link
    M: Träumen hat nix mit Dummheit zu tun es ist die Möglichkeit neues zu erdenken

  2. #2
    Neuer Benutzer Öfters hier
    Registriert seit
    05.01.2008
    Beiträge
    22
    ....Das mache ich so damit die Interrupts sich nicht gegenseitig unter Brechen. ...


    das machen die beim atmega nicht. jeder wird sauber beendet.
    das datenblatt vom atmega ist deine glaskugel.

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    05.01.2008
    Beiträge
    22
    ......Wenn ich mir jetzt andere Software so angucken gibt es welche die haben überhaupt kein Main (spich da steht nur wihle) und wieder ander arbeiten komplett ohen interupts bzw. mit nur sehr wenig. ......

    jeder , so wie er es braucht. der eine braucht es, der andere braucht es nicht. was spricht dagegen?

    oberstes gebot für die interrups : so wenig scheiss wie möglich darein packen.

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.791
    Hallo purebasic,

    willkommen im Forum.

    Ich hoffe, dass du hier im neuen Jahr konstruktiv und nicht konfrontativ mitarbeitest!

    Also pure-konstruktiv und pure-basic!

    Gruß Dirk

  5. #5
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    ..die interrups : so wenig scheiss wie möglich ..
    diese Strategie hat was, die kann man auch beim "main()" gut brauchen
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.791
    diese Strategie hat was, die kann man auch beim "main()" gut brauchen
    Yes! ... und auch sonst im "mainstream des Lebens"!
    Ist ja fast philisophisch!

    Verspäteter Neujahrsgruß
    Dirk

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    31.01.2004
    Ort
    36399
    Alter
    43
    Beiträge
    1.517
    Das man beim codieren so optimal wie möglich denken soll ist normal.
    Da ist aber "normaler" Weise in der Windowswelt unterwegs bin bei Programmieren ist es schon eine massive Veränderung.

    Wenn jetzt die Interrupt Routinen immer bis zum Ende abgearbeitet werden.
    Heist das sie so klein wie Möglich sein müssen. Den sonst Warten ja die anderen oder ? gehen vieleicht welche verloren ?

    Frage am Rande:
    Ist es normal das die Simulation des AVR Studios 100 % CPU braucht ?

    Gruß
    Home
    P: Meine Tochter (06.11.07) und Link
    M: Träumen hat nix mit Dummheit zu tun es ist die Möglichkeit neues zu erdenken

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    1.892
    Heist das sie so klein wie Möglich sein müssen. Den sonst Warten ja die anderen oder ? gehen vieleicht welche verloren ?
    Bei allen Punkten 100% - Genau so ist es.
    Interruptroutinen sollten so kurz wie nur irgend möglich sein.
    Ausserdem sollte man in Interrupts nicht auf irgendetwas warten - z.B. eine Änderung eines Eingangspins - da dadurch die komplette Programmabarbeitung ins stocken kommt und auch keine weiteren Interrupts ausgeführt werden können.
    Interrupt Anfragen laufen bei den AVR Controllern über Flags.
    Tritt ein Interrupt auf wird das entsprechende Flag gesetzt.
    Befindet sich der Controller gerade in einer Interruptroutine oder das I - Flag im Statusregister ( siehe Assembler CLI Befehl ) ist 0 wird so lange gewartet bis der Controller die Abarbeitung eines Interruptes zulässt.

    Treten in dieser Zeit mehrere Interrupts auf, werden diese nach ihrer Priorität ( Platz in der Interruptvektortabelle ) abgearbeitet.
    Tritt bei einem aktiven Interruptflag ein weiterer Interupt der selben Instanz auf, wird die Interruptroutine nur 1x ausgeführt, also 1 Interrupt verschluckt.
    Die Interruptflags werde übrigens nach Ausführung der dazugehörigen Interruptroutine automatisch gelöscht.
    Man kann aber ein aktives Interruptflag auch manuell per Programmcode löschen - Das musste man des öfteren schon mal bei den alten AT90S... Controllern machen, die nach der Initialisierung mancher Instanzen auch selbstständig gleich das zugehörige Interrupt Flag gesetzt haben.

  9. #9
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    31.01.2004
    Ort
    36399
    Alter
    43
    Beiträge
    1.517
    @wkrug erstmal danke.

    Wie ich sehe kann man das wohl leider nicht auf dem Papier klären das heist werde das mit echten Controller testen müssen. Leider scheif die Simulation vom studio auch nicht viel mit der realität zu tun zu haben den der Interupt des AD's (messung fertig) kommt nicht.

    da da jetzt auch noch I²C rein muss werden ich mit wohl zwei AVR's zum Testen suchen müssen.

    Also noch viel arbeit mal sehen wie ich das Hardware Problem löse.

    Gruß
    Home
    P: Meine Tochter (06.11.07) und Link
    M: Träumen hat nix mit Dummheit zu tun es ist die Möglichkeit neues zu erdenken

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    05.01.2008
    Beiträge
    22
    .....Leider scheif die Simulation vom studio auch nicht viel mit der realität zu tun zu haben den der Interupt des AD's (messung fertig) kommt nicht. ....

    zum zeitmessen und fehlersuche ist es gut aber nicht für die überprüfung der realität.

    so ist es. 2 atmega und es geht los.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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