Forum: Mikrocontroller und Digitale Elektronik Mehrfachverzweigung switch case


von Tim S. (m80)


Lesenswert?

Hallo,
Ich versuche gerade mir das programmieren mit einem Atmega 8 
beizubringen.
Leider komme ich gerade nicht weiter...
Ich würde gerne 3 LED mit einem Taster nacheinander durchschalten. Meine 
Idee wäre eine Switch-Case Verzweigung.
Problem bei der Verzweigung ist, dass bei erneutem Tastendruck der Wert 
nicht inkrementiert wird. Hier mal das Programm..
1
#define LED1 0
2
#define LED2 1
3
#define Taster1 2
4
5
int main(void)
6
{
7
  DDRD &= ~(1<<Taster1);          //PD2 ist ein Eingang
8
  PORTD |=(1<<PD2);          //Interner Pull Up eingeschaltet
9
  DDRB |=((1<<LED1)|(1<<LED2));  //PORT B Pin 0 0 und 1 werden als Ausgänge geschaltet
10
  
11
  
12
13
  uint8_t Cntr=0;
14
  if(!(PIND & (1<<Taster1)))
15
  ++Cntr;        //hier soll inkrementiert werden
16
17
    while (1) 
18
    {
19
    
20
      
21
    switch(Cntr)
22
    {
23
      
24
    case 1:
25
    
26
    PORTB|=(1<<LED1);
27
    
28
    break;
29
    
30
    case 2:
31
    
32
    PORTB|=(1<<LED2);
33
    break;
34
    default: break;
35
    }//switch ende
36
    
37
    }//while ende
38
}

Vielleicht hat jemand hier im Forum eine Idee wie man das realisieren 
könnte??
Für einen Denkanstoß wäre ich Dankbar...
(der obere Teil wird irgendwie nicht richtig dargestellt )

[MOD: weil du keine c-Tags eingefügt hast]

: Bearbeitet durch Moderator
von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

Tim S. schrieb:
> Für einen Denkanstoß wäre ich Dankbar...

Schau dir mal an was innerhalb deiner Schleife ist und was außerhalb.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Tim S. schrieb:
> Für einen Denkanstoß wäre ich Dankbar...
Spiel mal selber "Prozessor" und arbeite dein Programm mal Schritt für 
Schritt durch. Du wirst sehen: es tut das, was du hingeschrieben hast, 
der Cntr wird ein einziges Mal hochgezählt.

> Vielleicht hat jemand hier im Forum eine Idee wie man das realisieren
> könnte??
Erst Entprellung dann Flankenerkennung und mit jeder Flanke den Zähler 
hochzählen.

: Bearbeitet durch Moderator
von Ingo Less (Gast)


Lesenswert?

Irgend W. schrieb:
> Schau dir mal an was innerhalb deiner Schleife ist und was außerhalb.
Und überlege mal wie oft die Schleife durchlaufen wird pro Sekunde. Pack 
für den allerersten Anfang mal ein _delay_ms (300) an das Schleifenende.

von Tim S. (m80)


Lesenswert?

Unglaublich wie schnell einem hier geantwortet wird!!!!
Vielen Dank für die Tipp´s :-) Werde das heute Abend mal versuchen 
umzusetzen!

von Thomas E. (thomase)


Lesenswert?

Ingo Less schrieb:
> Und überlege mal wie oft die Schleife durchlaufen wird pro Sekunde. Pack
> für den allerersten Anfang mal ein _delay_ms (300) an das Schleifenende.

Und dann? Was soll der Sinn davon sein?

von Udo S. (urschmitt)


Lesenswert?

Thomas E. schrieb:
> Und dann? Was soll der Sinn davon sein?

Dass Taste gedrückt nicht alle paar µs zu einem neuen Zustand und einem 
Weiterschalten führt.
Der bessere Weg hat Lothar skizziert: Erst Entprellen und dann nur auf 
Ändern des Zustands des tasters (Flankenerkennung) etwas tun.

Aber der TO ist absoluter Anfänger, also ist der Tipp mit dem Delay 
völlig ok.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Thomas E. schrieb:
> Und dann? Was soll der Sinn davon sein?
Das ist quasi sowas wie eine "Zeitlupe für Anfänger", weil dann nach 
einem Schleifendurchlauf erst mal abgewartet wird, bis sie erneut 
durchlaufen wird. Auf diese Art spart man sich bei entsprechend zügiger 
Betätigung des Tasters sowohl das Entprellen wie auch die 
Flankenerkennung.

Der Arduino-Anfänger lernt dabei, dass so ein _delay_ms() sein Problem 
"gelöst" hat. Und merkt sich fürderhin: "Wenn Problem, dann _delay_ms()"

: Bearbeitet durch Moderator
von EAF (Gast)


