Forum: Mikrocontroller und Digitale Elektronik Menüsteuerung mit zwei Tasten (Up/Down) in Assembler


von Andreas K. (knuthy)


Lesenswert?

Hallo

Ich bin ein totaler Anfänger aber ich habe schon hin und wieder mal ein 
kleines Programm in Assembler geschrieben.
Ich habe jetzt eine kleine Relaisschalteinheit gebaut, ganz primitiv mit
einem ATmega 16, einem LCD, zwei Tasten und 7 Relais. Das LCD zeigt an 
den Schaltzustand an.
Die kleine Software lässt sich über eine Taste steuern. Taste drücken 
"Schalter 1" noch mal Taste drücken "Schalter 2" usw.
Die Taster hängen an int0 und int1.
Nun möchte ich aber hin und her schalten können ( vor und zurück ) und 
bekomme das nicht gebacken. :-(
Hat jemand einen kleinen Codeschnippzel für mich oder kann mir erklären 
wie man ein kleines up/down Menü mittels Interuptsteuerung in Assembler 
hin bekommt ?
Komme einfach nicht mehr weiter.

Danke schon mal im vorraus.

von oldmax (Gast)


Lesenswert?

Hi
Also, Taster an Interrupt halte ich nix von. Mach doch folgendes, was 
sich schon tausendfach bewährt hat. Nimm das EVA Prinzip. Einlesen, 
Verarbeiten und ausgeben. Dazu schreibst du dir erst einmal eine 
Routine, die die Eingänge in der Programmschleife einlesen und 
entprellen. Dazu gibt es genügend beispiele und ich hab da auch schon 
einiges dazu geschrieben. Anschließend bildest du dir eine Flanke, die 
du im Pogramm verarbeitest. Flankenbit gesetzt, dann Aktion und Bit 
zurücksetzen. Nnun muss erst wieder der Taster erneut betätigt werden, 
um ein Flankenbit zu setzen. Mit dieser Flanke kannst du nun zählen oder 
auch andere Aktionen durchführeen, aber vermutlich wirst du wohl mit 
einem Wert verschiedene Programmbereiche bearbeiten wollen.
Flanke zu erzeugen ist einfach.
Eingänge lesen
Exclusiv - Oder mit den zuletzt gelesenen Eigängen
Wenn nicht "0" dann Flankenbit durch
Und- mit altem Zustand ist fallende Flanke
Und mit neuem Zustand ist steigende Flanke
Anschließend neue Eingänge ablegen
1
RCALL Read_IO           ; Eingänge lesen
2
3
Read_IO: 
4
  IN   R15, Portx
5
  STS  New_In, R15
6
  Push R15
7
  LDS  R16, Old_In
8
  EOR  R15, R16
9
  Push R15              ; Ergebnis von R15 merken
10
  And  R15, R16         ; fallende Flanke, in R16 ist der alte Wert
11
  STS  In_To_Low, R15
12
  POP  R15              ; Ergebnis von Exclusiv Oder zurückholen
13
  POP  R16              ; neuen Eingangsstatus nach R!6
14
  And  R15, R16         ; steigende Flanke, in R16 ist der neue Wert
15
  STS  In_To_Hig, R15    
16
  STS  Old_In, R16
17
ret
 Bei der Bearbeitung prüfst du, ob ein bit in den Variablen für die 
Flanken gesetzt ist und setzt es nach Bearbeitung zurück. Hier geh ich 
davon aus, du hast die Taster an VCC Sind sie nach GND geschaltet, 
drehst du R15 gleich nach dem Einlesen vom Port mit COM-Befehl um. Die 
Entprellung ist hier noch nicht beerücksichtigt.
Gruß oldmax

von dennis (Gast)


Lesenswert?

Taster über externen interrupt kommt nicht gut, such hier einfach mal 
nach einem Artikel namens entprellung.

Für das Menü könnte ich dir Menü Nummern empfehlen, in Verbindung mit 
dem Befehl ijmp, sozusagen das durch ein flagbit welches angibt, das 
irgendeine taste gedrückt wurde, ein unterprogramm aufgerufen wird, 
welches zuerst den Befehl ijmp verarbeitet. An dem jeweiligen label 
kannst du dann auswerten, welche taste genau gedrückt wurde und. kannst 
dann entsprechend drauf reagieren. Bei deinem vorhaben ist die methode 
zwar nicht die kürzeste, aber irgendwann willst du sicher mal größere 
Menüs bauen, mit mehr tasten, da lohnt sich das dann.

Beispiele für den ijmp Befehl findest du hier im tutorial bei den 
vergleichen.

Mfg Dennis

von Hannes L. (hannes)


Lesenswert?

Andreas K. schrieb:
> wie man ein kleines up/down Menü mittels Interuptsteuerung in Assembler
> hin bekommt ?

Interrupt für Tasten ist die schlechteste Lösung...

Bei dem Betreff
> _Menüsteuerung mit zwei Tasten (Up/Down) in Assembler_
habe ich ein Verständnisproblem. Denn mit nur 2 Tasten stelle ich mir 
die Bedienung eines Menüs recht ätzend vor. Schreib' mal, wie Du Dir die 
Zuordnungen der Aktionen zu den Tastendrücken vorstellst, dann kann man 
Dir vielleicht konkret helfen. Bei der schwammigen Formulierung "Menü 
mit 2 Tasten" finde ich keinen Anfang.

Durch Menüs am LCD navigiere ich gern mit 4 Tasten oder einem Dehgeber 
mit Taster.

...

von Denis G. (denis)


Lesenswert?

steht doch da, eine Taste vor Relais +1, die zweite Taste zurück Relais 
-1 ...

von Hannes L. (hannes)


Lesenswert?

Denis G: schrieb:
> steht doch da, eine Taste vor Relais +1, die zweite Taste zurück Relais
> -1 ...

Richtig, das ist die Auswahl, welches Relais gemeint ist. Nun fehlt noch 
die Bedienung des ausgewählten Relais.

...

von Karl H. (kbuchegg)


Lesenswert?

Denis G: schrieb:
> steht doch da, eine Taste vor Relais +1, die zweite Taste zurück Relais
> -1 ...

und die dritte Taste: Relais betätigen

Oder alternativ, wenn man nur 2 Tasten hat:
  erste Taste: Relais + 1, wenn 7 -> dann 0
  zweite Taste: angewähltes Relais betätigen

Bei 7 Relais ist das noch akzeptabel.

Dreh und Angelpunkt des Ganzen ist aber, dass man ein Register dafür 
abstellt, das es die Nummer des 'aktiven' Relais hält.

Und auch ja: Tasten über Interrups sind eine schlechte Idee

von Hannes L. (hannes)


Lesenswert?

Karl Heinz Buchegger schrieb:
> erste Taste: Relais + 1, wenn 7 -> dann 0
>   zweite Taste: angewähltes Relais betätigen

Richtig, dazu muss man aber den momentanen Zustand der Relais kennen. 
Mir wäre es aber lieber, wenn man das Ding blind bedienen könnte, also 
separate Tasten für Ein/Aus hätte.

Denkbar und realisierbar wäre natürlich das Durchzappen mit kurzen 
Tastendrücken und das Schalten mit langen Tastendrücken. Aber ehe ich 
hier weiter herumspekuliere, sollte Andreas erstmal zu den bisherigen 
Antworten Stellung nehmen und die Aufgabestellung präzisieren.

...

von Peter D. (peda)


Lesenswert?

Ja, die Spekulationen zeigen sehr schön, daß die Aufgabenstellung völlig 
unausgegoren ist.
Was man sich nichtmal im Kopf überlegt hat, kann man natürlich auch 
nicht programmieren.

Überleg Dir also erstmal in Ruhe, was Du eigentlich willst. Und dann 
schreib es in Worten hin, sodaß jeder es auch verstehen kann.


Peter

von Andreas K. (knuthy)


Angehängte Dateien:

Lesenswert?

Hallo Hannes.

Erst einmal vielen dank an alle die hier posten,. Mit soviel Resonanz 
hatte ich gar nicht gerechnet.

Also mal kurz zu menem "Wunderkasten" Es handelt sich um ein 
Antennenschalter
für Sende- und Empfangsbetrieb inkl. einem 50 W Dummyload. Der 
Hardwareaufbau gestallte sich sehr aufwendig da 100w HF nicht den 
Prozessor "zu nahe kommen durften". Diese Hürde habe ich gemeistert und 
die HF macht auf dem Prossesor keinen Eindruck.
Sicherlich kann man so'n Ding viel einfacher bauen, aber das war ja 
nicht meine Antrieb. Mir ging es hauptsächlich darum die Software dafür 
zu schreiben. (learning by doing).

Zu meiner Menüvorstellung: 1. Vorwärts und rückwärts schalten (Up/Down)
                           2. In einer weiteren Entwicklungsphase
                              stelle ich mir vor ,in einem Untermenü,
                              die Eingänge zu Konfigurieren.Per längerem
                              Tastendruck in's Setup...... später.

Gut für mich, ist schon mal die Erkenntnis, das die Tastenabfrage per 
interupt nicht der bessere Weg zu seien scheint.

von Jens (Gast)


Lesenswert?

Hi,

...es ist definitiv der falsche Weg. Interrups sind dazu da um binnen 
kürzester Zeit (ns Bereich) auf Signale zu reagieren...

Bei einem Taster leigst du im 10ms Bereich. Das macht man indem man 
pollt und ggf eine kleine Entprellung schreibt. Pin checken, zählen, 
wieder checken, wenn gleicher Zustand nach x checks, dann ist das Signal 
stabil und man nimmt den Taster als gedrückt an, wenn nicht, Zähler =0 
und wieder checken.... so grob jedenfalls...

JJ

von spess53 (Gast)


Lesenswert?

Hi

>Gut für mich, ist schon mal die Erkenntnis, das die Tastenabfrage per
>interupt nicht der bessere Weg zu seien scheint.

Dann sieh dir das mal an:

http://www.mikrocontroller.net/articles/AVR-Tutorial:_Tasten

MfG Spess

von Andreas K. (knuthy)


Lesenswert?

Ja, diesem Artikel habe ich mir schon zum zigtem mal reingezogen aber 
irgend wie mach das kein Licht bei mir an. Warscheinlich sehe ich den 
Wald vor lauter Bäumen nicht.

von Jens (Gast)


Lesenswert?

angucken hilft auch nichts - lesen und verstehen schon eher...

...so eine Taste flattert halt unter Umständen wenn man sie drückt, das 
ist doch auch ganz logisch bei einem mechanischem Kontakt, der "zittert" 
halt...

Nun sieht du zu dass du deine Pinabfrage im Controller so gestaltest 
dass du etwa 5-10 mal schneller abfragst als so ein typischer Preller 
eben dauert...so hast du die möglichkeit mitzuzählen...

Man fragt also den pin ab, wenn er high (high sei mal bei gedrücker 
Taste)wird und das über x Runden bleibt ist der Tastzustand stabil, wenn 
er zwichendurch wieder low wird, zählt man wieder bei 0 los wenn er 
wieder high wird. Erst wenn x erreicht ist, ist klar, der Zustand ist 
stabil und man kann etwas machen...

Daran gibts nichts nicht zu verstehen...

JJ

von oldmax (Gast)


Lesenswert?

Hi
>Daran gibts nichts nicht zu verstehen...

Doch... gerade das ist es immer wieder, was hier nicht verstanden wird, 
sonst käme niemand auf die Idee, einen Taster per ISR abzufragen. Oder 
die Frage stellt, warum ein Zähler von Tastendrücken "Zufallszahlen" 
generiert.
Kontaktprellen muss man verstehen, dann weiß man auch, wie man damit 
umgehen muss.
Gruß oldmax

von -_- (Gast)


Lesenswert?

Jens schrieb:
> Man fragt also den pin ab, wenn er high (high sei mal bei gedrücker
> Taste)wird und das über x Runden bleibt ist der Tastzustand stabil, wenn
> er zwichendurch wieder low wird, zählt man wieder bei 0 los wenn er
> wieder high wird. Erst wenn x erreicht ist, ist klar, der Zustand ist
> stabil und man kann etwas machen...

Komische Erklärung... wahrscheinlich versteht das nur ein insider...
1. Die meisten Tasten liegen doch auf Masse, also Low
2. Bedeutung X Runden
3. Wer zählt
4. Bedeutung X erreicht

Könntest Du auf meine Punkte näher eingehen?
Vielleicht ein Flußdiagramm dazu?

Ich würde es gerne verstehen. Ich bin noch zu jung um zu sterben. :-)))

