Tasterroutinen Problem in C

Gast #1280338
Lesenswert?

Hallo Leute versuche vergebens meine Taster am Avr zum laufen zu 
bringen. Es scheitert schon beim Compilieren.Könnte jemand da vielleicht 
netterweise mal drübergucken oder mir nen heissen Tipp geben?

Hier mein code:
Main Code
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
 
4
/* Wir haben 3 Taster, in taster.h wird also angepasst zu
5
#define NUM_TASTER 3
6
*/
7
#include "taster.h"
8

9
/* 
10
 * Die Taster-Ports sind hartcodiert:
11
 * #0 --> PortB.4
12
 * #1 --> PortC.1
13
 * #2 --> PortD.2
14
 */
15

16
/* Bei 1MHz Grundtakt läuft Timer0 alle 256µs über.
17
 * Um auf rund 10ms zu kommen, rufen wir get_taster nur
18
 * jedes 39. mal auf. */
19
SIGNAL (SIG_OVERFLOW0)
20
{
21
    static unsigned char count_ovl0;
22
    unsigned char ovl0 = count_ovl0+1;
23

24
    if (ovl0 >= 39)
25
    {
26
        get_taster (0, PINB & (1<<PB4));
27
        get_taster (1, PINC & (1<<PC1));
28
        get_taster (2, PIND & (1<<PD2));
29
        
30
        ovl0 = 0;
31
    }
32

33
    count_ovl0 = ovl0;
34
}
35

36
void ioinit()
37
{
38
    /* Taster sind Input (default nach RESET) */
39
    /* An den Tastern die PullUps aktivieren */
40
    PORTB |= 1 << PB4;
41
    PORTC |= 1 << PC1;
42
    PORTD |= 1 << PD2;
43
 
44
    /* Timer0 ohne Prescaler starten */
45
    TCCR0 = 1 << CS00;
46
 
47
    /* Timer0-Overflow-Interrupt aktivieren */
48
    TIMSK |= (1 << TOIE0);
49
}
50

51
int main()
52
{
53
    ioinit();
54
 
55
    /* Taster konfigurieren (#define NUM_TASTER 3 in taster.h) */
56
    tasten[0].mode = TM_SHORT;
57
    tasten[1].mode = TM_LONG;
58
    tasten[2].mode = TM_REPEAT;
59
 
60
    /* Interrupts global aktivieren */
61
    sei();
62

63
    /* Hauptschleife */
64
    while (1)
65
    {
66
        signed char tast = taster;
67
  
68
        switch (tast)
69
        {
70
            default:
71
            case NO_TASTER:
72
                break;
73
    
74
            case 0:
75
                /* Taster 0 */
76
                break;
77
    
78
            case 1:
79
                /* Taster 1 kurz gedrueckt */
80
                break;
81
    
82
            case 1+TASTER_LONG:
83
                /* Taster 1 lange gedrueckt */
84
                break;
85
    
86
            case 2:
87
                /* Taster 2 */
88
                break;
89
        }
90
  
91
        if (tast != NO_TASTER)
92
            taster = NO_TASTER;
93

94
        /* ********************************** */
95
        /* Weiterer Code in der Hauptschleife */
96
    }
97
}


Taster.h
1
#ifndef _TASTER_H_
2
#define _TASTER_H_
3

4
/* Wert fuer taster, wenn nichts gedrückt wurde */
5
#define NO_TASTER (-1)
6

7
/* Maximale Anzahl der Taster */
8
#define NUM_TASTER 4
9

10
/* 0 --> Taster sind low-aktiv */
11
/* 1 --> Taster sind high-aktiv */
12
#define TASTER_LEVEL 0
13

14
/* Dieser Offset wird zur Tasten-Nummer addiert, */
15
/* wenn eine Taste lange gedrückt wurde */
16
#define TASTER_LONG 16
17

18
/* Zeitverzögerung (in Ticks), bis zum Beginn von auto-repeat */
19
#define TASTER_REPEAT_DELAY (60)
20

21
/* Zeitverzögerung (in Ticks), bis zum nächsten auto-repeat */
22
#define TASTER_REPEAT       (15)
23

24
/* Ab dieser Dauer wird der Tastendruck 'lange' */
25
#define TASTER_DELAY_LONG   (80)
26

27
typedef struct 
28
{
29
    /* private */
30
    const unsigned char delay, old;
31

32
    /* Mode des Tasters aus: TM_SHORT, TM_LONG, TM_REPEAT */
33
    unsigned char mode;
34
} taste_t;
35