Lesenswert?

Lothar M. schrieb:
> Der Arduino-Anfänger lernt dabei, dass so ein _delay_ms() sein Problem
> "gelöst" hat. Und merkt sich fürderhin: "Wenn Problem, dann _delay_ms()"
Richtig!
Was ja auch für diesen konkreten Fall ausreichend sein wird.
Oder?
Wobei ein Arduino Jünger dann allerdings delay() und nicht _delay_ms() 
verwenden würde. Was den Braten aber nicht viel fetter macht.

Und in einem weiteren Schritt lernt er dann, dass man so kaum 
Nebenläufigkeiten realisieren kann.
Dann erfolgt der nächste Schritt, in der Kompetenz Entwicklung.
Fein, eins nach dem anderen.
Das nennt man Entwicklung, Lernen.

Auch wenn du deine Erwartungshaltung in ein sarkastischen Mäntelchen 
packst, bleibt es doch eine Erwartungshaltung, die den Prozess des dazu 
lernens ignoriert/negiert
Zudem ist es aktives Arduinobashing (gegen die Plattform gerichtet), und 
eine Form des Mobbing, gegen die User.

Mit keinem Wort wurde, vom TE, in diesem Thread Arduino erwähnt.
Auch sieht sein Code nicht danach aus.

Klartext: Diese Salve war unanständig, eines Moderators unwürdig!
Oder hat man hier absichtlich den Bock zum Gärtner gemacht?

von Ingo Less (Gast)


Lesenswert?

Deswegen schrieb ich ja auch:
> Pack
> für den allerersten Anfang mal ein _delay_ms (300) an das Schleifenende.
Das das natürlich programmtechnisch Kacke ist, is mir klar. Aber für die 
ersten Gehversuche reichts. Eine Entprellung mit Timer wäre dann der 
nächste Schritt und angebracht.

von W.S. (Gast)


Lesenswert?

EAF schrieb:
> Klartext: Diese Salve war unanständig, eines Moderators unwürdig!
> Oder hat man hier absichtlich den Bock zum Gärtner gemacht?

Ja, was sonst hätte er schreiben sollen? Ich sehe hier fast überall 
Leute, die offenbar glauben, ein Mikrocontroller macht genau DAS, was 
ihnen grad so in den Sinn gekommen ist. Das ist ein kolossaler Irrtum, 
denn wenn nicht schon die Toolchain ein "stop, das geht nicht" schreit, 
dann macht anschließend der µC genau DAS, was man hingeschrieben hat und 
nicht das, was man sich eventuell dabei gedacht hat. Diese 
Herangehensweise sehe ich vornehmlich bei Arduino-Leuten. Ich sehe auch 
den Grund dafür: Mit den Arduinos wird den Leuten erzählt, daß dort 
schon alles bereitet sei, so daß man einen µC per Arduno auch beutzen 
kann, wenn man über das Thema nix weiß. Und das ist die falsche 
Botschaft. Vorher gründlich lesen und denken ist eine Notwendigkeit. 
Auch wenn sich gar manche darüber erhaben fühlen.

W.S.

von NurZufälligHier (Gast)


Lesenswert?

Nur als kleinen Tipp für das weitere Programmieren. Versuche dir am 
besten schnell einen gut lesbaren Programmierstil anzueignen. Bei der 
Frage wie der "richtige" Coding-Style aussieht scheiden sich die geister 
aber hier mal als Beispiel dein Code in einer recht üblichen 
Schreibweise. Eine einheitliche Schreibweise und vorallem Einrücken von 
Code-Zeilen und bennen von Variablen, Makros, etc. vereinfacht dir und 
anderen das Lesen deines Code. :)
1
#define LED_1 0
2
#define LED_2 1
3
#define TASTER_1 2
4
5
int main(void)
6
{
7
  uint8_t u8_cntr = 0;
8
9
  DDRD &= ~(1 << TASTER_1);         //PD2 ist ein Eingang
10
  PORTD |= (1 << PD2);              //Interner Pull Up eingeschaltet
11
  DDRB |= ((1 << LED_1) | (1 << LED_2));  //PORT B Pin 0 0 und 1 werden als Ausgänge geschaltet
12
  if(!(PIND & (1 << TASTER_1)))
13
  {
14
    ++u8_cntr;        //hier soll inkrementiert werden
15
  }
16
17
  while (1) 
18
  {
19
    switch(u8_cntr)
20
    {
21
      case (uint8_t)1: 
22
        PORTB |= (1 << LED_1);
23
        break;
24
25
      case (uint8_t)2:
26
        PORTB |= (1 << LED_2);
27
        break;
28
29
      default: 
30
        break;
31
32
    } //switch ende
33
34
  }//while ende
35
}

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

