PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Toggle Problem



Thorsten75
06.04.2007, 19:04
Hallo,

ich möchte dass beim 5. Impuls am Portb.1, der Ausgang Portc.1 auf 1 geht.
Wie programmiert man sowas am besten?
Ich habe schon einiges versucht, aber es funktioniert nicht.
Ist eine Toggle-Abfrage am Eingang überhaupt möglich und wie?

Ratber
06.04.2007, 20:50
Für dein Problem gibt es eine Menge Lösungen.

Du kannst zb. die Flanken manuell oder mit Interrupt (Pinchange) detektieren,Zählen und dann beim 5. Mal deinen Ausgang zu setzen.

Thorsten75
06.04.2007, 22:13
ja, manuell mit Flanken hört sich gut an , aber wie müßte das Programm konktret aussehen, bräuchte da mal ein Beispiel

Ratber
07.04.2007, 01:53
Ja,woher kommen die Impulse ?
Taste oder ein sauberes Signal ?

Für ne Taste reicht dieser Codeschnipsel aus




Do 'Hauptschleife
Debounce Pinb.1 , 1 , Taste , Sub
Loop

Taste:
Incr X
If x >= 5 then Set Portc.1
Return




Bei einem anderen Signal würde das prinzipiell auch reichen aber wenn das sehr kurz ist dann muß das Programm schnell reagieren können und ein Poll würde evtl. nicht mehr reichen.(Mit Config Debounce ist da noch einwenig rauszuholen)
Da wäre ein Interruptbetrieb sinvoller.
Das geht natürlich nur wenn der Controller auch einen Externen Int besitzt.

Also zb. so:




Config Int0 = Rising
On Int0 Taste
Enable Interrupts

Do 'Hauptschleife

Loop

Taste:
Incr X
If x >= 5 then Set Portc.1
Return



Natürlich ist es nicht fein in einer Interruptroutine groß herumzurechnen.
Der Grund ist das es Zeit kostet (LCD oder Serielle Ausgaben sind besonders Tödlich) und in dieser Zeit ein Weiteres Ereignis verloren gehen kann bzw. sich so mehrere Interrupts verschachteln können und dann der Stack überläuft usw. usw.
Deswegen gilt für Int. "Halte dich kurz"
Man kann also nur ein Flag setzen und die Abfrage dann woanders hinsetzen.


Zb. So




Config Int0 = Rising
On Int0 Taste
Enable Interrupts

Do 'Hauptschleife
If x >= 5 then Set Portc.1
Loop

Taste:
Incr X
Return



So,das reicht ja wohl erstmal zum Spielen.

Thorsten75
07.04.2007, 11:40
ja, das war erst mal sehr hilfreich.
Die Impulse kommen von einem Encoder eines Motors, der 15 Impulse pro Sekunde gibt, von daher muß die Verarbeitung doch sehr schnell gehen.
Ich möchte einfach nur die Impulse zählen, um sie dann abfragen zu können.
Das erste Beispiel funktioniert zwar, aber irgendwie nicht auf Flanken und nicht für diese Impulsgeschwindigkeit.

Die Beispiele mit den Interupts habe ich nicht zum laufen bekommen, da scheint noch was zu fehlen, oder?

Ich benutze den Atmega 16, wie ist das denn überhaupt mit den Interupts, ist der Int0 einem bestimmten Pin zugeordnet?

Kann man eine Flankenauswertung auch ohne Interupts machen?

Hier das Programm das nicht funktioniert:




$regfile = "m16def.dat"
$framesize = 32
$swstack = 32
$hwstack = 32
$crystal = 8000000

Dim X As Byte

Config Portc.1 = Output

Config Int0 = Rising
On Int0 Taste
Enable Interrupts

Do 'Hauptschleife
If X >= 5 Then Set Portc.1
Loop

Taste:
Incr X
Return

Ratber
07.04.2007, 13:44
Die Impulse kommen von einem Encoder eines Motors, der 15 Impulse pro Sekunde gibt, von daher muß die Verarbeitung doch sehr schnell gehen.