36
extern taste_t tasten[];
37

38
/* In dieser Variable kann abgefragt werden, welche Taste gedrückt wurde.
39
   --> NO_TASTER:
40
       es wurde nichts gedrückt
41
   --> 0..NUM_TASTER-1:
42
       Taster Numero 'taster' wurde (kurz) gedrückt
43
   --> TASTER_LONG ... TASTER_LONG + NUM_TASTER-1:
44
       Taster Numero 'taster-TASTER_LONG' wurde lange gedrückt
45
*/   
46
extern volatile signed char taster;
47

48
extern void get_taster (const unsigned char num, unsigned char tast);
49

50
enum
51
{
52
    TM_SHORT,
53
    TM_LONG,
54
    TM_REPEAT
55
};
56

57
#endif /* _TASTER_H_ */


Taster.c
1
#include "taster.h"
2

3
volatile signed char taster = NO_TASTER;
4

5
taste_t tasten[NUM_TASTER];
6

7
/*
8
 * Aktualisiert 'taster', falls taster==NO_TASTER
9
 * num:  Nummer des Tasters von 0...NUM_TASTER-1
10
 * TASTER_LEVEL=1:
11
 *    tast: ==0 falls der Taster gerade nicht gedrueckt wird
12
 *    tast: !=0 falls der Taster gerade gedrueckt wird
13
 * TASTER_LEVEL=0:
14
 *    tast: !=0 falls der Taster gerade nicht gedrueckt wird
15
 *    tast: ==0 falls der Taster gerade gedrueckt wird
16
 */
17
void get_taster (const unsigned char num, unsigned char tast) 
18
{
19
    const taste_t * const ptast = & tasten[num];
20
    const unsigned char taster_old = ptast->old;
21
    unsigned char pressed, press, release, mode, delay;
22

23
#if TASTER_LEVEL
24
    tast = !!tast;
25
#else
26
    tast = !tast;
27
#endif
28
 
29
    /* Was wurde gedrueckt/losgelassen...? */
30
 
31
    /* Taster bleibt gedrueckt */
32
    pressed =  taster_old &  tast;
33
    /* Taster neu gedrueckt */
34
    press   = ~taster_old &  tast;
35
    /* Taster losgelassen */
36
    release =  taster_old & ~tast;
37

38
    /* ptast->old = tast;
39
     * Der Cast dient zum Wegwerfen des 'const' Qualifiers. 
40
     * Die Komponente wurde als 'const' qualifiziert, 
41
     * damit es einen Fehler gibt, wenn versucht wird,
42
     * ihren Wert von aussen zu aendern (private). */
43
    *((unsigned char *) & ptast->old) = tast;
44
 
45
    tast = NO_TASTER;
46
 
47
    mode  = ptast->mode;
48
    delay = ptast->delay;
49
 
50
    if (press)
51
    {
52
        if (mode != TM_LONG)
53
            tast = num;
54
   
55
        delay = 0;
56
    }
57
    else if (pressed)
58
    {
59
        if (delay < 0xfe)
60
            delay++;
61
    }
62
    else if (release)
63
    {
64
        if (mode == TM_LONG && delay != 0xff)
65
            tast = num;
66
    }
67
 
68
    if (mode == TM_LONG)
69
    {
70
        if (delay == TASTER_DELAY_LONG)
71
        {
72
            tast = TASTER_LONG + num;
73
            delay = 0xff;
74
        }
75
    }
76
    else if (mode == TM_REPEAT)
77
    {
78
        if (delay == TASTER_REPEAT_DELAY)
79
        {
80
            tast = num;
81
            delay = TASTER_REPEAT_DELAY - TASTER_REPEAT;
82
        }
83
    }
84

85
    if (taster == NO_TASTER)
86
        taster = tast;
87
  
88
    /* siehe oben */
89
    *((unsigned char *) & ptast->delay) = delay;
90
}

Ich bekomme den Fehler beim Compilierent dass sowolh Taster,Tasten und 
get_taster nicht definiert sind? Habe ich jedoch gemacht?
#1280350
Lesenswert?

Taser schrieb:

> Ich bekomme den Fehler beim Compilierent dass sowolh Taster,Tasten und
> get_taster nicht definiert sind?

Das stellt aber nicht der Compiler fest, sondern der Linker.

> Habe ich jedoch gemacht?