EAF schrieb:
> Klartext: Diese Salve war unanständig, eines Moderators unwürdig!
Wo zur Hölle ist da eine Salve? Muss ich mich jetzt abmelden und anonym 
schreiben, damit sich nicht irgendwer irgendwie auf den Schlips getreten 
fühlt? Habe ich hier irgendwo den Moderator "raushängen" lassen? Darf 
ein Moderator auch als offensichtlicher User nur "weichgespülte" Töne 
von sich geben?

> Oder hat man hier absichtlich den Bock zum Gärtner gemacht?
Noch viel lächerlicher gehts aber nimmer, das ist dir hoffentlich klar.

[/offtopic]

: Bearbeitet durch Moderator
von EAF (Gast)


Lesenswert?

W.S. schrieb:
> Ich sehe hier fast überall
> Leute, die offenbar glauben, ein Mikrocontroller macht genau DAS, was
> ihnen grad so in den Sinn gekommen ist.
Sehr gut erkannt!

Genau das ist "Programmieren"!
Man hat in der Vorstellung, ein Verhalten, welches man auf einen µC 
übertragen möchte.
Wie gut, wie schnell, dass dann klappt, ist eine Frage der Kompetenz auf 
diesem Gebiet.

Ach ja: Kompetenz in Sachen Arduino...

Die muss ich dir leider absprechen.
Nach eigener Aussage (irgendwo), hast du dich noch nie wirklich mit 
Arduino beschäftigt, willst das auch nicht tun.
Das ist nicht schlimm, bleibt ganz dir überlassen.

Arduino verwendet zum größten Teil C++. Die User stellen sich also einer 
der schwierigsten/komplexesten/mächtigsten Programmiersprachen, welche 
es überhaupt für µC gibt.
Dazu bist du nach eigener Ansage auch nicht bereit.
Beispiel: Das C++ Buch welches du vor ca 20 Jahren entnervt beiseite 
gelegt hast und seit dem in deinem Regal ungestört vor sich hin 
oxidiert.
Auch das ist nicht schlimm.

Aber beides zusammen macht schon klar, dass deine Vorurteile durch 
keinerlei Fakten getrübt werden.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

EAF schrieb:
> Aber beides zusammen macht schon klar, dass deine Vorurteile durch
> keinerlei Fakten getrübt werden.

Er hat ja auch kein C Buch gelesen, alles drei zusammen machts noch 
schlimmer.
Will Leuten vorschreiben wie diese zu programmieren haben, aber ist 
absolut ahnungslos in C.

von W.S. (Gast)


Lesenswert?

Tim S. schrieb:
> Ich würde gerne 3 LED mit einem Taster nacheinander durchschalten.

Das kannst du machen, es besteht jedoch aus zumindest 3 Teilen:
1. Tastenereignis erkennen
2. Die Nummer der zu erhellenden LED weiterschalten
3. Jede andere LED löschen und nur die aktuelle LED einschalten

Zu 1.
Das Drücken einer Taste ist nicht den momentanen Zustand zu erkennen, 
sondern eigentlich das SoebenGedrücktWordenSein, also quasi so etwas 
ähnliches wie dessen 1. Ableitung. Also muß man dazu die besagte Taste 
beobachten und erkennen, ob sie vom ungedrückten Zustand in den 
gedrückten Zustand gewechselt hat. Dann kann man ein "Tastenereignis" 
draus generieren. Aber damit ist es nicht getan, denn Tasten können 
prellen. Also braucht es noch weitere Beobachtung, damit man das 
Loslassen und wieder Drücken der Taste unterscheiden kann vom etwaigen 
Prellen. Das ist alles besser in einer separaten Funktion unterbringbar, 
die aber zeitzyklisch in sinnvollen Zeitabständen aufgerufen werden 
soll, um besagte Beobachtung der Taste zu erledigen. Einfach nur so an 
irgend einer Stelle im eigentlichen LED-Algorithmus sich zu sagen "jetzt 
und hier will ich eine Tasteneingabe haben" ist die falsche Denkweise.

Zu 2.
Das ist eigentlich die leichteste Übung. Man braucht nur eine kleine 
Variable, wo man entweder von 1 bis 3 oder (hier wohl besser) von 0 bis 
2 zählt. Das darf dann aber eben nur dann erfolgen, wenn ein 
"Tastenereignis" festgestellt worden ist. Und dieses Tastenereignis muß 
"gegessen" werden. Also wenn du z.B. eine Variable hast, die eine 1 
abkriegt, wenn so ein Ereignis "Taste wurde gedrückt" eingetreten ist, 
dann mußt du eben diese Variable wieder auf z.B. 0 setzen, wenn du das 
Weiterschalten deiner LEDs und Punkt 3 erledigt hast.

