Forum: Mikrocontroller und Digitale Elektronik Tasterabfrage xmega8E


von hans (Gast)


Lesenswert?

Hallo,

ich versuche gerade mit einem XMEGA8E5 µController zwei Taster im 
Pollingbetrieb abzufragen und jenachdem ob taster1 oder taster 2 
gedrückt ist sollen andere Anweisungen erfüllt werden.

Aber es funktioniert nur eine Abfrage von dem Taster an PIN6 die zweite 
wird nicht ausgeführt...


sieht einer den Fehler im c-code und kann mir bitte weiterhelfen?
1
 void tasten_abfrage (void)
2
{
3
  uint8_t tastenwert_vorher = 1,tastenwert1_vorher = 1,tastenwert_jetzt = 0,tastenwert1_jetzt = 0;
4
  uint8_t anzahl = 0;
5
  
6
  while(1)
7
  {
8
    tastenwert_jetzt =  PORTA.IN & PIN6_bm; /*aktueller Tasterwert wird eingelesen*/
9
    tastenwert1_jetzt =  PORTA.IN & PIN7_bm; /* aktueller Tasterwert wird eingelesen */
10
    _delay_ms(20);
11
    
12
    if (tastenwert_jetzt != tastenwert_vorher) /*gibt es einen Unterschied?*/
13
    {
14
      if(tastenwert1_jetzt == 1) /* Tastendruck mitzählen */
15
      {
16
        anzahl++;
17
      }
18
      
19
      else 
20
      {
21
        if(tastenwert1_jetzt != tastenwert1_vorher)
22
        {
23
          if(tastenwert1_jetzt == 0)  
24
          {
25
            anzahl = 1;
26
            anzahl++;
27
          }
28
      
29
      
30
          switch (anzahl)
31
          {
32
        
33
            case 1: PORTC.OUT = 0x18; /*Taste POL 1 mal gedrückt -> POL an*/
34
            PORTC.OUTCLR = 0x04; /*UV-Beleuchtung aus*/
35
            PORTD.OUTCLR = PIN7_bm; /*Status-LED grün an*/
36
            PORTD.OUTSET = PIN6_bm;  /*Status-LED blau aus*/
37
            break;
38
        
39
        
40
            case 2: PORTC.OUT = 0x04; /*Taste UV 1 mal gedrückt -> UV an*/
41
            PORTC.OUTCLR = 0x18; /*POL-Beleuchtung aus*/
42
            PORTD.OUTCLR = PIN6_bm; /*Status-LED blau an*/
43
            PORTD.OUTSET = PIN7_bm;  /*Status-LED grün aus*/
44
            break;
45
      
46
        
47
            default: anzahl = 1;
48
          }
49
        }
50
      }
51
    }
52
    
53
    
54
    tastenwert_vorher=tastenwert_jetzt; /* aktuellen Tasterwert merken und wieder vergleichen */
55
  }
56
}

von Daniel S. (daniel_s49)


Lesenswert?

sorry, aber der Code ist echt wirr.

1) Dein äußeres if in der while fragt nur Pin6 ab. Wenn sich der Taster 
nicht ändert, dann kannst du an Pin7 so viel drücken wie du willst.

2) Wenn du Pin7 gedrückt hältst und Pin6 ein paar mal drückst, hast du 
Werte in anzahl, die deutlich größer sind als 2 und damit macht dein 
switch keine LED an.

3) Dein switch kann nur erreicht werden, wenn Pin7 nicht gedrückt 
wird. (ich gehe davon aus, dass 1=gedrückt und 0=nicht gedrückt)

4) tastenwert1_vorher wird nie neu gesetzt und ist damit immer 1

: Bearbeitet durch User
von hans (Gast)


Lesenswert?