von Jens (Gast)


Lesenswert?

Hi oldmax,

>>Kontaktprellen muss man verstehen...

du meinst wohl eher wie man dieses Problem löst.

Die Frage kommt nicht auf weil das Kontaktprellen nicht verstanden wird 
sondern weil es meistens eines der ersten Dinge ist über die man 
stolpert wenn man gerade am Anfang steht. Dahinter steckt die 
Anforderung der Umsetzung des erkannten Problems in eine Softwarelösung 
- das hat mit verstehen aber meiner Meinung nach weniger zu tun...

JJ

von Karl H. (kbuchegg)


Lesenswert?

Andreas K. schrieb:

> Zu meiner Menüvorstellung: 1. Vorwärts und rückwärts schalten (Up/Down)

OK. Ich hab mir dein Ausgansgposting noch mal durchgelesen.

Es scheint so zu sein, dass du etwas machen willst, was man zb in der 
Windowsprogrammierung einen 'Radio Button' nennt.

Das heißt bei dir:

Von 7 Ausgängen ist nur einer aktiv.
Mit den Tasten schaltest du den aktiven Ausgang um 1 weiter bzw. zurück.

Ist also zu einem beliebigen Zeitpunkt der Ausgang 2 aktiv, dann bewirkt
* ein Tastendruck 'Up':
     Ausgang 2 wird abgeschaltet.
     Ausgang 3 wird eingeschaltet
