Forum: Mikrocontroller und Digitale Elektronik an aus per software


von hein blöd (Gast)


Lesenswert?

Hello @all,

Ich möchte gerne mit einem µC und einem Taster etwas an- und 
ausschalten.

Das Programm von Peter Dannegger ist mir bekannt und es funktioniert 
auch auf meinen µC. Nur verstehe ich den Code noch nicht.
Ich möchte es von anfang an verstehen.
Das nur zur Funktion.

Ich habe das Gefühl das man es vielleicht mit weniger Zeilen und Aufwand 
hinbekommt.

Ich bin ein newbie, bitte um konstruktive Kritik. Alles andere bringt 
mich nicht weiter.

Nun zur Frage:
Wie weit ist der von mir entstandene Code zu optimieren?

Ich danke euch.
1
.include "tn2313def.inc"
2
.device    attiny2313
3
.equ    takt = 8000000
4
/*
5
*/
6
  ldi r16, 0xFF 
7
  out DDRB, r16    ;port B->Ausgang
8
//  ldi r16, 0x00
9
//  out PORTB, r16    ;port B ->low
10
11
  ldi r16, 0x00 
12
  out DDRD, r16    ;port D->Eingang
13
  ldi r16, 0x00
14
  out PORTD, r16    ;port D ->low
15
16
aus:
17
  sbic PIND, 2    ;überspringe nächsten befehl, wenn PIND.2 1 ist - taste gedrückt
18
  rjmp aus      ;springt ins label aus -> wenn PIND.2 0 ist 
19
  rcall warte      ;entprellzeit -> aufruf von label warte
20
  cbi PORTB, 3    ;PINB.3 0
21
  sbis PIND, 2    ;überspringe nächsten befehl wenn PIND.2 0 ist - taste nicht mehr gedrückt
22
  rjmp aus         ;springt ins label aus -> wenn PIND.2 1
23
  rcall warte      ;entprellzeit -> aufruf von label warte
24
  rjmp an        ;springt ins label an
25
26
an:
27
  sbic PIND, 2    ;überspringe nächsten befehl, wenn PIND.2 1 ist - taste gedrückt
28
  rjmp an        ;springt ins label aus -> wenn PIND.2 0 ist
29
  rcall warte      ;entprellzeit -> aufruf von label warte
30
  sbi PORTB, 3    ;PINB.3 1
31
  sbis PIND, 2       ;überspringe nächsten befehl wenn PIND.2 0 ist - taste nicht mehr gedrückt
32
  rjmp an        ;springt ins label aus -> wenn PIND.2 1
33
  rcall warte      ;entprellzeit -> aufruf von label warte
34
  rjmp aus      ;springt ins label aus
35
36
warte:               ;wartezeit wegen kontaktprellen erzeugen
37
  ldi R19,67         ;lade R19 mit 67
38
LOOP0:               ;äussere schleife
39
  ldi R18,198        ;lade R18 mit 198
40
LOOP1:          ;innere schleife
41
  dec R18       ;erniedrige R18 
42
  brne LOOP1         ;solange R18 nicht 0 ist, bleib in der schleife
43
  dec R19            ;erniedrige R19
44
  brne LOOP0         ;solange R19 nicht 0 ist, bleib in der schleife
45
  ret                ;wenn schleifenzeit um ist, hüpfe dahin, wo du hergekommen bist

von Dennis B. (danrulz81)


Lesenswert?


von Zittermann (Gast)


Lesenswert?

@Hein Blöd
Das Entprellen wird noch in 20 Jahren ein Thema sein, ueber das sich die
Leute streiten. Wenn Deine Methode funktioniert, behalte sie bei.
Es bringt mehr, eigenen Code zu entwickeln als sich in die Gedan-
kengaenge anderer hineinzusteigern. Wenn Du das gesamte Programm selbst
geschrieben hast, anstatt eine Routine von hier und eine von da 
zusammmen
zu kopieren, dann ist eine viel groessere Zufriedenheit da.

gez. Zittermann

von Peter D. (peda)


Lesenswert?

Zittermann schrieb:
> Wenn Deine Methode funktioniert, behalte sie bei.

