Forum: Mikrocontroller und Digitale Elektronik ATmega 328PB Taster einlesen


von Mans A. (mansmaak)


Lesenswert?

Hallo Community,

ich habe folgende Aufgaben bekommen:
--> ich muss einen Timer2 konfigurieren, dieser soll nach 10ms einen 
Interrupt auslösen

--> dieser Interrupt soll zwei tasks steuern eine mit 4s und die andere 
mit 50ms

Task1:
soll eine Sequenz von Leds aktivieren--> diese Aufgabe habe ich 
hingekriegt

Task2:
--> Taster SW2 einlesen
--> Mit diesem Taster soll LED1 im Wechsel mit 25% und 70% der 
Maximalleistung ansteuern
--> Beim ersten Drücken  LED 25%
--> Beim zweiten Drücken  LED 70%
--> Beim dritten Drücken  LED 25%
--> Und so weiter

Bei Task 2 brauche ich Hilfe! Wo ist denn mein Fehler
Das mein aktueller Code:
1
#define F_CPU 16000000UL
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <stdio.h>
5
6
#define PERIODE_TASK1_10MS 400  // for 4s task
7
#define PERIODE_TASK2_10MS 5    // for 50ms task
8
9
volatile char gTime1 = 0;
10
volatile char gTime2 = 0;
11
volatile char gState = 0;
12
volatile char gMute = 0;
13
volatile char gMute1 = 0;
14
volatile char state = 0;
15
volatile char gPushStateSW2 = 0;
16
enum {NO_PUSH, MAYBE, PROBABLY, PUSHED};
17
enum {LED_0, LED_25, LED_70};
18
19
20
21
22
23
void init_led(void)
24
{
25
   DDRB |= (1<<DDB5); // LED 3
26
   DDRB |= (1<<DDB4); // LED 4
27
}
28
29
void init_LED1(void)
30
{
31
  DDRB |= (1<<DDB1); // LED 1
32
}
33
34
void init_timer_10ms(void){
35
 // Timer 2  
36
 TCCR2B |= ((1<<CS22) | (1<<CS21) | (1<<CS20)); //Prescaler 1024
37
 TCCR2A |= (1<<WGM21); // CTC-Mode
38
 TIMSK2 |= (1<<OCIE2A);
39
 OCR2A = 155;
40
 // Timer 1
41
 TCCR1A |= ((1<<COM1A1) | (1<<COM1B1));//non inverting Mode
42
 TCCR1A |= (1<<WGM10);// Phase Correct Modus 8-Bit
43
 TCCR1B |= (1<<CS12);//Prescaler 256
44
}
45
46
void task1 () {
47
if (gState == 0){
48
  gState++;
49
  PORTB |= (1 << PORTB5);
50
  PORTB |= (1 << PORTB4);       
51
}
52
else if (gState == 1){
53
  gState++;
54
  PORTB &= ~(1<< PORTB5);
55
  PORTB &= ~(1 << PORTB4);       
56
}
57
else if (gState == 2){
58
  gState++;
59
  PORTB |= (1<< PORTB5);
60
  PORTB &= ~(1 << PORTB4);    
61
}
62
else if (gState == 3){
63
  gState++;
64
  PORTB |= (1<< PORTB4);
65
  PORTB &= ~(1 << PORTB5);
66
  if( gState == 4)
67
  {
68
    gState = 0;
69
  }
70
71
}
72
73
74
  
75
}
76
char get_button_state_sw2(void){
77
  // read status of pin
78
  char statusPinD3 = !(PIND & (1 << PIND3));
79
  // debounce (entprellen) with help of state machine:
80
  char sw2Pushed = 0;
81
  switch(gPushStateSW2){
82
    case NO_PUSH:
83
    if(statusPinD3){
84
      gPushStateSW2 = MAYBE;
85
      sw2Pushed = 0;
86
      return sw2Pushed;
87
      } else{
88
      gPushStateSW2 = NO_PUSH;
89
      sw2Pushed = 0;
90
      return sw2Pushed;
91
    }
92
    break;
93
    case MAYBE:
94
    if(statusPinD3){
95
      sw2Pushed = 0;
96
      gPushStateSW2 = PROBABLY;
97
      return sw2Pushed;
98
    }
99
    else{
100
      sw2Pushed = 0;
101
      gPushStateSW2 = NO_PUSH;
102
      return sw2Pushed;
103
    }
104
    break;
105
    case PROBABLY:
106
    if(statusPinD3){
107
      sw2Pushed = 1;
108
      gPushStateSW2 = PUSHED;
109
      return sw2Pushed;
110
    }
111
    else{
112
      sw2Pushed = 0;
113
      gPushStateSW2 = NO_PUSH;
114
      return sw2Pushed;
115
116
    }
117
    break;
118
    case PUSHED:
119
    if(statusPinD3){
120
      sw2Pushed = 0;
121
      gPushStateSW2 = PUSHED;
122
      return sw2Pushed;
123
      
124
    }
125
    else{
126
      sw2Pushed = 0;
127
      gPushStateSW2 = NO_PUSH;
128
      return sw2Pushed;
129
    }
130
    break;
131
  }
132
  
133
}
134
135
136
void LED1(){
137
OCR1A = 0;
138
139
while(gMute1>0){
140
  
141
  if(gMute==0){
142
    OCR1A = 64;
143
  }
144
  
145
  else if (gMute !=0){
146
    OCR1A = 179;
147
  }
148
  
149
}
150
151
}
152
    