* ein Tastendruck 'Down':
     Ausgang 2 wird abgeschaltet
     Ausgang 1 wird eingeschaltet

Ist es das, was du dir unter 'Menüsteuerung' vorstellst?

Da führt dann in der Tat kein Weg an einer sauberen Entprellung vorbei. 
Links wurden dir ja schon genannt.
Und ich würde nach wie vor empfehlen in einem Register die Nummer des 
'aktiven Ausgangs' zu halten. Diese Nummer wird entsprechend bei 
Tastendruck verändert und die Auswerteroutine schaltet dann die 
entsprechenden Relais ein/aus.

von Uwe (de0508)


Lesenswert?


von Jens (Gast)


Lesenswert?

1. Die meisten Tasten liegen doch auf Masse, also Low

die meisten tasten sind eckig oder rund - sie liegen auf der Platine. 
Sie sind im Grundzustand geöffnet, unterbrechen also den Stromkreis.

2. Bedeutung X Runden

Ist das eine Frage?

3. Wer zählt

ein in Software definierter Zähler? Oder wolltest du dich mit einer 
Stoppuhr daneben stellen?

4. Bedeutung X erreicht


steht oben.

>>Vielleicht ein Flußdiagramm dazu?

Poste mal einen Ansatz deines Flussdiagrammes!