Das Problem dabei ist nur, zu verifizieren, ob es auch wirklich 
fehlerfrei funktioniert.
Z.B. wenn man sich elektrostatisch geladen dem Draht zur Taste annähert.
Oder wenn noch ein langes Kabel zum Taster führt, welches parallel zur 
Netzleitung zum Staubsauger liegt.


Zittermann schrieb:
> Es bringt mehr, eigenen Code zu entwickeln als sich in die Gedan-
> kengaenge anderer hineinzusteigern.

Wenn man sich hineinsteigern muß, sollte man das Programmieren besser 
sein lassen. Zum Programmieren sollte man keinen Stress haben, sonst 
macht man nur Fehler.
Wenn man Code von Leuten, die schon ein paar Tage länger programmieren, 
verstehen will (und kann), ist das jedoch ein großer Vorteil. Dann ist 
man als Programmierer auf dem richtigen Weg.
Als Programmierer darf man sich nicht als Künstler sehen, sondern eher 
als Forscher, die voneinander gegenseitig lernen.


Zittermann schrieb:
> Wenn Du das gesamte Programm selbst
> geschrieben hast, anstatt eine Routine von hier und eine von da
> zusammmen
> zu kopieren, dann ist eine viel groessere Zufriedenheit da.

Die Zufriedenheit ist aber nicht von Dauer.
Die Delays werden Dir bei komplexeren Programmen irgendwann auf die Füße 
fallen.


Peter

von hein blöd (Gast)


Lesenswert?

Kann keiner näher auf meine Frage eingehen?

@Peter:
Ich habe Deine Infos mir zu Herzen genommen.
Nur würde ich das gerne von Anfang an verstehen.

Man lernt auch laufen mit einem Schritt nach dem anderen.

Vielen Dank

BR

von Karl H. (kbuchegg)


Lesenswert?

hein blöd schrieb:
> Kann keiner näher auf meine Frage eingehen?

Welche?
Die hier?
> Nun zur Frage:
> Wie weit ist der von mir entstandene Code zu optimieren?

Als Newbie solltest du dich um 'Optimierung' überhaupt noch nicht 
kümmern. Zum jetzigen Zeitpunkt gibt es nur 1 Frage: Funktioniert er 
bzw. unter welchen Nebenbedingungen funktioniert er nicht mehr.

> @Peter:
> Ich habe Deine Infos mir zu Herzen genommen.
> Nur würde ich das gerne von Anfang an verstehen.

Was würdest du gerne verstehen?
Die Danegger Entprellung?

Die ist so trickreich, das ist ok, wenn man die nicht versteht. Ist eine 
der wenigen Ausnahmen zur Regel, dass man als Anfänger jeglichen 
übernommenen Code verstehen sollte. An der genauen Funktionsweise 
beissen sich auch gestandene Profis die Zähne aus, so trickreich ist 
das. Hat man sie erst mal durchschaut, ist sie einfach. Aber bis man sie 
in allen Details versteht, .....

von Hannes L. (hannes)


Lesenswert?

hein blöd schrieb:
> Kann keiner näher auf meine Frage eingehen?

Beim Optimieren Deines Programmbeispieles werde ich Dir nicht helfen, 
denn das führt zu nichts.

Nimm die Dannegger-Bulletproof-Entprellung und analysiere sie. Es 
reicht, wenn Du sie ein einziges mal verstehst und dann nur noch 
benutzt. Um damit Dein Bit zu toggeln (an/aus-umschalten), kannst Du das 
Byte (mit Deinem Bit) mit key_press EXORen und key_press danach löschen. 
Somit kippt das Bit in Deinem Byte bei jedem Tastendruck in die andere 
Richtung. Dazu muss es natürlich an derselben Bitposition wie der Taster 
sein. Anhand dieses Bits kannst Du dann durch Bit-Prüfung (sbrs/sbrc) 
Schaltvorgänge auslösen. Das funktioniert ohne jegliche Wartezeiten, das 
Programm kann also nebenher noch genügend andere Dinge erledigen.

>
> @Peter:
> Ich habe Deine Infos mir zu Herzen genommen.
> Nur würde ich das gerne von Anfang an verstehen.