Zu 3.
Das ist der Teil des Ganzen, wo deine Idee einer switch-case Anweisung 
eventuell zum Tragen kommt. Ja, es geht auch anders. Im Prinzip mußt du 
hier 2 Dinge tun:
a) alle LEDs, die gerade nicht gemeint sind, ausschalten und die LED 
einschalten, die gemeint ist.

Nochwas: wahrscheinlich wirst du deinen Mikrocontroller mit einem Takt 
im Bereich 10..20 MHz betreiben. Die Abarbeitung der für dein Anliegen 
erzeugten Maschinenbefehle wird mal ganz grob auch in dieser 
Größenordnung liegen. Also wird deine Programmschleife wenigstens einige 
100000 mal pro Sekunde durchlaufen werden. Das ist allemal sehr viel 
schneller als du deinen Finger auf der Taste zucken lassen kannst und es 
ist auch immer noch sehr viel schneller, als du die LEDs angucken 
kannst. Du mußt also bei dem Konzipieren deiner Firmware davon ausgehen, 
wie der µC die Welt 'sieht' und nicht davon, wie DU als Mensch sie 
siehst.

W.S.

von EAF (Gast)


Lesenswert?

Lothar M. schrieb:
> Muss ich mich jetzt abmelden und anonym
> schreiben, damit sich nicht irgendwer irgendwie auf den Schlips getreten
> fühlt?
Das bekommt in einer solchen Situation jeder von mir zu hören.
Egal ob Moderator oder nicht.
Würde dir also nicht wirklich helfen.

Lothar M. schrieb:
> Habe ich hier irgendwo den Moderator "raushängen" lassen? Darf
> ein Moderator auch als offensichtlicher User nur "weichgespülte" Töne
> von sich geben?
Als Moderator hat man eine Vorbildrolle!
Ob du willst, oder auch nicht.

Das Arduino Bashing und Mobbing, sind hier im Forum weit verbreitet.
Ich erwarte von einem Moderator, dass er dieses deeskalierend moderiert.
Aber was ich keinesfalls erwarte, dass ein Moderator dieses aktiv 
befeuert. Öl ins Feuer gießt.
Das nenne ich "Bock zum Gärtner" machen.
Klar, verstehe ich, dass dir die Ansage nicht schmeckt.

Alternativ:
Seid dann doch so konsequent, und schreibt über dem "Themenstarter Feld"
> Hier sind Arduino Fragen/User unerwünscht.
> Denn die sind alle voll blöd.

Das wäre eine klare, ehrliche und offene Diskriminierung.
Dieses subtile, durch die Hintertür kommende, halte ich für eine ganz 
üble Tour.

Also meine Bitte:
Werdet euch klar, was ihr wirklich wollt, und setzt das konsequent um.

von W.S. (Gast)


Lesenswert?

EAF schrieb:
> Genau das ist "Programmieren"!

Nein, das ist kein Programmieren, sondern Pfuschen.
Leute, die über dieses Stadium nicht hinausgekommen sind, sieht man hier 
oft genug.

W.S.

von Stefan F. (Gast)


Lesenswert?

EAF schrieb:
> Als Moderator hat man eine Vorbildrolle!

Wieso, wer sagt das? Sind Politiker auch Vorbilder? Oder die 
Führungskräfte unserer Konzerne? Oder die Zensoren von Facebook?

Eigentlich ist das primär der Job von Eltern und Pädagogen.

von W.S. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> EAF schrieb:
>> Als Moderator hat man eine Vorbildrolle!
>
> Wieso, wer sagt das? Sind Politiker auch Vorbilder? Oder die
> Führungskräfte unserer Konzerne? Oder die Zensoren von Facebook?

Naja, ich meine, die Wahrheit liegt immer irgendwo zwischen den 
Extremen. Aber die allgemeine Erwartung ist, daß Moderatoren etwa 
seriöser auftreten als der Durchschnitt der Leute, die im Forum posten.

W.S.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

W.S. schrieb:
> daß Moderatoren etwa seriöser auftreten als der Durchschnitt der Leute
Aber die immer noch unbeantwortete Frage war doch die, was den EAF so 
anficht, dass er gleich abgeht wie Schmitz Katz.

EAF schrieb:
> Klar, verstehe ich, dass dir die Ansage nicht schmeckt.
Ja, weil sie schlicht und einfach herfabuliert ist.

Ich helfe auch Arduinisten mit viel Geduld und Ausdauer und wohlwissend, 
dass da oft noch viel Luft nach oben ist. Und manchmal wird die Ausdauer 
sogar belohnt und der Frager lernt etwas dazu.

So, und jetzt könnt ihr dem TO noch vollends helfen, ich habe genug von 
hier.

von Tim S. (m80)


