-
        

Ergebnis 1 bis 8 von 8

Thema: ATmega32: IRQ-Programmierung

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    22.02.2007
    Ort
    Köln
    Alter
    42
    Beiträge
    88

    ATmega32: IRQ-Programmierung

    Anzeige

    Hallo Profies,

    kann mir jemand einen guten Einstieg in die IRQ-Programmierung von ATmega32-uCn geben? Ich steige bei der Atmel-Dokumentation nicht so recht durch.

    Wie ich vorgehen möchte:
    1. Einen Timer konfigurieren, als IRQ-Quelle definieren und starten.

    2. Eine InterruptServiceRoutine definieren und verwenden können.

    Danke und Gruß,
    Lev

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    10.08.2004
    Ort
    Großbardorf
    Alter
    30
    Beiträge
    674
    Schau mal hier oder auf www.mikrocontroller.net im wiki. Da findest du auf jeden Fall was dazu.

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    12.01.2007
    Beiträge
    93
    also was du machen solltest ist die interrupts mal einschalten. sprich den globalen interrupbt mit sei() und dann noch den spezifischen zb den overflow-interrupt vom timer.

    und dann einfach die interrupt-routine in deinen quelltext mit rein hängen.

    sprich
    ISR(interrupt_vektor)
    {
    interrupt-routine
    }

    die interrupt-namen sind in den headerdatein von AVR definiert, z.b. beim atmega8 die iom8.h da steht zb für timer-overflow SIG_OVERFLOW0...

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    22.02.2007
    Ort
    Köln
    Alter
    42
    Beiträge
    88
    Wau, Ihr seid ja schnell dabei.
    Vielen Dank für die Hinweise. Eine Frage noch: Muß die IRQ-Routine ISR heißen, oder kann die jeden anderen Namen tragen? Wo finde ich da mehr zu?

    [Edit:] Ich möchte wissen, wie man das in C macht.


    Danke und Gruß,
    Lev

  5. #5
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    15.01.2006
    Ort
    Biberach
    Alter
    27
    Beiträge
    485
    Hi,
    Pascal hat dir nen Link gegeben wo es schön beschrieben wird:
    www.microcontroller.net
    Such da in der linken Spalte nach AVR-GCC TUtorial

    MfG

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    12.01.2007
    Beiträge
    93
    Zitat Zitat von Leverator
    Wau, Ihr seid ja schnell dabei.
    Vielen Dank für die Hinweise. Eine Frage noch: Muß die IRQ-Routine ISR heißen, oder kann die jeden anderen Namen tragen? Wo finde ich da mehr zu?

    [Edit:] Ich möchte wissen, wie man das in C macht.


    Danke und Gruß,
    Lev
    ja, ISR(vektor) ist hier sozusagen sowas wie der funktionsname und vektor ist der parameter welcher interrupt gemeint ist. aber durch substitution kannst es auch in günther umbenennen :P das ist dann dir überlassen.

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    22.02.2007
    Ort
    Köln
    Alter
    42
    Beiträge
    88
    Ja hallo,

    vielen Dank für die interessanten Tipps.
    Damit wir hier nicht so virtuell in den Äther diskutieren, hier mal etwas Code an dem ich gerade arbeite.


    Code:
    #ifndef _stepMotorClass_
    #define _stepMotorClass_
    
    #include <util/delay.h>
    #include <avr/io.h>
    
    class ClStepMotor {
    	private:
    		uint8_t stepNo;
    		int8_t direction;	// +1 / -1
    		uint16_t wait;
    
    	public:
    		ClStepMotor();
    		void setMotorStep(void);
    		void setWait(uint16_t*);
    		void setDirection(int8_t*);
    		void setMotorOff(void);
    		
    };
    
    
    #endif // stepMotorClass
    Und hier die ClStepMotor.cpp:

    Code:
    #include <util/delay.h>
    #include <avr/io.h>
    
    #include "ClStepMotor.h"
    
    
    ClStepMotor::ClStepMotor() {
    	// Den Schrittmotortreiber aktivieren. => Port D Bit 4 & 5 auf eins schalten
    	DDRD	|= (1<<PD4 | 1<<PD5);	// Die Bits 4 und 5 auf Ausgang setzen.
    	PORTD	|= (1<<PD4 | 1<<PD5);	// Die beiden Bits auf 1 setzen: High-Ausgang
    
    	// Die Steuerleitungen fuer den Schrittmotortreiber aktivieren => Port B Bit 0 und 1, Port C Bit 6 und 7
    	DDRB	|= (1<<PB0 | 1<<PB1);	// Port B aktivieren
    	DDRC	|= (1<<PC6 | 1<<PC7);	// Port C aktivieren
    
    	wait = 80;
    	stepNo = 0;
    	direction = 1;
    }
    
    
    void ClStepMotor::setWait(uint16_t *w) {
    	wait = *w;
    }
    
    void ClStepMotor::setDirection( int8_t *d ) {
    	direction = *d;
    }
    
    
    void ClStepMotor::setMotorStep(void) {
    	uint8_t valPrtB = 0;
    	uint8_t valPrtC = 0;
    	uint16_t w = wait;
    
    	stepNo += direction;
    
    	if( stepNo > 7 ) {     // auch 2'er-Komplementzahlen (negative) sind usigned größer als 7 :)
    		if ( direction > 0 )
    			stepNo = 0;
    
    		if ( direction < 0 )
    			stepNo = 7;
    	} 
    
    	switch( stepNo ) {
    
    		case 0:		valPrtB = 1<<PB0;	// 10-10
    				valPrtC = 1<<PC6;
    				break;
    
    		case 1:		valPrtB = 1<<PB0;	// 10-00
    				valPrtC = 0<<PC6;
    				break;
    
    		case 2:		valPrtB = 1<<PB0;	// 10-01
    				valPrtC = 1<<PC7;
    				break;
    
    		case 3: 	valPrtB = 0<<PB0;	// 00-01
    				valPrtC = 1<<PC7;
    				break;
    
    		case 4: 	valPrtB = 1<<PB1;	// 01-01
    				valPrtC = 1<<PC7;	
    				break;
    	
    		case 5:		valPrtB = 1<<PB1;	// 01-00
    				valPrtC = 0<<PC7;
    				break;
    
    		case 6:		valPrtB = 1<<PB1;	// 01-10
    				valPrtC = 1<<PC6;
    				break;
    
    		case 7:		valPrtB = 0<<PB1;	// 00-10
    				valPrtC = 1<<PC6;
    				break;
    
    		default:	stepNo = 0;
    				break;
    	}
    
    	PORTB = (PORTB & !(1<<PB0 | 1<<PB1) ) | valPrtB;	// Clear out old values and then set the new ones.
    	PORTC = (PORTC & !(1<<PC6 | 1<<PC7) ) | valPrtC;
    
    	while ( w-- )
    		_delay_us(1);
    }
    
    void ClStepMotor::setMotorOff(void) {
    	PORTB = (PORTB & !(1<<PB0 | 1<<PB1) );	// Clear out old values.
    	PORTC = (PORTC & !(1<<PC6 | 1<<PC7) );
    }
    Wie Ihr sehen könnt, programmiere ich gerne in C++. Das bringt mir die Vorteile, daß ich einmal geschriebenen Code wirklich einfach wiederverwenden kann. Aber in diesem Fall wird in der Prozedur motorStep() eine delay-Routine aufgerufen. Das ist natürlich nicht gut, und diese möchte ich gerne gegen die ISR ersetzen.

    Ansonten: Was haltet Ihr von meinem Code?


    Gruß,
    Lev

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    22.02.2007
    Ort
    Köln
    Alter
    42
    Beiträge
    88

    L293: Niemals zu schnell takten!

    Moin zusammen,

    ich habe die IRQ-Routine nun eingebaut.

    Dazu musste ich meine Klasse global definieren und konnte sie dann einfach auch in der ISR verwenden.

    Bei jedem Interrupt wird nun der Schrittmotor um einen Schritt weiter gedreht (Halb-Schritt).

    Das hat auch alles wunderbar funktioniert, bis ich auf die Idee kam, den Vorteiler statt auf 1024 auf 1 zu stellen. Daraufhin konnte mein Schrittmotortreiber (L293) den Impulsen nicht mehr recht folgen und fing zu qualmen an.

    Tolle Sache das.

    Auf jeden Fall Danke an Euch für Eure guten Tipps bisher.

    Gruß,
    Lev

Berechtigungen

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