Forum: PC-Programmierung bitte um hilfe bei switch case aufbau


von Huber M. (michael_h784)


Lesenswert?

Hallo,

ich möchte mit drei Tastern eine switch case Verzweigung üben.
-Taster1 soll PA3 schalten
-Taster2 soll PB1 schalten
-Taster3 soll PA7 schalten
und später soll es dann eine FMS werden, aber dazu will ich erstmal den 
grundliegenden switch case kennenlernen.
da ich aber nicht wirklich etwas bei google finde, und mit dem avr 
tutorial hier im forum alleine nicht weiter komme bitte ich euch um 
hilfe.

Als anfang will ich an PA3 eine LED über PA0 einschalten. doch das 
bereitet mir schon riesige probleme. so wie ich das verstanden habe 
arbeitet das ganze über variablen und habe folgendes probiert. da kommt 
dann gleich eine riesen fehlerliste. kann mir hier bitte jemand den 
richtigen einstieg zeigen?

/*
 * switch_case.c
 *
 * Created: 11.08.2016 08:37:07
 *  Author: Huber
 */


#include <avr/io.h>

int main(void)
{  //Ausgänge festlegen
  DDRA|= (1<<PA3)|(1<<PA7);
  DDRB|= (1<<PB1);
   //Eingänge festlegen pullups
   PORTA|= (1<<PA0)|(1<<PA1)|(1<<PA2);


  int  AUF = PA0;         // hier dachte ich, wenn ich jetzt PA0 drücke, 
dann geht PA3 an,Wo ist mein dekfehler?
  switch (AUF) {
  case 1: PORTA|=(1<<PA3);       // Anweisungen für diesen 
Zweig,variable ==
  break;

  default:      // Anweisungen wenn keine der oben definierten 
Bedingungen erfüllt ist
  break;
}
    while(1)
    {
        //TODO:: Please write your application code
    }
}

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Huber M. schrieb:
> int  AUF = PA0;         // hier dachte ich, wenn ich jetzt PA0 drücke,

Das funktioniert so nicht, denn du musst ja das PIN Register von Port A, 
also PINA erstmal einlesen.

denkbar wäre bei negativer Logik (Pin wird vom Taster auf low gezogen):
1
#define PINMASK (1<<PA0)|(1<<PA1)|(1<<PA2)
2
3
uint8_t n = ~PINA;           // lese Pins invertiert
4
n &= PINMASK;              // ausmaskieren unbenutzter Pins
5
   switch (n) {
6
     case (1 << PA0) :  // Taster 0 gedrückt tue was
7
                         break;
8
     case (1 << PA1) :  // Taster 1 gedrückt 
9
                         break;
10
     case (1 << PA2) :  // Taster 2 gedrückt 
11
                         break;
12
     case ((1 << PA0) | (1 << PA1)) : // zwei Taster gleichzeitig gedrückt
13
                         break;
14
     }
zugegeben, das auslesen der Pins ist mit der Maskiererei eine Zeile 
länger, aber damit vermeidet man unnötige Seiteneffekte. Man kann auch 
bei negativer Logik bleiben (also die Pins nicht invertieren), aber dann 
wird das switch case etwas unübersichtlicher. Es gibt viele Wege nach 
Rom und das werden hier sicher auch einige noch anmerken.

: Bearbeitet durch User
von Huber M. (michael_h784)


Lesenswert?

ok, so ungefähr hatte ich mir das vorgestellt, nur erstmal ohne 
invertieren. damit ich das ganze von grundauf richtig verstehe. Jetzt 
habe ich das mal aus dem Tutorial Mehrfachabzweigung raus kopiert.Es 
wären auch noch ein paar beispiele aufgeführt, aber alle in Asembler. 
Und davon verstehe ich garnix.

wie bekomme ich nachfolgendes dazu, dass mir im case1 PA0 (eingang) PA3 
(Ausgang) schaltet. Am besten für den anfang, wenn das mit int= möglich 
ist.



switch (variable) {
  case 1:       // Anweisungen für diesen Zweig, wenn variable == 1
    break;
  case 17:      // Anweisungen für diesen Zweig, wenn variable == 17
    break;
  case 33:      // Anweisungen für diesen Zweig, wenn variable == 33
    break;
  case 9:       // Anweisungen für diesen Zweig, wenn variable == 9
    break;
  case 22:      // Anweisungen für diesen Zweig, wenn variable == 22
    break;
  default:      // Anweisungen wenn keine der oben definierten 
Bedingungen erfüllt ist
    break;
}

von Draco (Gast)


Lesenswert?