>>Könntest Du auf meine Punkte näher eingehen?

Jemanden der keinen Namen hat, antworte ich eigentlich garnicht...

JJ

von -_- (Gast)


Lesenswert?

Uwe S. schrieb:
> Ok ?

Nein,
die Bilder und den Artikel dazu habe ich schon mehrfach gelesen.
Jens hat mir einen Anstoß gegeben. Nur die Punkte die ich aufgezählt 
habe sind mir nicht ganz klar.

Es muß doch dafür ein Schema geben wonach ich mich richten kann.

von -_- (Gast)


Lesenswert?

Jens schrieb:
> 1. Die meisten Tasten liegen doch auf Masse, also Low
> die meisten tasten sind eckig oder rund - sie liegen auf der Platine.
> Sie sind im Grundzustand geöffnet, unterbrechen also den Stromkreis.
> 2. Bedeutung X Runden
> Ist das eine Frage?
> 3. Wer zählt
> ein in Software definierter Zähler? Oder wolltest du dich mit einer
> Stoppuhr daneben stellen?
> 4. Bedeutung X erreicht
> steht oben.

>>>Vielleicht ein Flußdiagramm dazu?

> Poste mal einen Ansatz deines Flussdiagrammes!

>>>Könntest Du auf meine Punkte näher eingehen?

> Jemanden der keinen Namen hat, antworte ich eigentlich garnicht...

Also doch nur für insider?

von Jens (Gast)


Lesenswert?

...nein.

als erstes bitte mal eine vollständige Frage stellen. Wo hakt es denn 
mit dem Verständnis? Oder ist es vielleicht so, das die Vorkenntnis wie 
ein Controller arbeitet nicht vorhanden ist?

Wir alle hier können nicht erahnen was du nicht verstehst, dazu muss man 
erstmal verstehen was nicht verstanden wird...

Diese Erkenntnis ist die Basis um hier im Forum eine vernünftige Antwort 
zu bekommen :-)

JJ

von Karl H. (kbuchegg)


Lesenswert?

-_- schrieb:
> Uwe S. schrieb:
>> Ok ?
>
> Nein,
> die Bilder und den Artikel dazu habe ich schon mehrfach gelesen.
> Jens hat mir einen Anstoß gegeben. Nur die Punkte die ich aufgezählt
> habe sind mir nicht ganz klar.

Was daran ist unklar?

Taster werden sinnvollerweise so eingebaut, dass beim Drücken der Taster 
geschlossen wird und so der Taster eine Verbindung nach Masse herstellt.

Um das Prellen auszuschalten benutzt man die Information
* Taster prellen nicht ewig. Irgendwann hat sich die Feder im Taster 
beruhigt und bleibt dann im Zustand 'geschlossen'.

