Forum: Mikrocontroller und Digitale Elektronik µController programmierung


von Medi (Gast)


Lesenswert?

Hallo Community,

ich versuche erste Schritte mit den XMEGA8E5 zu machen leider komme ich 
an einer Stelle nicht weiter und brauche eure Hilfe bzw. Rat dazu:

Zum Problem:

Wenn in die Funktion "laden_USB" gesprungen wird dann werden die Tasten 
nicht mehr bzw. nicht mehr schnell genug ausgewertet das äußert sich so 
dass ich die Tasten mehrmals drücken muss dann gehen die LEDs irgendwann 
an und dann sofort aus.

Als würde aus der Funktion "laden_USB" kurz in die Funktion 
"tasten_abfrage" gesprungen werden und dann wieder zurück in die 
"laden_USB".

Was kann ich tun damit die Tasten immer abgefragt werden und 
vorallendingen das dann auch die Anweisung ausgeführt wird.


Hier ist der Quellcode:

Hoffe man kann verstehen was ich meine.....

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

von Route_66 H. (route_66)


Lesenswert?

Hallo!
wenn Du in der     laden_USB(); ein

    _delay_ms(500);

machst, wunderst Du Dich über Verzögerungen?

von Blinky (Gast)


Lesenswert?

Hallo,

Mit diesem Befehl "_delay_ms(500);" wartet der Controller in der 
"laden_USB" Funktion 500ms lang. Danach darf er mal kurz die Tastatur 
abfragen mit "tasten_abfrage()" in der Hauptschleife um danach wieder 
500ms zu warten.

Besser wäre das ganze über einen Timer Interrupt zu lösen der z.B. Nach 
Ablauf von Zählern ein bestimmtes Statusflag setzt das dann in der 
Hauptschleife die einzelnen Aktionen steuert (Stichwort State Engine).

von Medi (Gast)


Lesenswert?

Blinky schrieb:
> Hallo,
>
> Mit diesem Befehl "_delay_ms(500);" wartet der Controller in der
> "laden_USB" Funktion 500ms lang. Danach darf er mal kurz die Tastatur
> abfragen mit "tasten_abfrage()" in der Hauptschleife um danach wieder
> 500ms zu warten.
>
> Besser wäre das ganze über einen Timer Interrupt zu lösen der z.B. Nach
> Ablauf von Zählern ein bestimmtes Statusflag setzt das dann in der
> Hauptschleife die einzelnen Aktionen steuert (Stichwort State Engine).

ah okay das warten über delay macht das Problem.

Timer-Interrupt habe ich auch schon drinne allerdings verarbeite ich 
dort die Funktion "laden_DC()";

Wie meinst du das mit dem Statusflag kannst du vllt ein Beispiel machen 
wie man das bei mir umsetzen könnte?

von Little B. (lil-b)


Lesenswert?

als beispiel:
1
uint8_t TimerInterruptCounter = 0;
2
3
int main(void)
4
{    
5
  clock_init ();
6
  port_init();
7
  timer4_init();
8
  interrupt_init();  
9
  start_init();
10
  
11
  while(1)
12
    {    
13
    tasten_abfrage();
14
    if (TimerInterruptCounter >= 3) {
15
        laden_USB();
16
        TimerInterruptCounter = 0;
17
    }
18
  }
19
}
20
21
/*##################Timer-Interrupt############################*/
22
ISR(TCC4_OVF_vect)
23
{
24
  TCC4.INTFLAGS = TC4_OVFIF_bm;  
25
  laden_DC();
26
  TimerInterruptCounter++;
27
}

dann natürlich die delay500ms rausnehmen.

Timer Interrupt passiert alle 160ms
160msx3 = 480ms
kommt ungefähr hin...

von Route_66 H. (route_66)


Lesenswert?

Little Basdart schrieb:
> Timer Interrupt passiert alle 160ms

...und dort wird gegebenenfalls wiederum 250 ms sinnlos gewartet, weil 
laden_DC() aufgerufen wird.

von Medi (Gast)


Lesenswert?

Little Basdart schrieb:
> als beispiel:
> uint8_t TimerInterruptCounter = 0;
>
> int main(void)
> {
>   clock_init ();
>   port_init();
>   timer4_init();
>   interrupt_init();
>   start_init();
>
>   while(1)
>     {
>     tasten_abfrage();
>     if (TimerInterruptCounter >= 3) {
>         laden_USB();
>         TimerInterruptCounter = 0;
>     }
>   }
> }
>
> /*##################Timer-Interrupt############################*/
> ISR(TCC4_OVF_vect)
> {
>   TCC4.INTFLAGS = TC4_OVFIF_bm;
>   laden_DC();
>   TimerInterruptCounter++;
> }
>
> dann natürlich die delay500ms rausnehmen.
>
> Timer Interrupt passiert alle 160ms
> 160msx3 = 480ms
> kommt ungefähr hin...

habe das bei mir geändert-> Tastenerkennung geht jetzt gut aber es wird 
immer wieder aus der Tastenabfrage rausgesprungen d.h die LEDs gehen 
kurz an und dann wieder aus...

z.B. wird das
1
 switch (anzahl)
2
      {
3
        case 1:  PORTC.OUT = 0x10; //Taste UV 1 mal gedrückt -> UV an
4
            PORTC.OUTCLR = 0x0C; //POL-Beleuchtung aus
5
            PORTR.OUTCLR = PIN0_bm; //Status-LED blau an
6
            PORTD.OUTSET = PIN6_bm;  //Status-LED grün aus
7
            break;
8
            
9
            default: anzahl1 = 1;
10
      }