[c]
switch (variable) {
  case 1:       // Anweisungen für diesen Zweig, wenn variable == 1
    PORTA |= (1<<PA3);
    break;
  case 17:      // Anweisungen für diesen Zweig, wenn variable == 17
    break;
  case 33:      // Anweisungen für diesen Zweig, wenn variable == 33
    break;
  case 9:       // Anweisungen für diesen Zweig, wenn variable == 9
    break;
  case 22:      // Anweisungen für diesen Zweig, wenn variable == 22
    break;
  default:      // Anweisungen wenn keine der oben definierten
Bedingungen erfüllt ist
    break;
}

von Draco (Gast)


Lesenswert?

1
switch (variable) {
2
  case 1:       // Anweisungen für diesen Zweig, wenn variable == 1
3
    PORTA |= (1<<PA3);
4
    break;
5
  case 17:      // Anweisungen für diesen Zweig, wenn variable == 17
6
    break;
7
  case 33:      // Anweisungen für diesen Zweig, wenn variable == 33
8
    break;
9
  case 9:       // Anweisungen für diesen Zweig, wenn variable == 9
10
    break;
11
  case 22:      // Anweisungen für diesen Zweig, wenn variable == 22
12
    break;
13
  default:      // 
14
    break;
15
}

von Huber M. (michael_h784)


Lesenswert?

es tut mir wirklich leid, aber ich bringe es nicht zum laufen. Ich check 
den Anfang schon nicht. Hab mir zich videos etc. angesehen gelesen. Ich 
weiss was es machen  soll, aber ich kanns einfach nicht umsetzen. Selbst 
wenn ich den geschriebenen code von mathias sch. ein kopiere. Aber jetzt 
noch mal zum letzten was mache ich den hier falsch?

/*
 * switch_case_1.c
 *
 * Created: 11.08.2016 12:41:22
 *  Author: Huber
 */


#include <avr/io.h>

int main(void)
{//Ausgänge festlegen
DDRA|= (1<<PA3);
//Eingänge festlegen
PORTA|= (1<<PA1);

 int n= (1<<PA1);
  switch (n) {
  case 1:       // Anweisungen für diesen Zweig, wenn variable == 1
  PORTA |= (1<<PA3);
  break;
  case 17:      // Anweisungen für diesen Zweig, wenn variable == 17
  break;
  case 33:      // Anweisungen für diesen Zweig, wenn variable == 33
  break;
  case 9:       // Anweisungen für diesen Zweig, wenn variable == 9
  break;
  case 22:      // Anweisungen für diesen Zweig, wenn variable == 22
  break;
  default:      //
  break;
}

von restfet (Gast)


Lesenswert?

Wo ist die while(1) ?

von Huber M. (michael_h784)


Lesenswert?

oh, hier nochmal

/*
 * switch_case_1.c
 *
 * Created: 11.08.2016 12:41:22
 *  Author: Huber
 */


#include <avr/io.h>

int main(void)
{//Ausgänge festlegen
DDRA|= (1<<PA3);
//Eingänge festlegen
PORTA|= (1<<PA1);

 char n= (1<<PA1);

  switch (n) {
  case 1:       // Anweisungen für diesen Zweig, wenn variable == 1
  PORTA |= (1<<PA3);
  break;
  case 17:      // Anweisungen für diesen Zweig, wenn variable == 17
  break;
  case 33:      // Anweisungen für diesen Zweig, wenn variable == 33
  break;
  case 9:       // Anweisungen für diesen Zweig, wenn variable == 9
  break;
  case 22:      // Anweisungen für diesen Zweig, wenn variable == 22
  break;
  default:      //
  break;
}

    while(1)
    {
        //TODO:: Please write your application code
    }
}

von Draco (Gast)


Lesenswert?

Dein Problem ist... du ließt den Pin nicht ein, zumindest nicht so wie 
du das denkst:

Huber M. schrieb:
> int n= (1<<PA1);

damit schreibst du bloß in die Variable n ein 0b0000010... da wird kein 
Pin abgefragt oder sonstwas.

Matthias S. schrieb:
1
 #define PINMASK (1<<PA0)|(1<<PA1)|(1<<PA2)
2
 
3
 uint8_t n = ~PINA;           // lese Pins invertiert
4
 n &= PINMASK;              // ausmaskieren unbenutzter Pins
5
    switch (n) {
6
      case (1 << PA0) :  // Taster 0 gedrückt tue was
7
        PORTA |= (1<<PA3);   // <--- Deine Anweisung
8
        break;
9
      case (1 << PA1) :  // Taster 1 gedrückt
10
        break;
11
      case (1 << PA2) :  // Taster 2 gedrückt
12
        break;
13
      case ((1 << PA0) | (1 << PA1)) : // zwei Taster gleichzeitig 
14
 gedrückt
15
        break;
16
}

Das ist das in welche Richtung es geht. In PINx liegen die aktuellen 
Zustände der Pins und nicht in PAx.

Desweiteren hat dein gesamtes Programm einen fundamentalen Fehler. Es 
läuft einmal durch und das wars. Du brauchst eine Dauerschleife.
1
/*
2
 * switch_case_1.c
3
 *
4
 * Created: 11.08.2016 12:41:22
5
 *  Author: Huber
6
 */
7
8
9
#include <avr/io.h>
10
11
#define PINMASK (1<<PA0)|(1<<PA1)|(1<<PA2)
12
13
int main(void)
14
{
15
  //Als Ausgang definieren
16
  DDRA |= (1<<PA3); 
17
18
  //DDRA wäre sowieso 0b00001000 somit PA01,1,2 auf Eingang aber um
19
  //es nochmal zu zeigen wie auf Eingang gestellt wird:
20
  DDRA &= ~((1<<PA0) | (1<<PA1) |(1<<PA2));
21
22
  //Hier wird NICHT auf Eingang gestellt, sondern der Pullup gezogen!
23
  PORTA|= (1<<PA0) | (1<<PA1) | (1<<PA2);
24
25
  while(1)      // Die Dauerschleife!
26
  { 
27
    uint8_t n = ~PINA;           // lese Pins invertiert
28
    n &= PINMASK;              // ausmaskieren unbenutzter Pins
29
    switch (n) {
30
      case (1 << PA0) :  // Taster 0 gedrückt tue was
31
        PORTA |= (1<<PA3);   // <--- Deine Anweisung
32
        break;
33
      case (1 << PA1) :  // Taster 1 gedrückt
34
        break;
35
      case (1 << PA2) :  // Taster 2 gedrückt
36
        break;
37
   }             // Ende der Dauerschleife
38
}

Das dürfte funktionieren, habs aber nicht getestet nur 
runtergeschrieben.

von Dieter F. (Gast)


Lesenswert?

Arbeite das

https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial

mal bis einschliesslich Kapitel 9 durch.

Dann kannst Du auch Deinen Switch-Case programmieren :-)
Dir fehlen schlicht alle Grundlagen - die musst Du Dir halt erst mal 
erarbeiten.

von Huber M. (michael_h784)


Lesenswert?

Danke dir, jetzt kann ich das langsam nachvollziehen, aber  es gibt nur 
noch ein Problem. Beim kompilieren kommt noch ein fehler. kann aber 
nicht sehen was fehlen würde oder zuviel da wäre. Ich bekomme bald nen 
Nervenzusammenbruch :-).