Lesenswert?

Also erstmal ein riesiges Dankeschön an allen die sich hier so eine 
enorme Mühe gemacht haben!!!
Da die µC-programmierung für mich noch absolutes Neuland ist, versuche 
ich mir dennoch ein guten Programmierstil anzueignen. Darum finde ich es 
auch nicht falsch, wenn man auf Dinge wie Taster entprellen ( als 
Elektriker in der Hauselektrik musste ich mir noch keine Gedanken über 
die Entprellung eines Taster bei einer Stromstoßschaltung machen ;-) ). 
Da werde ich mich noch einmal mit auseinandersetzen.
Meine Hardware ist das myAVR Board MK2 Version 2.20....
Dann erstmal noch einen schönen Abend an alle...

von Tim S. (m80)


Lesenswert?

Noch eine kurze Frage..
Ist es möglich mit einem Poti einen Timer in einem bestimmten 
Zeitberreich zu steuern?? Z.B 1-10s; 1-10min...
vG

von Stefan F. (Gast)


Lesenswert?

Tim S. schrieb:
> Ist es möglich mit einem Poti einen Timer in einem bestimmten
> Zeitberreich zu steuern?

Ja sicher. Du liest die Stellung des Poti mit dem ADC aus und berechnest 
damit die Anzahl der Timer-Takte die für die gewünschte Zeit nötig sind.

Damit das ganze parallel zur Tastenabfrage funktioniert, musst du eine 
Art von Multitasking implementieren. Die klassische Methode dazu wäre 
der sogenannte Zustandsautomat.

Ich glaube das ist im Moment aber ein bisschen zu viel auf einmal für 
dich.

von EAF (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Damit das ganze parallel zur Tastenabfrage funktioniert, musst du eine
> Art von Multitasking implementieren. Die klassische Methode dazu wäre
> der sogenannte Zustandsautomat.

Zustandsautomaten und Multitasking sind 2 völlig unterschiedliche Dinge.
Multitasking ist erst bei 2 oder mehr Zustandsautomaten nötig.

Ja, beide Konzepte kommen oft im Verbund vor, aber sind weder gleich, 
noch irgendwie Äquivalent.

von Stefan F. (Gast)


Lesenswert?

EAF schrieb:
> Zustandsautomaten und Multitasking sind 2 völlig unterschiedliche Dinge.
> Multitasking ist erst bei 2 oder mehr Zustandsautomaten nötig.

Was ich meinte ist: wenn er seine zwei Tasks als Zustandsautomat 
implementiert, dann kann er sie ohne große Klimmzüge quasi parallel 
ausführen.

von Sebastian (Gast)


Lesenswert?

Ich versteh den Code des TO nicht. Die Endlosschleife while(1) wird nie 
verlassen, und würde sie verlassen würde das Programm enden (main(), 
nicht loop())???

LG, Sebastian

von HildeK (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Damit das ganze parallel zur Tastenabfrage funktioniert, musst du eine
> Art von Multitasking implementieren. Die klassische Methode dazu wäre
> der sogenannte Zustandsautomat.

Da braucht man doch nichts dergleichen.
Man liest die Taste, ist sie gedrückt worden, liest man den Potiwert und 
berechnet daraus die Timersettings und startet den Timer.
Typisches Beispiel: Treppenhauslicht, Dauer einstellbar.
Durch zyklisches Abfragen des Timerstands oder per Interrupt erfasst man 
das Ende der Zeitspanne - ob man nur wartet oder ob man noch was anderes 
in der Zwischenzeit tun will, ist dann egal.

Du meinst zwar prinzipiell das Selbe, aber für einen Anfänger verwirren 
die Begriffe 'Zustandsautomat' und 'Multitasking' in dem Zusammenhang 
nur.

von Stefan F. (Gast)


Lesenswert?

HildeK schrieb:
> Da braucht man doch nichts dergleichen.

Ich habe auch nicht gesagt dass man das braucht. Wir können hier jetzt 
gerne eine umfassende Diskussion dieses Themas führen, aber der versteht 
davon sicher nichts.

HildeK schrieb:
> für einen Anfänger verwirren die Begriffe 'Zustandsautomat' und
> 'Multitasking' in dem Zusammenhang nur.

Gut dass wir beide klare Vorstellungen davon haben, was der gewöhnliche 
Anfänger versteht, und was nicht. Dann sind wir beide ja die Top 
Lehrmeister hier. Man darf uns nur nicht zusammen in einen Raum lassen.

von W.S. (Gast)


Lesenswert?

Tim S. schrieb:
> Ist es möglich mit einem Poti einen Timer in einem bestimmten
> Zeitberreich zu steuern?? Z.B 1-10s; 1-10min...

Na klar, hatte ich als Bub für die selbstgebaute Belichtungskammer 
(Sperrholz) für meine Rollfilm-Fotos gebaut. Mit einer Röhre.

Bloß die relativ langen Zeiten waren auch entsprechend unzuverlässig.

W.S.

von W.S. (Gast)


Lesenswert?

Lothar M. schrieb:
> Aber die immer noch unbeantwortete Frage war doch die, was den EAF so
> anficht, dass er gleich abgeht wie Schmitz Katz.

Manche haben gelegentlich mal einen schlechten Tag.
Aber der eigentliche Sinn dieses Forums ist mMn das Geben von 
sachdienlichen Antworten. Und nicht das sich echauffieren über andere.

OK, manchmal geht es einem über die Hutschnur, wenn bei einer Anfrage zu 
erkennen ist, daß da aus schlichter Faulheit andere animiert werden 
sollen, jemandem die Arbeit (z.B. des eigenen Lesens von Datenblättern) 
zu machen. Oder wenn ein Moderator schlichten Unfug schreibt und sich 
trotz dezenter Korrektur seiner Behauptungen so sehr fachlich überlegen 
fühlt, daß er dann noch dagegen schreibt, anstatt mal nachzulesen.

W.S.

Beitrag #6883960 wurde von einem Moderator gelöscht.
von Tim S. (m80)


Lesenswert?

Hallo,
Habe mal versucht diese Funktion bei mir einzubinden.
https://www.mikrocontroller.net/articles/Entprellung#Flankenerkennung

Es ist doch richtig, dass der Funktionsaufruf in der while Schleife 
erfolgen muss?? Oder sehe ich das falsch?
vG

von EAF (Gast)


Lesenswert?

Tim S. schrieb:
> Es ist doch richtig, dass der Funktionsaufruf in der while Schleife
> erfolgen muss??

Zumindest muss sie oft genug aufgerufen werden, damit überhaupt 
entprellt werden kann.
Das gebietet die Logik.
Wenn das bei dir in einer while Schleife passieren muss, dann ist das 
wohl so.

von Stefan F. (Gast)


Lesenswert?

EAF schrieb:
> Zumindest muss sie oft genug aufgerufen werden, damit überhaupt
> entprellt werden kann.

Oder so selten, dass Entprellung nicht mehr nötig ist.

von Tim S. (m80)


Lesenswert?

Danke!!!
Das funktioniert erstmal so alles...
Jetzt noch damit die switch case Geschichte realisieren;-) na mal 
schauen..

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Tim S. schrieb:
> Das funktioniert erstmal so alles...
Wäre jetzt ganz nett gewesen, wenn du dein Zwischenergebnis auch 
veröffentlicht hättest. Könnte ja sein, dass es einer mal brauchen 
könnte. Und schlimmstenfalls kann es immer noch als abschreckendes 
Beispiel dienen... ;-)