* Was wird man daher tun?
Man wird mit dem Auftreten des ersten Kontaktes diesen nicht sofort als 
'Taster geschlossen' werten, sondern einfach mal eine gewisse Zeit 
abwarten und nachsehen, was da so am Eingang passiert. Ändert sich der 
Pegel in diesem Zeitraum wieder, dann prellt die Taste immer noch. 
Findet man den Eingang aber eine gewisse Zeit lang in immer demselben 
Zustand vor (und ist diese Zeit größer als das vermutete Prellen), dann 
kann man davon ausgehen, dass sich alles beruhigt hat und die Taste 
jetzt (für die nächste Zeit) dauerhaft als geschlossen zu betrachten 
ist. Denn: Kein Mensch kann eine Taste so schnell drücken und wieder 
loslassen, dass man das mit Prellen verwechselt. Prellen findet im 
Millisekunden bereich statt, Drücken und Loslassen dauert aber meistens 
mit Sicherheit länger als 1/10 Sekunde. Und das ist eine völlig andere 
Zeitdimension.

von Uwe (de0508)


Lesenswert?

Hallo - Namen kennen wir jetzt nicht -.

Ich hatte mich in den Anfängen auch mit Entpressen beschäftigt und dann 
auf die Erklärungen in den beiden Thread zurückgegriffen:

Beitrag "Tasten entprellen - Bulletproof"
Beitrag "Entprellen für Anfänger"

Nun verwende ich die Routinen von Peter Dannegger in einer angepassten 
Version in "C" und denke über das 'Problemchen' nicht mehr nach.

Nur noch das Modul einbinden, die Tasten und den Port definieren, den 
Timer auf das Debounce-Intervall einstellen und los geht es.

Ich verwende meistens einen Timer (0) mit 1ms und das Debounce-Intervall 
von 10ms. Je nach Anwendung aktiviere ich dann noch Defines um die 
Repeat (get_key_short() + get_key_long()) oder die Release Funktionen 
(get_key_release()) frei zu schalten.

Vielleicht hilft dir das auch weiter.

Ok ?

von Peter D. (peda)


Lesenswert?

Andreas K. schrieb:
> Zu meiner Menüvorstellung: 1. Vorwärts und rückwärts schalten (Up/Down)

Ich vermute mal, Du meinst damit einen Umschalter, d.h. es ist immer nur 
ein Relais gezogen.
Dann müßte man noch wissen, erfolgt die Umschaltung unterbrechend oder 
überbrückend.

Oder soll die Umschaltung ohne Last erfolgen?
D.h. die HF wird ausgeschaltet, das alte Relais abgeschaltet, das neue 
zugeschaltet und dann wieder die HF ein. Und bei jedem Schritt einige 
100ms warten. Das wird dann eine Statemaschine.


Peter

von Andreas K. (knuthy)


Lesenswert?

Hallo Karl Heinz

Dein Ansatz sieht viel verspechend aus. Ich werde das mal daran 
probieren..

An Peter

Der Amateurfunk ist keine zeitkritische Anwendung :-)
Geschaltet wird nur lastfrei ( 1000 Euro Hardware werden es danken !) 
und wenn es ein,zwei oder drei sekunden dauert ist das durchaus ok.


An sonsten glaube ich dass das jetzt hier vollkommen abschweift. Es geht 
nur um ein programmtechnisches hin und herschalten !

Relais 1 an, Relais 1 aus, Relais 2 an ..... usw.

von Uwe (de0508)


Lesenswert?

Hallo Andreas,

kannst Du in "C" programmieren ?

Dann könnte auch dieser Scheduler [1] und die tolle Idee dahinter, die 
richtige zeitliche Abfolge von Programmfolgen sehr erleichtern.
Man(n) muss aber erst mal hinter die Idee des Beispielcodes kommen.

Sehr zu empfehlen !

Link:
[1] Beitrag "Wartezeiten effektiv (Scheduler)"

von Peter D. (peda)


Lesenswert?

Andreas K. schrieb:
> An sonsten glaube ich dass das jetzt hier vollkommen abschweift. Es geht
> nur um ein programmtechnisches hin und herschalten !

Wie Du meinst. Ich wollte nur drauf hinweisen, was Dein Programm alles 
beachten muß.

Wir haben ähnliche Anwendungen, Hochspannung (bis 30kV) muß lastfrei 
umgeschaltet werden, sonst kleben die Relais.
Der MC überwacht alle Netzteile, daß ja nicht ein Relais unter Spannung 
schaltet. Er macht also eine komplexe Ablaufsteuerung, die auch 
Wartezeiten beinhaltet, bis die Netzteile vollständig entladen sind. 
Dann schaltet er um und fährt die Netzteile wieder langsam hoch.


Peter

von oldmax (Gast)


Lesenswert?