Error  1  expected declaration or statement at end of input 
C:\Dokumente und Einstellungen\Huber\Eigene Dateien\Atmel 
Studio\6.2\GccApplication16\GccApplication16\GccApplication16.c  38  1 
GccApplication16

von Huber M. (michael_h784)


Lesenswert?

@dieter.f. da hast du schon recht. Da bin ich ja dabei, aber ich wollte 
das mit den case üben. Da ich eine Alternative zur if Anweisung brauche. 
Und mit interrupts habe ich auch kein problem. Ich wollte schon länger 
den case switch verstehen. Ich tu mich nur leichter, wenn sich was 
bewegt auf meiner platine :-)

: Bearbeitet durch User
von Draco (Gast)


Lesenswert?

Setz noch ne Klammer drann ( } ) dann gehts... :-) Die hab ich bei der 
Switch Case vergessen:
1
/*
2
 * switch_case_1.c
3
 *
4
 * Created: 11.08.2016 12:41:22
5
 *  Author: Huber
6
 */
7
8
9
#include <avr/io.h>
10
11
#define PINMASK (1<<PA0)|(1<<PA1)|(1<<PA2)
12
13
int main(void)
14
{
15
  //Als Ausgang definieren
16
  DDRA |= (1<<PA3); 
17
18
  //DDRA wäre sowieso 0b00001000 somit PA01,1,2 auf Eingang aber um
19
  //es nochmal zu zeigen wie auf Eingang gestellt wird:
20
  DDRA &= ~((1<<PA0) | (1<<PA1) |(1<<PA2));
21
22
  //Hier wird NICHT auf Eingang gestellt, sondern der Pullup gezogen!
23
  PORTA|= (1<<PA0) | (1<<PA1) | (1<<PA2);
24
25
  while(1)      // Die Dauerschleife!
26
  { 
27
    uint8_t n = ~PINA;           // lese Pins invertiert
28
    n &= PINMASK;              // ausmaskieren unbenutzter Pins
29
    switch (n) {
30
      case (1 << PA0) :  // Taster 0 gedrückt tue was
31
        PORTA |= (1<<PA3);   // <--- Deine Anweisung
32
        break;
33
      case (1 << PA1) :  // Taster 1 gedrückt
34
        break;
35
      case (1 << PA2) :  // Taster 2 gedrückt
36
        break;
37
     }           // <---- Die Schleife hatte gefehlt.
38
   }             // Ende der Dauerschleife
39
}

von Peter D. (peda)


Lesenswert?