Daniel S. schrieb:
> sorry, aber der Code ist echt wirr.
>
> 1) Dein äußeres if in der while fragt nur Pin6 ab. Wenn sich der Taster
> nicht ändert, dann kannst du an Pin7 so viel drücken wie du willst.
>
> 2) Wenn du Pin7 gedrückt hältst und Pin6 ein paar mal drückst, hast du
> Werte in anzahl, die deutlich größer sind als 2 und damit macht dein
> switch keine LED an.
>
> 3) Dein switch kann nur erreicht werden, wenn Pin7 nicht gedrückt
> wird. (ich gehe davon aus, dass 1=gedrückt und 0=nicht gedrückt)
>
> 4) tastenwert1_vorher wird nie neu gesetzt und ist damit immer 1

okay ich habe das jetzt anders gelöst funktioniert soweit auch nur habe 
ich noch jetzt ein weiteres Problem:

ich frage die Taster im Timer Interrupt mit der Funktion 
tasten_abfrage(); ab

jetzt habe ich jedoch noch eine weitere Funktion laden_DC(); in der 
while-schleife.

möchte ich jetzt beide funktionen benutzen dann geht nicht wirklich 
was...

kommentiere ich eine der beiden funktionen aus gehen alle fuktionen 
wieder.


Woran kann es liegen? Takte ich den µC zu langsam oder habe ich noch 
einen bock in den Funktionen (wobei die ja einzeln funktionieren)?
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#define F_CPU 8000000UL
4
#include <util/delay.h>
5
6
void clock_init (void)
7
{
8
  OSC.CTRL |= OSC_RC8MEN_bm; /*Oszillator auf 8 Mhz einstellen*/
9
  while(!(OSC.STATUS & OSC_RC8MRDY_bm)); /*Warten bis der Oszillator
10
  bereit ist*/
11
  CCP = CCP_IOREG_gc; /*Schützt I/O Register, Interrupts werden
12
  ignoriert*/
13
  CLK.CTRL = (CLK.CTRL &~ CLK_SCLKSEL_gm) | CLK_SCLKSEL_RC8M_gc;
14
  /*aktiviert den internen Oszillator*/
15
}
16
17
18
19
void port_init (void)
20
{
21
  /*Charge_Voltage*/
22
  PORTA.DIR &= ~PIN1_bm; /*PORTA.1 als Eingang definiert (0,93V-1,4V)*/
23
  
24
  /*Charge_Current*/
25
  PORTA.DIR &= ~PIN0_bm; /*PORTA.0 als Eingang definiert (1.5V = 1.2A)*/
26
  
27
  /*Reedkontakt init*/
28
  PORTC.DIR &= ~ PIN5_bm; /*PORTC.5 auf Eingang Reedkontakt*/
29
  PORTC.PIN5CTRL |= PORT_OPC_PULLUP_gc; /*Pull-Up Widerstand am PORTC.5 aktiv (Reedkontakt)*/
30
  
31
  /*LEDs init*/
32
  PORTC.OUT &= ~ PIN2_bm; /*PORTC.2 auf low UV-LEDs->aus*/
33
  PORTC.OUT &= ~ PIN3_bm; /*PORTC.3 auf high WW-LEDs->aus*/
34
  PORTC.OUT &= ~ PIN4_bm; /*PORTC.4 auf high KW-LEDs->aus*/
35
  //PORTC.OUT |= PIN3_bm; /*PORTC.3 auf high WW-LEDs->an 100%*/
36
  //PORTC.OUT |= PIN4_bm; /*PORTC.4 auf high KW-LEDs->an 100%*/
37
  PORTC.DIR = 0x1C;      /*PORTC auf Ausgang LEDs*/
38
  
39
  /*System ON/OFF*/
40
  PORTC.DIR |= PIN1_bm; /*PORTC.1 auf Ausgang ON/OFF*/
41
  PORTC.OUT &= ~PIN1_bm; /*PORTC.1 auf low*/
42
  
43
  /*Status LED Init*/
44
  PORTD.DIR |= PIN6_bm; /*LED Blau*/
45
  PORTD.OUT |= PIN6_bm;
46
  
47
  PORTD.DIR |= PIN7_bm; /*LED Grün*/
48
  PORTD.OUT |= PIN7_bm;
49
  
50
  
51
  PORTR.DIR |= PIN0_bm; /*LED Rot*/
52
  PORTR.OUT |= PIN0_bm;
53
  
54
  /*Charger Fault*/
55
  PORTD.DIR &= ~PIN5_bm; /*PORTD.5 als Eingang definiert*/
56
  
57
  /*DC-Power OK*/
58
  PORTD.DIR &= ~PIN4_bm; /*PORTD.4 als Eingang definiert*/
59
  
60
  /*Charger ON/OFF*/
61
  PORTD.DIR |= PIN3_bm;
62
  PORTD.OUT &= ~ PIN3_bm;
63
  
64
  /*Charger Indikator*/
65
  PORTD.DIR &= ~PIN2_bm; /*PORTD.2 als Eingang definiert*/
66
  
67
  /*USB-Power OK*/
68
  PORTD.DIR &= ~PIN1_bm; /*PORTD.1 als Eingang definiert*/
69
  
70
  /*Taster Init*/
71
  PORTA.DIR &= ~PIN7_bm; /*PORTA7 als Eingang definieren (Taster POL)*/
72
  PORTA.PIN7CTRL |= PORT_OPC_PULLUP_gc; /*Pull-Up Widerstand am PORTA7 aktiv (Taster POL)*/
73
  
74
  PORTA.DIR &= ~PIN6_bm; /*PORTA6 als Eingang definieren (Taster UV) */
75
  PORTA.PIN6CTRL |= PORT_OPC_PULLUP_gc; /*Pull-Up Widerstand am PORTA6 aktiv (Taster UV)*/
76
  
77
  //PORTA.DIR &= ~PIN5_bm; /*PORTA5 als Eingang definieren (Taster Reserved)*/
78
  //PORTA.PIN5CTRL |= PORT_OPC_PULLDOWN_gc; /*Pull-Up Widerstand am PORTA7 aktiv (Taster3)*/
79
}
80
81
82
void interrupt_init (void)
83
{
84
  PMIC.CTRL |= PMIC_LOLVLEN_bm; /*Interrupt eingeschaltet*/
85
  sei(); /*Interrupt freischalten*/
86
}
87
88
89
90
void timer4_init (void)
91
{
92
  TCC4.CTRLA = TC45_CLKSEL_DIV256_gc; /*Vorteiler auf 8 eingestellt*/
93
  TCC4.CTRLB = TC45_WGMODE_NORMAL_gc; /* Timer auf normal Mode (hochzählend) eingestellt */
94
  TCC4.PER = 65436; /*Timer vorladen 65436*/
95
  TCC4.INTCTRLA = TC45_OVFINTLVL_LO_gc; /*Interrupt Modus aktiv*/
96
  TCC4.INTFLAGS = TC4_OVFIF_bm;
97
}
98
99
100
void tasten_abfrage (void)
101
{
102
  uint8_t tasterwert_vorher = 1, tasterwert_jetzt = 0, anzahl = 0;  
103
  
104
  while(1)
105
  {
106
    tasterwert_jetzt = PORTA.IN & PIN7_bm; /*aktueller Tasterwert wird eingelesen*/  
107
    _delay_ms(20);
108
    
109
    if(!(PORTA.IN & PIN6_bm)) 
110
    {
111
      PORTC.OUT = 0x04; /*Taste UV 1 mal gedrückt -> UV an*/
112
      PORTC.OUTCLR = 0x18; /*POL-Beleuchtung aus*/
113
      PORTD.OUTCLR = PIN6_bm; /*Status-LED blau an*/
114
      PORTD.OUTSET = PIN7_bm;  /*Status-LED grün aus*/   
115
    }
116
      
117
    if(tasterwert_jetzt != tasterwert_vorher)  
118
    {
119
      if(tasterwert_jetzt == 0)  
120
      {
121
        anzahl++;
122
      }
123
      
124
      switch (anzahl)
125
      {
126
        case 1: PORTC.OUT = 0x18; /*Taste POL 1 mal gedrückt -> POL an*/
127
            PORTC.OUTCLR = 0x04; /*UV-Beleuchtung aus*/
128
            PORTD.OUTCLR = PIN7_bm; /*Status-LED grün an*/
129
            PORTD.OUTSET = PIN6_bm;  /*Status-LED blau aus*/             
130
            break;
131
            
132
            
133
        case 2: PORTC.OUTCLR = 0x18; /*POL-Beleuchtung aus*/
134
            PORTD.OUTSET = PIN7_bm;  /*Status-LED grün aus*/
135
            PORTD.OUTCLR = PIN6_bm; /*Status-LED blau an*/            
136
            break;
137
            
138
            default: anzahl = 0;
139
      }
140
    }
141
    tasterwert_vorher=tasterwert_jetzt; /* aktuellen Tasterwert merken und wieder vergleichen */  
142
  }
143
}
144
145
146
147
void laden_DC (void)
148
{
149
  
150
  
151
  if((PORTC.IN & PIN5_bm) && (!(PORTD.IN & PIN4_bm)) && (!(PORTD.IN & PIN2_bm))) /*Reedkontakt OK (high) & DC-PWR OK (low) & Charge Indicator (low)*/
152
  {
153
    PORTC.OUTCLR = 0x1C;
154
    _delay_ms(300);
155
    PORTD.OUTTGL = 0x80; /*grüne Status LED toggeln*/
156
  }
157
  else
158
  {
159
    if(PORTD.IN & PIN2_bm) /*Charge Indicator (high)*/
160
    {
161
      PORTC.OUTCLR = 0x1C;
162
      PORTD.OUT &= ~ PIN5_bm; /*grüne Status LED an*/
163
    }
164
  }
165
}
166
167
int main(void)
168
{
169
    
170
  clock_init ();
171
  port_init();
172
  timer4_init();
173
  interrupt_init();  
174
  
175
  while(1)
176
    {
177
    laden_DC();           
178
    }
179
}
180
181
182
ISR(TCC4_OVF_vect)
183
{
184
  TCC4.INTFLAGS = TC4_OVFIF_bm;
185
  tasten_abfrage();
186
  
187
}

