PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Von Unterprogramm zum Hauptprogrammanfang springen



Hübi
03.02.2007, 13:49
Moin,
ich sitz da jetzt schon einige Stunden drüber, und komm nicht drauf wie ich das am besten lösen kann. Ich möchte eine Zeitschaltung für meinen Lötkolben bauen. Dafür soll wenn ein Taster gedrückt wird der Lötkolben angehen. Wenn eine Zeit von 29.30min überschritten ist soll ein Alarm losgehn. Dann, 30 sek später, soll der Lötkolben samt Alarm abgeschaltet werden.
doch der "Countdown" soll jederzeit durch druck auf den Taster wieder auf Null gestellt werden. (auch während des Alarmes)

Aber mein Programm funktioniert nicht so wie ich mir das vorstelle, könnt ihr mir villeicht sagen wo mein Fehler liegt?

und ob es überhaupt möglich ist aus einem Unterprogramm zum Hauptprogramm-anfang zu springen?

Mfg Hübi



'--------------------------------------------------------------
$regfile = "attiny2313.dat" ' ATtinny 2313
$crystal = 1000000 'Quarz: 1,0 MHz


'******** Deklarationen ********

'******** Initialisierung ******** '
Enable Int0
Enable Interrupts
On Int0 Taste0int

Ddrb = &B11111111 ' port B als Ausgang
Ddrd = &B0100000 ' pin D2 asl eingang
Portd.2 = 1 ' interne pullup widerstände aktivieren
'******** Hauptprogramm ********

Do
Start:
If Pind.2 = 0 Then 'Wenn Taster Pind.2 gedrückt, dann
Portb = &B10000000 'Lötkolben an
Wait 1770 ' warte 29.30 min
Portb = &B11000000 ' Alarm wird zugeschaltet (spätestes jetzt könnte man resetten)
Wait 30 ' warte 30 Sekunden
Portb = &B00000000 ' alles wird ausgeschaltet

End If
Loop
'******** Unterprogramme ********
Taste0int:
Sound Portd.0 , 1000 , 82 'wenn Taster Pind.2 gedrückt, dann piept es
Goto Start ' Springe zu start und fange von vorn an


End

linux_80
03.02.2007, 14:50
Hallo,

Taste0int ist kein Unterprogramm in dem Sinne, sondern eine ISR (Interrupt).
Da kann man nicht ungestraft in das Hauptprogramm zurückspringen ! ;-)

Du kannst Dir aber eine Variable anlegen, die im Hauptprogramm abgefragt wird, und in der ISR gesetzt wird, damit man den Tastendruck mitbekommt.
Ein Sound in der ISR kommt auch nicht gut, würde ich auch in die Hauptschleife legen und über eine Variable starten.
Statt dem Wait 1770 machst Du Wait 1 und zB. eine For-Schleife drumrum die bis 1770 zählt, und die Variable der ISR abgefragt wird, wenn die Variable gesetzt ist (also einen bestimmten Wert hat), einfach Sound aufrufen, For-Schleife beenden usw.

So in der Richtung würde ich das anfangen.
Eine Sekunde Verzögerung ist hier ja kein Problem.

Hübi
03.02.2007, 15:37
Moin

danke für deine schnelle Antwort, ich habe versucht das was du sagst umzusetzten aber irgentwie haut das nicht so richtig hin, ich hoffe die Ansätze sind wenigstens richtig
mfg Hübi




'--------------------------------------------------------------
$regfile = "attiny2313.dat" '
$crystal = 1000000 'Quarz: 1,0 MHz


'******** Deklarationen ********
Dim A As Word
'******** Initialisierung ******** '
Enable Int0
Enable Interrupts
On Int0 Taste0int

Ddrb = &B11111111 ' port B als Ausgang
Ddrd = &B0100000 ' pin D2 asl eingang
Portd.2 = 1 ' interne pullup widerstände aktivieren

'******** Hauptprogramm ********

Do
If Pind.2 = 0 Then Portb = &B10001000
Wait 1
A = A + 1
If A > 1770 Then
Portb = &B11000000
End If
If A > 1800 Then
Portb = &B00000000
End If

Loop
'******** Unterprogramme ********
Taste0int:
A = 0

End

patti16
03.02.2007, 17:46
Hallo

du müsstest praktisch a nicht als null setzen sondern als 1 weil 0 = 0+ 1 wäre wieder null aber wenn 1 = 1+1 =2 usw. dann zählt er.

hier der code: mit Print gibste RS232 aus und kannst dann schauen das er hoch zählt.




'--------------------------------------------------------------
$regfile = "attiny2313.dat" '
$crystal = 1000000 'Quarz: 1,0 MHz


'******** Deklarationen ********
Dim A As Word
'******** Initialisierung ******** '
Enable Int0
Enable Interrupts
On Int0 Taste0int