aus der Funktion tasten_abfrage kurz ausgeführt und dann wieder das
1
if(!(PORTD.IN & PIN1_bm) && (!(PORTD.IN & PIN2_bm))) //USB-Power OK (low) & Charge_Indicator (low)
2
  {
3
    PORTC.OUTCLR = 0x1C; //Beleuchtung aus
4
    PORTR.OUTSET = PIN0_bm;  //Status-LED blau aus
5
    //_delay_ms(500);
6
    PORTD.OUTTGL = 0x40; //Status-LED grün toggeln
7
  }

aus der Funktion laden_USB

wie kann ich es so programieren, dass wenn die taste gedrückt wird wenn 
man sich schon in der Funktion laden_USB befindet in die tasten_abfrage 
Funktion gesprungen wird und dort verharrt?

von Fritz G. (fritzg)


Lesenswert?

Medi schrieb:
> tasterwert1_vorher=tasterwert1_jetzt; //aktuellen Tasterwert merken
> tasterwert_vorher=tasterwert_jetzt; //aktuellen Tasterwert


Du weisst, dass diese zwei Zuweisungen bei jeden Aufruf gemacht werden, 
unabhängig davon, wie der Zustand ist?

von Medi (Gast)


Lesenswert?

Fritz Ganter schrieb:
> Medi schrieb:
>> tasterwert1_vorher=tasterwert1_jetzt; //aktuellen Tasterwert merken
>> tasterwert_vorher=tasterwert_jetzt; //aktuellen Tasterwert
>
> Du weisst, dass diese zwei Zuweisungen bei jeden Aufruf gemacht werden,
> unabhängig davon, wie der Zustand ist?

stimmt du hast Recht die zwei Taster werden immer abgefragt was auch 
okay ist nur möchte ich das in zwei verschiedenen Fällen das selbe 
ausgeführt wird d.h wenn mann sich in der Funktion "laden_USB" befindet 
die man erreicht wenn die if-bedingung wahr ist. Wenn dann auch noch ein 
Tastendruck erkannt wird soll jenachdem welche taste erkannt wurde das 
ausgeführt werden was in der Funktion "taster_abfrage" steht

wie gehe ich in meinem Fall vor ?

folgende Überlegung habe ich gemacht

es gibt eine Funktion "start_init" diese soll als erste ausgeführt 
werden wenn der controller gestartet wird, dort sind alle dafault werte 
für z.B. Status-LED und die LED-Beleuchtung hinterlegt.

Im Timerinterrupt werden die Tasten abgefragt und jenachdem ob Taster an 
PORTA.6 oder PORTA.7 gedrückt wurde wird die LED-Beleuchtung 
umgeschaltet und die Status-LED (ist eine separate led) hat eine andere 
Farbe/Zustand.


dann kommen noch andere Fuktionen dazu wie z.b das Laden über USB wo der 
Ladevorgang gestartet wird und ein Status über die Farbe der Status-LED 
angezeigt wird.

wird jetzt aber beim Laden eine der Tasten wieder gedrückt soll dann der 
ladevorgang weiterlaufen aber zusätzlich die LED-Beleuchtung angehen 
etc. sprich wieder Funktion "taster_abfragen" ausgeführt werden



wahrscheinlich muss ich dann mit Flags arbeiten die jeden Zustand 
erfassen und jenachdem eine Aktion ausführen. Kriege das aber irgendwie 
nicht auf die Reihe in meinem Quellcode es kommt immer was dazwischen 
oder es wird nur kurz ausgeführt....


wäre schön wenn einer ein Beispiel in Bezug zu meinem Quellcode machen 
könnte.  komme selber nicht weiter :-(

von Medi (Gast)


Lesenswert?

Kann keiner einen Rat geben wie ich die Zustände zwischenspeichern kann, 
damit ich immer auf die Ereignisse reagieren kann?

von Peter D. (peda)


Lesenswert?

Die Tastenentprellung und Flankenerkenung macht man am besten komplett 
im Timerinterrupt und das Main holt sich die Events ab, wenn es ihm 
paßt.

Die Abläufe in der Mainloop macht man dann mit State-Machines.

von Medi (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Die Tastenentprellung und Flankenerkenung macht man am besten
> komplett im Timerinterrupt und das Main holt sich die Events ab, wenn es
> ihm paßt.
>
> Die Abläufe in der Mainloop macht man dann mit State-Machines.

Okay so habe ich mir das gedacht mit der Interruptabfrage der Taster 
bekomme ich denke hin. Aber mit der State-machines ist mir das Prinzip 
nicht klar obwohl ich den artikel hier schon drüber gelesen habe kannst 
du vllt ein Beispiel an Hand meines quellcodes zeigen, wäre echt super

von Peter D. (peda)


Lesenswert?

Medi schrieb:
> kannst
> du vllt ein Beispiel an Hand meines quellcodes zeigen, wäre echt super

Dazu müßte man ja erstmal wissen, was das Programm machen soll.
Bevor man mit dem Programmieren anfangen kann, benötigt man zuerst mal 
eine vollständige Funktionsbeschreibung (Text, Zeichnung).

Allgemein:
https://www.mikrocontroller.net/articles/Statemachine

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.