Forum: Mikrocontroller und Digitale Elektronik Tiny13 Tasten entprellen


von Rico (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

ich bin absoluter Neuling beim Thema AVR Programmierung. Bei einem 
Fortbildunglehrgang den ich gerade besuche haben wir z. Zeit das Thema 
Mikrocontrollerprogrammierung und unser Dozent hat sich als einstieg in 
das Thema das Franzispaket mit dem ATTiny 13 rausgesucht. Die Grundlagen 
sind mir so weit auch so langsam geläufig nur ein sauberes entprellen 
der Tasten mit den hier im Forum vorgestellten Routinen will mir nicht 
so gelingen. Meine Schaltung hat 2 Taster an PB3 und 4 gegen Masse, eine 
LED an PB1 die im Takt des Timers blinkt und an PB2 ist eine 
Relaissteuerung angeschlossen. Die Codeschnipsel in dem Quelltext sind 
von Hannes Lux (Melodiegenerator mit Tiny 15) und eine abgeänderte 
Vorlage aus dem Franzis Baukasten. Ziel ist es mit einem Taster das 
Relais sauber zu schalten.


Gruß Rico

von Karl H. (kbuchegg)


Lesenswert?

1
        ldi        A,5        ;Start mit Vorteiler / 1024
2
        out        TCCR0B,A
3
        ldi        A,2
4
        out        TIMSK0,A     ;Timer Interrupt freigeben

Schreib das nicht so!
Benutze die Bitnamen!
1
        ldi        A, (1<<CS02) | (1<<CS00)  ;Start mit Vorteiler / 1024
2
        out        TCCR0B,A
3
        ldi        A, (1<<TOIE0)
4
        out        TIMSK0,A     ;Timer Interrupt freigeben


Ich sehe in deinem Code nicht, wo du das einer Taste zugeordnete Bit 
wieder löscht, nachdem du den Tastendruck abgearbeitet hast.


> nur ein sauberes entprellen
> der Tasten mit den hier im Forum vorgestellten Routinen will mir
> nicht so gelingen.

Das bedeutet was genau?

Gehört jetzt zwar nicht zum Problem, aber
Code so einfach wie möglich schreiben! Gerade in Assembler
1
taste1:
2
    sbis  pinb,2
3
        rjmp  relais_an
4
    sbic  pinb,2
5
    rjmp  relais_aus
6
relais_aus:

Ein Bit kann entweder gesetzt oder gelöscht sein, aber nicht beides 
gleichzeitig. Wenn also relais_an nicht zutrifft, dann muss es 
relais_aus sein. Es gibt keine andere Möglichkeit. Daher muss man das 
auch nicht testen. Auch willst du hier eigentlich nicht das PIN Register 
abfragen, sondern das PORT Register. Denn du willst ja wissen, was du 
als letztes rausgeschrieben hast, welchen Zustand der Ausgang hat. PIN 
benutzt du, wenn es sich um einen echten Eingang handelt, also jemand 
von aussen am physikalischen Pin rumwerkelt (wie zb ein Taster)
1
taste1:
2
    sbis  PORTB,2
3
    rjmp  relais_an
4
relais_aus:

Auch solche Dinge solltest du vermeiden
1
    rjmp  ende_r
2
Ende_r:
Das ist sinnlos und zieht den Code nur unnötig in die Länge. Die 
Grundidee einen gemeinsamen Rücksprungpunkt zu haben würde ich 
allerdings nicht unbedingt in Frage stellen auch wenn es in diesem 
konkreten Fall nicht notwendig ist. Man könnte das alles so schreiben
1
taste1:
2
    sbis   PORTB,2
3
    rjmp   relais_an
4
relais_aus:
5
    cbi    PORTB,2
6
    rjmp   Schleife
7
relais_an:
8
    sbi    PORTB,2
9
    rjmp   Schleife

aber so, finde ich, ist das auch noch ok
1
taste1:
2
    sbis   PORTB,2
3
    rjmp   relais_an
4
relais_aus:
5
    cbi    PORTB,2
6
    rjmp   ende_r
7
relais_an:
8
    sbi    PORTB,2
9
Ende_r:
10
    rjmp   Schleife

Gerade in Assembler ist der Grat zwischen "zu kompakt" und "gerade noch 
lesbar aber doch noch wartbar" sehr schmal. Aber grundsätzlich ist jede 
Anweisung eine potentielle Fehlerquelle und je weniger Anweisungen du 
hast, desto weniger Fehlerquellen gibt es (daher auch den überflüssigen 
Test entfernen. Der bringt nichts ausser der Gefahr die falsche 
Testbedingung oder den falschen Pin zu erwischen)

von Joan P. (joan)


Lesenswert?

Rico schrieb:
> ich bin absoluter Neuling beim Thema AVR Programmierung.
Und warum dann in Assembler?

von Hannes L. (hannes)


Lesenswert?

Karl heinz Buchegger schrieb u.A.:

> Schreib das nicht so!
> Benutze die Bitnamen!

Es kommt immer auf die Situation an. Für "Schalter-Bits" nutze ich 
selbstverständlich die Bitnamen. Für Nummern-Bits (Zahl gibt die Zeile 
in einer Liste bzw. Tabelle an, hier die Liste der Vorteiler) bevorzuge 
ich allerdings die Zahl.

>
> Ich sehe in deinem Code nicht, wo du das einer Taste zugeordnete Bit
> wieder löscht, nachdem du den Tastendruck abgearbeitet hast.

Da wird der Hase im Pfeffer liegen... ;-)


