- SF800 Solar Speicher Tutorial         
Ergebnis 1 bis 10 von 59

Thema: Interrupt-Abfrage >>> Routine vereinfachen

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    148
    Du hast natürlich Recht - in diesem Fall kann nichts passieren - man/ich sollte aber "Narrensicher" entwickeln, könnte ja mal in andere Hände gelangen.
    Mittlerweile halte ich die Lösung mit der Ein/Ausgangs-Umschaltung für praxisfern.

    Vielleicht ist eine andere Variante mit dem "Stummschalten" durch volatile-Variablen sinnvoll.
    Bsp:
    Im main(), sequneziell PA4 und/oder PA5; Variable "PA4freischalt=1;", "PA5freischalt=1;"
    Innerhalb des ISR (Timer) oder dessen Funktionsaufruf; if (PA4freischalt == 1) {} // Eingangsimpuls wird weiter verarbeitet
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |

  2. #2
    Erfahrener Benutzer Robotik Visionär Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    37
    Beiträge
    5.093
    Das ist die Variante die ich gemeint habe. Ich würde aber eine Bytevariable nehmen und einzelne Bits einem Eingang zuordnen. Bei dir ist es "Resourcenverschwendung" weil du für jeden Eingang eine Bytevariable verwendest.

    Also z.B. eine Hilfsvariable "char hilfsvariable" => Bit 0 = Freigabe PA4, Bit 1 = Freigabe PA5
    Der Code sieht dann so aus
    Code:
    if ((PINA & (1<<PA4)) && (hilfsvariable & (1<<0))){...}
    Das gleiche gilt auch für PA5. Die Schleife wird nur ausgeführt wenn PA4 == 1 und hilfsvariable == 1.

    MfG Hannes

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    148
    Verstehe, das Prinzip ist ok, aber zu viel Speicherplatz verschwendet wenn zB. 10 Eingänge ins Spiel kommen. Hier ist mir (als Anfänger) die transparenz und einfacherere Lesbarkeit wichtig!
    Ich hatte nur bedenken wegen der Übersicht bei mehreren volatile-Variablen. Sehe hier aber keinen Ausweg.

    - - - Aktualisiert - - -

    Ist es eigentlich normal, dass bei Timer-ISR mehrere volatile-Variable eingesetzt werden?
    Folgend schon wieder eine, nur um einen Intervall-Zähler zu erhalten;
    Code:
    volatile uint8_t EingIntervall=0;									
    																			
    ISR(TIM1_COMPA_vect)
    {
    	OverflowZaehler++;
    	EingIntervall++;
    
    	if(OverflowZaehler >= 60000)		// 1ms*60 000 = 1Min
    	{
    		OverflowZaehlerReset();
    	}
    
    	if (EingIntervall==10)			// alle 10[ms] werden die Eingangskontakte abgefragt
    	{
    		RegA_KontaktAbfrage();  // Eingänge auf Veränderung analysiert
    		EingIntervall=0;
    	}
    }
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    37
    Beiträge
    5.093
    Meiner Meinung nach ist es nicht besser lesbar. Wie man die Hilfsvariable nennt ist egal, mann kann sie z.B. auch "FreigabeEingaenge" oder sonst wie nennen.
    Ob man 1 Variable benötigt, oder 3 wird egal sein. Wenn man aber mehrere hat und so arbeitet bekommt man irgendwann ein Speicherproblem (z.B. wenn man Eingänge eines ganzen Ports steuern will). Deswegen sollte man sorgsam mit den Resourcen umgehen.

    Man kann auch mit #define arbeiten.
    z.B.
    Code:
    #define  PA4_ein  hilfsvariable |= (1<<0)
    #define  PA4_aus hilfsvariable &= ~(1<<0)
    #define  PA4_freigabe  hilfsvariable & (1<<0)
    Wenn du es nutzen willst schreibst du:

    Code:
    PA4_ein; // PA4 freigeben
    PA4_aus; // PA4 sperren
    
    if ((PINA & (1<<PA4)) && PA4_freigabe) {...}  // Abfrage auf PA4 und Freigabe PA4

    Bei der ISR kann man es so machen wie du und mehrere Variablen nehmen, oder du konfigurierst die ISR so das du alle 10ms einen Interrupt bekommst (geht nicht immer).
    Wenn man z.B. alle 10ms einen Int haben will muss man den Timer so anpassen das du, wenn du den Timer von 0-Max laufen lässt, über die 10ms kommst (Prescaler anpassen). Anschließend musst du einen "Startwert" für den Timer ausrechnen. Den musst du in der ISR jedes mal neu übergeben. Also wenn du z.B. bei einem 8bit Timer jede ISR den Wert 250 in das TCNT Register schreibst zählt er von 250 bis 255 und löst dann wieder einen Int aus.

    MfG Hannes

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    148
    Zitat Zitat von 021aet04 Beitrag anzeigen
    Bei der ISR kann man es so machen wie du und mehrere Variablen nehmen, oder du konfigurierst die ISR so das du alle 10ms einen Interrupt bekommst (geht nicht immer).
    Dieser Timer ist als Generaltaktgeber (1ms) für das gesamte Prog konfiguriert.
    Da hängen später auch Zeitstufen/Countdownzähler etc drann.

    Die Idee mit #define finde ich gut!
    Auch die LED-Steuerungen, LEDgn_ein() etc. könnte ich direkt mit #define bestimmen.
    Wo siehst du die Grenze zw. Funktion() und #define ?

    Code:
    #define LEDgn_ein PORTB |= (1<<PB0)
    #define LEDgn_aus PORTB &= ~(1<<PB0)
    
    // statt
    
    void LEDgn_ein(void)	 // LED einschalten
    {
    	PORTB |= (1<<PB0);
    }
    
    void LEDgn_aus(void)	// LED ausschalten
    {
    	PORTB &= ~(1<<PB0);
    }
    Geändert von frabe (15.08.2019 um 14:01 Uhr)
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |

  6. #6
    Erfahrener Benutzer Robotik Visionär Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    37
    Beiträge
    5.093
    Wenn du eine 1ms ISR benötigst geht es nicht anders als du es machst.

    Es hat jeder seinen eigenen Programmierstil. Wichtig ist nur das es lesbar bleibt. Du musst denken das du z.B. in einem Jahr das Programm anschaust und du bzw jemand anderes ohne "Studium" deinen Code ohne Probleme lesen können musst. Deswegen solltest du Variablen, Defines, Funktionen,... so benennen das es logisch ist und du nicht erst suchen muss was das gerade macht.

    Defines kannst du immer nehmen wenn du nur eine "Aktion" hast, wie z.B. einen Ausgang setzen. Wenn du mehrere Dinge machen musst und diese öfters ausführst, solltest du Funktionen verwenden.

    Wichtig wird es aber wenn du eigene Bibliotheken erstellst. Dann hast du eine Headerdatei (*.h) und eine dazugehörende Codedatei (*.c). In die Headerdatei kommen die ganzen Defines und Funktionsprototypen und in die Codedatei kommen die eigentlichen Funktionen.

    MfG Hannes

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    148
    Hallo Leute.
    Habe an meinem Code weiter gearbeitet, hänge aber gerade an Tasten-/Kontaktentprellung fest.

    Bis auf folgende Anweisung mit "i"-Schleife, funktioniert alle einwandfrei - dank Eurer anregungen!
    "i" in RegA_Abfrage() sollte die 10ms-Schleifen hoch zählen. Sind 30ms (Entprellzeit) keine Veränderung vorgekommen, werden die veränderten Eingänge ausgewertet und verarbeitet.

    Irgendwo scheint sich hier ein Logikfehler zu verstecken, da RegA_Auswertung() nicht mehr angesprochen wird.

    Code:
    ISR(TIM1_COMPA_vect)
    {
    	OverflowZaehler++;
    	EingIntervall++;
    	
    	if(OverflowZaehler >= 60000)				// 1ms*60 000 = 1Min // uint16_t 0…65.535
    	{
    		OverflowZaehlerReset();
    	}
    	if (EingIntervall==10)					// alle 10[ms] werden die Eingangskontakte abgefragt
    	{
    		RegA_Abfrage();					// Eingänge auf Veränderung analysiert
    		EingIntervall=0;
    	}
    }
    
    void RegA_Abfrage(void)
    {	
    	uint8_t RegA_neu;
    	uint8_t RegA_dif;
    	uint8_t i;
    
    	RegA_neu = PINA;						// PINA-Regist. wird ausgelesen
    	if(((RegA_dif = RegA_akt ^ RegA_neu) !=0) && i>=3) // Änderungen gegenüber Vor-Interrupt=1 UND >=30ms
    	{
    		RegA_Auswertung(RegA_dif, RegA_neu);		// Pins einzeld auswerten
    		i=0;
    	}
    	i++;
    	RegA_akt = RegA_neu;						// akt. PINA in Vor-Interrupt speichern, für den nächsten ISR
    }
    
    void RegA_Auswertung (uint8_t RegA_dif, uint8_t RegA_neu)  // Pins einzeld auswerten
    {
    	uint8_t RegA_high;
    	uint8_t RegA_low;
    	uint8_t Zuweisung=0;
    	
    	RegA_high = RegA_dif & RegA_neu;		// Pins von 0 auf 1 = 1
    	RegA_low = RegA_dif & ~RegA_neu;	// Pins von 1 auf 0 = 1
    
    	if(((RegA_high & (1<<PINA4)) != 0) && (PA4frei==1))	Zuweisung=41;		// PA4 wurde high
    	if(((RegA_low & (1<<PINA4)) != 0) && (PA4frei==1))	Zuweisung=40;		// PA4 wurde low		
    	if(((RegA_high & (1<<PINA5)) != 0) && (PA5frei==1))	Zuweisung=51;		// PA5 wurde high
    	if(((RegA_low & (1<<PINA5)) != 0) && (PA5frei==1))	Zuweisung=50;		// PA5 wurde low
    
    	switch(Zuweisung)
    	{
    		case 41:	LEDrt_ein;	Zuweisung=0;	break;	// PA4 high
    		case 40:	LEDrt_aus;	Zuweisung=0;	break;	// PA4 low
    		case 51:	SUM_ein;	Zuweisung=0;	break;	// PA5 high
    		case 50:	SUM_aus;	Zuweisung=0;	break;	// PA5 low
    	}
    }
    Bemerkung:
    - OverflowZaehler ist static und wird mit 1ms, über Timer-Interrupt getaktet/hoch gezählt.
    - PA4frei, PA5frei static-Var., kommen aus dem main und schalten die jeweiligen Pin ein/aus.
    - RegA_akt, RegA_neu, EingIntervall sind static-Var.

    - - - Aktualisiert - - -

    Fehler gefunden!
    "i" muss eine static-Variable sein!
    Klappt jetzt prime - was haltet ihr von der Struktur?
    Geändert von frabe (20.08.2019 um 14:28 Uhr)
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |

Ähnliche Themen

  1. [ERLEDIGT] Interrupt Routine
    Von Saturas077 im Forum Assembler-Programmierung
    Antworten: 8
    Letzter Beitrag: 23.04.2014, 12:46
  2. Codebeispiel für Lesen von RC5 Code mit Interrupt-Routine
    Von -tomas- im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 19
    Letzter Beitrag: 25.05.2011, 12:54
  3. Interrupt Routine
    Von luvat im Forum Schaltungen und Boards der Projektseite Mikrocontroller-Elektronik.de
    Antworten: 4
    Letzter Beitrag: 16.03.2008, 20:54
  4. Interrupt in ISR-Routine freigeben
    Von dj5am im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 5
    Letzter Beitrag: 10.08.2007, 08:44
  5. uart interrupt routine
    Von Computerkora im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 25.11.2006, 13:45

Berechtigungen

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

Solar Speicher und Akkus Tests