Für die Abfrage einzelner Bits ist switch/case nicht geeignet, da die 
Nachbarbits mit eingehen.
Außerdem ist kein Mensch in der Lage, aus CPU-Sicht 2 Tasten 
gleichzeitig zu drücken (innerhalb 50ns) oder loszulassen.

In der Regel ist eine direkte Portabfrage auch nicht sinnvoll, da Tasten 
oftmals entprellt werden müssen, bevor man sie auswerten kann.
Die Entprellroutine kann dann auch ein Intervall für Gleichzeitigkeit 
bereitstellen (z.B. 500ms). Oder für lang/kurz drücken.

von Huber M. (michael_h784)


Lesenswert?

Danke nochmal für die Mühe.Es ist rüber gespielt. Gehe ich jetzt recht 
der Annahme, wenn ich an PA0 einen Taster (0,1uf entprellt) anschliesse, 
diesen betättige,dann sollte PA3 einschalten? Es funktioniert nämlich 
nicht. Ja ich habe die Hardware überprüft verkabelung usw. mehrmals, 
wenn ich es mit ner if Anweisung mache gehts. Es muss doch nur noch ne 
Kleinigkeit sein, aber welche?

von Peter D. (peda)


Lesenswert?

Huber M. schrieb:
> wenn ich es mit ner if Anweisung mache gehts.

Damit hast Du schön bewiesen, welches Werkzeug das richtige dafür ist.
Warum willst Du unbedingt das falsche nehmen?

von Huber M. (michael_h784)


Lesenswert?

weil ich endlich mal mit der Switch Case anweisung arbeiten will. Und 
ich will das ja dann mal ausweiten, wenn ich einmal den PA3 
eingeschaltet bekomme.Wie ich anfangs ja schon schrieb, will ich mich in 
ferner Zukunft an eine state machine ran arbeiten.


-Aber es müsste doch jetzt eigentlich funktionieren. Kann sich keiner 
vorstellen, warum das nicht geht. Habe an PA0 nen Taster dran und an PA3 
eine LED, aber es tut sich nichts, ja die Led ist nicht defekt, oder die 
anderen komponenten, es liegt nur an mir und diesem Code.

/*
 * switch_case_1.c
 *
 * Created: 11.08.2016 12:41:22
 *  Author: Huber
 */


#include <avr/io.h>

#define PINMASK (1<<PA0)|(1<<PA1)|(1<<PA2)

int main(void)
{
  //Als Ausgang definieren
  DDRA |= (1<<PA3);

  //DDRA wäre sowieso 0b00001000 somit PA01,1,2 auf Eingang aber um
  //es nochmal zu zeigen wie auf Eingang gestellt wird:
  DDRA &= ~((1<<PA0) | (1<<PA1) |(1<<PA2));

  //Hier wird NICHT auf Eingang gestellt, sondern der Pullup gezogen!
  PORTA|= (1<<PA0) | (1<<PA1) | (1<<PA2);

  while(1)      // Die Dauerschleife!
  {
    uint8_t n = ~PINA;           // lese Pins invertiert
    n &= PINMASK;              // ausmaskieren unbenutzter Pins
    switch (n) {
      case (1 << PA0) :  // Taster 0 gedrückt tue was
        PORTA |= (1<<PA3);   // <--- Deine Anweisung
        break;
      case (1 << PA1) :  // Taster 1 gedrückt
        break;
      case (1 << PA2) :  // Taster 2 gedrückt
        break;
     }           // <---- Die Schleife hatte gefehlt.
   }             // Ende der Dauerschleife
}

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Ich habs mal eben im Simulator getestet und es funktioniert so wie 
erwartet. Allerdings wird PA3 ja nur einmal im ganzen Programm auf high 
gesetzt und dann nie wieder zurück. Um es besser zu testen, kannst du in 
ein anderes 'case' mal
PA3 &= ~(1<<PA3);
einsetzen, um den Pin wieder auszuschalten.

Peter D. schrieb:
> Für die Abfrage einzelner Bits ist switch/case nicht geeignet, da die
> Nachbarbits mit eingehen.

Doch, ist ja oben schon gemacht worden. Deswegen werden auch die Pins 
mit Knöpfen maskiert.
Switch-Case ist immer dann sinnvoll, wenn nur eine Funktion aus vielen 
ausgeführt werden soll. Das kann auch zur Verriegelung von Tasten oder 
für Mehrfachkombinationen benutzt werden.
Wenn man so einen Buttoninterpreter baut, sollte man ihn allerdings 
nicht mit der vollen Tektfrequenz durchrennen lassen, sondern mit ein 
paar ms Intervall. Dann klappt das schon recht gut.

von Huber M. (michael_h784)


Lesenswert?

Guten Morgen,
ok, das was du hier beschreibtst, soll es auch irgendwann mal werden. 
und zwar soll es am Gartenteich eine Schiebetür nach oben und unten mit 
drei Sensoren immer auf den mittleren Pegel-Stand gehalten werden, je 
nach Wasserstand.Aber dazu muss ich die switch case verstehen.Und da bin 
ich noch weit entfernt.