Ja hast da.
Aber weiss deine Entwicklungsumgebung auch, dass Tester.c zum Projekt 
mit dazugehört und daher compiliert und ins EXE mit eingelinkt werden 
muss?
#1280417
Lesenswert?

Wenn alle Stricke reissen und du nichts rausfindest, dann Plan B 
starten:

Neues AVR-Studio Projekt anlegen. Mega8 auswählen.
Die Source Code Dateien aufs Projektverzeichnis kopieren und mit 'Add 
Source Files' hinzufügen. Das Default-generierte File rauswerfen und 
Projekt builden lassen.

Plan B geht oft schneller als das Rausfinden, wie und wo du das alte 
Projekt verkonfiguriert hast.
Gast #1281156
Lesenswert?

Ich hab gestern nochmals vergeblich probiert die Taster zum Laufen zu 
bringen:
Folgender Code wurde verwendet und die entsprechende lcd.h sowie lcd.c 
wurden im Source Ornder neu angeleget um etwaige Fehler wie zuvor zu 
vermeiden.
Der Code sieht nun so aus:
1
//  ATMega8 LCD Driver
2
//
3
//  (C) 2009 Radu Motisan , radu.motisan@gmail.com
4
//  www.pocketmagic.net
5
//  All rights reserved.
6
//
7
//  test.c: sample test for the HD44780 LCD functions
8
//  For more details visit the website.
9

10

11
#include <avr/io.h>
12
#include <avr/interrupt.h>
13
 
14
/* Wir haben 3 Taster, in taster.h wird also angepasst zu
15
#define NUM_TASTER 3
16
*/
17
#include "taster.h"
18
#include "lcd.h"
19
/* 
20
 * Die Taster-Ports sind hartcodiert:
21
 * #0 --> PortB.4
22
 * #1 --> PortC.1
23
 * #2 --> PortD.2
24
 */
25

26
/* Bei 1MHz Grundtakt läuft Timer0 alle 256µs über.
27
 * Um auf rund 10ms zu kommen, rufen wir get_taster nur
28
 * jedes 39. mal auf. */
29
SIGNAL (SIG_OVERFLOW0)
30
{
31
    static unsigned char count_ovl0;
32
    unsigned char ovl0 = count_ovl0+1;
33

34
    if (ovl0 >= 39)
35
    {
36
        get_taster (0, PINB & (1<<PB4));
37
        
38
        
39
        ovl0 = 0;
40
    }
41

42
    count_ovl0 = ovl0;
43
}
44

45
void ioinit()
46
{
47
    /* Taster sind Input (default nach RESET) */
48
    /* An den Tastern die PullUps aktivieren */
49
    PORTB |= 1 << PB4;
50
    
51
 
52
    /* Timer0 ohne Prescaler starten */
53
    TCCR0 = 1 << CS00;
54
 
55
    /* Timer0-Overflow-Interrupt aktivieren */
56
    TIMSK |= (1 << TOIE0);
57
}
58

59
int main()
60
{  
61
  lcd_init();
62
    ioinit();
63
 
64
    /* Taster konfigurieren (#define NUM_TASTER 3 in taster.h) */
65
    tasten[0].mode = TM_SHORT;
66
    tasten[1].mode = TM_LONG;
67
    tasten[2].mode = TM_REPEAT;
68
 
69
    /* Interrupts global aktivieren */
70
    sei();
71

72
    /* Hauptschleife */
73
    while (1)
74
    {
75
        signed char tast = taster;
76
  
77
        switch (tast)
78
        {
79
            default:
80
            case NO_TASTER:
81
                break;
82
    
83
            case 0:
84
                /* Taster 0 */
85
                break;
86
    
87
            case 1:
88
               lcd_string2("Hello World! ");
89
                break;
90
    
91
            case 1+TASTER_LONG:
92
                /* Taster 1 lange gedrueckt */
93
                break;
94
    
95
            case 2:
96
                /* Taster 2 */
97
                break;
98
        }
99
  
100
        if (tast != NO_TASTER)
101
            taster = NO_TASTER;
102

103
        /* ********************************** */
104
        /* Weiterer Code in der Hauptschleife */
105
return 0;
106
    }
107
}
Ich hab jetzt einfach mal einen Output für das Lcd in die Switch 
Anweisung geschrieben.
Angezeigt am Lcd bekomme ich nur Balken. Der Taster ist ein uTaster 
ausgelötet aus dem Bedienpanel einer alten Stereoanlage  und wurde auf 
Funktionialität mit dem Durchgangsprüfer geprüft. Ergebnis: Taster funzt
Ich habe den Taster so verschaltet wie im uC.net Tutorial, ich glaube 
das heisst low-active oder so.