Diesen Thread hast Du auch gelesen?
Beitrag "Bitte um Erklärung der Entprellroutine"

>
> Man lernt auch laufen mit einem Schritt nach dem anderen.

Eben. Und manchen Schritt muss man wiederholen, wenn man ihn zuvor nicht 
verstanden hat.

>
> Vielen Dank
>
> BR

...

von hein blöd (Gast)


Lesenswert?

Hannes Lux schrieb:
> Beim Optimieren Deines Programmbeispieles werde ich Dir nicht helfen,
>
> denn das führt zu nichts.

Das möchte ich auch nicht.
Nur ich möchte wissen ob ich auf den richtigen Holzweg bin.

Ich benötige kein Code, nur ein paar konstruktive Hinweise.

Vielen Dank.

BR

von Mitarbeiter (Gast)


Lesenswert?

hein blöd schrieb:
> Ich benötige kein Code, nur ein paar konstruktive Hinweise.

Mein Tipp: guck dir an, was andere machen.
Und dann trotzdem was eigenes schreiben.

So mach ich das. Erstmal abkupfern, bzw. Ideen sammeln, und danach doch 
eigenen Code schreiben. Es sei denn, das "geklaute" ist sehr gut, und 
habe es wirklich verstanden.

von hein blöd (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Was würdest du gerne verstehen?
>
> Die Danegger Entprellung?

Jaein, bei der Software vom Peter  begreife ich es nicht wie man es 
ändern muss z. B. das wenn ich am Eingang von PD1 ein Taster betätigen 
möchte das bei PB3 dann meine LED zum leuchten bekomme.

Bei der Software wird gleich der ganz PD am eingang somit entprellt.

Denn wenn ich nur zwei Tasten benötige und ich möchte den Rest meiner 
I/Os nicht verschwenden.

Ich hoffe das ich mich einigermassen ausdrücken konnte.

Vielen Dank

BR

von Loonix (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Die Delays werden Dir bei komplexeren Programmen irgendwann auf die Füße
> fallen.

100% ACK

Aber manch einer muss eben erst den Schmerz erleben, bevor er seinen 
Horizont erweitert. Das ist keine Schande, aber die eigene verschwendete 
Zeit. Muss also jeder für sich entscheiden wie viel Zeit man liegen 
lassen kann.

von Karl H. (kbuchegg)


Lesenswert?

hein blöd schrieb:
> Karl heinz Buchegger schrieb:
>> Was würdest du gerne verstehen?
>>
>> Die Danegger Entprellung?
>
> Jaein, bei der Software vom Peter

Bitte sag nicht 'Bei der Software vom Peter'
Peter hat wahrscheinlich hunderte Codeschnipsel hier im Forum 
hinterlassen.

Sag konkret: Dieses und jenes Codestück.
Garniert mit einem Link bzw. kopiere es hier rein.

Dann weiß jeder wovon du eigentlich sprichst.

von Karl H. (kbuchegg)


Lesenswert?

hein blöd schrieb:

> Bei der Software wird gleich der ganz PD am eingang somit entprellt.
>
> Denn wenn ich nur zwei Tasten benötige und ich möchte den Rest meiner
> I/Os nicht verschwenden.

Reden wir von der Komfort-Lösung?

Du musst nicht einen kompletten Port für Taster abstellen.
Du kannst. Aber du musst nicht.

Frag die entsprechenden Taster einfach nicht ab und sie werden dir nicht 
in die Quere kommen. Es spricht auch nichts dagegen, am Tastenport 
einige Pins auf Ausgang zu stellen. Die Auswertung berücksichtigt sie 
zwar als sowas ähnliches wie Tasten. Da das aber keine zusätzliche 
Rechenzeit kostet, spielt es weiter keine Rolle.

von Hannes L. (hannes)


Lesenswert?

hein blöd schrieb:
> Hannes Lux schrieb:
>> Beim Optimieren Deines Programmbeispieles werde ich Dir nicht helfen,
>>
>> denn das führt zu nichts.
>
> Das möchte ich auch nicht.
> Nur ich möchte wissen ob ich auf den richtigen Holzweg bin.
>
> Ich benötige kein Code, nur ein paar konstruktive Hinweise.

Na gut, ich beziehe mich auf die Bulletproof-Version in ASM...

Mechanische Tasten prellen. Um sicher zu sein, dass die Taste betätigt 
oder unbetätigt ist, liest man den Zustand in regelmäßigen Zeitabständen 
ein und vergleicht ihn mit dem vorher eingelesenen Zustand. Dabei zählt 
man mit, wie oft der neue Zustand sich wiederholt. Man braucht also eine 
Zeitverzögerung und einen Entprellzähler.

Zur Zeitverzögerung sollte man einen Timer-Interrupt nutzen. Dies 
bietet im Gegensatz von Warteschleifen die Möglichkeit, dass der 
Controller außerhalb der Tastenabfrage noch andere Dinge tun kann. Bei 
Verwendung von Warteschleifen muss die CPU ja Takte zählen und hat keine 
Zeit, andere Dinge abzuarbeiten.

Der Entprellzähler soll die Anzahl der gleichen Zustände des 
Tastereingangs zählen, jeder Tastereingang braucht seinen eigenen 
Zähler. Man könnte nun jedem Taster ein Byte (Register, Variable) 
spendieren, das wäre aber pure Verschwendung und würde bei mehreren 
Tasten auch den Programmablauf verlangsamen. Stattdessen nimmt man zwei 
Register als Zähler für 8 Taster, wobei jeder Zähler 2 Bit hat 
(Zählumfang 0 bis 3), die sich in unterschiedlichen Registern befinden. 
Das eine Register enthält also das Bit 0 aller 8 Zähler, das andere 
Register das Bit 1 aller Zähler. Der große Vorteil besteht darin, dass 
alle 8 Zähler mit wenigen Logikbefehlen gleichzeitig arbeiten. Wenn Du 
den Zähler verstehen willst, dann schau Dir an, wie man einen Zähler mit 
Logikgattern realisiert.

Außer den beiden Zählerbytes gibt es noch den Tastenstatus (Key_State) 
und die Tastenflags (Key_Press). Im Status steht der zuletzt gültige 
Zustand der 8 Tasten. Er dient zum Vergleich mit den neuen 
Eingangszuständen und kann vom Hauptprogramm genutzt (aber nicht 
verändert!) werden, um eine momentan gedrückte Taste (Shift) zu 
erkennen. Ist nun der neu eingelesene Zustand (im Tempregister) gleich 
wie der zuletzt gültige Zustand (in Key_State), so wird der jeweilige 
Prellzähler gelöscht. Ist der Zustand anders, wird der Prellzähler 
erhöht. Erreicht der jeweilige Prellzähler den Wert 3 (Bit in beiden 
Zählerbytes gesetzt), so kommt das Bit im Tempregister durch 
(anderenfalls wird es ja per AND gelöscht) und kann den gültigen Status 
(Key_State) toggeln (EXOR). Durch ein weiteres AND wird geprüft, ob der 
(entprellte, gültige) Status jeder Taste 0 oder 1 ist. Ist er 0, wird 
das entsprechende Bit im Tempregister gelöscht. Ist er 1, so kommt das 
Bit im Tempregister durch und darf das Merkerbit im Register Key_Press 
setzen. Dieses zeigt dem Hauptprogramm, dass die entsprechende Taste neu 
betätigt wurde. Das Hauptprogramm verzweigt nun anhand der gesetzten 
Bits in Key_Press zu den Tastenbehandlungsroutinen. Diese erledigen den 
zur Taste gehörenden Job und löschen das Tastenbit in Key_Press, denn 
der Job ist ja erledigt.

Fazit:
Timer-Interrupt mit 10ms oder 20ms Aufrufintervall einrichten, darin die 
Routine der Tastenentprellung unterbringen und noch andere Dinge, die 
einen festen Zeittakt brauchen, z.B. Uhr.

Im Hauptprogramm nur das Register Key_Press auf gesetzte Bits prüfen und 
bei gesetztem Bit zur jeweiligen Behandlungsroutine springen. In dieser 
das Bit in Key_Press löschen (damit der Job nur einmal erledigt wird) 
und den Job erledigen.

>
> Vielen Dank.
>
> BR

...

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.