von Peter D. (peda)


Lesenswert?

Matthias S. schrieb:
> Switch-Case ist immer dann sinnvoll, wenn nur eine Funktion aus vielen
> ausgeführt werden soll.

Genau.
Tasten sind aber unabhängig voneinander, daher nimmt man if.
Z.B. eine Taste klemmt oder hat ne Zinnbrücke und schon suchst Du ewig 
und 3 Tage, warum die andere Taste nicht mehr funktioniert.

Programmieren heißt nicht nur, es wird schon irgendwie funktionieren, 
sondern es funktioniert immer zuverlässig und Fehler oder Defekte lassen 
sich schnell debuggen und finden.

von Huber M. (michael_h784)


Lesenswert?

ah, ok, dann werd ich es mir mit if else auf schreiben. Trotzdem Danke 
für die Mühe, denn ich wollte schon länger mit case switch basteln. 
Jetzt läuft es ja soweit zum testen.

zitat.:Programmieren heißt nicht nur, es wird schon irgendwie 
funktionieren,
sondern es funktioniert immer zuverlässig und Fehler oder Defekte lassen
sich schnell debuggen und finden.

Genau das will ich mir erarbeiten. Ich habe eigentlich genaue 
Vorstellung davon wie es funktionieren soll, nur bin ich auch auf der 
Suche mit welchen Code, und meinen noch wenigen Fähigkeiten ich das 
umsetzen soll. Jetzt bin ich dem ganzen schon wieder ein Stück näher. 
Ich habe einen Frequenzumrichter eine Platine mit relais und diversen 
stift leisten bestückt, die in ein Alugehäuse passt. Und die ich mit dem 
avr mk2 isp programmieren kann. Muss nur noch meinen Algoryhtmus da rein 
bringen :-)

Ps.: jetzt erstmal zwei wochen Urlaub

: Bearbeitet durch User
von Paul B. (paul_baumann)


Lesenswert?

Huber M. schrieb:
> Ps.: jetzt erstmal zwei wochen Urlaub

Ja, nach der Strapaze auch verdient. "C" zehrt unheimlich an den 
Reserven des Benutzers.
:)
mfG Paul

von Peter D. (peda)


Lesenswert?

switch/case ist ideal für Statemachines und darin kann man dann z.B. 
Ereignisse abfragen:
1
  switch( state ){
2
    case STATE_X: if( key_pressed( KEY_UP ))
3
                    state = STATE_Y;
4
                  break;
5
    case STATE_Y:
6
// usw.
7
  }
Ereignisse deshalb, weil nur selten der Zustand interessiert, sondern 
oft das Ereignis, daß gerade jemand drauf gedrückt hat.

Es gibt zu jedem Werkzeug dazu passende Aufgaben (und umgekehrt).

von Huber M. (michael_h784)


Lesenswert?

Guten tag mal wieder,


ich dachte jetzt habe ich die Logik der case verzweigung endlich mal 
richtig verstanden, das ich es selbstständig schreiben kann. Und vor 
allem möchte ich das ganze im absolouten anfänger beispiel testen. Ohne 
Bits invertiert zu lesen. wenn ich es im AVR Simulator debugge und so 
schreibe.
1
uint8_t x = 1; // oder x = 2 dann springt er in die zweite zeile
2
3
switch(x)
4
5
case 1: PORTD |= (1<<PD0); break;
6
case 2: PORTD |= (1<<PD0); break;

klappt es, und ich kann es absolout nachvollziehen. Will ich es aber mit 
einem Tatster machen, komme ich einfach nicht klar. Wenn ich 
nachfolgendes flashe dann fängt PD0 einfach dauerhaft an zu leuchten. 
Und direkt am controller kann ich es nicht debuggen ( Tasterpin im I/O 
view ansehen), weil mein MK2 das nicht unterstützt. Wie kann ich das 
jetzt ohne invertieren umsetzen

grüsse huber

1
/*
2
 * GccApplication2.c
3
 *
4
 * Created: 09.10.2016 14:48:27
5
 *  Author: HUBER M
6
 */ 
7
8
9
#include <avr/io.h>
10
11
#define tasterpins (1<<PD5)
12
13
int main(void)
14
{       
15
        DDRC &= (1<<PC5); //Eingang
16
  PORTC = (1<<PC5); //Pullup Eingang
17
  DDRD = (1<<PD0);  //Ausgang LED
18
  
19
  
20
    while(1)
21
    {
22
     uint8_t  n = tasterpins;
23
        
24
        switch (n)
25
        {
26
        case (1<<PC5) :
27
        
28
        PORTD |= (1<<PD0);  // soll led an PD0                    einschalten
29
        
30
          break;
31
        }
32
        
33
    }
34
}

von Dieter F. (Gast)