von Tim S. (m80)


Lesenswert?

Haha wohl eher abschreckend :-)... Na klar!
1
#define F_CPU 4000000UL
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <util/delay.h>
5
6
#define TASTERPORT PIND
7
#define TASTERBIT PIND2
8
#define LED_1 0
9
10
11
char taster(void)    //Funktion zur Flankenerkennung und Entprellung des Tasters
12
{
13
  static unsigned char zustand;
14
  char rw = 0;
15
16
  if(zustand == 0 && !(TASTERPORT & (1<<TASTERBIT)))   //Taster wird gedrueckt (steigende Flanke)
17
  {
18
    zustand = 1;
19
    rw = 1;
20
  }
21
  else if (zustand == 1 && !(TASTERPORT & (1<<TASTERBIT)))   //Taster wird gehalten
22
  {
23
    zustand = 2;
24
    rw = 0;
25
  }
26
  else if (zustand == 2 && (TASTERPORT & (1<<TASTERBIT)))   //Taster wird losgelassen (fallende Flanke)
27
  {
28
    zustand = 3;
29
    rw = 0;
30
  }
31
  else if (zustand == 3 && (TASTERPORT & (1<<TASTERBIT)))   //Taster losgelassen
32
  {
33
    zustand = 0;
34
    rw = 0;
35
  }
36
37
  return rw;
38
}
39
int main(void)
40
41
{  
42
43
44
  
45
  DDRD &= ~(1<<TASTERBIT);    //Eingang gesetzt
46
  PORTD |=(1<<PIND2);        //Pull up wird eingeschaltet
47
  DDRB |=(1<<LED_1);        //Ausgang gesetzt
48
  
49
  PORTB &= ~(1<<LED_1);      //PORTB LED_1 wird ausgeschaltet
50
  
51
52
    while (1) 
53
    {
54
    
55
    char tasterein=taster();  //Funktonsaufruf: Rückgabewert (rw) von der 
56
                  //Funktion Taster wird an Variable tasterein übergeben
57
  
58
    
59
    if(( (tasterein==1)))    //Wenn rw=1 LED_1 wird eingeschaltet
60
    {
61
      PORTB |= (1<<LED_1);  //Wenn erfolgreich wird LED_1 eingeschaltet
62
      _delay_ms(3000);
63
      
64
      
65
    }
66
    else            //ansonsten aus
67
    
68
    
69
    {
70
      PORTB &= ~(1<<LED_1);
71
      
72
    }
73
    
74
    }// while Ende
75
  return 0;
76
}  //ende main
Ist das so ok?