von Daniel S. (daniel_s49)


Lesenswert?

ähm ... du startest in der ISR eine Endlosschleife und wunderst dich, 
warum das Programm nicht funktioniert? Könnte dran liegen, dass der 
Mikrocontroller für immer in der tasten_abfrage() hängt, ohne jemals 
wieder in die lade_DC() zurück zu kommen.
Normalerweise sollte man ISRs so kurz wie möglich halten. Schleifen und 
alles was Zeit kostet, haben da drin nix verloren.

: Bearbeitet durch User
von hans (Gast)


Lesenswert?

Daniel S. schrieb:
> ähm ... du startest in der ISR eine Endlosschleife und wunderst
> dich,
> warum das Programm nicht funktioniert? Könnte dran liegen, dass der
> Mikrocontroller für immer in der tasten_abfrage() hängt, ohne jemals
> wieder in die lade_DC() zurück zu kommen.
> Normalerweise sollte man ISRs so kurz wie möglich halten. Schleifen und
> alles was Zeit kostet, haben da drin nix verloren.

du hast recht sehe ich jetzt auch.

Komme aber im Moment nicht auf die Lösung wie müsste ich das dann mit 
der Abfrage gestalten?

Damit beide Funktion gehen?

von Peter D. (peda)


Lesenswert?

hans schrieb:
> Komme aber im Moment nicht auf die Lösung wie müsste ich das dann mit
> der Abfrage gestalten?

Beitrag "Universelle Tastenabfrage"

Für Tasten lohnt sich eine eigene Lib. Der Timerinterrupt bereitet die 
Tasten auf und das Main holt sich dann nur die fertigen Events ab.

Das Vermengen des Entprellen mit der Mainloop macht nur Ärger und den 
Code unübersichtlich.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.