153
  
154
155
void task2(){
156
  if(get_button_state_sw2()){
157
    gMute1++;
158
    if(gMute == 0){gMute = 1;}
159
    else if(gMute == 1){gMute = 0;}
160
  }
161
}
162
163
164
  
165
166
167
168
ISR(TIMER2_COMPA_vect){
169
  if (gTime1 > 0) {--gTime1;}
170
  if (gTime2 > 0) {--gTime2;}
171
}
172
173
174
175
176
int main(void) {
177
  
178
  // do all initializations
179
  init_timer_10ms();
180
  init_led();
181
  get_button_state_sw2();
182
  LED1();
183
  init_LED1();
184
185
  sei();
186
  
187
  // control task-activation-scheme in endless loop
188
  // TODO: task2 needs to be added
189
  while (1){
190
    if (gTime1 == 0) {
191
      gTime1 = PERIODE_TASK1_10MS;
192
      task1();
193
    }
194
    if (gTime2 == 0) {
195
      gTime2 = PERIODE_TASK2_10MS;
196
      task2();
197
    }
198
  }
199
}

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Mans A. schrieb:
> Wo ist denn mein Fehler

Langen Quelltext als Anhang.
So ist es nur schwer zu lesen.
Das get_button_state_sw2 sieht sehr umständlich aus, ich kann daher 
nicht sagen, ob es klappt.
Aber man will nicht den Zustand, sondern die Flanke auswerten. Ich 
schaue daher immer, ob der Tasteneingang unterschiedlich zum 
gespeicherten Zustand ist. Wenn ja, dann zähle ich 4 Durchläufe. Wenn 
dann immer noch unterschiedlich, dann toggle ich den gespeicherten 
Zustand und wenn die gedrückt Flanke, dann setze ich ein Ereignisbit, 
was dann die Mainloop abfragen kann.
Der Einfachheit halber mache ich das für einen ganzen Port parallel 
(vertical Counter), d.h. bis zu 8 Tasten.

: Bearbeitet durch User
von Mans A. (mansmaak)


Lesenswert?

Danke! Das hat mir schon weitergeholfen

von Veit D. (devil-elec)


Lesenswert?

Hallo,

die grundlegende Idee ist mittels dem 10ms Timer den Taster zu 
entprellen. Die Tasterauswertung muss man sich so bauen das er einem 
nicht retriggerbaren Monoflop entspricht. Also erst wieder auf erneuten 
Tasterdruck reagiert und nicht auf gedrückthalten. Wenn du das hast 
kannst du sauber durch eine Statemachine wandern.

Im 10ms Timer Interrupt baust du noch zwei Zähler rein der Vielfachen 
für 4s und 50ms zählt. Damit baust du dir 2 weitere bool Trigger.

Den Rest würde ich mit enum und switch-case erschlagen.

von Mans A. (mansmaak)


Lesenswert?

Danke man!

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.