- Akku Tests und Balkonkraftwerk Speicher         
Seite 5 von 6 ErsteErste ... 3456 LetzteLetzte
Ergebnis 41 bis 50 von 60

Thema: C-Programm mit einfachen Funktionen für AT90S2313

  1. #41
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Anzeige

    LiFePo4 Akku selber bauen - Video
    Zitat Zitat von funky78
    #pragma cd pl (9999)
    #include <reg51.h>
    void to_int(void) interrupt INT_T0...
    Das Zeug ist compilerspezifisch. Jeder Compiler hat seinen eingenen Weg, Interrupts und Signale zu definieren und implementiert unterschiedliche Pragmas -- wenn überhaupt.
    avr-gcc zB implementiert überhaupt keine Pragmas und externen Interrupt0 definiert man via
    Code:
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    
    // keine rekursiven Interrupts 
    SIGNAL (SIG_INTERRUPT0)
    {
    	// ...
    }
    
    // rekursive Interrupts
    INTERRUPT (SIG_INTERRUPT0)
    {
    	// ...
    }
    Eine Möglichkeit, auf Tastendruck/Loslassen zu reagieren, ist über externe Interrupts. Zum Entprellen wartet man danach eine kurze Zeit, bis man wieder auf nen Tastendruck reagiert.
    Oder man schaut in regelmässigen Abständen in einem Timer-Interrupt, ob sich an den Tastern was getan hat.

    Der erste Weg hat den Nachteil, daß man so nur einen Taster checken kann und auch eine Zeitbasis braucht. Zudem landet man bei prellendem Taster oft im Interrupt. Tastendrucke sind keine zeitkritischen Ereignisse, da rechts es wenn man alle 10ms drauf schaut und sich externe Interrupts für wichtige Sachen aufspart.

  2. #42
    Benutzer Stammmitglied
    Registriert seit
    07.07.2005
    Beiträge
    32
    Zitat Zitat von SprinterSB
    Zitat Zitat von funky78
    #pragma cd pl (9999)
    #include <reg51.h>
    void to_int(void) interrupt INT_T0...
    Das Zeug ist compilerspezifisch. Jeder Compiler hat seinen eingenen Weg, Interrupts und Signale zu definieren und implementiert unterschiedliche Pragmas -- wenn überhaupt.
    avr-gcc zB implementiert überhaupt keine Pragmas und externen Interrupt0 definiert man via
    Code:
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    
    // keine rekursiven Interrupts 
    SIGNAL (SIG_INTERRUPT0)
    {
    	// ...
    }
    
    // rekursive Interrupts
    INTERRUPT (SIG_INTERRUPT0)
    {
    	// ...
    }
    Eine Möglichkeit, auf Tastendruck/Loslassen zu reagieren, ist über externe Interrupts. Zum Entprellen wartet man danach eine kurze Zeit, bis man wieder auf nen Tastendruck reagiert.
    Oder man schaut in regelmässigen Abständen in einem Timer-Interrupt, ob sich an den Tastern was getan hat.

    Der erste Weg hat den Nachteil, daß man so nur einen Taster checken kann und auch eine Zeitbasis braucht. Zudem landet man bei prellendem Taster oft im Interrupt. Tastendrucke sind keine zeitkritischen Ereignisse, da rechts es wenn man alle 10ms drauf schaut und sich externe Interrupts für wichtige Sachen aufspart.
    OK...danke...hört sich logisch an...
    Jetzt muss ich schauen, wie ich das realisiere...

  3. #43
    Benutzer Stammmitglied
    Registriert seit
    07.07.2005
    Beiträge
    32


    Angenommen ich bekomme das mit dem Timer hin (was ich auch bezweifle ), muss ich dann in meinem Tasterinterrupt den Timer Interrupt einfügen.
    Des weiteren muss ich doch den Taster abfragen, oder?
    Ich mein ok, abfragen mit...

    a=PIND;
    a=a&0b00001000;

    kann man ja irgendwie...

    aber wie dann der Verweis auf den TasterInterrupt...

    Ich schreibe mal eben, wie ich es "versucht" habe...mit einer quick&dirty Zählschleife...

    Code:
    {
    int a, b, c;
    	a=PIND;
    	a=a&0b00001000;
    	b=a/8;
    
    	for (i=0; i<255; i++)   //Warteschleife
               for(j=0; j<255;j++) 
                   k++;            
    	
    	if (~b)
    	 { 
                 //Wenn b = 0 gehe in Interruptschleife...bitte nicht lachen...
    
    	    SIGNAL(SIG_INTERRUPT1)			// Taster an PD3 löst Interrupt aus
    	 {
    
                        //...Interruptbefehle...
              }

  4. #44
    Benutzer Stammmitglied
    Registriert seit
    07.07.2005
    Beiträge
    32
    Ok, neuer versuch...

    Code:
    SIGNAL(SIG_INTERRUPT1)			// Taster an PD3 löst Interrupt aus
    {
    		for (i=0; i<4000; i++)    // Warteschleife...
               for(j=0; j<20;j++) 
                   k++;            
    		
    						
    	if(status_taster==1)
    	{
    				
    				PORTB |= (1<<PB3);			/*Setzt PB3 HIGH...LED aus	\			*/	
    				PORTB &= ~(1<<PB4); 		//Setzt PB4 LOW...LED an	 } Zustand 1
    				PORTD |= (1<<PD5);			//Setzt PD5 HIGH			/
    	
    				status_taster=2;
    	}
    		
    	else
    	{
    		
    		for (i=0; i<4000; i++)		// Warteschleife...   
               for(j=0; j<20;j++) 
                   k++;            
    					 	   
    				PORTB &= ~(1<<PB3);		/*Setzt PB3 LOW...LED an	\			*/
    				PORTB |= (1<<PB4); 		//Setzt PB4 HIGH...LED aus	 } Zustand 2
    				PORTD &= ~(1<<PD5);		//Setzt PD5 LOW				/
    	
    				status_taster=1;
    	}
    		
    	GIFR=0;
    }
    Kann man das so lassen?
    Es wird zwar ziemlich langsam umgeschaltet, aber zu mindestens tritt das "Überschwingen" nicht so oft auf...erst dann wenn ich den Taster mit dem Finger leicht und schnell antippe...

    Weiterhin sind auch ein 100nF Kondensator und ein 11kOhm Wiederstand an den Taster angelötet...

    Reicht das alles aus?

  5. #45
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Haupsache es geht mal.
    Den C und den R solltest du eigentlich nicht brauchen...

    Zu deinem Code:
    • Falls du GCC optimieren lässt, wird er die Warteschleife komplett in die Tonne kloppen, weil sie nix macht. Also zB ein k = PORTB oder ein _NOP(); (gibts mit #include <avr/ina90.h>)
    • Die 2.Warteschleife ist zu viel, so wartest du 2x.
    • Die Warteschleife besser ans Ende der Interrupt-Routine, vor das GIFR=...
    • Falls während der Routine der Taster flackert, wird ja wieder das INTF1 Flag gesetzt, das du versuchst zurück zu setzen. Das geht, indem man eine 1 hin schreibt (keine 0):
      GIFR = _BV(INTF1); // reset INT1 Flag
    • INT1 so initialisieren, daß er flankengetriggert ist, also nur bei Änderung anspricht; nicht levelgetriggert, sonst landest du auch dauernd im Interrupt solange der Taster noch gedrückt ist.


    Falls dein Prog sonst nix maches soll, ist's ok. Aber wenn sonst noch Zeug zu erledigen ist, muss dir klar sein, daß zu ziemlich lange im Interrupt rumschnarchst...

  6. #46
    Benutzer Stammmitglied
    Registriert seit
    07.07.2005
    Beiträge
    32
    Zitat Zitat von SprinterSB
    Haupsache es geht mal.
    Den C und den R solltest du eigentlich nicht brauchen...

    Zu deinem Code:
    • Falls du GCC optimieren lässt, wird er die Warteschleife komplett in die Tonne kloppen, weil sie nix macht. Also zB ein k = PORTB oder ein _NOP(); (gibts mit #include <avr/ina90.h>)
    • Die 2.Warteschleife ist zu viel, so wartest du 2x.
    • Die Warteschleife besser ans Ende der Interrupt-Routine, vor das GIFR=...
    • Falls während der Routine der Taster flackert, wird ja wieder das INTF1 Flag gesetzt, das du versuchst zurück zu setzen. Das geht, indem man eine 1 hin schreibt (keine 0):
      GIFR = _BV(INTF1); // reset INT1 Flag
    • INT1 so initialisieren, daß er flankengetriggert ist, also nur bei Änderung anspricht; nicht levelgetriggert, sonst landest du auch dauernd im Interrupt solange der Taster noch gedrückt ist.


    Falls dein Prog sonst nix maches soll, ist's ok. Aber wenn sonst noch Zeug zu erledigen ist, muss dir klar sein, daß zu ziemlich lange im Interrupt rumschnarchst...
    Hallo und schönen guten Abend...
    Vielen Dank für diese Tipps...
    Die Sache mit der prellenden Taste habe ich dann doch hardwaremäßig gelöst.
    Ich habe den 100nF gegen einen 1uF Tantal Kondensator ausgetauscht. Der Widerstand ist bei 10kOhm geblieben. Erreiche hiermit eine Zeit von ca. 11ms wodurch das Problem mit dem prellenden Taster aus der Welt geschaffen ist.
    Sicherlich ist es angenehmer die Sache softwaremäßig zu lösen, doch für einen Neuling wird es schwierig, auch noch den Timer zu implementieren.

    Ach ja, INT1 ist auf fallende Flanke initialisiert.

    So langsam habe ich den gesamten Code, dank eurer Hilfe zusammen...

    Heute Abend bin ich noch an den Kommentaren usw. dran...

    Im großen Ganzen verstehe ich auch das, was ich geschrieben habe. Doch es gibt bestimmte Stellen, wo ich nicht ganz schlüssig werde.

    Würde mich freuen, wenn ich noch einige Verständnisfragen stellen dürfte (falls notwendig )

    Hier schon die erste...

    GIFR = _BV(INTF1);
    was bedeutet hier das _BV?

    Nochmals aber vielen Dank für die tolle Unterstützung... =D>

  7. #47
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    28.04.2004
    Ort
    Nähe Köln
    Alter
    58
    Beiträge
    247
    Hallo

    _BV steht für Bit Value. Es wird das Bit INF1 gesetzt.

    Ist das gleiche wie GIFR = ( 1<< INF1)

    Schaui mal in der Doku de AVR LIBC unter Related Pages / FAQ

    Gruß
    Dieter

  8. #48
    Benutzer Stammmitglied
    Registriert seit
    07.07.2005
    Beiträge
    32
    Guten Morgen...
    _BV...BitValue...wusste ich doch, dass ich das mal irgendwo gelesen hatte...vielen Dank Dieter...


    Ok, ein neuer Tag, und ich denke ich stehe heute total auf dem Schlauch.

    Irgendwie schaffe ich es nicht mehr, meinem Compiler beizubringen, dass er PD7 bzw. PIND7 erkennt. Er meckert, dass es "undeclared" ist


    Code:
    #include <avr/io.h> 
    #include <inttypes.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    
    
    DDRD  = 0b11110110; //Alles außer PD0 und PD3 als Ausgang
    PORTD = 0b01111111;
    
    /*Nun möchte ich PD7 abfragen, schauen ob er beim Einschalten HIGH oder LOW gesetzt wurde und dementsprechen was auf dem Bildschirm ausgeben (was ich ja mitlerweile mit eurer Hilfe kann :-)...*/
    ...
    if (PD7) //akzeptiert er so nicht...
    PORTB = 0b11110111;
    
    else 
    PORTB = 0b11101111;
    ...
    statt dem PD7 habe ich auch

    PORTD&0b10000000
    bzw.
    PIND7

    probiert...hilft alles nichts...

  9. #49
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    AT90S2313 hat keinen PortD.7
    Oder verwendest du inzwischen nen anderen Controller?
    In dem Falle must du avr-gcc mit der korrekten -mmcu=... aufrufen, sonst generierst du falschen Code.

  10. #50
    Benutzer Stammmitglied
    Registriert seit
    07.07.2005
    Beiträge
    32
    Zitat Zitat von SprinterSB
    AT90S2313 hat keinen PortD.7
    Oder verwendest du inzwischen nen anderen Controller?
    In dem Falle must du avr-gcc mit der korrekten -mmcu=... aufrufen, sonst generierst du falschen Code.
    Mensch bin ich doof...

    Ok, dann probier ich das ganze mal mit PD5.

    Code:
    int main( void ) 
    { 
    	DDRB  = 0b11111111;            
    	PORTB = 0b11111111;
    	
    	DDRD  = 0b00100000;
    	PORTD = 0b11011111;
    
       for(;;)
       {
    	
    	if (PD5)
    	PORTB = 0b11110111;
     	
    	else
    	PORTB = 0b11101111;
       }
    
    }
    wenn ich
    PORTD = 0b11111111;
    sollte er in die if-Schleife rein und LED an PB3 müsste brennen. Tut sie auch.

    wenn ich dann
    PORTD = 0b11011111;
    schreibe, müsste er doch in die else-Schleife und LED ab PB4 müsste brennen...tut sie aber nicht...PB3 brennt immer.

    mit dem Oszi an PD5 gemessen kommt das Signal so, wie es kommen soll. Also mal High, mal Low...

    Was mache ich falsch?
    [-o<

Seite 5 von 6 ErsteErste ... 3456 LetzteLetzte

Berechtigungen

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

Labornetzteil AliExpress