Ich bin echt ratlos was dieses Problem betrifft und ich hoffe erneut , 
dass ein Netter "Mituser" sich meiner erbarmt und mir ein bisschen auf 
die Sprünge hilft.
Vielen Dank
#1282130
Lesenswert?

da du deine Taster über nen Timer abfragst und der Balken immer kommt 
und geht auch ohne gedrückten Taster, wird das nicht an prellenden 
Tastern liegen. Sieht wirklich so aus als würde dein LCD ständig neu 
initialisiert (return 0, is ja jetzt weg, oder?). Schreib mal in einen 
case eine Endlosschleife, wenn das Programm da rein kommt sollte der 
Blaken dauerhaft wegbleiben.
#1287235
Lesenswert?

Taser schrieb:
> Es funktioniert auch mit einer Endlosschleife nicht...:(
> Mit leds klappts auch nicht? Schön langsam bin ich mit meinem Latein am
> Ende ...


Tastenentprellung:

http://www.mikrocontroller.net/articles/Entprellung#Komfortroutine_.28C_f.C3.BCr_AVR.29


LCD-Ansteuerung:

http://www.mikrocontroller.net/attachment/30300/lcd_drv.zip


Dann funktionierts auch.


Peter
#1288791
Lesenswert?

Für dich sind diese #define interessant
1
#define KEY_DDR         DDRB
2
#define KEY_PORT        PORTB
3
#define KEY_PIN         PINB
4
#define KEY0            0
5
#define KEY1            1
6
#define KEY2            2
7
#define ALL_KEYS        (1<<KEY0 | 1<<KEY1 | 1<<KEY2)
8
 
9
#define REPEAT_MASK     (1<<KEY1 | 1<<KEY2)       // repeat: key1, key2

KEY_DDR, KEY_PORT, KEY_PIN  legen fast an welchem Port sich die Tasten 
befinden.
KEY0, KEY1, KEY2 (und wenn du brauchst KEY3, KEY4, KEY5, KEY6 und KEY7) 
legen fest welche Pins an diesem Port benutzt werden, um Tasten 
auszulesen.

ALL_KEYS ist die Zusammenfassung aller definierten KEYx. Wenn du also 
noch ein zusätzliches KEY3 hast, dann nimmst du das dort mit auf
1
#define KEY2            2
2
#define KEY3            5    // der vierte Taster liegt an Pin 5
3
#define ALL_KEYS        (1<<KEY0 | 1<<KEY1 | 1<<KEY2 | 1<<KEY3)

und die REPEAT_MASK schlussendlich legt fest, auf welche der Taster ein 
automatischer Autorepeat gelegt werden soll.

Für die Tastenmakros kann man auch schöne, anwendungsbezogene Namen 
nehmen. Die entsprechenden #define werden nur in der Auswertung benutzt. 
Die eigentliche Entprellerei ist davon unbeeindruckt.
1
#define KEY_DDR         DDRB
2
#define KEY_PORT        PORTB
3
#define KEY_PIN         PINB
4

5
#define KEY_LEFT        2    // Taster an PB2 ist 'Links'
6
#define KEY_RIGHT       1    // Tastre an PB1 ist 'Rechts'
7
#define KEY_ENTER       5    // Taster an PB5 ist 'Enter'
8
#define ALL_KEYS        (1<<KEY_LEFT | 1<<KEY_RIGHT | 1<<KEY_ENTER)
9
 
10
#define REPEAT_MASK     (1<<KEY_LEFT | 1<<KEY_RIGHT)

Dann sieht eine Auswertung zb so aus
1
  while(1){
2
    if( get_key_press( 1<<KEY_LEFT ) || get_key_rpt( 1<<KEY_LEFT ))
3
    {
4
       // Cursor nach links bewegen
5
    }
6

7
    else if( get_key_press( 1<<KEY_RIGHT ) || get_key_rpt( 1<<KEY_RIGHT ))
8
    {
9
       // Cursor nach rechts bewegen
10
    }
11
 
12
    else if( get_key_press( 1<<KEY_RIGHT ))
13
    {
14
       // Benutzer hat Eingabe bestätigt
15
    }
16
  }

und das hat dann schon eine eigene selbstdokumentierende Code-Qualität, 
die zusätzliche Kommentare überflüssig macht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren