-
        

Ergebnis 1 bis 9 von 9

Thema: Einfache ISR mittels GCC (Anfänger)

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    07.07.2011
    Ort
    nähe Bremen
    Alter
    27
    Beiträge
    14

    [Gelöst] Einfache ISR mittels GCC (Anfänger)

    Anzeige

    SMARTPHONES & TABLETS-bis zu 77% RABATT-Kostenlose Lieferung-Aktuell | Cool | Unentbehrlich
    Liebe Roboternetz-Gemeinde,

    früher hatte ich bereits kurz mit den Mikrocontrollern zu tun gehabt (kleines Schulprojekt) und
    bin nun aber auch auf den Geschmack gekommen. Obwohl ich ehrlich gesagt noch nicht so die Ahnung in Sachen
    Elektrotechnik habe, bin ich bereit mich dahinter zu klemmen und voll durchzustarten.

    Ein paar Dinge habe ich auch schon bereits geschafft:

    Mein Steckboard ist seit ein paar Stunden folgendermaßen bestückt:

    -> Stromversorgung via Festspannungsregler
    -> ATmega644P + Ext. 20Mhz Quarz
    -> 4x 5V LED`s an Ports (PORTB 0 - 3)

    Ansteuerung der LED`s funktioniert wunderbar über folgenden Code...

    Code:
    #include <avr/io.h>
    //definiert den CPU Takt
    #define F_CPU 20000000UL
    #include <util/delay.h>
    #include <inttypes.h>
    #include <avr/interrupt.h> 
    
    int main()
    {
    	DDRB 	|= (1<<0) | (1<<1) | (1<<2) | (1<<3);	// LED-Ausgänge Output schalten...
    
    	// Die LED`s werden der Reihe nach ein bzw. ausgeschaltet...
    	while(1){
    
    		PORTB 	|= (1<<0);
    		_delay_ms(500);
    		PORTB 	&= (0<<0);
    		PORTB 	|= (1<<1);
    
    		_delay_ms(500);
    		PORTB 	&= (0<<1);
    		PORTB 	|= (1<<2);
    
    		_delay_ms(500);
    		PORTB 	&= (0<<2);
    	}
    }
    Nun würde ich es ganz gerne schaffen, das ich auf Ereignisse wie bspw. das Drücken von Tastern (PortA0 [INT0]) reagieren kann.
    Diese Routinen sollen natürlich nicht im Hauptprogramm Main als Schleife verewigt werden, sondern "nebenbei" herlaufen.
    Also über eine ISR wenn ich das richtig verstanden habe. Leider habe ich noch nicht wirklich den Bogen raus, wie das ganze funktionieren soll.

    Finde leider keine simplen Beispiele dafür. Und wenn dann nur für Assembler oder Bascom.

    Kann mir wer einen Tipp geben?


    Vielen Dank schonmal im vorraus


    Propeller Clock
    Geändert von Propeller Clock (12.07.2011 um 18:19 Uhr)

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    29
    Beiträge
    4.544
    Willkommen im Forum,
    hier habe ich ein Beispiel von Mikrocontroller.net. Es verwendet zwar einen Timerinterrupt, aber es ist einfach zu verstehen, da es nicht sehr groß ist. Es werden nur die für das Programm nötigen Befehle verwendet. Wie und welche Befehle man verwenden muss steht im Datenblatt des µC. Hier der Link http://www.mikrocontroller.net/artic..._Hauptprogramm .

    PS: Es wird hier nicht gerne gesehen, wenn man nicht sucht. Es ist Eigeninitiative nötig.

    MfG Hannes

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    07.07.2011
    Ort
    nähe Bremen
    Alter
    27
    Beiträge
    14
    Vielen Dank 021aet04!

    Auf Mikrocontroller.net, Roboternetz.de etc. war ich bereits unterwegs und habe mich versucht schlau zu lesen.
    Beim Datenblatt des Atmega644P sind natürlich die einzelnen Register gelistet und es wird auch kurz angesprochen welche Abhängigkeiten diese haben etc.
    Ich Suche allerdings wirklich nach einem Programmierbeispiel für GCC welches mir veranschaulicht wie in die nötige Funktion gesprungen wird und welchen Aufbau diesen haben müssen.

    Selbstverständlich will ich nicht das mir einer eine Lösung schreibt und ich daraufhin "Copy-Paste" betreiben kann. Ich wills ja verstehen.
    Die Timerinterrupt-Lösung wie sie oben verlinkt ist prüft ja auch nur in einer Endlosschleife ob "Flag" gesetzt wurde. Eben genau das möchte ich ja vermeiden.
    Wenn mein Programm später größer wird, soll es nicht erst 400ms dauern bis darauf reagiert werden kann. Ich habe allerdings auch gelesen das man die Schritte nicht selbst
    in der ISR abarbeiten soll.


    MfG Propeller Clock

  4. #4
    Erfahrener Benutzer Roboter Experte Avatar von BurningWave
    Registriert seit
    22.12.2007
    Ort
    nahe Stuttgart
    Alter
    23
    Beiträge
    656
    Tasten werden normalerweise immer in einer Schleife innerhalb des Hauptprogramms (oder einer Unterfunktion) abgefragt. Externe Interrupts sollte man nur verwenden, wenn man sie wirklich braucht (z.B. Not-Aus-Funktion etc.), da man nur 2 zur Verfügung hat.
    Hier ein paar Links:
    http://diyundso.de/?page=4&ref=1
    http://www.mikrocontroller.net/articles/Interrupt
    http://www.mikrocontroller.net/artic...mit_Interrupts
    meine Homepage: http://www.jbtechnologies.de
    Hauptprojekte: Breakanoid 2 - Sound Maker

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    29
    Beiträge
    4.544
    Das Programm ist ein Beispiel. Du musst die einzelnen Register ändern. Diese findest du im DB (Datenblatt). Die verwendeten Register im Beispiel ist "TCCR2" und "TIMSK". Du musst das Programm jetzt ändern.
    Ich verwende dieses DB http://www.atmel.com/dyn/resources/p...ts/doc2593.pdf
    Ab Seite 60 fängt das Kapitel Externe Interrupts an.
    Du musst jetzt die richtigen Register heraussuchen. Z.B. das EICRA, EIMSK
    Wenn du jetzt den INT 0 mit steigender Flanke verwenden willst musst du das in den entsprechenden Registern einstellen.
    Code:
    .........
    EICRA |= (1<<ISC00) | (1<<ISC01);
    EIMSK |= (1<<INT0);
    .....
     sei();
    ......
    while(1)
    {
    .....
    }
    Es gibt aber auch noch andere Interrupts. Z.B. die PCINT (Pin Change Interrupts). Diese reagieren auf einen Flankenwechel (egal ob rising oder falling edge).

    Die ISR musst du natürlich auch ändern. Das wirst du aber schon schaffen. Man sollte zwar nicht zuviele Zeilen in der ISR haben, aber wenn es nur z.B. 5 Zeilen sind mache ich die Auswertung direkt in der ISR. Wenn man mehr machen muss sollte man es so machen, wie im nächsten Beispiel im Link, den ich vorher gepostet habe (UART Beispiel).

    PS: Wenn man mit Interrupt arbeitet muss man die Interrupts freigeben. Eine generelle Freigabe wir mit "sei();" gemacht, man kann es aber auch sperren, das ist wichtig wenn etwas wichtiges auf keinen Fall unterbrochen werden darf. Dieser Befehl lautet "cli();". Etwas das auch wichtig ist ist bei der Deklaration von Variablen das "volatile". Für was das ist gibt es Google.

    MfG Hannes

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    07.07.2011
    Ort
    nähe Bremen
    Alter
    27
    Beiträge
    14
    Okay ich hab nun eigentlich versucht das ganze über PCINT laufen zu lassen, allerdings funktioniert es noch nicht so wie ich`s mir erhofft hatte.

    Code:
    #define F_CPU 20000000UL
     
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
     
    volatile  uint8_t flag;
    
    int main(){
     
     	// #### IO`s etc. konfigurieren....
    	DDRB |= (1<<PB0);				// LED Output schalten...
    	flag = 0;
    
    
    	EICRA |= (1<<ISC00) | (0<<ISC01);		// Modus: "Any edge of INT0 generates asynchronously an interrupt request"
    	EIMSK |= (1<<INT0);				
    	
    
    	PCMSK0 |= (1<<PCINT7);				// PA7 als Interrupt-Pin....
    	PCICR  |= (1<<PCIE0);			        // Das dazugehörige Register...
    
    	// ISR`s freigeben...
    	sei();
     
        while(1){
    		// Endlosschleife...
    		if(flag==1){
    			_delay_ms(3000);
    			PORTB &= (0<<PB0);	// LED AUS...
    			flag=0;
    		}
        }
    
    }
     
    
    ISR( PCINT0_vect ){
    	flag = 1;
    	PORTB |= (1<<PB0);	// LED AN...
    }
    Die LED fängt direkt nach gefühlten 600ms an zu leuchten und schaltet nach 3 Sekunden ab.
    Das mit dem abschalten stimmt ja soweit, aber wieso geht diese einfach von alleine an?

    Hab bis auf den ISP und der LED (PB0) noch nichts weiter angeschlossen.

    Hat wer nen Tipp? Oder sagt Ihr euch, ich sollte morgen lieber nochmal komplett neu ansetzen

    MfG

    Propeller Clock

  7. #7
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Offene Eingänge sind sehr empfindlich und fangen gerade mit den Steckbrett schnell mal Störungen ein. Das mindeste ist es die internen Pullup Widerstände einzuschalten (DDRA auf 0, also Eingänge und PORTA auf 1) . Auch damit kann es noch zu gelegentlichen Störungen kommen.

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    07.07.2011
    Ort
    nähe Bremen
    Alter
    27
    Beiträge
    14
    Gehe ich doch noch heute Abend mit einem kleinem Erfolgserlebnis zu Bett *freu* =)

    Wenn auch einwenig kompliziert geschrieben der Code, aber er funktioniert.

    Der nächste Schritt wird sein, meinen Infrarot-Empfänger auszuwerten. Aber damit mache ich morgen weiter.

    Vielen Dank an euch drei !!!


    Ps.: Auf den Teil mit der Störungsempfindlichkeit ... darauf wäre ich ja nie gekommen.

    Code:
    #define F_CPU 20000000UL
     
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
     
    volatile  uint8_t flag;
    
    int main(){
     
     	// #### IO`s etc. konfigurieren....
    	DDRB |= (1<<PB0);				// LED Output schalten...
    
    	
    	DDRA &= ~( (1<<PA0) | (1<<PA1) | (1<<PA2) | (1<<PA3) | (1<<PA4) | (1<<PA5) | (1<<PA6) | (1<<PA7)  );
    	PORTA |= (1<<PA0) | (1<<PA1) | (1<<PA2) | (1<<PA3) | (1<<PA4) | (1<<PA5) | (1<<PA6) | (1<<PA7);
    
    	flag = 0;
    
    
    	EICRA |= (1<<ISC00) | (0<<ISC01);		// Modus: "Any edge of INT0 generates asynchronously an interrupt request"
    	EIMSK |= (1<<INT0);				
    	
    
    	PCMSK0 |= (1<<PCINT7);					// PA7 als Interrupt-Pin....
    	PCICR  |= (1<<PCIE0);			
    
    	// ISR`s freigeben...
    	sei();
     
        while(1){
    		// Endlosschleife...
    		if(flag==1){
    			_delay_ms(3000);
    			PORTB &= (0<<PB0);	// LED AUS...
    			flag=0;
    		}
        }
    
    }
     
    
    ISR( PCINT0_vect ){
    	flag = 1;
    	PORTB |= (1<<PB0);	// LED AN...
    }

  9. #9
    Erfahrener Benutzer Robotik Einstein Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    29
    Beiträge
    4.544
    Sehr schön, wenn es funktioniert. Wenn du mehrere Pins gleichzeitig konfigurieren willst (wie bei dir DDRA bzw PORTA) kannst du die kürzere Schreibweise mit Hexadezimalzahlen verwenden.


    Wie man das anwendet findet man im Internet.

    MfG Hannes

Ähnliche Themen

  1. CRP5: meine Erweiterung (vom Anfänger für Anfänger)
    Von loewenzahn im Forum Robby CCRP5
    Antworten: 11
    Letzter Beitrag: 21.03.2007, 19:37
  2. LED-Steuerung mittels PIC16F627 (blutiger Anfänger)
    Von rossi_2 im Forum PIC Controller
    Antworten: 7
    Letzter Beitrag: 09.12.2005, 20:34
  3. LCD Ansteurung mittels C
    Von semicolon im Forum C - Programmierung (GCC u.a.)
    Antworten: 5
    Letzter Beitrag: 19.10.2005, 17:58
  4. Antworten: 3
    Letzter Beitrag: 14.08.2005, 14:21
  5. Anfänger: welches modul sollte man als anfänger nehmen???
    Von patti16 im Forum AVR Hardwarethemen
    Antworten: 5
    Letzter Beitrag: 04.01.2005, 09:44

Stichworte

Berechtigungen

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