Hi Werner,
willst du ihn jetzt aufs Glatteis führen ?
müsste es in deinem Code nicht heissen:
enable interruptS
und fehlt nicht:
enable timer0
enable timer1
und evtl:
start timer0
start timer1
??
Druckbare Version
Hi Werner,
willst du ihn jetzt aufs Glatteis führen ?
müsste es in deinem Code nicht heissen:
enable interruptS
und fehlt nicht:
enable timer0
enable timer1
und evtl:
start timer0
start timer1
??
@werner_just
OK ich sehs ja aber deine letzten "Hilfen" brachten mich nicht weiter ( trotzdem Danke )Zitat:
Wozu ICH nicht bereit bin, und das Thema hatten wir hier schonmal, ist Deine Arbeit zu machen. Ich erkläre Dir gerne wie man mit Interrupts umgeht, ich schaue auch gerne mal über Deinen Code und gebe meinen Senf dazu was man imo besser oder anders machen könnte. Aber Programmieren musst Du Dein Programm schon selbst.
Ich zitiere:
Sei doch mal ehrlich, ist das nicht was man als erstes macht???Zitat:
Suche in der BASCOM-Hilfe
Diese Info brachte mir genau so viel, hatte glaube vorher erwähnt, das ich mich mit dem Timer/Counter NICHT auskenne.Zitat:
Stop Timer 0
Timer0 = 218
Start Timer0
Start Timer1
Do
Loop Until Interrupt_Zähl_Variable = 39
Stop Timer1
Stop Timer0
Da war der Timer Lehrgang mit dem alleserklährenden Code doch die besste Antwort ( langsam geht mit ein :idea: auf )
Vielleicht lag es auch an meiner Fragestelung, das anfangs nix rauskamm 8-[ . Aber jetzt hab ichs geblickt (das mit dem auslesen /zusammen Spiel)
Werde mich mal ans Programmieren machen ( Wochenende ), währst du dann vielleicht bereit mein Code zu korrigieren? Die Arbeit hatte ja dan ich.
Ach eine Frage, geht es ,dass ich das Ergebnis anzeige ( Multiplex[Code siehe Seite 1{Geb ruhig deinen Senf dazu}]) und GLEICHZEITIG Messe, denn so wie ich euch verstanden hab hat ja der Timer nix mim Programm zu tun ( Außer Auslese ).
Gruß teslanikola
Hallo Gast,
sorry Teslanikola,
> willst du ihn jetzt aufs Glatteis führen ?
war nicht meine Absicht aber Du hast natürlich recht.
>enable interruptS
>enable timer0
>enable timer1
sowas passiert wenn man abends nur noch mal eben seine privaten emails abrufen will und dann doch noch ins Forum guckt. War zu dem Zeitpunkt schon 17h auf den Beinen. Soll man nicht machen sowas!
>und evtl:
>start timer0
>start timer1
Timer brauchen nicht explizit gestartet zu werden. Sie starten nach der initialisierung automatisch. "start timer" wird nur benötigt wenn er vorher mit "stop timer" explizit angehalten wurde. Es stört aber auch nicht wenn "start timer" drin steht.
Ciao,
Werner
Halo Teslanikola,
> OK ich sehs ja aber deine letzten "Hilfen" brachten mich nicht weiter
> ( trotzdem Danke )
hm, ein kleiner Hinweis wo Du nicht durchblickst?
Es ging nur darum wie man die 0,1469 der benötigten 38,1469 Timer-Überläufe realisiert. (Für 1s Torzeit bei 8bit Timer, 10MHz Takt und Prescale = 1024)Zitat:
[Beispiel "vorsetzen des Timers"]
Diese Info brachte mir genau so viel, hatte glaube vorher erwähnt, das ich mich mit dem Timer/Counter NICHT auskenne.
Welchen meinst Du?Zitat:
Da war der Timer Lehrgang mit dem alleserklährenden Code doch die besste Antwort ( langsam geht mit ein :idea: auf )
> währst du dann vielleicht bereit mein Code zu korrigieren?
Das hab ich Dir ja angeboten. Andere gucken hoffentlich auch drüber, sonst passiert wieder sowas wie beim Beispiel gestern abend ](*,). Sorry falls Du viel Zeit damit vertrödelt hast.
Stimmt, die Timer laufen völlig unabhängig vom Programm. Nur die Interrupts und das Auslesen verbrauchen etwas Programmzeit.Zitat:
Ach eine Frage, geht es ,dass ich das Ergebnis anzeige ( Multiplex[Code siehe Seite 1{Geb ruhig deinen Senf dazu}]) und GLEICHZEITIG Messe, denn so wie ich euch verstanden hab hat ja der Timer nix mim Programm zu tun ( Außer Auslese ).
Du kannst daher Messen und gleichzeitig Ausgeben. (Wobei man bei einem Frequenzzähler nicht unbedingt merken würde wenn er das nacheinender macht) Ist auf jeden Fall eine schöne Programmieraufgabe.
Ciao,
Werner
Hallo Werner, haste mein Multiplexcode mal angesehen?
Das glaub ich dir auf Wort :wink:Zitat:
Ist auf jeden Fall eine schöne Programmieraufgabe.
Den Mein ich:Zitat:
Welchen meinst Du?Zitat:
Da war der Timer Lehrgang mit dem alleserklährenden Code doch die besste Antwort ( langsam geht mit ein auf )
Also z.B.
Gruß teslanikolaZitat:
Code:$regfile = "M8def.dat"
Dim Var1 as Byte
Dim Var2 as Byte
On Timer0 Test1
On Timer1 Test2
Enable Interrupt
Config Timer0 = Timer, Prescale = 1
Config Timer1 = Timer, Prescale = 1
Do
loop
Test1:
incr Var1
Return
Test2:
incr Var2
Return
Hallo Teslanikola,
Ich hab zwar mal über den Multiplex-Thread geguckt, aber Deinen Code hab ich nicht gefunden. Vielleicht war ich aber auch einfach nur blind.Zitat:
haste mein Multiplexcode mal angesehen?
Der Code hat Dir also weitergeholfen... grübel.Zitat:
Dim Var1 as Byte
Dim Var2 as Byte
[...]
Prima, dann lasse ich in Zukunft immer ein paar wesentliche Sachen weg und dann passt das schon :twisted:
Spaß beiseite, freut mich daß Du trotz meiner Fehler damit etwas anfangen konntest.
Ciao,
Werner
hallo werner,
Denn Code mein ich.Code:$regfile = "2313def.dat"
$crystal = 10000000
Config Portb = Output
Config Portd = Output
Dim A As Byte
Dim S As String * 5
Dim X As Byte
Dim Pos As Byte
Dim Z As String * 1
Dim L As Byte
Do
S = Str(w)
L = Len(s)
For A = 0 To 10
For X = 1 To L
S = Str(w)
Pos = L - X
Pos = Pos + 1
Z = Mid(s , Pos , 1)
If Z = "0" Then Portb = 63
If Z = "1" Then Portb = 34
If Z = "2" Then Portb = 94
If Z = "3" Then Portb = 118
If Z = "4" Then Portb = 99
If Z = "5" Then Portb = 117
If Z = "6" Then Portb = 125
If Z = "7" Then Portb = 38
If Z = "8" Then Portb = 127
If Z = "9" Then Portb = 119
If X = 1 Then Portd = 1
If X = 2 Then Portd = 2
If X = 3 Then Portd = 4
If X = 4 Then Portd = 8
If X = 5 Then Portd = 16
If L = 1 Then Waitus 9996
If L = 2 Then Waitus 4996
If L = 3 Then Waitus 3327
If L = 4 Then Waitus 2496
If L = 5 Then Waitus 1996
Next X
Next A
Loop
Grüßle
Hallo Werner,
endlich ist es so weit der Code ist fertig \:D/ \:D/ \:D/
Hier der Code ( hoffe du bist zufrieden ):
Bitte kontollieren!Code:$regfile = "2313def.dat"
Dim Var1 As Byte
Dim Var2 As Byte
Dim Freq As Integer
Dim Tim As Long
Config Timer0 = Timer , Prescale = 1024
Config Timer1 = Counter , Edge = Rising
Config Pinb.5 = Input
Portb.5 = 0
On Timer0 Test1
On Timer1 Test2
Enable Interrupts
Mess:
Timer0 = 550
Timer1 = 0
Start Timer0
Start Timer1
Do
' Hier Zeige ich Tim an
loop
Test1:
Incr Var1
If Var1 = 9 Then
Freq = Timer1
Tim = Var2 * 1024
Freq = Tim + Freq
Var1 = 0
Var2 = 0
Stop Timer0
Stop Timer1
Goto Mess
End If
Return
Test2:
Incr Var2
Return
Gruß teslanikola
Hallo Teslanikola,
äh....Zitat:
endlich ist es so weit der Code ist fertig \:D/ \:D/ \:D/
Hier der Code ( hoffe du bist zufrieden ):
> Bitte kontollieren!
wird heute und morgen nichts mehr werden. So 'nen Lappsus wie gestern möchte ich möglichst vermeiden und morgen bin ich auf Messfahrt.
Aber 10 Minuten hab ich :Haue
> Timer0 = 550
- Interessant das der Compiler nicht mosert wenn einer 8 bit Register ein Wert > 255 zugewiesen wird.
- Dann schau Dir den Post von "Gast" nochmal an. Stichwort "Lappsus"
- Wie kommst Du auf den Wert 9 in "If Var1 = 9 Then"
- Wie wo was ist Tim?
- unabhängig davon, Tim ist long, Freq ist integer
"Freq = Tim + Freq" passt irgendwie nicht so richtig.
[0...+-2^15] = [0...2^32] + [0...+-2^15]
Ciao,
Werner
P.S. Wie der BASCOM-Simulator funktioniert weißt Du?
ach sch*** das erklärt auch die var1 = 9 then ...Zitat:
Timer0 = 550
- Interessant das der Compiler nicht mosert wenn einer 8 bit Register ein Wert > 255 zugewiesen wird.
muss eigentlich so heisen
If var1 = 38 then ... ( anzahl der überläufe zur Sek)
Tim ist : counter ( timer1) und die anzahl der "Überläufe"*255
also gesammtcounts
Muss ich gleich mal verbessern
Gruß
Ps des mit den Simulieren kann ich nur teils
Hallo Teslanikola,
wenn Du schon dabei bist Deinen Code zu überarbeiten...
Zwei Fragen...
1. warum verwendest Du für die Variable Freq den Datentyp integer?
negative Frequenzen tauchen nur mathematisch bei komplexen Rechnungen im Frequenzbereich auf. Real gibt es sie nicht.
2. wenn "Tim = counter ( timer1) und die anzahl der Überläufe*255"
wieso dann im Code "Tim = Var2 * 1024"
Abgesehen davon, Timer1 hat wieviele bits? und
nach wievielen Zähl-Takten kommt es zu einem Überlauf bei einem 8 o. 16bit Timer?
Da Du inzwischen sicher einiges an Deinem Code geändert hast, postest Du den aktuellen nochmal?
> ach sch*** das erklärt auch die var1 = 9 then ...
> muss eigentlich so heisen
> If var1 = 38 then ... ( anzahl der überläufe zur Sek)
stimmt. 38 ist sehrviel näher dran als als 9.
Es geht noch näher, aber das besprechen wir wenn Dein Code erstmal läuft. Genauso wie man Berechnungen ala "Überläufe * 256" elegant umgehen kann. Multiplikation brauchen immer unangenehm viel Rechenzeit.
Ciao,
Werner
So Update 1.2 is fertig, währe das jezt IO,hab au die Multipikation weggekriegt.
Gruß teslanikolaCode:$regfile = "2313def.dat"
Dim Var1 As Byte
Dim Var2 As Byte
Dim Freq As Word
Config Timer0 = Timer , Prescale = 1024
Config Timer1 = Counter , Edge = Rising
Config Pinb.5 = Input
Portb.5 = 0
On Timer0 Test1
On Timer1 Test2
Enable Interrupts
Mess:
Timer0 = 126
Timer1 = 0
Start Timer0
Start Timer1
Do
' Hier Zeige ich freq an
Loop
Test1:
Incr Var1
If Var1 = 38 Then
Freq = Timer1
Freq = Var2 + Freq
Var1 = 0
Var2 = 0
Stop Timer0
Stop Timer1
Goto Mess
End If
Return
Test2:
Var2 = Var2 + 256
Return
Hallo Teslanikola,
nette Idee das mit dem Var2 = Var2 + 256
lassen wir es vorerst dabei. Wie man das elegant macht kommt später.
Mein "Lappsus" ist immer noch drin. Siehe Post von "Gast".
OnTimer0/1 schaltet nicht den Interrupt ein! Es sagt nur wohin gesprungen werden soll wenn der Interrupt denn eingeschaltet, freigegeben und aufgetreten ist.
Dann wird Deine Frequenz doch sicher > 65kHz werden. Wolltest Du nicht bis zu 1-2 MHz messen?
Was passiert wenn Du zu einer Byte-Variablen 256 dazu addierst?
Eine Interrupt Routine wird nur und immer nur mit Return verlassen (ultra wichtig!) . Man springt NIEMALS mit einem Goto aus einer Interupt Routine.
Hintergrund: der µC speichert die Stelle im Programm, von dem aus er in die Interrupt-Routine gesprungen ist auf dem Stack. Dort schaut er beim Return auch nach, wohin er zurück springen soll und löscht dann den Eintrag im Stack wieder. Wenn Du mit einem GOTO aus der Interrupt Routine springst, werden die Daten auf dem Stack nicht gelöscht. Der Stack belegt immer mehr Speicher und irgendwann überschreibt er den vom Programm genutzten Speicher. Das Ergebnis ist, der µC hängt sich auf.
So, kann Montag werden bis ich wieder online bin. Vielleicht auch mal kurz irgendwann am Wochenende. Weiß ich noch nicht.
Ciao,
Werner
Hi Teslanikola,
Also, wenn ich den Thread schon vorher gesehen hätte, hätte ja gleich am Anfang gesagt:
Lies http://www.lugbz.org/documents/smart-questions_de.html!
Da steht z.B. nochmal drin, wieso dir wohl kaum jemand den kompletten Code schreiben wird...
Und lerne Englisch: wie willst du denn jemals ein Datenblatt lesen können und jemals die einfachsten Schaltungen bauen können?
Ich bin ja auch Anfänger, aber ich habe herausgefunden, dass man, wenn man mal ein AVR Datenblatt liest doch relativ weit kommt...
Dann muss man noch gucken wie die Befehle in Basic heißen und schon bekommt man zumindest mal den Code zusammen...
Naja und dann gehört es doch wohl dazu das man seinen Code zumindest mal simuliert, ob jetzt im Kopf und auf Papier, oder mit dem mitgelieferten Simulator...
Zeig doch mal ein bisschen mehr Engagement!
Viele Grüße,
Daniel
Servus, hab eure Ips mal eingebaut, außer das mit Goto hab nen Kom. dazugeschrieben, kann sein das ihr das ja nicht verstandenhabt was ich damit will.Danke für eure HilfeCode:$regfile = "2313def.dat"
Dim Var1 As Byte
Dim Var2 As Word
Dim Freq As Word
Config Timer0 = Timer , Prescale = 1024
Config Timer1 = Counter , Edge = Rising
Config Pinb.5 = Input
Portb.5 = 0
On Timer0 Test1
On Timer1 Test2
Enable Interrupts
Mess:
Timer0 = 126
Timer1 = 0
Start Timer0
Start Timer1
Do
' Hier Zeige ich freq an
Loop
Test1:
Incr Var1
If Var1 = 38 Then
Freq = Timer1
Freq = Freq + Var2
Var1 = 0
Var2 = 0
Stop Timer0
Stop Timer1
Goto Mess 'soll nur bei Var1 = 38 zu Mess Springen, wenn man hier kein goto MESS setzten darf , wo/wie dann
End If
Return
Test2:
Var2 = Var2 + 256
Return
Servus, hab den Multiplex auch mit eingebaut:
Gruß teslanikolaCode:$regfile = "2313def.dat"
Dim Var1 As Byte
Dim Var2 As Word
Dim Freq As Word
Config Portb = Output
Config Portd = Output
Dim A As Byte
Dim S As String * 5
Dim X As Byte
Dim Pos As Byte
Dim Z As String * 1
Dim L As Byte
Dim W As Long
Config Timer0 = Timer , Prescale = 1024
Config Timer1 = Counter , Edge = Rising
Config Pinb.5 = Input
Portb.5 = 0
On Timer0 Test1
On Timer1 Test2
Enable Interrupts
Mess:
Timer0 = 126
Timer1 = 0
Start Timer0
Start Timer1
Do ' Anzeige Multiplex
S = Str(freq)
L = Len(s)
For A = 0 To 10
For X = 1 To L
S = Str(w)
Pos = L - X
Pos = Pos + 1
Z = Mid(s , Pos , 1)
If Z = "0" Then Portb = 63
If Z = "1" Then Portb = 34
If Z = "2" Then Portb = 94
If Z = "3" Then Portb = 118
If Z = "4" Then Portb = 99
If Z = "5" Then Portb = 117
If Z = "6" Then Portb = 125
If Z = "7" Then Portb = 38
If Z = "8" Then Portb = 127
If Z = "9" Then Portb = 119
If X = 1 Then Portd = 1
If X = 2 Then Portd = 2
If X = 3 Then Portd = 4
If X = 4 Then Portd = 8
If X = 5 Then Portd = 16
If L = 1 Then Waitus 99813
If L = 2 Then Waitus 49906
If L = 3 Then Waitus 33271
If L = 4 Then Waitus 24953
If L = 5 Then Waitus 19963
Next X
Next A
Loop
Test1:
Incr Var1
If Var1 = 38 Then
Freq = Timer1
Freq = Freq + Var2
Var1 = 0
Var2 = 0
Stop Timer0
Stop Timer1
Goto Mess 'soll nur bei Var1 = 38 zu Mess Springen, wenn man hier kein goto MESS setzten darf , wo/wie dann
End If
Return
Test2:
Var2 = Var2 + 256
Return
Halllo Teslanikola
und Du hast nicht verstanden das das nicht geht!Zitat:
Servus, hab eure Ips mal eingebaut, außer das mit Goto hab nen Kom. dazugeschrieben, kann sein das ihr das ja nicht verstandenhabt was ich damit will.
Mit dem Goto läuft Dein Stack über und der µC schmiert ab!
Der Sprung zurück zum Lable Mess: muß daher ins Hauptprogramm. Oder Du verzichtest auf den Sprung und setzt die Timer in der Interrupt Routine neu.
Wie Du das machst ist eigentlich egal, solange Du nicht mit einem GOTO aus der Interrupt-Routine springst! z.B. kannst Du eine Abfrage ala If Var1=38 then goto Mess: in die Do-Loop-Schleife einbauen.
[Daniel schrieb:]
> Zeig doch mal ein bisschen mehr Engagement!
und lies gründlich und vollständig was geschrieben wird.
Es tut schon fast weh, wenn nach dem 3. Hinweis auf den Beitrag von "Gast" immernoch die beiden Zeilen:
[ nach reiflicher Überlegung gelöscht]
fehlen.
nichts für ungut, aber wir sollten noch beim Code-ohne-Multiplexer bleiben. Es wird sonst leicht etwas unübersichtlich.Zitat:
Servus, hab den Multiplex auch mit eingebaut:
Ciao,
Werner
So endlich hab ichs, nach den vielen Tipps; das GOTO ist raus, ich hab den Befehl RETURN verwendet und ein paar Kleinichkeiten verändert. Wenn das jetzt so laufen würde ohne das mir die µC abschmiert oder sonst was passiert was nicht soll bin ich wahnsinnig GLÜCKLICH ( ich betonte WENN)
PS:Code:$regfile = "2313def.dat"
Dim Var1 As Byte
Dim Var2 As Word
Dim Freq As Word
Config Portb = Output
Config Portd = Output
Dim A As Byte
Dim S As String * 5
Dim X As Byte
Dim Pos As Byte
Dim Z As String * 1
Dim L As Byte
Dim W As Long
Config Timer0 = Timer , Prescale = 1024
Config Timer1 = Counter , Edge = Rising
Config Pinb.5 = Input
Portb.5 = 0
On Timer0 Test1
On Timer1 Test2
Enable Interrupts
Timer0 = 126
Timer1 = 0
Start Timer0
Start Timer1
Do ' Anzeige Multiplex
Loop
Test1:
Incr Var1
If Var1 = 38 Then
Freq = Timer1
Freq = Freq + Var2
Var1 = 0
Var2 = 0
Stop Timer0
Stop Timer1
Timer0 = 126
Timer1 = 0
Start Timer0
Start Timer1
Return
'soll nur bei Var1 = 38 zu Mess Springen, wenn man hier kein goto MESS setzten darf , wo/wie dann
End If
Return
Test2:
Var2 = Var2 + 256
Return
Hallo werner-just haste mir schon viel geholfen, und das ich die langsam nerve ist mir auch klar! SorryZitat:
Es tut schon fast weh, wenn nach dem 3. Hinweis auf den Beitrag von "Gast" immernoch die beiden Zeilen:
[ nach reiflicher Überlegung gelöscht]
fehlen.
Hallo werner, hab noch was vergessen:
Will nicht frech sein , aber es sind DREI.Zitat:
Es tut schon fast weh, wenn nach dem 3. Hinweis auf den Beitrag von "Gast" immernoch die beiden Zeilen:
Code:$regfile = "2313def.dat"
Dim Var1 As Byte
Dim Var2 As Word
Dim Freq As Word
Config Portb = Output
Config Portd = Output
Dim A As Byte
Dim S As String * 5
Dim X As Byte
Dim Pos As Byte
Dim Z As String * 1
Dim L As Byte
Dim W As Long
Enable Interrupts
Enable Timer0
Enable Timer1
Config Timer0 = Timer , Prescale = 1024
Config Timer1 = Counter , Edge = Rising
Config Pinb.5 = Input
Portb.5 = 0
On Timer0 Test1
On Timer1 Test2
Enable Interrupts
Timer0 = 126
Timer1 = 0
Start Timer0
Start Timer1
Do ' Anzeige Multiplex
Loop
Test1:
Incr Var1
If Var1 = 38 Then
Freq = Timer1
Freq = Freq + Var2
Var1 = 0
Var2 = 0
Stop Timer0
Stop Timer1
Timer0 = 126
Timer1 = 0
Start Timer0
Start Timer1
Return
'soll nur bei Var1 = 38 zu Mess Springen, wenn man hier kein goto MESS setzten darf , wo/wie dann
End If
Return
Test2:
Var2 = Var2 + 256
Return
Hallo Teslanikola
ich hatte die Hoffnung schon fast aufgegeben die beiden Zeilen in Deinem Code zu sehen.Code:Enable Timer0
Enable Timer1
> Will nicht frech sein, aber es sind DREI.
Welche ist die Dritte? "Enable Interrupts" hab ich nicht vermisst, die hattest Du ja :-)
Ciao,
Werner
OK OK , du bist wie mein lieblings Opa, der hat auch immer das letzte Wort, aber ich muss dir rechtgeben, dein letztes Wort ist berechtigt.
Geht das Programm jetzt so oder gibts noch was zu verändern, ach werner würde mich interessieren wie du das mit den Überläufen gemacht hättest
Gruß teslanikola
Hallo Jungspund
es gibt noch viel zu tun, packen wir es später an. Sorry im Moment werde ich hier auf der Arbeit reichlich beansprucht.Zitat:
Geht das Programm jetzt so oder gibts noch was zu verändern,
hab ich doch schon geschrieben...Zitat:
ach werner würde mich interessieren wie du das mit den Überläufen gemacht hättest
1s Torzeit = 10E6 Prozessortakte bei 10MHz Quarz.
10E6 sind 38.147 Überläufe des Timer0 (8bit) bei Prescale = 1024
Also, entweder...
man vergisst 0.147 Überlaüfe und misst nur während 38*256*1024 = 9.961.147 Prozessor-Takten == 0,9961s
In dem Fall startet man den Timer bei "0" und zählt bis zum 38ten Überlauf
oder...
man setzt den Timer auf (256-0.147*256 = 219) vor und zält bis zum 39ten Überlauf.
In dem Fall ergibt sich die Torzeit zu 38*256*1024+ 1*(256-219)*1024 = 9.999.360 Prozessor-Takten == 0,9999360s
Ciao,
Werner
Aha, hab ja au die 2. gememacht Zähle doch bis zu 38, müsste 39 sein, und starte den timer bei 126, müsste 216 sein, sonnst hab ichs ja so wie du wolltest!!
Hallo Teslanikola,
und warum 216?Zitat:
Aha, hab ja au die 2. gememacht Zähle doch bis zu 38, müsste 39 sein, und starte den timer bei 126, müsste 216 sein,
Ich will nicht!Zitat:
sonst hab ichs ja so wie du wolltest!!
Ich meine höchstens etwas ist sinnvoller/besser!
Wenn Du etwas anders machst und erklären kannst warum Du es anders machst, ich wäre der zufriedenste Mensch auf Erden weil Du dann nicht nur abkupferst sondern angefangen hast mitzudenken.
Aber wenden wir uns der Variablen Var2 und der Verknüpfung von Var2 mit dem Wert Timer1 zur Frequenz zu.
Du willst Frequenzen bis zu 1-2 MHz messen. Deine Variable "Freq" muß daher so groß sein, das Zählerstände >= 1-2 Millionen reinpassen.
Mit 16bit = 2 Byte kannst Du bis 2^16 - 1 = 65535 zählen. Das reicht nicht.
Mit 24bit = 3 Byte kommst Du bis über 16.7 Millionen, reicht, aber einen 24bit Datentyp kennt BASCOM nicht.
Bleibt der 4Byte Variablentyp, auch bekannt als "long". Die sind zwar viel zu groß, aber kleinere haben wir nunmal nicht. Die Arbeit sowas in BASCOM von Hand zu managen machen wir uns auch nicht.
Also...
Dann brauchen wir noch eine Variable für den Wert von Timer1 und eine Variable zum zählen der Überläufe. Timer1 ist 16 bit breit entsprechend muß die Variable für den Zählerstand vom Datentyp Word damit der Zählestand da rein passt. Für die Überläufe reicht eine Byte-Variable, wir nehmen trotzdem ein Word. (Einziger Grund ist, daß ich hoffe das was jetzt kommt ist dann leichter zu verstehen. Es geht auch mit 'ner Byte-Variablen.)Code:Dim Frequenz as long
Also...
Wie bekommst Du nun die beiden Variablen "Freq_low_word" und "Freq_high_word" in die Variable Frequenz.Code:Dim Freq_low_word as Word ' Speicher für den Wert von Timer1
Dim Freq_high_word as Word 'Zähler für die Überläufe. "as Byte" geht ausch
Du erinnerst Dich, Frequenz = Anz_Überläufe "+" Timerwert1
("+" == aneinandergehängt)
Das erste was einfällt, man multipliziert Freq_high_word mit 2^16 und addiert dann Freq_low_word. So hast Du es vor ein paar Versionen auch schon gemacht. (Nun gut, Du meitest zwar * 256 würde reichen, aber bis Du das selbst gefunden hast bin ich wirklich Opa geworden.)
Es geht aber pfiffiger.
Die Variable "Frequenz" belegt im Speicher genau 4 Bytes. Wenn wir nun die Variablen Freq_low_word und Freq_high_word genau auf die gleichen Speicherstellen legen, dann haben wir ohne jede Rechnung genau das was wir wollen.
also
Und genau das kann BASCOM in dem Du die Variablen so deklarierst.Code:Variable Variable Variable
Frequenz Freq_low Freq_high
1.Byte = 1.Byte
2.Byte = 2.Byte
3.Byte = 1.Byte
4.Byte = 2.Byte
Du hast nun 3 Variablen, die in Wirklichkeit aber nur eine einzige sind.Code:Dim Frequenz as long
Dim Freq_low_word as word at Frequenz OVERLAY
Dim Freq_high_word as word at Frequenz+2 OVERLAY
Sie belegen im Speicher nur die 4 Bytes, die auch die Variable "Frequenz" belegt. Mit Freq_low_byte sprichst Du die Bytes 1+2 der Frequenz-Variablen an und mit Freq_high_byte die Bytes 3+4.
Wenn Du jetzt in der Interrupt Routine den Befehl
ausführst, wird "Freq_high_word" um eins erhöht und (weil "Freq_high_word" auf der 3.+4. Speicherstelle der Variablen "Frequenz" liegt) wird "Frequenz" quasi nebenbei um 2^16 erhöht.Code:incr Freq_high_word
Als Gerüst ergibt sich dann für Deinen Frequenzzähler...
Mach was draus!Code:' ## BASCOM settings
$regfile = ...
$crystal = ...
$baud = ...
[...]
' ## Definitionen
const Preset_Timer0 = 219
const OvF_Timer0 = 39
[...]
Dim Torzeit as Byte
Dim Frequenz as long
Dim Freq_low_word as word at Frequenz OVERLAY
Dim Freq_high_word as word at Frequenz+2 OVERLAY
[...]
' ## Initialisierung
On Timer0 ...
On Timer1 ...
enable ...
enable ...
enable ...
Timer0 = Preset_Timer0
' ## Hauptschleife
Do
' ## Messzeit abgelaufen?
if Torzeit = OvF_Timer0 Then
Freq_low_word = Timer1
' ## Ausgabe
[hier: Ausgabe der Variablen "Frequenz"]
' ## Messung neu initialisieren
Torzeit = 0
Freq_low_word = 0 'braucht nicht drin sein, da der Wert oben mit "=" zugewiesen wird
Freq_high_word = 0
Timer0 = Preset_Timer0
Timer1 = 0
Start Timer0
Start Timer1
end if
' ## hier kannst Du noch beliebige ander Sachen machen.
' Achtung, sobald Du oben die Messung neu initialisierst, wird der Wert in
' der Variablen Frequenz wieder verändert.
' Wenn Du den Wert hier noch brauchst, z.B. für eine Ausgabe über die
' Serielle Schnittstelle, dann mußt Du ihn vorher in eine andere Variable
' sichern.
loop
' ## Schlußbemerkung:
' Wenn ich den Code so wie er hier steht 1:1 in Deinem Programm
' wiederfinde, dann hau ich ihn Dir eine halbe Stunde lang um die Ohren.
' (Falls wir uns irgendwann mal persönlich begenen sollten.)
' Nimm ihn als Vorlage, versuch ihn zu verstehen und programmier dann
' Deinen eigenen! Der Code den Du schon mühsam selbst geschrieben hast
' ist dazu eine gute Grundlage. Den Rest, besonders die Funktion der
' OVERLAY Option düfte hiermit soweit klar sein, daß Du es auch selber
' kannst. Wenn nicht, dann FRAGE!
End
' ## Interrupt Timer0 Überlauf
Timer0_Ueberlauf_int:
incr Torzeit
if Torzeit = OVF_Timer0 Then
Stop Timer1
Stop Timer0
end if
return
' ## Interrupt Timer1 Überlauf
Timer1_Ueberlauf_int:
incr Freq_high_word
Return
Ich hab den Code nicht getestet, ich kann etwas ultra wichtiges vergessen haben, ich kann Fehler drin haben.
Ciao
Werner
Danke , war nenn toller code, aber warum hast du alles geändert , war meins den so sch***. ich glaube, ich hab jetzt verstanden Worum es Kommentare im Quellcode gibt! Damit andere auch verstehen was ich meine. Zugegeben dein Code ist echt kompliziert, geht das echt nicht einfacher?
Code:## Definitionen
const Preset_Timer0 = 219
const OvF_Timer0 = 39
[...]
Dim Torzeit as Byte
Dim Frequenz as long
Dim Freq_low_word as word at Frequenz OVERLAY
Dim Freq_high_word as word at Frequenz+2 OVERLAY
[...]
' ## Initialisierung
On Timer0 ...
On Timer1 ...
enable ...
enable ...
enable ...
Timer0 = Preset_Timer0
' ## Hauptschleife
Do
' ## Messzeit abgelaufen?
if Torzeit = OvF_Timer0 Then
Freq_low_word = Timer1
' ## Ausgabe
[hier: Ausgabe der Variablen "Frequenz"]
' ## Messung neu initialisieren
Torzeit = 0
Freq_low_word = 0 'braucht nicht drin sein, da der Wert oben mit "=" zugewiesen wird
Freq_high_word = 0
Timer0 = Preset_Timer0
Timer1 = 0
Start Timer0
Start Timer1
end if
' ## hier kannst Du noch beliebige ander Sachen machen.
' Achtung, sobald Du oben die Messung neu initialisierst, wird der Wert in
' der Variablen Frequenz wieder verändert.
' Wenn Du den Wert hier noch brauchst, z.B. für eine Ausgabe über die
' Serielle Schnittstelle, dann musst Du ihn vorher in eine andere Variable
' sichern.
loop
' ## Schlußbemerkung:
' Wenn ich den Code so wie er hier steht 1:1 in Deinem Programm
' wiederfinde, dann hau ich ihn Dir eine halbe Stunde lang um die Ohren.
' (Falls wir uns irgendwann mal persönlich begenen sollten.)
' Nimm ihn als Vorlage, versuch ihn zu verstehen und programmier dann
' Deinen eigenen! Der Code den Du schon mühsam selbst geschrieben hast
' ist dazu eine gute Grundlage. Den Rest, besonders die Funktion der
' OVERLAY Option düfte hiermit soweit klar sein, daß Du es auch selber
' kannst. Wenn nicht, dann FRAGE!
End
' ## Interrupt Timer0 Überlauf
Timer0_Ueberlauf_int:
incr Torzeit
if Torzeit = OVF_Timer0 Then
Stop Timer1
Stop Timer0
end if
return
' ## Interrupt Timer1 Überlauf
Timer1_Ueberlauf_int:
incr Freq_high_word
Return
Würde dich nie so dermasen beleidigen!!!!!!!!!Zitat:
Wenn ich den Code so wie er hier steht 1:1 in Deinem Programm
' wiederfinde, dann hau ich ihn Dir eine halbe Stunde lang um die Ohren.
' (Falls wir uns irgendwann mal persönlich begenen sollten.)
Hier mein Code MIT Kommentar:
Hatte doch noch ein paar Fehlerchen korrigiert!Code:$regfile = "2313def.dat"
Dim Var1 As Byte
Dim Var2 As Long
Dim Freq As Long
Config Portb = Output
Config Portd = Output
Enable Interrupts
Enable Timer0
Enable Timer1
Config Timer0 = Timer , Prescale = 1024
Config Timer1 = Counter , Edge = Rising
Config Pinb.5 = Input
Portb.5 = 0
On Timer0 Test1 ' Springe zu Test1 wenn Timer0 "voll"
On Timer1 Test2 ' Springe zu Test2 wenn Timer1 "voll"
Timer0 = 216 ' Constante zum erzeugen einer "Exacten" Sek.
Timer1 = 0
Start Timer0
Start Timer1 'Auf die Pins, Fertig, Messen!
Do ' Anzeige Schlaufe
Loop
Test1:
' Wenn Timer0 (Gatetimer) voll, dann Var1 + 1
Incr Var1
If Var1 = 39 Then 'Wenn Timer0 39 überlief (1 Sek) dann:
Freq = Timer1 ' Lese Timer1 aus ( Counter )
Freq = Freq + Var2 ' Addiere Timer1 und Anzahl der überlaufe von Timer1*256
Var1 = 0
Var2 = 0
Stop Timer0 ' Starte Messung erneut
Stop Timer1
Timer0 = 126
Timer1 = 0
Start Timer0
Start Timer1
Return
End If
Return
Test2: ' Wenn counter (Timer1) überlauft, dann addiere 65536
Var2 = Var2 + 65536
Return
Jetzt versteht man meinen Code besser.
Gruß teslanikola
Hallo Teslanikola,
ich hab doch fast nix verändert.Zitat:
toller code, aber warum hast du alles geändert , war meins den so sch***.
Ich hab andere Variablenbezeichnungen verwendet, weil ich bei Var1,Var2, Test1, Test2 immer durcheinander komme welche nun welche ist. Ich konnte ja nicht ahnen, das Du dein Programm rund um das Beispiel herum schreibst, das eigentlich nur die Timerinterrupts erklären sollte.
Ansonsten sind nur Sachen drin, über die schon gesprochen wurde.
Das mit dem Overlay ist oben erklärt, Dein Goto ist durch eine If-abfrage im Hauptprogramm ersetzt und das mit den Überläufen ist auch so drin wie von Dir bereits verwendet (bis auf die 216 und die 38 )
Auch wenns anders aussieht, schau nochmal genau hin, Du dürftest nichts finden, daß Du nicht kennst und das nicht in diesem Thread besprochen wurde.
Stimmt, ich hätte einige Kommentare einfügen sollen. Ich hab aber ehrlich nicht damit gerechnet, daß Du noch Schwierigkeiten damit haben könntest.Zitat:
ich glaube, ich hab jetzt verstanden Worum es Kommentare im Quellcode gibt! Damit andere auch verstehen was ich meine.
Das der Code komplizierter ist als Deiner würde ich rundweg abstreiten, aber der selbstgeschriebene Code erscheint immer einfacher.Zitat:
Zugegeben dein Code ist echt kompliziert, geht das echt nicht einfacher?
Aber bitte nimm Dir 'ne Stunde Zeit, guck ihn Dir nochmal genau an und Du wirst feststellen, es haben sich die Variablennamen geändert und sonst nix was nicht vorher erklärt wurde.
Das einzige was vielleicht ein bisschen komplizierter ist als in Deinem Code, ist die Sache mit dem Overlay. Es vereinfacht aber extrem viel, nicht nur hier, sondern bei fast allen Programmen die man schreibt.
Setz Dich mal hin und schreib ein kleines Testprogramm, in dem Du nur das mit dem Overlay ausprobiert. Vieleicht verstehst Du es dann.
Ciao,
Werner
Hallo Tesnikola,
hast Du das interesse am Frequenzzähler verloren oder grübelst Du noch über dem Code?
Ciao,
Werner
sorry hatte wenig Zeit, immer diese Arbeiten in der Schule. Brenne heute mal den Code ins Flash und mache mak nen kl. Test.
servus, irgendwas geht nicht, wenn der Timer0 oder timer1 voll ist, springt der nicht zu Test1 oder 2 ( in der Sim )
Hallo Teslanikola,
schick mal Deinen Code.
Ciao,
Werner
problem 1 gelöst: Irn realität springt er zu Test1!!!
Problem 2 ( neu ): Counter zählt nicht, hab die verschiedensten Signale eingespeist ( Rechteck, Sinus, Dreieck, Sägezahn ) nix geht, habs mit Taster probiert ( mit Pull-Down-Widerstand von 10k ), liegt woll am Prog.
HELP!!!
Code:$regfile = "2313def.dat"
Dim Var1 As Byte
Dim Var2 As Long
Dim Freq As Long
Config Portb = Output
Config Portd = Output
Enable Interrupts
Enable Timer0
Enable Timer1
Config Timer0 = Timer , Prescale = 1024
Config Timer1 = Counter , Edge = Rising
Config Pinb.5 = Input
Portb.5 = 0
On Timer0 Test1: ' Springe zu Test1 wenn Timer0 "voll"
On Timer1 Test2: ' Springe zu Test2 wenn Timer1 "voll"
Timer0 = 216 ' Constante zum erzeugen einer "Exacten" Sek.
Timer1 = 0
Start Timer0
Start Timer1 'Auf die Pins, Fertig, Messen!
Do ' Anzeige Schlaufe
Loop
Test1:
' Wenn Timer0 (Gatetimer) voll, dann Var1 + 1
Incr Var1
If Var1 = 39 Then 'Wenn Timer0 39 überlief (1 Sek) dann:
If Portd.5 = 0 Then Portd.5 = 1 Else Portd.5 = 0 ' Wenn Sek. vorbei schaltet LED an oder aus ( zur Kontrolle )
Freq = Timer1 ' Lese Timer1 aus ( Counter )
Freq = Freq + Var2 ' Addiere Timer1 und Anzahl der überlaufe von Timer1*256
Var1 = 0
Var2 = 0
Stop Timer0 ' Starte Messung erneut
Stop Timer1
Timer0 = 126
Timer1 = 0
Start Timer0
Start Timer1
Return
End If
Return
Test2: ' Wenn counter (Timer1) überlauft, dann addiere 65536
Var2 = Var2 + 65536
Return
servus Werner haste ICQ
Hallo Teslanikola
no, ich hab kein ICQ.
Also bei mir funktioniert Dein Code bis auf die immer noch eingebauten offensichtlichen Fehler. Die haben aber nichts mit der prinzipiellen Funktion zu tun.
Überlauf Timer0 springt nach test1: und erhöht Var1.
Wenn Var1 = 39, dann wird Freq berechnet und die Timer neu gestartet.
Anschließend verabschiedet sich der Controller ins Nirvana, was zwar nicht OK ist, aber bei dem 2. Return innerhalb der IF-Schleife normal seien dürfte.
Überlauf Timer1 springt nach Test2: und erhöht Var2 um 2^16.
Soweit alles OK.
Was nicht funktioniert ist das Zählen der externen Impulse mit Timer1.
Zum einen könnte das daran liegen, daß Du den Counter-Eingang von Timer1 nicht als Eingang definierst. Dann gehst Du hin und toggelst den Pin auch noch in Deiner Interrupt Routine. (Warum überhaupt?)
Wenn ich beides ändere, dann gehts aber trotzdem nicht. In der Zeile "config Timer1..." könnte noch der Eintrag zum Prescale fehlen. Ob BASCOM den zwingend braucht weiß ich aber nicht. Den eingesetzt ergibt aber auch keine Änderung. :-(
Sprich es sind mehrer Fehler drin und mindestens einen davon sehe oder verstehe ich im Moment auch nicht.
Ciao,
Werner
Hallo, der Counter geht, hatte nen wackelkontakt, aber wenn ich meinen anzeigecode einfüge zeigt er als freq immer nur 0 an. der müsste doch den counter auslesen und als freq speichern., wenn ich den counter aber in der Anzeigeschlaufe auslese ziegt er mir ne zahl an ( zählt schnell aufw. und wird nach ner sek. wieder auf 0 gesezt).wieso speichert er bei Test1 nicht den counter auf Freq?????????????????????????
Hallo Teslanikola,
tut er auch, das Problem tritt erst unmittelbar danach auf.Zitat:
Hallo, der Counter geht, hatte nen wackelkontakt, aber wenn ich meinen anzeigecode einfüge zeigt er als freq immer nur 0 an.
der müsste doch den counter auslesen und als freq speichern.
Lösch das 'Return' aus der IF-Abfrage in der Interrupt-Routine Test1:
dann müsste es funktionieren.Code:[Test1: [...]
Timer0 = 126 ' ???
Timer1 = 0
Start Timer0
Start Timer1
' Return
End If
Return
Wenn ich Deinen Code im Simulator teste, dann zählt Timer1 nicht. Schreibe ich aber ein Testprogramm, in dem nur der Counter und der Überlauf drin ist, dann gehts. Very Strange!
Du hast übrigens vergessen das Timer0=126 in der Interrupt-Routine zu ändern. Geändert hast Du es nur bei der Erstinitalisierung.
Wenn Du bestimmte Werte mehrfach in einem Programm brauchst, dann ist es sinnvol die im Quelltext als Konstanten zu definieren.
z.B. Const OvF_1s = 126
Im Programm schreibst Du anschließend überall wo Du die 126 haben willst einfach OvF_1s. Wenn Du die 126 in 226 ändern willst, dann brauchst Du nur noch an der einen Stelle den Wert zu ändern und mußt nichtmehr den Code durchsuchen wo Du überall 126 geschrieben hast..
Ciao,
Werner
OH HAPPY DAY, OH JESUS CHRIST!!!!!
Danke Werner du bist der GRÖÖÖÖÖÖÖÖÖÖÖÖSTE [schild=1 fontcolor=000000 shadowcolor=C0C0C0 shieldshadow=1]Thank you!!![/schild] , es funkt.
Eslag nur an dem sch*** RETURN :MistPC . Hab in der Praxis noch nen paar Probs mit der Anzeige ( nen paar Segmente leuchten nicht mehr [ schon wieder nen Wackelkontakt ] )
Werde die Schaltung und das Prog zu ner Anleitung zusammenstellen, ne Platine entwickle ich au noch, dann werde ich es hier Veröffentlichen ( darf ich deinen Namen nennen? Als Quellcodekontolleur? )
Echt noch mal fett Danke!!!!!
Hallo Teslanikola,
freut mich das es läuft.
Ich hoffe Du hast die anderen 'Fehler' auch noch ausgemerzt.
Meinen Namen darfst Du nennen, aber bitte nicht als Quellcodekontrolleur. Nachher denkt noch jemand ich hätte den Code abgesegnet. Dabei hätte ich ALLES ganz angers gemacht! ;-)
Kannst ja behaupten ich hätte mit 'nem Holzhammer hinter Dir gestanden und Dir bei jedem Fehler einen übergebraten. Den Vorschlaghammen, den es für eleganten Code benötigt hätte, den hatte ich leider nicht.
Hauptsache es läuft! :-)
Ciao,
Werner
Um genauigkeit zu verbessern könnte man auch ein 8MHz Quarz nehmen
mit ner Teilung von 8. Dann muss man der Timer bei 192 Starten und 3906 mal überlaufen lassen. Das gibt EXACT 1,0 Sek.
Oder ich nehme ein 10MHz Quartz mir ner Teilung von 8, dann bei 184 Starten und 4882 mal überlaufen lassen. Auch ned EXACTE Sek.