Ddrb = &B11111111 ' port B als Ausgang
Ddrd = &B0100000 ' pin D2 asl eingang
Portd.2 = 1 ' interne pullup widerstände aktivieren

'******** Hauptprogramm ********

Do
If Pind.2 = 0 Then Portb = &B10001000
Wait 1
A = A + 1
Print A
If A > 1770 Then
Portb = &B11000000
End If
If A > 1800 Then
Portb = &B00000000
End If

Loop
'******** Unterprogramme ********
Taste0int:
A = 1

End

linux_80
03.02.2007, 17:55
Bei den If-Abfragen musst Du noch ausschliessen, das beide gleichzeitig zutreffen können, wenn der Wert über 1800 ist, ist er auch über 1770 !
Die Zeit dazwischen ist zwar sehr kurz, aber dazwischen wird erstmal der Ausgang gesetzt.
Erst den höheren Wert abfragen und im Else den kleineren, dann werden nicht beide ausgeführt.

Vielleicht kann man auch so abfragen, solange der Wert kleiner 1770 ist, den einen Ausgang setzen, wenn >1800 alles aus, ansonsten Ausgang und Alarm.

Evtl. musst Du noch den Int0 konfigurieren, denn da kommt nix vor.
Jetzt wird ein Int ausgelöst solange der Pegel Low ist.

Hübi
03.02.2007, 18:47
so, ich hoffe nun stimmt es,

@patti16 du meinst wenn ich ein Display anschließe oder?


'--------------------------------------------------------------
$regfile = "attiny2313.dat" '
$crystal = 1000000 'Quarz: 1,0 MHz


'******** Deklarationen ********
Dim A As Word
'******** Initialisierung ********
Config Int0 = Falling '
Enable Int0
Enable Interrupts
On Int0 Taste0int

Ddrb = &B11111111 ' port B als Ausgang
Ddrd = &B0100000 ' pin D2 asl eingang
Portd.2 = 1 ' interne pullup widerstände aktivieren

'******** Hauptprogramm ********

Do
If Pind.2 = 0 Then Portb = &B10000000
Wait 1
A = A + 1
If A > 1800 Then
Portb = &B00000000
End If
If A > 1770 Then
Portb = &B11000000
Else
Portb = &B10000000
End If

Loop
'******** Unterprogramme ********
Taste0int:
A = 1

End

patti16
03.02.2007, 18:59
ich meine die Belgung der Ports im Programm von mir musste auf deins übertragen falls es nicht gleich angeschlossen ist.

haste mal probiert?

gruß
patrick

helimike0705
03.02.2007, 19:14
hallo , habe mir auch mal ein paar gedanken gemacht.
also im simulator läuft das prog. und auf meinem bord auch
der einfachheitshalber habe ich mal die zeiten 1770 in 170
und 1800 in 180 geändert,damit es schneller abläuft im test.
also wieder in deine zeiten ändern.

gruß mike


'--------------------------------------------------------------
$regfile = "attiny2313.dat" '
$crystal = 1000000 'Quarz: 1,0 MHz
'$sim

'******** Deklarationen ********
Dim A As Word


Ddrb = &B11111111 ' port B als Ausgang
Ddrd = &B0100000 ' pin D2 asl eingang
Portd.2 = 1 ' interne pullup widerstände aktivieren

'******** Hauptprogramm ********
Portb.1 = 1 'zeigt ausgeschalteten zustand an
Main1:

Do

If Pind.2 = 0 Then
Goto Main2
Else
End If

Loop

Main2:

Portb = &B10000000


Do

If Pind.2 = 0 Then
A = 0
Portb = &B10000000
Else
End If

Wait 1
A = A + 1
Print A
Toggle Portb.0 'lötkolben an
If A > 177 Then
Portb = &B11000000
Sound Portd.0 , 1000 , 82
End If

If A > 180 Then
Portb = &B00000000
End If

Loop Until A > 180

Portb.1 = 1 'zeigt ausgeschalteten zustand an

Do

If Pind.2 = 0 Then Goto Main1

Loop

End

linux_80
03.02.2007, 20:04
@Hübi:
Fast, die Abfrage nach den 1700 noch in das Else der 1800, denn sonst geht es nie aus:

If A > 1800 Then
Portb = &B00000000
else
If A > 1770 Then
Portb = &B11000000
Else
Portb = &B10000000
End If
End If


Also wenn der Wert über 1800 kommt ist alles aus,
ist er unter 1800 aber über 1770 geht der Alarm mit an,
ist der unter 1770 ist nur der Ausgang eingeschaltet.

Ob in der ISR auf 0 oder 1 gesetzt wird ist eigentlich egal,
bei 0 läuft die Schleife eine Sekunde länger.

helimike0705
04.02.2007, 11:57
man kann nach der until abfrage die do loop schleife durch goto main1
ersetzten , sonst ist es ja doppelt gemobbelt.