Lesenswert?

Huber M. schrieb:
> Wie kann ich das
> jetzt ohne invertieren umsetzen

https://www.mikrocontroller.net/articles/Bitmanipulation

Was soll das

Huber M. schrieb:
> DDRC &= (1<<PC5); //Eingang

und das bewirken?

Huber M. schrieb:
> PORTC = (1<<PC5); //Pullup Eingang
>   DDRD = (1<<PD0);  //Ausgang LED

Wozu gibt es & und | ?

Was macht man, um EIN Bit auf 0 bzw. auf 1 zu setzen?


Mal abgesehen davon, das Du Dir auch mal den Artikel über 
Tasten-Entprellung durchlesen solltest (und versuchen, es zu verstehen 
...).


Übrigens ist das

Huber M. schrieb:
> uint8_t x = 1; // oder x = 2 dann springt er in die zweite zeile
>
> switch(x)
>
> case 1: PORTD |= (1<<PD0); break;
> case 2: PORTD |= (1<<PD0); break;

vollkommen sinnfrei, wenn Du bei jedem Zustand das Gleiche ausführst. Da 
dürfte auch ein Test schwer fallen :-)

von Huber M. (michael_h784)


Lesenswert?

Dieter F. schrieb:
> vollkommen sinnfrei, wenn Du bei jedem Zustand das Gleiche ausführst. Da
> dürfte auch ein Test schwer fallen :-)

das ist mir schon klar, ich wil ja nur mit einem tastendruck mal in die 
Schleife kommen, dann kann ich mir mal was überlegen was ein bischen 
Sinn macht.

von Dieter F. (Gast)


Lesenswert?

Huber M. schrieb:
> das ist mir schon klar

Huber M. schrieb:
> wenn ich es im AVR Simulator debugge und so
> schreibe.
>
> uint8_t x = 1; // oder x = 2 dann springt er in die zweite zeile
>
> switch(x)
>
> case 1: PORTD |= (1<<PD0); break;
> case 2: PORTD |= (1<<PD0); break;
>
> klappt es, und ich kann es absolout nachvollziehen.

Was kannst Du DA nachvollziehen? Das PIND0 immer 1 ist? Egal, welchen 
Wert X hat? Quatsch ... :-)

Versuche "Bitmanipulation" zu verstehen ...

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Huber M. schrieb:
> while(1)
>     {
>      uint8_t  n = tasterpins;
>
>         switch (n)
>         {
>         case (1<<PC5) :
>
>         PORTD |= (1<<PD0);  // soll led an PD0
> einschalten
>
>           break;
>         }
>
>     }
> }

Dein switch-ase bearbeitet den Fall, das PC5 auf high ist. Und das ist 
er dank Pullup immer, wenn der Taster nicht gedrückt ist.
Entweder schreibst du die Case Bedingung um oder das Switch Argument
1
    uint8_t n = ~(PINC);   // oder eben das richtige Pinregister deiner Taster invertiert einlesen
2
    switch (n) {
3
4
    case  (1 << PC5)  :   PORTD |= (1 << PD0); break;   // LED ein bei Taste PC5
5
    case  (1 << PC4)  :   PORTD &= ~(1 << PD0); break;  // LED aus bei Taste PC4
6
    }

: Bearbeitet durch User
von Huber M. (michael_h784)


Lesenswert?

Matthias S. schrieb:
> Dein switch-ase bearbeitet den Fall, das PC5 auf high ist. Und das ist
> er dank Pullup immer, wenn der Taster nicht gedrückt ist.
> Entweder schreibst du die Case Bedingung um oder das Switch Argument

Ok,das leuchtet ein, das heisst, wenn ich Taster an PC5 drücke sollte 
PD0 angehen oder ?
1
/*
2
 * GccApplication2.c
3
 *
4
 * Created: 09.10.2016 14:48:27
5
 *  Author: HUBER M
6
 */ 
7
8
9
#include <avr/io.h>
10
11
#define tasterpins (1<<PC5)
12
13
int main(void)
14
{   
15
  PORTC |= (1<<PC5); //Pullup Eingang
16
  DDRD |= (1<<PD0);  //Ausgang LED
17
  
18
  void tastertest()
19
  {
20
    if (!(PINC &(1<<PC5)))
21
    {
22
      PORTD |= (1<<PD0);
23
    } 
24
    else
25
    {
26
      PORTD &= ~(1<<PD0);
27
    }
28
  }    
29
    while(1)
30
    {
31
      
32
      
33
       uint8_t n = ~(PINC);   // oder eben das richtige Pinregister deiner Taster invertiert einlesen
34
       switch (n) 
35
       {
36
37
         case  (1 << PC5)  :   PORTD |= (1 << PD0); break;   // LED ein bei Taste PC5
38
         case  (1 << PC4)  :   PORTD &= ~(1 << PD0); break;  // LED aus bei Taste PC4
39
       }
40
41
        
42
    }
43
}
 weshalb leuchtet hier PD0 nicht?

