- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 13

Thema: Tastenabfrage (Kur/Lang gedrückt)

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    24.08.2009
    Beiträge
    30

    Tastenabfrage (Kur/Lang gedrückt)

    Anzeige

    Powerstation Test
    Hallo Leute,

    ich habe miraus der Wiki dieses Beispiel herausgesucht und versucht in meinen Aufbau zu integrieren: Taster-Abfrage in C

    Nur leider tut das ganze nicht so wie es soll.
    Mein Beispiel sieht folgendermaßen aus:

    Code:
    //----------------------------------------
    // Titel	: Arcade Tastenprogrammierung
    //----------------------------------------
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/pgmspace.h>
    #include <avr/eeprom.h>
    #include "taster.h"
    
    typedef unsigned char BYTE;
    typedef unsigned int WORD;
    
    BYTE bPortB;
    BYTE nKeyPress;
    uint8_t eeFooByte;
    
    volatile uint8_t gKeyCounter;
    volatile signed char taster = NO_TASTER;
    taste_t tasten[NUM_TASTER];
    
    const unsigned char Tabelle[] PROGMEM = {249, 164, 176, 153, 146, 130, 248, 128, 144};
    
    SIGNAL (SIG_OVERFLOW0)
    {
        static unsigned char count_ovl0;
        unsigned char ovl0 = count_ovl0+1;
    
        if (ovl0 >= 39)
        {
            get_taster (1, PINB & (1<<PB4));
            ovl0 = 0;
        }
        count_ovl0 = ovl0;
    }
    
    void ioinit()
    {
        PORTB |= 1 << PB4;
    	DDRD = 0xFF;
        TCCR0 = 1 << CS00;
        TIMSK |= (1 << TOIE0);
    }
    
    int main (void)
    {
        ioinit();
    	
    	bPortB = 1;
    	nKeyPress = 0;
    	// nKeyPress = eeprom_read_byte(&eeFooByte);
    	gKeyCounter = 0;
    
        tasten[0].mode = TM_SHORT;
        tasten[1].mode = TM_LONG;
        tasten[2].mode = TM_REPEAT;
    
        while(1)
    	{
            signed char tast = taster;
    		PORTD = pgm_read_byte(&Tabelle[nKeyPress]);
    
     		switch (tast)
            {
                default:
                case NO_TASTER:
                    break;
        
                case 1:
    	if (nKeyPress < 8)
    				{
    					nKeyPress++;
    				}
    				else
    				{
    					nKeyPress = 0;
    				}
                    break;
        
                case 1+TASTER_LONG:
                    eeprom_write_byte(&eeFooByte, nKeyPress);
                    break;
            }
            if (tast != NO_TASTER)
                taster = NO_TASTER;
    	}
    	return 0;
    }
    void get_taster (const unsigned char num, unsigned char tast) 
    {
        const taste_t * const ptast = & tasten[num];
        const unsigned char taster_old = ptast->old;
        unsigned char pressed, press, release, mode, delay;
    
    #if TASTER_LEVEL
        tast = !!tast;
    #else
        tast = !tast;
    #endif
    
        /* Taster bleibt gedrueckt */
        pressed =  taster_old &  tast;
        /* Taster neu gedrueckt */
        press   = ~taster_old &  tast;
        /* Taster losgelassen */
        release =  taster_old & ~tast;
    
        *((unsigned char *) & ptast->old) = tast;
     
        tast = NO_TASTER;
     
        mode  = ptast->mode;
        delay = ptast->delay;
     
        if (press)
        {
            if (mode != TM_LONG)
                tast = num;
       
            delay = 0;
        }
        else if (pressed)
        {
            if (delay < 0xfe)
                delay++;
        }
        else if (release)
        {
            if (mode == TM_LONG && delay != 0xff)
                tast = num;
        }
     
        if (mode == TM_LONG)
        {
            if (delay == TASTER_DELAY_LONG)
            {
                tast = TASTER_LONG + num;
                delay = 0xff;
            }
        }
        else if (mode == TM_REPEAT)
        {
            if (delay == TASTER_REPEAT_DELAY)
            {
                tast = num;
                delay = TASTER_REPEAT_DELAY - TASTER_REPEAT;
            }
        }
    
        if (taster == NO_TASTER)
            taster = tast;
      
        *((unsigned char *) & ptast->delay) = delay;
    }
    Bei einem Tastendruck passiert leider nichts.
    Hat jemand eine Idee wo da der Hund begraben sein könnte?

  2. #2
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Hat jemand eine Idee wo da der Hund begraben sein könnte?
    Ich sehe keinerlei "sei()".
    MfG
    Stefan

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    24.08.2009
    Beiträge
    30
    Zitat Zitat von sternst
    Ich sehe keinerlei "sei()".
    Du hast recht!
    Habs ergänzt.

    Leider wars das jedoch noch nicht.

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    24.08.2009
    Beiträge
    30
    Hat vielleicht jemand ein einfacheres Beispiel für mich?
    Im Grunde möchte ich nur abfragen ob der Taster kurz oder lan(ca. 2 Sek) gedrückt wurde.
    Und je nachdem entweder eine Variable um 1 hochzählen oder den aktuellen Wert im EEPROM speichern.

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    31
    Beiträge
    1.578
    Hallo DerSchatten,

    da ich kein C beherrsche, werde ich mal versuchen, dir ein einfaches Beispiel (also die Funktionsweise) zu erklären:
    Wenn der Taster gedrückt worden ist, geht das Programm in eine kleine Schleife, in welcher 1ms lang gewartet wird und dann wird eine Variable erhöht. Wenn der Taster wieder losgelassen wurde, verlässt der µC die Schleife. Nun wird die Variable abgefragt, ob sie größer als 2000 (also 2000ms entspricht 2s) ist. Anschließend soll der µC darauf reagieren und die Variable muss wieder auf 0 gesetzt werden. Allerdings ist das ganze nicht gerade "schnell", da der µC ziemlich lange in der Schleife feststecken kann. Außerdem musst du aufpassen, dass die Variable nicht überläuft.
    Hier mal ein Pseudocode:
    Code:
    wenn taster1 = gedrückt dann
     solange taster1 gedrückt
     1ms warten
     variable xy um 1 erhöhen
     wenn nicht mehr gedrückt, schleife verlassen
     wenn variable xy >= 2000 
      taster = mindestens 2s lang gedrückt
     allenfalls
      taster = maximal 2s lang gedrückt
     ende wenn
     varaible xy = 0
    ende wenn
    Hier mal das ganze in BASCOM, ist meiner Meinung nach leicht verständlich:
    Code:
    if t1 = 0 then
    while t1 = 0
    waitms 1
    xy = xy + 1
    wend
    if xy >= 2000
    taster = 2
    else
    taster = 1
    endif
    xy = 0
    endif
    Ich hoffe, ich konnte dir helfen.
    Wenn du das ganze allerdings schneller programmieren möchtest, solltest du einen timer so einstellen, dass er jede millisekunde (am besten) überläuft und dann das ganze in die ISR packen.

    Gruß
    Chris

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    30.12.2008
    Beiträge
    1.427
    eine aufbau möglich keit wäre
    do
    wenn taster=gedrückt dann gedrückt dauer+1
    wenn nicht dann wenn gedrück dauer >10 dann variable+1
    wenn gedrückt dauer>20 dann in eepromspeichern
    dedrückt dauer=0
    warte 100ms
    müsste so gehen

    loop

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    24.08.2009
    Beiträge
    30
    Hm, wo ist der Fehler?

    Code:
    while(1)
    	{
    		PORTD = pgm_read_byte(&Tabelle[nKeyPress]);
    		if (bit_is_clear (PINB, PINB0))
    		{
    			if (bPortB) // wenn Taster gedrückt
    			{
    				dauer++;
            	}
    			else // wenn nicht gedrückt
    			{
    				if 	(dauer > 10)
    				{
    					if (nKeyPress < 8)
    					{
    						nKeyPress++;
    						bPortB = 0;
    					}
    					else
    					{
    						nKeyPress = 0;
    						bPortB = 0;
    					}
    				}
    				if 	(dauer > 20) // wenn länger gedrückt
    				{
    					eeprom_write_byte(&eeFooByte, nKeyPress);
    					dauer = 0;
    					Warte (100);
    				}
    			}
        	}
        	else
    		{
            	bPortB = 1;
        	}
    	}
    	return 0;

  8. #8
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.652
    Zitat Zitat von DerSchatten
    Hm, wo ist der Fehler? ...
    Mit meinen bescheidenen Kenntnissen in C tue ich mir immer schwer, daher auch meine Unfähigkeit (und Abneigung), Codebruchstücke auf Fehler zu durchleuchten. Vor allem bei minimalistischen Kommentaranteilen.

    Bei mir gibt es Tasten, die beim Drücken den zugehörigen Eingang - mit internem PullUp - einfach auf GND legen. Ich habe mir für die Tastenverwaltung eine Timerroutine geschrieben, die mit 100 Hz eine ISR aufruft. Darin wird u.a. dies gemacht:
    Code:
    // Globale Deklarationen und so:
    
     #define rLED    3              // Rote LED       auf PB3
     #define TAU     1              // Taster "Aufwärts", PB1
     #define TAB     2              // Taster "Abwärts",  PB2 = "Start"Taste
    
      volatile uint8_t TABsts;      // Status derTaste TAB
                                    //   = 0 <=> nicht gedrückt, =1 <=> gedrückt
      volatile uint8_t TAUsts;      // Status derTaste TAU, wie oben
      volatile uint8_t TABcnt;      // Counter für Taste TAB
      volatile uint8_t nTABcnt;     // Counter für Taste notTAB
      volatile uint8_t TAUcnt;      // Counter für Taste TAU, wie oben
      volatile uint8_t nTAUcnt;     // Counter für Taste notTAU, wie oben
                                    //
    // ================================================================================
    // ===  Nicht unterbrechbare ISR für timer1 =======================================
    // Interrupt mit ca. 100 Hz/10 ms. Diese ISR wird benutzt
    //   A  zum Auslesen der Tasten
    //      Nach Ende der Routine sind die Tastenstati in den Statusbytes
    // ...
    //
     ISR(TIM1_COMPA_vect)           // Vektor 4 (1 ... 4 !!!)                 doc S  50
     {                                
     ...
    // - -  Zuerst für TAB   - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     TABsts = (!(PINB & (1<<TAB))); // Status von Taste TAB holen
                                      
     if (TABsts)                    // Taste TAB gedrückt?
     {                                
       if (TABcnt < 254)            // Wenn counter < 250
       {                              
         TABcnt     ++;             //   dann hochtackern
         nTABcnt    = 0;            //   und Nicht-TABcount auf Null setzen
       }                              
     }                                
     else                           // Taste TAB ist nicht gedrückt
     {                                
       if (nTABcnt < 254)           // Wenn Not-counter < 250
       {                              
         nTABcnt    ++;             //   dann hochtackern
         TABcnt     = 0;            //   und TABcount auf Null setzen
       }                              
     }                                
    // .... und so weiter
    // ================================================================================
    
    
    // ================================================================================
    // ===  Initialisierung fuer Timer1 tiny85 ========================================
    // ===    Interner Oszillator, 8 MHz mit CKDIV8   =================================
     void TC1TMR_init(void)         // Init Tmr/Cntr1, 8-Bit auf ca. 100 Hz = 10 ms
     {	                          
      TCCR1  |=  (1<<CTC1);         // Timer im CTC-Mode, Top=OCRA            doc S  92
      TCCR1  |=  (1<<CS12)|(1<<CS11)|(1<<CS10);
                                    // Prescaler Clock1/64                    doc S  93
      OCR1C   =   152;      // Preset/Preload = 152 => getestet ca. 0,010s @ 1,0Mhz
      TIMSK  |=  (1<<OCIE1A);       // Tmr/Cntr1 CompareA interrupt enabled
     }                                
    // ================================================================================
    So - damit kann ich im main oder sonstwo bequem feststellen, ob und wie lange eine Taste gedrückt wurde - alles über 2,5 sec ist eben "ewig". Ausserdem ist damit auch feststellbar, wie lange die Taste nach dem letzten Drücken gelöst wurde - auch hier beginnt die Ewigkeit schon bei 2,5 sec. Läuft problemlos - und ist recht resistent gegen Spikes und so.

    Zitat Zitat von DerSchatten
    Hat vielleicht jemand ein einfacheres Beispiel für mich ...
    Ob das für Dich nun einfach(er) ist, weiß ich natürlich nicht.
    Ciao sagt der JoeamBerg

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    24.08.2009
    Beiträge
    30
    Hi, vielen dank!
    Ich bin jedoch langsam am verzweifeln.
    Ich blick hier nicht ganz durch.

    So wie ich das verstanden habe machst du alles mit Interrupts, oder?
    AVRStudio meckert bei mir fast bei jeder Zeile wenn ich den Code 1:1 reinkopiere.

    Was macht dieses Teil hier:
    ISR(TIM1_COMPA_vect)
    Wo gehört da die zugemachte Klammer hin?

    Bei TCCR1 meint er das die Variable nicht definiert ist.

    Verzweifel!

  10. #10
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.652
    Zitat Zitat von DerSchatten
    ... Ich bin jedoch langsam am verzweifeln ... Ich blick hier nicht ganz durch ...
    Du machst einen beliebten Anfängerfehler: Du programmierst irgendwo zusammenkopierte Codeteile ohne jeden Peil, was da passiert - und wir sollns richten.

    1. Du hast nirgendwo genannt, welchen Controller Du verwendest, Takt, etc.
    2. Du hast möglicherweise ein älteres AVRStudio/AVRGCC. Ich denke dass als ISR-Aufruf die Form "ISR(TIM1_COMPA_vect)" üblich ist. Die Form "SIGNAL (SIG_OVERFLOW0)" ist doch schon etwas veraltet, oder nicht ? ?
    3. Du hast nicht gemerkt, dass meine Codebeispiele für einen tiny85 steht - weil Du kopierst ohne zu lesen, was da steht.
    4. Hast Du eine Dokumentation zu Deinem Controller (und GELESEN) ?
    Gibt es in Deinem Controller denn ein Register namens TCCR1?
    5. Dein Compiler stolpert spätestens über die Stelle, an der ich geschrieben hatte:
    // .... und so weiter
    denn mein Code ist ein BEISPIEL - kein vollständiges Programm für einen mir garnicht bekannten Controller.
    6. Lern mal die Grundlagen der Programmierung von Mikrocontrollern in C - sonst wirst Du noch mehr verzweifeln. Zu Grundlagen der Programmierung von Mikrocontrollern gibts hier etliche Empfehlungen (klick).

    Und warum das alles lesen?
    Zitat Zitat von DerSchatten
    ... AVRStudio meckert bei mir fast bei jeder Zeile wenn ich den Code 1:1 reinkopiere ...
    Damit Du weisst, was Du da gemacht hast.

    Viel Erfolg.
    Ciao sagt der JoeamBerg

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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

LiFePO4 Speicher Test