hallo linux_80 :
ist dein prog-beitrag auf meinen code gemünzt,oder ?

linux_80
04.02.2007, 12:51
@helimike0705
war jetzt nicht meine Absicht ;-)
kann aber sein das es auch rein passt.


PS:
Wenn man im Forum jemand bestimmten meint, hat es sich so ergeben, dass man das mit einem @ angibt an wen es gerichtet ist.

helimike0705
04.02.2007, 13:00
ja, schon okay,dachte nur du meinetes meine code,ist ja nicht der
optimalste und verbesserungen sind immer willkommen,proge erst
seit dez 06 mit bascom und habe vorher noch nie etwas mit mc gemacht.
also habe schon verstanden das es nicht bös gemeint war.

gruß

Hübi
05.02.2007, 19:18
Moin,

@helimike0705
ja, dein Programm funzt bei mir auch super, vielen dank für deine Mühen. (nur das "Print A" verstehe ich nicht wofür ist das gut?) Ich denke ich werde es später auch so in meiner "lötstation" verwenden. Aber ich würde trotzdem gerne noch mein eigenes Programm zur Funktion bringen (zum lernen, nur so für mich) denn bei meinen nächsten Projekten will ich euch nicht immer wieder mit meinen Anfängerfragen nerven. Mich würde interessieren ob und welche Lehrmaterialen du verwendest um das Programmieren zu erlernen(bücher ect.)


@linux_80
ja, stimmt jetzt geht es auch aus, aber leider nicht wieder an, wenn ich die taste drücke. Irgentwo muss noch ein Fehler versteckt sein, ich kann ihn aber nicht finden :-#




'--------------------------------------------------------------
$regfile = "attiny2313.dat" '
$crystal = 1000000 'Quarz: 1,0 MHz


'******** Deklarationen ********
Dim A As Word
'******** Initialisierung ********
Config Int0 = Falling '
Enable Int0
Enable Interrupts
On Int0 Taste0int

Ddrb = &B11111111 ' port B als Ausgang
Ddrd = &B0100000 ' pin D2 asl eingang
Portd.2 = 1 ' interne pullup widerstände aktivieren

'******** Hauptprogramm ********

Do
If Pind.2 = 0 Then Portb = &B10000000
Wait 1
A = A + 1
If A > 1800 Then
Portb = &B00000000
Else
Portb = &B10000000
If A > 1770 Then
Portb = &B11000000
End If
End If

Loop


'******** Unterprogramme ********
Taste0int:
A = 1

End

linux_80
05.02.2007, 20:56
Es gibt auch noch ein weiteres Problem, da A immer weitergezählt wird, wird das irgendwann überlaufen, und A ist wieder 0,
dann geht der Lötkolben wieder an, nach etwa (65536-1800) sec. !
Das zählen sollte dann in den Else-Teil der 1. If-Abfrage, am besten zwischen die beiden End If's.

Und wegen dem nicht mehr einschalten, ich weiss zwar nicht obs hilft, aber schreib mal gleich nach dem Wait ein Disable Interrupts, und unten vor Loop ein Enable Interrupts. Sodass die ganze Berechnung und Auswertung von A nicht unterbrochen werden kann.
Sollte währenddessen ein Int0 auftreten, wird der ausgeführt, wenn die Interrupts wieder aktiviert werden.
Das ist zwar nur eine Vermutung, kann aber auftreten, da hier mit 2 Bytes gerechnet wird.

helimike0705
06.02.2007, 06:17
hallo hübi,
das print a war nur für den simulator gedacht,kannst dies streichen.
habe es vergessen heraus zu nehmen.aber freut mich das es dir
gefällt.lernunterlagen ist momentan nur das internet alles was ich zu microkontrollern finde.

gruß mike

helimike0705
06.02.2007, 18:26
habe die ganze sache mal nur auf dem portd umgestellt und schon läuft nix mehr.also sprich die ledanzeigen auf pin 4,5,6.starttaste gelassen auf pin2,sowie nach dem brennen rennt das prog sofort los. warum?egal welchen atmel ich benutze ,at90s2313 oder attiny2313.wollt auf portb mein lcd anschliessen und nun das.
auch hängt sich das programm auf ,aber im sim läuft es,
wieder ein problem das gelöst werden muss,wer weiß rat.

helimike0705
06.02.2007, 19:15
hallo hübi, dein programm aus dem ersten thread läuft !
du machst bestimmt nur einen tastendrück von kurzer dauer,richtig.
also so etwa ein halbe sekunde.lasse mal den taster solang gedückt bis
der beep zu ende ist.dann läuft es. der grund ist das der sound befehl
den programmablauf solange stopt und erst nach dem ende zur do loop
schleife springt. wenn du in der soundausgabe die 1000 (1 sekunde) auf
100 reduzierst (100 millisekunden),ist dein programm schneller.

gruß mike