Joan P. (joan) schrieb:

> Und warum dann in Assembler?

Vermutlich deshalb, um den Tiny13 (und damit den AVR-Kern) verstehen 
zu lernen. Der kann nämlich kein C (und auch kein Bascom), der kann nur 
Maschinencode und der ist nunmal nur in ASM 1 zu 1 notierbar. Auch dem 
noch so coolen C++-Programmierer schadet etwas ASM-Wissen nicht, wenn er 
AVRs programmieren will.

...

von Rico (Gast)


Angehängte Dateien:

Lesenswert?

Danke für die ersten Antworten. Ich habe den Quelltext jetzt den 
Hinweisen nach überarbeitet: Bitnamen statt Dezimalzahlen, unnötige 
Zeilen entfernt, und einen eigenen Zuordnungsfehler beseitigt. Leider 
funktioniert das Programm in Sachen Tastenabfrage immer noch nicht. Es 
tut sich nichts außer der blinkenden LED.
Da die Tasten ja Low-Active arbeiten weiß ich auch nicht so recht wie 
ich die Pins von PortB im Simulator im AVR Studio einstellen soll (alle 
Pins auf High bis auf jenes wo eine Taste drückt sein soll oder einfach 
alles auf Low lassen).
Danke für weiter Hinweise

Gruß Rico

von Karl H. (kbuchegg)


Lesenswert?

Rico schrieb:

> Zeilen entfernt, und einen eigenen Zuordnungsfehler beseitigt. Leider
> funktioniert das Programm in Sachen Tastenabfrage immer noch nicht. Es
> tut sich nichts außer der blinkenden LED.

:-)

Du schaltest auf Ausgang:
  PB0 und PB1

wenn du das Relais umschalten willst, änderst du den Pin: PB2

PB2 ist aber gar nicht auf Ausgang gestellt

Mach dir doch auch für das Relais und die LED ein .equ genauso wie du es 
für die Taster auch gemacht hast, dann passiert dir das nicht. 
(Übrigens: man muss das nicht t1 nennen, taster1 würde auch gehen, dann 
kann man plötzlich zb

  sbrc  TastenFlags, Taster1      ;Taste 1 bet�tigt gewesen? - nein...

im Source Code lesen :-)

Die Initialisierung würde dann zb so aussehen

    ldi    A, (1<<Led ) | (1<<Relais)
    out    DDRB,A

und das ein bzw. Ausschalten des Relais
    sbi    PORTB, Relais
bzw.
    cbi    PORTB, Relais


und das hat dann doch gleich eine ganz andere dokumentarische Qualität 
als

  cbi    portb,0

(vor allen Dingen, weil an Portpin 0 eigentlich ja gar nichts 
angeschlossen ist :-)
2 Fliegen mit einer Klappe: Ein Fehler weniger und verstehen kann man 
auch leichter was der Sinn der Sache ist

Und das beste vom ganzen: Wenn das Relais mal vom Pin 2 auf Pin 0 
umziehen muss, brauchst du nur an einer Stelle (beim .equ) ändern und 
alles andere passt sich von alleine an.

> Da die Tasten ja Low-Active arbeiten weiß ich auch nicht so recht wie
> ich die Pins von PortB im Simulator im AVR Studio einstellen soll (alle
> Pins auf High bis auf jenes wo eine Taste drückt sein soll

ganz genau so.
Denn so ist das ja auch in der Realität

von Rico (Gast)


Angehängte Dateien:

Lesenswert?

Es spielt!!!
Danke für diese Hilfe mit den letzte Korrekturen im equ Bereich stimmen 
jetzt alle Portbeziehungen. Das wichtigste was ich bislang noch nicht 
gewusst habe, sich aber jetzt geklärt hat ist das der Timer Interrupt 4 
mal durchlaufen werden muss bis das ganze als Tastendruck gewertet wird 
und bei dem langsamen Takt mit dem der Tiny aus dem Franzis-Projekt 
läuft und den 1024 Teiler dauert es ca. 2 sek bis ein Tastendruck 
ausgewertet wird. Ich hab jetzt den Teiler auf 64 reduziert und jetzt 
geht alles in Echtzeit.

Problem gelöst. Der Quelltext in diesem Beitrag enthält die 
funktionierende Fassung, falls mal ein anderer vor einem ähnlichen 
Problem steht.


Dank und Gruß Rico

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.