Hi
Ich will da noch mal mit einsteigen. Macht es ihm doch nicht so schwer 
und lasst ihn das ruhig in Assembler machen. Ist doch gar nix dabei.
Also, deine Tasten schalten nach GND. Ist ja auch praktisch, da kannst 
du die internen Pull-Up Widerstände des Controllers nutzen. Wie weit 
bist du mit deinem programm. Timer und IO-Parametrierung klar?

Ich zeig dir mal, wie ich das löse. Meine Programmschleife besteht aus 
Loop:
 gefolgt von Read_IO
 mit Chk_IO teste ich die Ereignisse
 und mit Write_IO setze ich die Ausgänge.
kurz
1
Loop:
2
  RCALL  Read_IO
3
  RCALL  IO_Debounce
4
  RCALL  Chk_IO
5
  RCALL  Write_IO
6
RJMP  Loop
Die Initialisierung hab ich mal weggelassen, aber ich setze vorraus, das 
deine Timer_ISR im ms-Takt aufgerufen wird.
Die Read_IO hab ich ja schon einmal beschrieben, aber jetzt mal mit 
einer "Entprellung".
1
;------Lesen aller Eingänge und Signalanpassung ---_--
2
;*****************************************************
3
;*   Port D 2-7 Eingänge (Taster)    *
4
;*  Port D 0  Bit 0 + 1 serielle Verbindung  *
5
;***************************************************** 
6
Read_IO:        ; Eingänge einlesen
7
  In   R16, PInD  ; Port B lesen
8
  COM  R16    ; Bits drehen
9
  ANDI  R16, 0b11111100 ; Bits 0 und 1 ausblenden
10
  STS  New_In, R16
11
End_Read_IO:
12
  
13
RET
14
15
;*********************************************************
16
;----------------- Eingänge entprellen -------------------
17
;*********************************************************
18
;* für 6 Eingänge werden bei Wechsel der Pegel separate  *
19
;* Prellzeiten gestartet. Nach Ablauf der Prellzeit ist  *
20
;* in Work_Reg das gültige Eingangsbit gesetzt.       *
21
;*********************************************************
22
IO_Debounce:        ; Prellzeit
23
24
  LDS  R16, In_Debounce  ; Eingänge unter Kontrolle
25
  LDS  R17, New_In    
26
  MOV  Ablage_A, R17
27
  EOR  R16, R17  
28
  BREQ  Deb_Time    ; keine Änderung mehr
29
;--------------------------  prellt noch -------------------------------- 
30
  STS  In_Debounce, R17
31
  LDI  R17, 5            ; für 50 mSekunden Prellzeit
32
  STS  Deb_Time, R17
33
  RJMP  End_Dbnc
34
;------------------------ Ablauf Prellzeit ------------------------------
35
Deb_Time:      ; Prellzeit abwarten
36
  LDS  R16, Deb_Time
37
  CPI  R16, 0
38
  BREQ  End_Dbnc    ; keine Prellzeit gesetzt
39
;--------------------  Millisekunden Flag auswerten ---------------------
40
  LDS  R18, Time_Flag
41
  ANDI  R18, 0b00000001  ; mSek Flag aus Timer bearbeiten
42
  BREQ  End_Dbnc
43
;------------------------------ Flag bearbeiten -------------------------
44
  LDS  R18, Time_Flag
45
  ANDI  R18, 0b11111110   ; 10 mSekunden
46
  STS  Time_Flag, R18  ; und quittieren
47
  Dec   R16  
48
  STS  Deb_Time, R16
49
  CPI  R16, 0    ; Prellzeit 50 mSekunden abgelaufen ?
50
  BRNE  End_Dbnc
51
;--------------- Flankenmerker 0->1 setzen ------------------
52
  MOV  R17, Ablage_A
53
  LDS  R16, Old_In    ; Eingang ist stabil
54
  MOV  Ablage_B, R16
55
  EOR  R16, R17             ; steigende Flanke  in Reg_A bilden
56
  MOV  R17, Ablage_A    ; letzten gültigen Status
57
  AND  R17, R16
58
  LDS  R18, Event_To_1
59
  OR  R17, R18
60
  STS  Event_To_1, R17    ; neuen Eingang merken
61
  MOV  R17, Ablage_B
62
  AND  R17, R16
63
  LDS  R18, Event_To_0
64
  OR  R17, R18
65
  STS  Event_To_0, R17
66
  MOV  R17, Ablage_A    ; Flankenmerker laden
67
  STS  Old_In, R17