: Bearbeitet durch Moderator
von Udo S. (urschmitt)


Lesenswert?

Was mir sofort auffällt in der Funktion taster:

  static unsigned char zustand;
  char rw = 0;

  if(zustand == 0 && !(TASTERPORT & (1<<TASTERBIT)))   //Taster wird
gedrueckt (steigende Flanke)

zustand ist eine lokale Variable aud dem Stack. Damit ist sie 
uniitialisiert.
Du benutzt sie in dem if mit inem zufälligen Wert.
Lokale Variablen immer erst zuweisen oder mit 0 initialisieren bevor du 
sie verwendest.
Wenn das im Moment funktioniert dann nur zufällig weil taster() als 
einziges aufgerufen wird und deshalb zustand immer die gleiche 
Stackposition benutzt.

Du musst hier Zustand entweder static oder global machen.

von Johannes S. (Gast)


Lesenswert?

Wie oft muss man denn static vor eine Variablendeklaration schreiben 
damit sie static wird?

von EAF (Gast)


Lesenswert?

Udo S. schrieb:
> zustand ist eine lokale Variable aud dem Stack. Damit ist sie
> uniitialisiert.

zustand ist eine statische Variable und wird somit sehr wohl 
initialisiert.

von Tim S. (m80)


Lesenswert?