wenn ich meine tastertest Funktion in die while schleife schreibe. Und 
die Taste drücke dann leuchtet PD0. Also an der Verkabelung kann es 
schon mal nicht liegen
1
 while(1)
2
   {
3
     
4
     tastertest();
5
    // uint8_t n = ~(PINC);   // oder eben das richtige Pinregister deiner Taster invertiert einlesen
6
     //switch (n)
7
    // {
8
9
      // case  (1 << PC5)  :   PORTD |= (1 << PD0); break;   // LED ein bei Taste PC5
10
      // case  (1 << PC4)  :   PORTD &= ~(1 << PD0); break;  // LED aus bei Taste PC4
11
    // }
12
13
     
14
   }

: Bearbeitet durch User
von Dieter F. (Gast)


Lesenswert?

Ich kann leider nicht alles zitieren - aber:

Scharf - "Der goldene Troll 2016" ist Dir sicher :-)

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Uups, dir muss man ja alles vorkauen, aber gut. Du solltest die Buttons 
natürlich ausmaskieren, und nicht den gesamten Ausdruck verwenden, der 
aus dem Pinregister kommt.
Am übersichtlichsten wird das mit defines:
1
// Ausgangsport
2
#define LED1 PD0
3
#define LEDPORT PORTD
4
#define LEDDIR DDRD
5
// Eingangsport
6
#define BUTTONPINS PINC
7
#define BUTTONDIR
8
#define BUTTONPORT PORTC
9
10
#define BUTTON1 PC5
11
#define BUTTON2 PC4 
12
13
#define BUTTONMASK (1 << BUTTON1) | (1 << BUTTON2)
14
15
void init_ports(void) {
16
 BUTTONDIR = ~(BUTTONMASK);  // nicht wirklich nötig nach Reset
17
 BUTTONPORT = BUTTONMASK;  // init pullups
18
 LEDDIR = (1 << LED1);  // LED Ausgang
19
}
20
21
// aus dieser Routine wird ein gegen GND gedrückter Taster als high retourniert
22
// aber pins die nicht in der BUTTONMASK sind, ignoriert
23
uint8_t keyin(void) {
24
return (~(BUTTONPINS) & BUTTONMASK);
25
}
26
// das hauptprogramm
27
int main (void {
28
init_ports();
29
// Hauptschleife
30
while (1) {
31
   switch (keyin()) {
32
      case (1 << BUTTON1) : LEDPORT |= (1 << LED1); break;  // Ausgang high
33
      case (1 << BUTTON2) : LEDPORT &= ~(1 << LED1); break;  // Ausgang low
34
   }
35
  }  // ende while
36
}  // ende main
Natürlich führen viele Wege nach Rom. Die defines erleichtern aber 
Erweiterung und etwaige Umbelegungen.

von Huber M. (michael_h784)


Lesenswert?

Morgen,

ich weiß schon, ich bin schlimm, war wohl schon wieder zu lange davor 
gesessen. Hatte eine totale Hirnblockade, aber trotzdem Danke für deine 
Mühe.

von Huber M. (michael_h784)


Lesenswert?

so, jetzt habe ich nochmal ein Problem. Und zwar würde ich gerne einen 
Fall bearbeiten , wenn ein taster nicht gedrückt ist, mach irgend was. 
Jetzt, wenn ich bei PA0 eine 0 reinschreibe funktioniert das auch wunder 
bar, bei PA0. Bei PA1 das selbe und er meckert beim compilieren 
:::duplicate case value:::

ich habe natürlich auch schon probiert ~(1<<PA0)invertiert das in der 
klammer doch ?

&= ~(1<<PA0) löscht das bit.

(PINA&(1<<PA0)) wenn bit high
(!(PINA&(1<<PA0))) wenn bit low

oder muss ich hier extra nochmal definieren?
1
switch (n) {
2
      case (1 << PA0) :  PORTA |=  (1<<PA3);  break; // PA0 gedrückt
3
      case (0 << PA0) :  PORTA &= ~(1<<PA3);  break; // PA0 nicht gedrückt
4
      
5
    case (1 << PA2) :  PORTB |=  (1<<PB1);  break; //
6
    case (0 << PA2) :  PORTB &= ~(1<<PB1);  break; //

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Huber M. schrieb:
> Bei PA1 das selbe und er meckert beim compilieren
> :::duplicate case value:::

Und da hat er recht.
Du hast den Sinn von switch/case immer noch nicht verstanden.

Wie schon gesagt:
Beitrag "Re: bitte um hilfe bei switch case aufbau"

: Bearbeitet durch User
von Huber M. (michael_h784)


Lesenswert?

ja, aber ich hatte es ja schon mal hinbekommen vor ein paar wochen, habs 
mir aber wieder gelöscht :-(, und vergessen wie ich es gemacht habe. Und 
ich stelle mir das so vor, wenn ich mir ein paar Taster anschließe, die 
dann in der Praxis drücke und danach drauf komme, den fall hatte ich 
hier nicht mit berechnent, dann schreib ich mir einfach einen neuen fall 
dazu, so in etwa.Und ich bin wieder glücklich.

von Justus S. (jussa)


Lesenswert?

Peter D. schrieb:
> Du hast den Sinn von switch/case immer noch nicht verstanden.

das "Nicht verstehen" fängt doch schon ganz unten an, bei 
Bitmanipulation und Pinabfrage, und hat mit switch/case (noch) nix zu 
tun

@TE: leg den µC beiseite und lern erstmal die C Grundlagen 'normal' am 
PC, ohne Hardwarebezug, bevor du dich dann an µCs wagst...

von Huber M. (michael_h784)


Lesenswert?

habe seit vorletzter Woche das buch C programmiern von anfang an. Darin 
übe ich mich mit Codeblocks. Und Avr microcontroller in c Programmieren 
schon etwas länger. Das einzige das ich momentan damit nicht zu hundert 
prozent durcharbeiten kann, ist zb. taster beim debuggen im I/O view 
beobachten. da mir zu anfang der mk2 isp programmer empfohlen worden 
ist. und der keine debugg Funktion hat. Und deshalb tu ich mich da so 
schwer das zu verstehen. Brauche erstmal dennächst den avr dragon o.ä. 
dann muss ich auch nicht mehr soviel fragen.

von Peter D. (peda)


Lesenswert?

Der Debugger kann Dir auch nichts anderes dazu sagen:
1 Taster = 1 IO-Pin = 1 Bit.
Da noch Nachbarpins hinein zu verwursten, muß in die Hose gehen und geht 
auch in die Hose, wie Du ja gemerkt hast.
Schau Dir einfach mal an, wie andere ihre Tasten auswerten.

von Oliver S. (oliverso)


Lesenswert?

Ein Dragon ändert weder was dan den Compilerfehlermeldungen, die dein 
Code versursacht, noch an deinem fehlenden grundlegenden Verständnis der 
Sprache C. Da wirst du erst mal die Grundlagen lernen müssen. Danach ist 
der natürlich eine gute Hilfe.

Oliver

von Huber M. (michael_h784)


Lesenswert?

Oliver S. schrieb:
> Ein Dragon ändert weder was dan den Compilerfehlermeldungen, die dein
> Code versursacht

das ist mir schon klar, dann wäre ich aber gleich viel eher drauf 
gekommen.

Peter D. schrieb:
> Schau Dir einfach mal an, wie andere ihre Tasten auswerten.

warscheinlich mit if..else if....

ich habe auch kein grösseres Problem mir ne state maschine zu bauen, wie 
beispielsweise bei ner Ampel. Ich dachte ich habe mal gelesen das die 
case verzweigung eine elegantere Lösung für die if abfrage ist. Da habe 
ich wohl irgendwas falsch verstanden


ps.: ich glaube bei ner rollo taster schaltung wurde die case mal zu mir 
gesagt. weil man da jeden Fall abdecken kann.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Huber M. schrieb:
> warscheinlich mit if..else if....

Eher ohne "else".
Es sei denn, Du willst explizit verbieten, daß mehrere Tasten betätigt 
werden dürfen.
Auch fragt man Tasten nie im Code direkt ab, sondern nur die Ereignisse, 
die eine Entprellroutine liefert.

von Daniel A. (daniel-a)


Lesenswert?

Ein switch wie folgendes:
1
switch(x){
2
  case 1:
3
  case 2:
4
    do_something1();
5
    break;
6
  case 3:
7
  case 4:
8
    do_something2();
9
    break;
10
  default:
11
    do_something();
12
}
Kann man mit if's so schreiben:
1
if( x == 1 || x == 2 ){
2
  do_something1();
3
}else if( x == 3 || x == 4 ){
4
  do_something2();
5
}else{
6
  do_something();
7
}

Switch überprüft immer, ob ein Wert gleich einer Konstante ist. Du hast 
aber folgende situation:
1
if( x & (1<<0) ){ // ist bit 1 gesetzt?
2
}
3
if( x & ( (1<<1) | (1<<2) ) ){ // ist bit 2 oder bit 3 gesetzt?
4
}
Das kann man nicht mit switch case abbilden, denn es ist kein Vergleich 
ob ein Wert gleich einem anderen ist, sonderneine Verundung, bei der die 
Werte in der Bitmaske übrig bleiben, und auf nicht gleich 0 getestet 
werden. Das ist kein Vergleich zwischen x und der Bitmaske/konstante, 
ergo nicht mit switch case abbildbar. (ausser man macht 128 cases pro 
prüfung bei 8 bit)

: 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.