www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Warum funzt meine Funktion nicht (Tasterentprellung)


Autor: Rush (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Leute...

Ich habe die Funktion von
http://www.mikrocontroller.net/articles/Entprellung
bereits erfolgreich auf einem ATmega8 eingesetzt.
Nun möchte ich gerne diese auf einem ATTiny2313 zum Laufen bringen. Der 
Win-AVR spuckt keinerlei Fehlermeldung oder Warnung aus, allerdings 
werden die Tastendrück nicht erkannt.

Hier der Code
#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <stdint.h>

volatile int i = 0;
volatile char MODE_VAL = 0;
#define  PWM_WS    OCR1A      //Pin Ausgang
#define  PWM_BL    OCR1B 
#define  LED_WS    PB3
#define  LED_BL    PB4
#define  DDR_IN    DDRD
#define  PULLUP    PORTD
#define  PIN_IN    PIND
#define  MODE    PD0
#define  UP      PD1
#define  DOWN    PD2
#define  PORT_IN  PORTD
#define  DDR_OUT  DDRB
#define  PORT_OUT  PORTB
#define  LED_CHK  PB7

#ifndef EEMEM
// alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
#define EEMEM  __attribute__ ((section (".eeprom")))
#endif

uint16_t eeTOP_WS EEMEM;
uint16_t eeTOP_BL EEMEM;
uint16_t eePWM_WS EEMEM;
uint16_t eePWM_BL EEMEM;
uint16_t eeSPEED  EEMEM;// = 1023;  //eeTOP ist der Speicherbereich im EEPROM
volatile uint16_t intTOP_WS;
volatile uint16_t intTOP_BL;
volatile uint16_t intPWM_WS;
volatile uint16_t intPWM_BL;
volatile uint16_t intSPEED;


//------------ Taster entprellen ------------
#define ALL_KEYS        (1<<MODE | 1<<UP | 1<<DOWN)
 
#define REPEAT_MASK     (1<<UP | 1<<DOWN)       // repeat: key1, key2
#define REPEAT_START    50                        // after 500ms
#define REPEAT_NEXT     20                        // every 200ms
           // every 200ms

volatile uint8_t key_state;                                // debounced and inverted key state:
                                                  // bit = 1: key pressed
volatile uint8_t key_press;                                // key press detect
 
volatile uint8_t key_rpt;                                  // key long press and repeat
 
 
ISR( TIMER0_OVF_vect )                            // every 10ms
{
  static uint8_t ct0, ct1, rpt;
  uint8_t i;
 
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
 
  i = key_state ^ ~PIN_IN;                        // key changed ?
  ct0 = ~( ct0 & i );                             // reset or count ct0
  ct1 = ct0 ^ (ct1 & i);                          // reset or count ct1
  i &= ct0 & ct1;                                 // count until roll over ?
  key_state ^= i;                                 // then toggle debounced state
  key_press |= key_state & i;                     // 0->1: key press detect
 
  if( (key_state & REPEAT_MASK) == 0 )            // check repeat function
     rpt = REPEAT_START;                          // start delay
  if( --rpt == 0 ){
    rpt = REPEAT_NEXT;                            // repeat delay
    key_rpt |= key_state & REPEAT_MASK;
  }
}
 
///////////////////////////////////////////////////////////////////
//
// check if a key has been pressed. Each pressed key is reported
// only once
//
uint8_t get_key_press( uint8_t key_mask )
{
  cli();                                          // read and clear atomic !
  key_mask &= key_press;                          // read key(s)
  key_press ^= key_mask;                          // clear key(s)
  sei();
  return key_mask;
}
 
///////////////////////////////////////////////////////////////////
//
// check if a key has been pressed long enough such that the
// key repeat functionality kicks in. After a small setup delay
// the key is reported beeing pressed in subsequent calls
// to this function. This simulates the user repeatedly
// pressing and releasing the key.
//
uint8_t get_key_rpt( uint8_t key_mask )
{
  cli();                                          // read and clear atomic !
  key_mask &= key_rpt;                            // read key(s)
  key_rpt ^= key_mask;                            // clear key(s)
  sei();
  return key_mask;
}
 
///////////////////////////////////////////////////////////////////
//
uint8_t get_key_short( uint8_t key_mask )
{
  cli();                                          // read key state and key press atomic !
  return get_key_press( ~key_state & key_mask );
}
 
///////////////////////////////////////////////////////////////////
//
uint8_t get_key_long( uint8_t key_mask )
{
  return get_key_press( get_key_rpt( key_mask ));
}



void pwm_init(void)
{
  //http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#PWM_.28Pulsweitenmodulation.29
  //fast-pwm; clear on compare match, set at top
  TCCR1A |= (1<<WGM10) | (1<<WGM11) | (1<<WGM12) | (1<<COM1A1) | (1<<COM1A0) | (1<<COM1B1) | (1<<COM1B0);
  TCCR1B |= (1<<CS10);
  //OCR1A = pwm;    //compare match
}

void debounce_init(void)
{
  TCCR0A = (1<<CS02)|(1<<CS00);      // divide by 1024; timer for decouncing
  TIMSK = 1<<TOIE0;
}

void init_io(void)
{
  DDR_OUT |= (1<<LED_WS) | (1<<LED_BL) | (1<<LED_CHK);
  PORT_OUT |= (1<<LED_WS) | (1<<LED_BL) | (1<<LED_CHK);
  DDR_IN &=~ (1<<MODE) | (1<<UP) | (1<<DOWN);
  PULLUP |= (1<<MODE) | (1<<UP) | (1<<DOWN); 
  


}
void flush(void)
{
  for (i = 0; i < intTOP_WS; i++)
  { 
    PWM_WS++; 
    PWM_BL--;
  _delay_ms(6);

  }

  for (i = 0; i < intTOP_BL; i++)
  { 
    PWM_WS--; 
    PWM_BL++;
  _delay_ms(6);

  }

}

void main(void)
 {
   init_io();
   debounce_init();
   pwm_init();
   intTOP_WS = eeprom_read_word(&eeTOP_WS);
   intTOP_BL = eeprom_read_word(&eeTOP_BL);
   PWM_BL = intTOP_BL;
   sei();
   while(1)
   {
   if( get_key_press( 1<<MODE ) || get_key_rpt( 1<<MODE ))
      
   {
    PORT_OUT &=~ (1<<LED_CHK);
    intTOP_WS = 250;
      eeprom_write_word(&eeTOP_WS, intTOP_WS); // schreiben
    intTOP_WS = eeprom_read_word(&eeTOP_WS);


    intTOP_BL = 250;
      eeprom_write_word(&eeTOP_BL, intTOP_BL); // schreiben
    intTOP_BL = eeprom_read_word(&eeTOP_BL);
    PWM_BL = intTOP_BL;
   }

  // - Pwm in eprom ablegen und auf ocxn schalten
  /*if ( !(PIN_IN & (1<<MODE)) )
  {
    PORT_OUT &=~ (1<<LED_CHK);
    intTOP_WS = 250;
      eeprom_write_word(&eeTOP_WS, intTOP_WS); // schreiben
    intTOP_WS = eeprom_read_word(&eeTOP_WS);


    intTOP_BL = 250;
      eeprom_write_word(&eeTOP_BL, intTOP_BL); // schreiben
    intTOP_BL = eeprom_read_word(&eeTOP_BL);
    PWM_BL = intTOP_BL;
    }*/

   
    

     flush();

 
     }


    
    
   
  }
Das selbe Programm mit der IF-Abfrage in der main funktioniert wie 
erwartet, lediglich mit der get_key_press-Funktion nicht.
Die Register des mega8 und des Tiny2313 habe ich bereits verglichen. 
Stimmt alles!

Seht ihr noch etwas was ich falsch gemacht habe ?

Danke schonmal im Voraus...

Autor: g-ast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo und wie sind denn die Tasten angeschlossen?

Autor: Rush (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich benutzte momentan noch das STK500.
Tasten schalten gegen Masse.
Und wo die Tasten angeschlossen sind siehst du in den Defines.
#define  MODE    PD0
#define  UP      PD1
#define  DOWN    PD2

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rush wrote:

>
> #define REPEAT_MASK     (1<<UP | 1<<DOWN)       // repeat: key1, key2
...
>    if( get_key_press( 1<<MODE ) || get_key_rpt( 1<<MODE ))
> 

get_key_rpt( 1<<MODE ) liefert immer 0, da MODE nicht als Repeat-Taste 
definiert ist.


Peter

Autor: Rush (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mich noch nie so richtig mit diesen Entprellfunktionen 
beschäftigt, bin nur froh dass sie funktionieren ;-)
Aber sind die Tasten die als REPEAT_MASK definiert sind nicht nur die 
Tasten die auf längere Tastendrücke reagieren sollen und nicht nur auf 
kurzzeitige?

Durch Hinzufügen der Taste MODE zu REPEAT_MASK reagiert das Programm 
ebenfals nicht auf den Tastendruck.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Teile Deine Problem auf und prüfe nacheinander, was funktioniert.

Und beschreibe mal, was das Programm überhaupt machen soll und wie es 
davon abweicht.

Wenn ich das richtig verstehe, wird beim 1. Tastendruck 2-mal 250 in den 
EEPROM geschrieben.
Danach passiert scheinbar nichts mehr, da ja die 250 gespeichert 
bleiben.


Peter

Autor: Rush (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja fast richtig
if( get_key_press( 1<<MODE ) || get_key_rpt( 1<<MODE ))
      
   {
    PORT_OUT &=~ (1<<LED_CHK);
    intTOP_WS = 250;
      eeprom_write_word(&eeTOP_WS, intTOP_WS); // schreiben
    intTOP_WS = eeprom_read_word(&eeTOP_WS);


    intTOP_BL = 250;
      eeprom_write_word(&eeTOP_BL, intTOP_BL); // schreiben
    intTOP_BL = eeprom_read_word(&eeTOP_BL);
    PWM_BL = intTOP_BL;
   }

Wenn das Programm hier angekommen ist läuft bereits TIMER1 im PWM-Mode. 
Er soll mir zwei an OC1A und OC1B angeschlossene LEDs dimmen. Wenn der 
Taster nicht gedrück ist, werden die LEDs nicht gedimmt da intTOP_WS und 
intTOP_BL noch NULL sind.
void flush(void)
{
  for (i = 0; i < intTOP_WS; i++)
  { 
    PWM_WS++; 
    PWM_BL--;
  _delay_ms(6);

  }

  for (i = 0; i < intTOP_BL; i++)
  { 
    PWM_WS--; 
    PWM_BL++;
  _delay_ms(6);

  }

}

Nachdem ich den Taster gedrückt habe, wird der Wert 250 in intTOP_WS und 
intTOP_BL geschrieben. Dann dimmen die LEDs. Die Variablen PWM_WS und 
PWM_BL sind OCR1A und OCR1B, also die Vergleichsregister.

Also wie gesagt, die Entprellfunktionen auf einem mega8 laufen ohne 
Probleme, nur auf dem Tiny2313 eben nicht.
Wenn ich die Abfrage über die klassische IF-Funktion mache, funktioniert 
das Programm ja ohne Probleme. Also muss das Problem irgendwo in den 
Entprellfunktionen oder in deren Aufruf liegen.
Die Register für die Funktionen sind die selben wie beim mega8. Das habe 
ich wie gesagt schon überprüft.

Autor: Rush (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Entwarnung.... habs jetzt hinbekommen.

Es lag an dem TCCR0A Register. Es muss das TCCR0B sein und nicht das A.

Aber trotzdem vielen Dank für die Bemühungen.

Gruß, Konrad

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.