68
End_Dbnc:
69
RET
Nachn dieser Routine hast du die Eingänge von Port D 2- 7 in den 
Variablen "Event_To_1" und "Event_to_0" stehen, wenn das prellen vorbei 
ist. Sicher,von den Befehlen her geht's auch kompakter, aber ich denke, 
so ist es leichter nachvollziehbar. Alles, was du jetzt in Chk_IO machen 
musst, ist die Auswertung der Flankenbits. Du kannst beispielsweise mit 
dem Betätigen des Tasters ein Relais abschalten und beim loslassen eins 
vor oder zurückschalten und Relais wieder zuschalten. Als Ausgang 
definier ich mal Port B. Wenn du keinen externen Quarz dran hast 
(bezieht sich auf Atmega8), hast du ein volles Byte, also 8 Ausgänge. 
Auch hier verwendest du eine Variable für die Ausgangsbits als 
Zwischenpuffer.
Da dein Programm nur auf die Flags reagiert, wird die Schleife ständig 
durchlaufen, das Ereignis aber nur einmal bearbeitet.
1
Chk_IO:
2
   LDS   R16, In_To_1
3
   Mov   R1, R16
4
   ANDI  R16, 0b00001100    ; Taster 1 und 2 abfragen
5
   BREQ  Chk_T1_off         ; Wenn Ergebnis =0, dann weiter
6
   LDS   R17, Schiebe_Var   ; Variable mit Schieberegister für Hoch/runter
7
   COM   R17
8
   LDS   R16, Ausgabe
9
   And   R16, R17           ; löscht das aktuel gesetzte Bit in der Ausgabe
10
   STS   Ausgabe, R16
11
   Mov   R16, R1
12
   ANDI  R16,0b11110011
13
   STS   In_To_1, R16       ; Flankenbit löschen
14
   RJMP  End_Chk_IO         ; Routine beenden
15
Chk_T1_Off:
16
   LDS   R16, In_To_0
17
   Mov   R1, R16
18
   ANDI  R16,0b00000100     ; jetzt nur Taster 1 abfragen
19
   BREQ  Chk_T2_off         ; Wenn Ergebnis =0, dann weiter mit Taster 2
20
   LDS   R17, Schiebe_Var   ; Variable mit Schieberegister für Hoch/runter
21
   ROR   R17                ; schiebe nach rechts
22
   BRNE  Set_Bit_ok          ; Wenn nicht 0 dann ablegen
23
   LDI   R17, 0b10000000    ; Bit 7 setzen
24
   RJMP  Set_Bit_Ok
25
Chk_T2_Off:
26
   Mov   R16, R1            ; noch mal abfallende Flanken laden
27
   ANDI  R16,0b00001000     ; jetzt nur Taster 2abfragen
28
   BREQ  End_Chk_IO         ; Wenn Ergebnis =0, dann Ende
29
   LDS   R17, Schiebe_Var   ; Variable mit Schieberegister für Hoch/runter
30
   ROL   R17                ; schiebe nach links
31
   BRNE  Set_Bit_ok         ; Wenn nicht 0 dann ablegen
32
   LDI   R17, 0b00000001    ; Bit 0 setzen
33
Set_Bit_Ok:
34
   STS   Ausgabe, R17       ; Schiebevariable in Ausgabevariable schreiben
35
   Mov   R16, R1
36
   ANDI  R16,0b11110011     ; Ereignisbits löschen
37
   STS   In_To_0, R16       ; und zurückschreiben
38
End_Chk_IO:
39
RET
Nun, es sollte klar sein, habe ich eine Taste gedrückt, ist un der 
Variablen "Ausgabe" kein Bit gesetzt. Ich hätte genausogut einfach eine 
0 hinein schreiben können. Wenn aber nicht alle Bits benötigt werden, 
kann ja sein, sollte auch nur das Bit vom Schieberegister ausgeblendet 
werden.
Ok, nun sind wir schon fast durch
1
Write_IO
2
   LDS   R16, Ausgabe
3
   ;COM   R16          ; Falls Relais auf "0"-Signal schalten...
4
   Out   PortB
5
RET
Fehlt eigentlich nur noch die Timer-ISR. Die solltest du so einstellen, 
das du den Interrupt jede msek. ausführst. Dann einfach entsprechend 
reservierte Register hochzählen, so das du beliebige Zeiten erhälst. 
z.B. ich mach dir das mal mbis zur Sekunde, ohne jetzt die Register zu 
retten,
1
Timer_ISR:
2
    Push .....
3
    LDS   R17, Time_Flag
4
    LDI   R16,10
5
    Inc   MSekunden
6
    CP    MSekunden, R16
7
    BRLO  End_Timer
8
    ORI   R17, 0b00000001      ; 10 Millisekunden
9
    CLR   MSekunden
10
    Inc   MSek_10
11
    CP    MSek_10, R16
12
    BRLO  End_Timer
13
    ORI   R17, 0b00000010      ; 100 Millisekunden