Das ginge noch locker "Zufuß" aber dann muß man ganz genau auf die Programmlaufzeiten achten das auch alle Impulse mitbekommen werden.



Ich möchte einfach nur die Impulse zählen, um sie dann abfragen zu können.

Ja,entweder im Programm zählen oder per Timer als Zähler (Läuft unabhängig)



Das erste Beispiel funktioniert zwar, aber irgendwie nicht auf Flanken und nicht für diese Impulsgeschwindigkeit.

Doch das reagiert auf Steigende Flanken.
Sollte so funktionieren.
Bei 15 Hz sind das 66ms pro Puls.
Debounce ist standardmässig auf 20ms eingestellt.
Sollte also so gradenoch gehen.
Wenn das Signal nicht "Prellt" (Dafür ist Debounce ja eigentlich da) kannst du die Zeit auf 1 setzen.
Wie gesagt,mit Int ist es wesentlich eleganter.




Ich benutze den Atmega 16, wie ist das denn überhaupt mit den Interupts, ist der Int0 einem bestimmten Pin zugeordnet?

Ja,so isses.
Beim M16 ist Int0 auf Pin D.2
Steht aber alles im Datenblatt



Kann man eine Flankenauswertung auch ohne Interupts machen?

Ja,ganz zufuß mit Merkern für den derzeitigen Zustand und ständige Abfragen.
Das ist aber völlige Verschwendung von Resourcen.
Ich nehme mal an dein Controller soll ausser Impulse zählen noch was anderes machen.
Da wirst du bald das Problem bekommen das du vieleicht Impulse verpast weil gerade was anderes gemacht wird.
Da müßtest du schon sehr vorsichtig und umständlich Programieren.
Mit Int oder Timer-Zähler ist es sooooo kinderleicht.


Hier das Programm das nicht funktioniert:

Ja,mein Fehler und auch deiner.

Da fehlt noch "Enable int0" von mir.
Und du hast einen fehler bei der Port-/Pindefinition gemacht.

Mit "Config Portx Input/Output/X/&bxxxxxxxx" wird immer der gesammte Port configuriert.
Einzelne Pinne werden mit "Config Pinx.y = Input/Output" konfiguriert.



Hier,ich habs mal etwas umgeschrieben.



$regfile = "m16def.dat"
$framesize = 32
$swstack = 32
$hwstack = 32
$crystal = 8000000

Dim X As Byte

Config Pinc.1 = Output
Config Pind.2 = Input

Config Int0 = Rising
On Int0 Taste
Enable Int0
Enable Interrupts

Do 'Hauptschleife
If X >= 5 Then
Toggle Portc.1
X = 0
End If
Loop

Taste:
Incr X
Return


Bei jeder steigenden Flanke wird x um eins erhöht.
Bei X=5 wird Pin C.1 umgeschaltet (Toggle) und x wieder auf 0 gesetzt.
Eine LED am Pin C.1 sollte bei deinen 15 Hz vom Geber mit ca. 2.5Hz blinken.
So kannst du besser sehen ob das Signal auch wirklich ankommt.
Bei der Konfiguration des Int0 kannst du ja mal mit Rising/Falling/Change probieren.


Wie gesagt beim M16 ist der Int0 auf Pin D.2 (Und Int1 auf D.3. Mehr hat er nicht)
Mit anderen gehts nicht.

Nochwas:

Auch wenn beim AVR alle freien Pinne beim einschalten auf "Eingang" mit aktiviertem Pullup stehen solltest du die genutzten Portpinne dennoch configurieren.

Die Zeile "Config Pind.2 = Input" sollte also trotzdem da stehen.

Einen hab ich noch:

Da ja wie gesagt die internen Pullups standardmäßig aktiviert sind bringen nach Vcc geschaltete Signale ohne "Pulldown" natürlich kein brauchbares Signal.
Ein 1-10K Widerstand von Pin D.2 nach Masse bringt da abhilfe wenn der Geber es nicht anders kann.

LEs dir mal die Befehlsreferenz durch und experimentier damit.
Damit lernt mal viel. ;)