Hallo,
ich hänge leider immer noch an meiner Switch case Verzweigung:-(!
Mein Ziel ist es, dass eine Anweisung in einem case solange ausgeführt 
wird bis der Taster betätigt wird. Nach Betätigung desselben Taster´s 
soll ein Sprung in die nächste case Anweisung erfolgen. Sobald die letze 
case Anweisung erreicht ist, soll wieder zurück in case 1 gesprungen 
werden...
goto einzusetzen soll ja eigentlich vermieden werden. Jemand von euch 
eine Idee?
VG Tim

#define F_CPU 4000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <inttypes.h>


#define TASTERPORT PIND
#define TASTERBIT PIND2
#define LED_1 0
#define LED_2 1


char taster(void)    //Funktion zur Flankenerkennung und Entprellung des 
Tasters
{
  //_delay_ms(300);
  static unsigned char zustand=0;
  char rw = 0;

  if(zustand == 0 && !(TASTERPORT & (1<<TASTERBIT)))   //Taster wird 
gedrueckt (steigende Flanke)
  {
    zustand = 1;
    rw = 1;
  }
  else if (zustand == 1 && !(TASTERPORT & (1<<TASTERBIT)))   //Taster 
wird gehalten
  {
    zustand = 2;
    rw = 0;
  }
  else if (zustand == 2 && (TASTERPORT & (1<<TASTERBIT)))   //Taster 
wird losgelassen (fallende Flanke)
  {
    zustand = 3;
    rw = 0;
  }
  else if (zustand == 3 && (TASTERPORT & (1<<TASTERBIT)))   //Taster 
losgelassen
  {
    zustand = 0;
    rw = 0;
  }

  return rw;
}
int main(void)

{

  DDRD &= ~(1<<TASTERBIT);    //Eingang gesetzt
  PORTD |=(1<<PIND2);        //Pull up wird eingeschaltet
  DDRB |=(1<<LED_1);        //Ausgang gesetzt
  DDRB |=(1<<LED_2);        //Ausgang gesetzt

  PORTB &= ~(1<<LED_1);      //PORTB LED_1 wird ausgeschaltet
  PORTB &= ~(1<<LED_2);      //PORTB LED_2 wird ausgeschaltet
  //GICR |= (1 << INT0);      //PD2 Interrupt wird eingeschaltet
  //MCUCR |= (1 << ISC00);    //Wird bei jeder Flanke eingeschaltet
  //sei();            //Setze I-Bit in SREG
  while (1)
  {
      //PORTB &= ~(1<<LED_1);      //PORTB LED_1 wird ausgeschaltet

       // PORTB &= ~(1<<LED_2);      //PORTB LED_1 wird ausgeschaltet


    char tasterein=taster();  /*Funktonsaufruf: Rückgabewert (rw) von 
der
                  Funktion Taster wird an Variable tasterein übergeben*/

    uint8_t u8_cntr = 0;



    if(( (tasterein==1)))

    {
      //for(u8_cntr=0; u8_cntr<=0;u8_cntr++);
      //++u8_cntr;        //hier soll inkrementiert werden
      //u8_cntr=0;
      u8_cntr=u8_cntr+1;


    }

    switch(u8_cntr)


    {

      case (uint8_t)1:

      do
      {
        PORTB |= (1 << LED_1);
        //_delay_ms(3000);

      }
      while (tasterein ==1);
      {

        u8_cntr=u8_cntr++;
      }

      break;

      case (uint8_t)2:

      PORTB |= (1 << LED_2);

      _delay_ms(3000);

      break;

      default:

      break;

    } //switch ende

  }    // while Ende
  return 0;
}     //ende main
//Interrupt Routine für externe Interrupt
/*ISR(INT0_vect)
{
  PORTB ^= (1<<LED_2);    //Toggle LED_2
}*/

von Gener Vter (Gast)


Lesenswert?

Tim S. schrieb:
> Jemand von euch eine Idee?

Was bitte ist an dem Text "Wichtige Regeln - erst lesen, dann posten!"
nicht zu verstehen? Gibt es Probleme im Detail oder ist die
Schrift unleserlich?

von kseege (Gast)


Lesenswert?

Tim S. schrieb:
> Jemand von euch eine Idee?

Mehrere.

Aus meiner Sicht gehört dein Programm bereits in die Kategorie, die
Roedy Green in "How to write unmaintainable Code" beschrieben hat.

Mein Eindruck ist darüberhinaus, daß Du den Unterschied von
"Top down" und "Bottom up" Programmierung nicht kennst.

Wer einfach mal was eintippt und schaut, ob es funktioniert, der
sollte "Bottom Up" programmieren, weil man dann sofort sieht,
wo die Fehler liegen.
Wer "Top down" programmiert sollte einen In-Circuit-Emulator oder
einen Debugger benutzen und sich im Einzelschrittmodus oder per
Breakpoints durch sein Programm hangeln.

Du programmierst aber "Top down", alles wird komplett in einem riesigen
Hefekuchen verrührt und schaust, ob es klappt. Das funktioniert nur
bei den absoluten Genies. Die Kombination "Top down" und "Schaun mer 
mal"
ist toxisch. Daher mein Rat:
Entweder einen Debugger und Simulation benutzen (Atmel Studio könnte 
das),
oder auf "Bottom Up" umschalten, in sinnvoller Reihenfolge nach und nach 
immer nur eine(!) Funktion einflicken und schauen, was passiert.

Die Kombination von Programmlogik und hardwareabhängigem Bitgeklapper
ist ebenfalls abschreckend, nur Masochisten quälen sich durch sowas 
durch. Dafür wurden Unterprogramme erfunden.

Ich drücke Dir die Daumen, daß Du vorankommst!

von Tim S. (m80)


Lesenswert?

Hallo,
Erstmal Danke für die Kritik, aber wie soll man sowas übersichtlicher 
schreiben? Ich habe eine seperate Funktion zur Entprellung und 
Flankenerkennung auf die ich in meinem Hauptprogramm zugreifen kann. Das 
kann doch eigentlich nicht falsch sein. Des weiteren folgt in der Main 
nur die Switch-Case Anweisung mehr nicht.
Vg

von Zupfal (Gast)


Lesenswert?

Lothar M. schrieb:
> EAF schrieb:
>
>> Klartext: Diese Salve war unanständig, eines Moderators unwürdig!
>
> Wo zur Hölle ist da eine Salve? Muss ich mich jetzt abmelden und anonym
> schreiben, damit sich nicht irgendwer irgendwie auf den Schlips getreten
> fühlt? Habe ich hier irgendwo den Moderator "raushängen" lassen? Darf
> ein Moderator auch als offensichtlicher User nur "weichgespülte" Töne
> von sich geben?
>> Oder hat man hier absichtlich den Bock zum Gärtner gemacht?
>
> Noch viel lächerlicher gehts aber nimmer, das ist dir hoffentlich klar.
> [/offtopic]

Nein lieber Lothar.
Da hat er schon recht.
Großmut kommt vor dem Fall !

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Tim S. schrieb:
> Erstmal Danke für die Kritik, aber wie soll man sowas übersichtlicher
> schreiben?

Erst einmal die korrekten Formatierungs-Tags benutzen.
Dann noch sauber einrücken.

Man kommentiert nichts, was sowieso bereits im Quelltext steht.
Dies ist also Quatsch:
1
int a = 1 + 2;   // Addiere 1 und 2 und lege das Ergebnis in die Integer-Variable a ab.

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.