14
    CLR   MSek_10
15
    Inc   MSek_100
16
    CPI   MSek_100, R16
17
    BRLO  End_Timer
18
    ORI   R17, 0b00000100      ; 1 Sekunde
19
    CLR   MSek_100
20
    Inc   Sekunden
21
    LDI   R16, 60
22
    CPI   Sekunden, R16
23
    BRLO  End_Timer
24
    CLR  Sekunden
25
    ORI   R17, 0b00001000      ; 1 Minute
26
    ....
27
28
End_Timer:
29
    STS  Time_Flag, R17
30
    Pop  .....
31
RETI
Sollten Fehler drin sein, ich hab es nicht getestet, ist nur mal so 
schell runter geschmiert. Sollte dir aber bei deinem Problem helfen, den 
richtigen Ansatz zu finden.
Gruß oldmax

von Andreas K. (knuthy)


Lesenswert?

Aber Hallo :-)

Das ist der Lösungsansatz den ich gesucht habe.!!! Danke Dir Oldmax.
Es gibt sicherlich auch andere Wege, Aber den durchschaue ich :-)


An alle C Programmierer:
... warum Assembler ? Na ja, ich finde Assembler einfacher als C und man 
kommt mit weniger Aufwand zum Ziel. Die Größe des Programmcodes spricht 
Bände. Auch die ewige Tipperei des Makefiles macht mich schlapp. Da ich 
absolut kein Windows benutze ist Assembler die erste Wahl für mich, 
Außerdem glaube ich nicht das es irgend etwas gibt das man nicht in 
Assembler programmieren kann. Meine Unwissenheit tut da nichts zur 
Sache.

von Simon K. (simon) Benutzerseite


Lesenswert?

Andreas K. schrieb:
> An alle C Programmierer:
> ... warum Assembler ? Na ja, ich finde Assembler einfacher als C und man
> kommt mit weniger Aufwand zum Ziel. Die Größe des Programmcodes spricht
> Bände. Auch die ewige Tipperei des Makefiles macht mich schlapp. Da ich
> absolut kein Windows benutze ist Assembler die erste Wahl für mich,
> Außerdem glaube ich nicht das es irgend etwas gibt das man nicht in
> Assembler programmieren kann. Meine Unwissenheit tut da nichts zur
> Sache.

Also das sind ja wohl alles Witzpunkte. Wenn du wenigstens vernünftige 
Argumente bringen würdest ;-)

- Weniger Aufwand zum Ziel? Ich wette mit dir, dass du weniger Lines of 
Code in C hast, bei gleichem Programm
- Größe des Programmcodes ist vor 10 Jahren die Waffe der 
Assemblerjünger gewesen. Außerdem kriegst du für nichtbenutzten Flash 
kein Geld zurück.
- kein Windows? Sondern? Linux? Das ist doch mit GCC die C-Plattform 
schlecht hin
- Makefiles schreibt man, wenn überhaupt ein mal. Oder man lässt sie 
sich automatisch generieren. Das kann sogar AVR-Studio.
- Ich glaube nicht, dass es irgendwas nicht gibt, was man in C 
programmieren kann.

Du hast nur keine Lust die Sprache zu lernen, was (für mich) Ok ist. 
Aber schiebe hier nicht so einen Unsinn vor.

von Andreas K. (knuthy)


Lesenswert?

Na ganz so ist dem nicht :-)
Ich habe mit C Angefangen und bin dann bei Assembler gelandent, und ja 
es gibt kein Geld zurück, und ja du hast recht Linux ist die Oberfläche 
für C. WinAVR ist nur Portiert.
Trotzdem komme ich mit ASM besser zu recht. Es gibt für alles ein für 
und wieder. Am Ende muss das jeder für sich entscheiden.

Einen schönen Abend wünsche ich Dir noch Simon.

von Simon K. (simon) Benutzerseite


Lesenswert?

Andreas K. schrieb:
> Am Ende muss das jeder für sich entscheiden.
Wohl wahr! Jedem so wie er das will.

> Einen schönen Abend wünsche ich Dir noch Simon.
Dito

von Hannes L. (hannes)


Angehängte Dateien:

Lesenswert?

Andreas K. schrieb:
> Trotzdem komme ich mit ASM besser zu recht.

Ich auch...

Hier mal ein 4 Jahre altes Beispiel für so etwas Ähnliches (kein 
Antennenumschalter, sondern ein Antennen-Anpassgerät, dass verschiedene 
Spulen in die Zuleitung einschleift bzw. wieder herausnimmt. Statt LCD 
wird allerdings Siebensegmentanzeige benutzt.

...

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.