Archiv verlassen und diese Seite im Standarddesign anzeigen : Howto Frequenzzähler
teslanikola
06.03.2005, 21:02
Hi Leuts, hab´n klenes problem 8-[
ich will ein [scroll:d9b288b528]Frequenzzähler[/scroll:d9b288b528] aufbauen ( Hardware ist kein Problem)
aber die software:
Ich weis das man einen Timer ( 1 oder 0 ) benutzen muss, aber wie?
Also das brauch ich: ein Codeschnippsel der in 1er Sekunde die impulse an einem pin zählt. est ist wichtig das die sekunde auch eine sekunde ist!!
Hat mal jemand ein tipp?? :-s
sebastian.heyn
07.03.2005, 15:45
Ja, hab ich auch schonmal gemacht. den eingang der impulse ziehst du mit ner z diode auf 5v, dann hängst du das an nen interrupt.
timer baust du wie mit dem programm "RNAVR" beschrieben (das rechnet dir alles genau aus)
wenn interrupt von pin kommt machst du incr variable
und jede sekunde dann von timer1 kannst du den wert verarbeiten und danach wieder auf 0 setzen
teslanikola
07.03.2005, 18:01
Hallo, will dich nicht beleidigen aber was genau heist das jezt. :-s
Ich hab zwar ne menge Bascom und Basic erfahrung aber des mit den Interups peil ich nich. Ein codeschnipsel sagt doch mehr als 10000 Worte!!!!!! Haste mal ein Codeausschnitt, die Variable ( wert ) zeig ich mit ner multiplex an ( die Funktioniert schon ) aber um was anzuzeigen brauch ich was zum anzeigen. danke für deine Hilfe!
sebastian.heyn
07.03.2005, 18:29
Hoffe es hilft dir ein bisschen weiter.
bei steigender flanke an int0 (portb.0 beim mega128) wird gezählt.
$regfile = "m128def.dat"
$crystal = 16000000
$baud = 9600
Config Timer1 = Timer , Prescale = 256
Ddrb = &B11111100 'set portb.0,portb.1, inputs.
Portd = &B00000001 'interner Pullup an PD0 aktivieren
Dim Puls As Integer
Dim Actspeed As Integer
On Timer1 Timer1int
Timer1 = 3036
On Int1 Intr
Config Int1 = Rising
'=======PROGRAMM=====================
Puls = 0
Actspeed = 0
Enable Interrupts
Enable Int1
Enable Timer1
Start Timer1
Do
'Hier könnte deine ausgabe stehen (actpuls)
Loop
End
Timer1int:
Actpuls = Puls 'jetzt übertragen wir den wert
Puls = 0
Timer1 = 3036 '0,3 Sekunde
Return 'ende des timerinterrupts
Intr:
If Pind.1 = 1 Then incr Puls
Enable Int1
Return
teslanikola
07.03.2005, 22:01
tut mir leid ich habs ned verstanden :?: , kanste des ned für ein AT90s2313
modifizieren?
hab dir hier mal mein multiplex 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
Dim W As Word
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
W = W + 1
Loop
Schon mal danke für dein bemühen!!
Grüßle
.... timer baust du wie mit dem programm "RNAVR" beschrieben (das rechnet dir alles genau aus) ....
wo gibt es denn das Progr. RNAVR zu, Download ??
Danke !
Gerhard
sebastian.heyn
08.03.2005, 09:17
@Gerhardt: Hier im forum habe ich das mal irgendwo gefunden..
@Teslanikola: Es ist doch ganz einfach:
Im hauptprogramm läuft deine Ausgabe...
Im hintergrund läuft timer1 und löst ein mal pro sekunde einen interrupt aus.wenn du einen impuls am eingang von int0 hast (musst im datenblatt schauen welcher pin es genau ist) wird die variable puls um eins erhöht. (weil frequenz= impulse pro sekunde) dann wird wenn der timer jede sekunde den interrupt auslöst wird PULS in die varible actpuls geschrieben. danach wird puls zurückgesetzt, sodass du von vorne anfangen kannst mit zählen... Versuch es einfach selber zu bauen, da ist der lerneffekt höher
Hallo,
anstatt die Frequenzzählung per Software auszuführen,
bietet es sich doch an die vorhandene
und dafür vorgesehene Hardware auf dem 2313 zu benutzen.
Einen TIMER/Counter-0 als Gate für 1sec,
und einen anderen Timer/COUNTER-1 als Zähler.
Dann kannnst du wesentlich höhere Frequenzen messen,
als mit der Software-Methode.
Per Hardware gehen Frequenzen bis zur halbe Taktfrequenz des 2313.
Und der Prozessor hat fast nix zu tun damit,
der kann inzwischen Rechnen, Display, Kommunikation usw. machen.
Guck dir mal im Datenblatt des 2313 die Input-Capture-Unit des Counter1 an,
und die Möglichkeit den Counter extern zu takten.
Gruß Jan
teslanikola
08.03.2005, 13:03
Hi janB,
hab deine idee versanden, bin aber in bascom ned so sattelfest,
haste nen codeschnippsel??
Gruß
Hallo,
haste nen codeschnippsel??
nee, einen fertigen Code hab ich nicht parat.
Aber dieser Tage, spätestens am Wochenende,
werd ich das mal testen, interessiert mich auch,
wie die Timer-Counter zusammenspielen.
Ist ja nicht soviel Aufwand.
Wenn du solange warten kannst ?
Sonst must du eben selbst ran,
dabei lernst du auch am meisten.
Wie hoch sind die Frequenzen, die du zählen willst ?
Gruß Jan
teslanikola
09.03.2005, 15:30
von 1 Hz bis 4 MHz
Hallo,
von 1 Hz bis 4 MHz
Da hast du mit den AVR ohne externe Bauteile keine Chance,
was Vernünftiges hinzukriegen für so hohe Frequenzen.
Überleg mal:
Wenn du den 2313 mit 16Mz taktest,
dann kann er in einer Periode der 4 Mhz,
also in 1/4000000stel Sekunde bis 2 zählen.
Mehr schafft er nicht.
Das ergibt dann 8E6 / 2 = 4MHz. Soweit so gut.
aber was ist die nächste niedrigere Frequenz ?
Das würde der Zähler bis 3 Zählen. Dazwischen gips ja nix.
Das entspricht dann 8E6 / 3 = 2,66 MHz.
Es gäbe also keinen Messschritt zwischen 4 und 2,66 MHz.
Das ist nicht das, was ich unter Messen verstehe.
Sinn macht das höchstens bis 1MHz, da wäre die Auflösung
dann etwa 10%.
Darunter wird es dann immer besser.
Gruß Jan
Klaus_0168
09.03.2005, 18:35
Hi all,
was haltet ihr von einem vorgeschalten Hardwarezähler als Vorteiler. Auf dieser Weise könntet ihr jede beliebige Frequenz messen und die Messung im optimalen Bereich halten.
Über eine Auswahlschaltung sollte das Teilerverhältnis einstellbar sein.
Gruß Klaus
teslanikola
09.03.2005, 21:35
hallo janB, hab ich gesagt das ich KEINE externen tackt verwenden
möchte??? Kann mich ned erinnern, aber mal ne frage kann ich ned
einen der Xtal eingänge als clockout verwenden und dann als input für den Timer/ counter benutze?
teslanikola
09.03.2005, 21:37
hallo klaus, wie teile ich den Frequenz mit > 4MHz, nen normaler CMOS
packt des doch ned, Gibts so was wie ein Hightspeed CMOS??
teslanikola
09.03.2005, 21:42
Wenn du den 2313 mit 16Mz taktest,
dann kann er in einer Periode der 4 Mhz,
also in 1/4000000stel Sekunde bis 2 zählen
Wieso um alles in der welt teilst du den tackt durch 4
ein AT schafft doch ein befehl pro clock
Hallo,
kann ich ned
einen der Xtal eingänge als clockout verwenden und dann als input für den Timer/ counter benutze? ??? Das verstehe ich nicht.
Das sind doch entweder Clk-Oszillator-Anschlüsse oder Port-A E/As.
...teilst du den tackt durch 4
ein AT schafft doch ein befehl pro clock]
Ich gehe von einer Periodendauermessung mit einem internen Counter aus.
Und der schafft eben max. halbe Taktfrequenz.
Das hat mit den Befehls-Taktzyklen nichts zu tun.
Gruß Jan
teslanikola
10.03.2005, 13:52
na ich nein schon ein XTAL pinn, da wo du dein Quarz anschliesch
teslanikola
10.03.2005, 14:14
hab hier mal nen Oszi von einem XTAL pin, wenn man diese Signal verstärken könnte ( HF Transistor) könnte man es doch als In für den timer benutzen. Oder was denkt ihr
TESLA FOR EVER
teslanikola
10.03.2005, 14:16
ach ich vergass: Quarz= 10MHz, C = 27p
0.1µsec/cm und 0.2V/cm
Werner_Just
10.03.2005, 14:56
Hallo teslanikola,
hab hier mal nen Oszi von einem XTAL pin, wenn man diese Signal verstärken könnte ( HF Transistor) könnte man es doch als In für den timer benutzen. Oder was denkt ihr
Warum sollte man das Verstärken? Die Timer im Atmel können auch so mit der Quarzgeschwindigkeit zählen.
Config Timer1 = Timer, Prescale = 1
Ich glaub Du solltest Dir erstmal ein paar Gedanken machen wie Du Deinen Frequenzzähler realisieren möchtest.
1) als Impulszähler mit fester Zähldauer oder
2) als Periodendauermessung mit anschließender Umrechnung
In beiden Fällen gilt, die zu messende Frequenz muß deutlich kleiner als die Quarzfrequenz des Atmel sein.
Bei Realisierung nach 1) verschluckt der Atmel sonst zu zählende Impulse oder nach 2) geht Deine Messgenauigkeit gegen Null.
Ciao,
Werner
Klaus_0168
10.03.2005, 15:43
Hi teslanikola,
zugegeben, wenn Du auf CMOS bestehst sind nicht mehr als 5 - 6 Mhz bei einer Versorgungsspannung von 15V drin.
Einige TTL-IC's (Bsp.74S196 dekadischer Zähler max. 100Mhz) hängen die CMOS-Typen ohne weiteres ab. Mal abgesehen davon, das der uC sowieso schon mit 5V versorgt wird, sehe ich keine Gründe gegen den Einsatz eines TTL-IC's.
Zur maximalen Zählfrequenz :
Laut Fourier beträgt die maximal messbare Frequenz die Hälfte der maximalen Eingangsfrequenz des Messgerätes. Es kann sonst nicht garantiert werden, das alle Zyklen der Messfrequenz gezählt werden können.
Wenn also ein mit 16Mhz getakteter 2313 maximal 4Mhz am Countereingang verarbeiten kann (hab' jetzt nicht im Datenblatt nachgesehen !!), beträgt die maximal messbare Frequenz 2MHz. Bei höheren Frequenzen nehmen die Messfehler rasant zu.
Gruß Klaus
teslanikola
10.03.2005, 15:47
Nenne keine Namen, aber irgend wer wollte einen external oszi für den Timer/counter. Aber ich brauch ja keinen.
PS : 2 Mhz sind doch genug!!!
Was jetzt fehlt is nen Codeschnippsel, da ich mich mit timer ned auskenne tu
Gruß
Klaus_0168
10.03.2005, 15:55
klingt jetzt ein bischen frech, aber wie wäre es mit der BasCom-Doku ??
Hilfedatei und Programmbeispiele sind eine Schnipseljagt schon wert. :cheesy:
Weiter kann ich nicht helfen, da ich mir diese Aufgabenstellung noch nicht gestellt habe
Klaus
Werner_Just
10.03.2005, 16:08
Hallo Klaus,
Zur maximalen Zählfrequenz :
Laut Fourier beträgt die maximal messbare Frequenz die Hälfte der maximalen Eingangsfrequenz des Messgerätes.
jein(*), aber er will Frequenzen messen und nicht ein Signal rekonstruieren. Frequenzzählung ist kein Abtast-Problem.
Er hat nicht das Problem, das er wissen will, ob das Signal das er misst ein Sinus, Dreieck, Rechteck oder irgendetwas dazwischen ist.
Ciao,
Werner
(*) Es war nicht Fourier und sondern Nyquist und es heißt <2 und selbst nahe bei 2 gilt nur bei unendlich langen periodischen Signalen.
Werner_Just
10.03.2005, 16:28
Hallo teslanikola,
Nenne keine Namen, aber irgend wer wollte einen external oszi für den Timer/counter. Aber ich brauch ja keinen.
Wenn wir den gleichen Post meinen, dann wollte er keinen externen Oszillator, er wollte einen Teiler vorschalten. Und das ist eine gute Idee bei hohen Frequenzen.
PS : 2 Mhz sind doch genug!!!
Was jetzt fehlt is nen Codeschnippsel, da ich mich mit timer ned auskenne tu
Dann setz Dich hin und lies a) die Bascom Hilfe und b) die Atmel Appnote zum Umgang mit den Timern.
Und wenn Du bereit bist etwas Geld auszugeben lies c) das Buch von Rowalt. Als ersten Einstieg eignen sich auch seine Artikel aus der Zeitschrift Funkamateur.
http://www.rowalt.de/mc/index.htm
Einführung 1...6
Bei einem Frequenzzähler ist nun wirklich nichts was duch Tricks gelöst werden muß. Das sind Grundlagen und die solltest Du Dir imo erarbeiten und nicht anhand von "Codeschnippseln" abkupfern.
jm2ct
Werner
teslanikola
10.03.2005, 16:29
ich hätte gern einmal die 1, zum mitnehmen Bitte
teslanikola
13.03.2005, 21:16
Servus, danke für eure Beiträge
hab mal nen code geschrieben,
könnt ihr mal euren Senf dazugeben, weis nicht ob der so richtig ist
:-k
Gruß
teslanikola
teslanikola
13.03.2005, 22:26
hallo
](*,)
wie bin ich blöd, was wollt ihr den ohne code kontollieren
also hier der Code: ist der Richtig so???
$regfile = "2313def.dat"
$crystal = 10000000
Config Pinb.5 = Input ' Signal Input
Dim Erge As Long
Portb.5 = 0 ' Aktiviert int. Pulldown
Config Timer0 = Timer , Prescale = 1 ' Config. Timer0 als Timer
Config Timer1 = Counter , Edge = Rising
' Config. Timer1 als Counter mit steigender Flanke
Mess:
Start Timer0 'Startet Messung
Start Timer1
Do
Loop Until Timer0 = 40
Stop Timer0 ' 40 Timerdurchläufe = 1sek
Stop Timer1
Erge = Timer1
Timer0 = 0 'Auslesen des Counters
Timer1 = 0
' Anzeigeroutine
Goto Mess
Werner_Just
14.03.2005, 09:26
Hallo Teslanikola,
vom Grundaufbau geht das so.
Zwei Sachen:
1) mit Timer0 willst Du eine Sekunde Messzeit erzeugen.
Das heist, Du must 10E6 Timer-Takte warten bis Du die Zähler wieder stoppst. Du wartest aber nur 40 Takte.
Da Du 10E6 Takte nicht direkt mit Timer0 zählen kannst, brauchst Du eine weitere Variable, die die Anzahl der Overflow-Interrupts (Interrupt: OnTimer0) zählt.
1 Overflow_int = ein Timerdurchlauf
Ich würde zusätzlich den Prescale von Timer0 erhöhen.
Takte = Anz-Interrupts * Timerbreite * Prescale
10E6 = 38,1469 * 256 * 1024
38,1469 lassen sich nicht unmittelbar realisieren, Du kannst aber Timer0 mit einem Wert vorsetzen und dann bis zum 39sten Interrupt zählen.
Stop Timer 0
Timer0 = 218
Start Timer0
Start Timer1
Do
Loop Until Interrupt_Zähl_Variable = 39
Stop Timer1
Stop Timer0
d.h. der erste Overflow kommt nach (256-218) * 1024 Takten und jeder weitere Interrupt nach 256 * 1024 Takten.
Der 39ste Interrupt kommt also nach (256-218)*1024 + 38*256*1024 Takten. Ingesammt also nach 10.000.384 Takten.
Damit liegst Du nur um 38.4 µs neben Deiner geforderten Messzeit. Hinzu kommt noch die Zeit für das abarbeiten des Programms vom Interrupt bis zum Timer-Stop.
Das ganze lässt sich auch noch optimieren, z.B. indem Du die benötigten Takte, die für das Abarbeiten berücksichtigst und gegen den Vorsetz-Wert aufrechnest.
2) Timer1 ist 16Bit breit. D.h. Du kannst bei 1s Messzeit Frequenzen bis 65535 Hz messen. Wird die Frequenz höher läuft Dir Timer1 über.
Um den Wert zu erhöhen musst Du wie beim Timer0 die Anzahl der OnTimer1-Interrupts zählen. Bei 1-2 MHz wirst Du irgendwann an Herdware Grenze des Atmel-Chips kommen. Höhere Frequenzen kannst Du dann nur noch messen, wenn Du sie vor der Messung z.B. mit einigen Flipflops runterteilst.
Ciao,
Werner
teslanikola
14.03.2005, 13:05
Hallo, danke für die Antwort, wie kann isch den Interupt von Timer0, und die Anzahl der "überläufe" von Timer1 ( hier counter1) auslesen?
aber das stimmt oder:
Config Pinb.5 = Input ' Signal Input
Dim Erge As Long
Portb.5 = 0 ' Aktiviert int. Pulldown
Config Timer0 = Timer , Prescale = 1 ' Config. Timer0 als Timer
Config Timer1 = Counter , Edge = Rising
' Config. Timer1 als Counter mit steigender Flanke
Werner_Just
14.03.2005, 13:43
Hallo Teslanikola,
wie kann isch den Interupt von Timer0, und die Anzahl der "überläufe" von Timer1 ( hier counter1) auslesen?
Du kannst die Anzahl der Überläufe nicht auslesen.
Du schreibst für Timer0 und Timer1 jeweils eine Interrupt Routine und gibst die Interrupts frei. Bei jedem Überlauf wird dann in die jeweilige Routine gesprungen. In den Routinen erhöhst Du jeweils Die zugehörige Zählvariable.
Stichworte für die Suche in der BASCOM-Hilfe sind
On Interrupt
On Timer0 (1)
Enable Timer0 (1)
Enable Interrupts
sowie generell Timer0 und Timer1
> aber das stimmt oder:
> Config Pinb.5 = Input ' Signal Input
Ich hab gerade nicht im Kopf, ob PinB.5 der Counter-Eingang für Timer1 ist. Wenn ja, dann stimmt das
> Dim Erge As Long
Timer1 ist nur 16 bit breit (Word). Bascom konvertiert aber automatisch.
Du kannst mit "Overlay" Deinen Überlauf-Zähler und den Timer1-Wert prima zu einem long zusammenfassen. s. BASCOM Hilfe zu DIM und OVERLAY.
> Portb.5 = 0 ' Aktiviert int. Pulldown
Die AVRs haben keinen int. Pulldown. Du schaltest 'nur' den int. Pullup aus.
>Config Timer0 = Timer , Prescale = 1 ' Config. Timer0 als Timer
Prescale = 1024
Ciao,
Werner
teslanikola
14.03.2005, 15:42
Hab nen Code vor nem Frequenzzähler gefunden und geändert
würde das so hinhauen????
$regfile = "2313def.dat"
$crystal = 16384000 'Quarz: 16,384MHz
Dim Lcount As Long At &H60 'Zähler-Variable
Dim Wcountlo As Word At &H60 Overlay 'LoWord der Zählervariablen
Dim Wcounthi As Word At &H62 Overlay 'HiWord der Zählervariablen
Dim Sresult As String * 16 At &H64 'Ausgabestring
Dim Result(16) As Byte At &H64 Overlay 'Ausgabestring als Byte-Array
Dim I As Byte
Dim Gate As Byte
'Timer0 (Torzeit) und Timer1 (Zähler) konfigurieren:
On Timer0 Ongatetime 'Interrupt-Routine für die Torzeit
On Timer1 Oncounteroverflow 'Interrupt-Routine fürs HiWord des Zählerstands
Config Timer0 = Timer , Prescale = 1024 'Torzeit-Timer mit Takt/1024
Config Timer1 = Counter , Edge = Rising 'Zähler an steigender Signalflanke
Ddrd.5 = 0 'PD5/T1 auf Eingang setzen (Zähler-Eingang)
Enable Timer0 'Timer0-Interrupts ein (Torzeit)
Enable Interrupts 'Interrupts global einschalten
Start Timer0
Main:
Goto Main
Ongatetime: 'Timer0-Torzeit beendet
If Gate = 0 Then 'Zähler starten
Enable Counter1 'Zähler-Overflow-Interrupts einschalten
Start Counter1
Gate = 1
Elseif Gate < 40 Then '40 Timer0-Umläufe warten
Incr Gate
Else 'Tor zumachen, Zähler auslesen
Stop Counter1
Disable Counter1 'Zähler-Overflow-Interrupts ausschalten
Wcountlo = Counter1 'LoWord in die LONG-Zählervariable holen
Counter1 = 0 'Zähler zurücksetzen (Voreinstellen geht hier auch!)
Gate = 0
'ANZEIGERUTINE
Tifr.tov0 = 1 'Timer0-Overflow-Flag löschen (nicht = 0!!!)
Tifr.tov1 = 1 'Timer1-Overflow-Flag löschen (nicht = 0!!!)
End If
Return
Oncounteroverflow:
Incr Wcounthi 'HiWord der Zählervariablen erhöhen (lCount=lCount+65536)
Return
Werner_Just
14.03.2005, 16:15
Hallo,
> Hab nen Code vor nem Frequenzzähler gefunden
das merkt man :-( ...
> und geändert
aber nicht verstanden.
Dabei war Dein eigenes Programm doch fast schon fertig. Fehlten noch die Interrupts, das wäre es gewesen. Warum schmeist Du das was Du selbst geschrieben hast so einfach weg. Da (scheinst) Du gewust zu haben wie das Programm arbeitet, auch wenn noch Fehler drin waren. Bei der jetzt verwendeten fremden Lösung bezweifel ich das.
> würde das so hinhauen????
nein, würde es nicht. Beim Timer1 Interrupt fehlt die Hälfte.
Was ich auch nicht verstehe, BASCOM hat einen recht gut funktionierenden und einfach zu bedienenden Simulator. Warum probierst Du es nicht aus.
Ciao,
Werner
teslanikola
14.03.2005, 16:31
Hallo, ich weis des war nen echter Seiten sorung kommt nich wieder vor, aber du hast mir was von interupts und overlay usw geschrieben und wie du mir geraten hast in der Help nachgeschaut und TADA da hat es Klick gemacht nicht der verstand sondern die Hauptsicherung im Hirn ](*,) fazit:
Weniger Verstanden als vorher ( naja ohne gescheite Englisch kommste ne arg weit, bis jetzt hatts immer gereicht :D )
Hab dir doch nen Code geschickt, es würde mir helfen wenn du ihn so modifizieren würdest das es Hinhaut, das mit der Multiplexanzeige hab ich ja schon gelöst ( war leicht :D ), aber da ich mich mit Timer so gut auskenn wie der Metzger vom Brotbacken wurde das klene Problem zu nem großen. Wie ich aus deine Beiträgen ersehen konnte weist du von was du redest könntest du mir vielleicht modifizieren [-o< ( ob als WERt ein String oder ne Variable rauskommt is mir wurscht)
Vielen dank für dein bemühen mir was beizubringen.
Grüßle teslanikola
Werner_Just
14.03.2005, 17:28
Hallo Teslanikola,
Danke für den Honig, aber ich bin fast genauso Anfänger wie Du und
Programme für andere schreibe ich nur gegen Geld. :evil:
> Weniger Verstanden als vorher
Dann solltest Du da genau etwas mehr Zeit investieren bzw. genau nach dem fragen was Du nicht verstanden hast.
z.B. Kann mir jemand erklären wie man Interrupts verwendet?
Oder...
Was hat es mit dem Overlay auf sich?
Das Buch von Rowalt ist zudem auf deutsch. Wie schon gesagt, ich kann es nur empfehlen.
> Hab dir doch nen Code geschickt, es würde mir helfen wenn du ihn so modifizieren würdest das es Hinhaut
No, mach ich nicht. Wenn Du es nicht selber machen/schaffen willst, dann geh in einen Elektronikladen und kauf Dir einen Frequenzzähler.
> das mit der Multiplexanzeige hab ich ja schon gelöst ( war leicht :D ),
und ein Frequenzzähler ist genauso leicht.
>aber da ich mich mit Timer so gut auskenn wie der Metzger vom Brotbacken wurde das klene Problem zu nem großen.
Wo ist das Problem?
Ein Timer kann Zählen.
Er zählt entweder interne Takte == Timer, oder er zählt externe Ereignisse == Counter. Er kann zusätzlich einen Interrupt auslösen wenn er überläuft.
Einige können zusätzlich Interrupts auslösen wenn ein bestimmter Zählerstand erreicht ist == Compare und Zählerstände bei externen Ereignissen speichern == Capture.
Mehr gibts eigentlich nicht zu wissen, alles andere kann man nachschlagen.
> Vielen dank für dein bemühen mir was beizubringen.
Gern geschehen.
Ciao,
Werner
teslanikola
14.03.2005, 17:46
Hallo werner,
wenn ich mir selber helfen könnte , dann hätte ich die frage doch nicht in ein forum gestellt.
Selbsthilfe e.V.
teslanikola
14.03.2005, 18:17
Sorry, wenn ich so böse war, aber wer 2 Stunden damit beschäftigt war herrauszufinden wie man 2 Timer als Counter und timer zusammen bringt und nach den 2 stunden soweit wie vorher ist dem brennt schon mal ein Fusebit durch. wollte dich nicht beleidigen, aber hier werden ja Bücher über ein Problem geschrieben, das man mit nen paar befehlen Quellcode lösen kann. Zwar lernt man besser wenn man alles selber rausfindet aber ich will das problem halt so einfach wie möglich lösen, wenn man dan nen code bekommt und sich den mal GENAU anschaut lernt man doch auch was! Ich hab mir bis jetzt alles selberbeibringen können ( immer so weit bis mein RS-Enbglisch versagt ) aber das mit dem Timer verstehe ich echt nicht hat den niemand EIN CODE, muss doch ned fertig sein, aber so das man ihn benutzten kann ( WERT auslesen ). Echt tut mir leid. :cry:
SORRY
teslanikola
14.03.2005, 18:18
Aber die Frage ging nicht nur an werner, wer mir helfen kann der helfe
Werner_Just
14.03.2005, 21:23
Hallo Teslanikola
wenn ich mir selber helfen könnte , dann hätte ich die frage doch nicht in ein forum gestellt.
ist ja auch OK, ich und vermutlich auch alle anderen hier sind gerne bereit Dir zu helfen.
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 mußt Du Dein Programm schon selbst.
Sorry, wenn ich so böse war, aber wer 2 Stunden damit beschäftigt war herrauszufinden wie man 2 Timer als Counter und timer zusammen bringt und nach den 2 stunden soweit wie vorher ist dem brennt schon mal ein Fusebit durch.
Armer schwarzer Kater!
Aber warum fragst Du dann nicht nach DEM womit Du ein Problem hast? Du fragst immer nur danach wer eine Lösung hat. Am besten gleich für das ganze Programm.
Wie Du 2 Interrupts ans laufen bringst ... kein Problem ...
Im abgekupferten Code hast Du für Timer0 stehen:
On Timer0 Overflow_Routine_Timer0
Enable Interrupt
Genau das "On Timer ..." fehlt für Timer 1!
On Timer0 Overflow_Routine_Timer0
On Timer1 Overflow_Routine_Timer1
Enable Interrupt
Mit On Timer0 (1) sagst Du dem Compiler das er 1. den Overflow-Interrupt einschalten soll und du sagst ihm 2. wohin er bei einem Interrupt springen soll. Nämlich zum Lable Overflow_Routine...
Also z.B.
$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
Schau Dir im Simulator mal an was mit den Variablen Var1 & Var2 passiert und wann es passiert. Klar?
Ciao,
Werner
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
??
teslanikola
14.03.2005, 22:48
@werner_just
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.
OK ich sehs ja aber deine letzten "Hilfen" brachten mich nicht weiter ( trotzdem Danke )
Ich zitiere:
Suche in der BASCOM-Hilfe
Sei doch mal ehrlich, ist das nicht was man als erstes macht???
Stop Timer 0
Timer0 = 218
Start Timer0
Start Timer1
Do
Loop Until Interrupt_Zähl_Variable = 39
Stop Timer1
Stop Timer0
Diese Info brachte mir genau so viel, hatte glaube vorher erwähnt, das ich mich mit dem Timer/Counter NICHT auskenne.
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
Werner_Just
15.03.2005, 08:01
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
Werner_Just
15.03.2005, 08:38
Halo Teslanikola,
> OK ich sehs ja aber deine letzten "Hilfen" brachten mich nicht weiter
> ( trotzdem Danke )
hm, ein kleiner Hinweis wo Du nicht durchblickst?
[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.
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)
Da war der Timer Lehrgang mit dem alleserklährenden Code doch die besste Antwort ( langsam geht mit ein :idea: auf )
Welchen meinst Du?
> 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.
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 ).
Stimmt, die Timer laufen völlig unabhängig vom Programm. Nur die Interrupts und das Auslesen verbrauchen etwas Programmzeit.
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
teslanikola
15.03.2005, 13:07
Hallo Werner, haste mein Multiplexcode mal angesehen?
Ist auf jeden Fall eine schöne Programmieraufgabe.
Das glaub ich dir auf Wort :wink:
Da war der Timer Lehrgang mit dem alleserklährenden Code doch die besste Antwort ( langsam geht mit ein auf )
Welchen meinst Du?
Den Mein ich:
Also z.B.
$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
Gruß teslanikola
Werner_Just
15.03.2005, 13:32
Hallo Teslanikola,
haste mein Multiplexcode mal angesehen?
Ich hab zwar mal über den Multiplex-Thread geguckt, aber Deinen Code hab ich nicht gefunden. Vielleicht war ich aber auch einfach nur blind.
Dim Var1 as Byte
Dim Var2 as Byte
[...]
Der Code hat Dir also weitergeholfen... grübel.
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
teslanikola
15.03.2005, 18:01
hallo werner,
$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
Denn Code mein ich.
Grüßle
teslanikola
15.03.2005, 19:47
Hallo Werner,
endlich ist es so weit der Code ist fertig \:D/ \:D/ \:D/
Hier der Code ( hoffe du bist zufrieden ):
$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
Bitte kontollieren!
Gruß teslanikola
Werner_Just
15.03.2005, 20:36
Hallo Teslanikola,
endlich ist es so weit der Code ist fertig \:D/ \:D/ \:D/
Hier der Code ( hoffe du bist zufrieden ):
äh....
> 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?
teslanikola
15.03.2005, 21:06
Timer0 = 550
- Interessant das der Compiler nicht mosert wenn einer 8 bit Register ein Wert > 255 zugewiesen wird.
ach sch*** das erklärt auch die var1 = 9 then ...
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
Werner_Just
17.03.2005, 13:18
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
teslanikola
17.03.2005, 14:22
So Update 1.2 is fertig, währe das jezt IO,hab au die Multipikation weggekriegt.
$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
Gruß teslanikola
Werner_Just
17.03.2005, 15:06
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
DanTheMan
18.03.2005, 11:40
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
teslanikola
18.03.2005, 13:01
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.
$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
Danke für eure Hilfe
teslanikola
18.03.2005, 13:06
Servus, hab den Multiplex auch mit eingebaut:
$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
Gruß teslanikola
Werner_Just
18.03.2005, 14:33
Halllo Teslanikola
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.
und Du hast nicht verstanden das das nicht geht!
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.
Servus, hab den Multiplex auch mit eingebaut:
nichts für ungut, aber wir sollten noch beim Code-ohne-Multiplexer bleiben. Es wird sonst leicht etwas unübersichtlich.
Ciao,
Werner
teslanikola
18.03.2005, 15:28
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)
$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
PS:
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-just haste mir schon viel geholfen, und das ich die langsam nerve ist mir auch klar! Sorry
teslanikola
18.03.2005, 15:32
Hallo werner, hab noch was vergessen:
Es tut schon fast weh, wenn nach dem 3. Hinweis auf den Beitrag von "Gast" immernoch die beiden Zeilen:
Will nicht frech sein , aber es sind DREI.
$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
Werner_Just
18.03.2005, 16:00
Hallo Teslanikola
Enable Timer0
Enable Timer1
ich hatte die Hoffnung schon fast aufgegeben die beiden Zeilen in Deinem Code zu sehen.
> Will nicht frech sein, aber es sind DREI.
Welche ist die Dritte? "Enable Interrupts" hab ich nicht vermisst, die hattest Du ja :-)
Ciao,
Werner
teslanikola
18.03.2005, 16:56
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.
teslanikola
20.03.2005, 17:19
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
Werner_Just
21.03.2005, 11:55
Hallo Jungspund
Geht das Programm jetzt so oder gibts noch was zu verändern,
es gibt noch viel zu tun, packen wir es später an. Sorry im Moment werde ich hier auf der Arbeit reichlich beansprucht.
ach werner würde mich interessieren wie du das mit den Überläufen gemacht hättest
hab ich doch schon geschrieben...
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
teslanikola
21.03.2005, 15:02
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!!
Werner_Just
21.03.2005, 16:00
Hallo Teslanikola,
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,
und warum 216?
sonst hab ichs ja so wie du wolltest!!
Ich will nicht!
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...
Dim Frequenz as long
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.)
Also...
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
Wie bekommst Du nun die beiden Variablen "Freq_low_word" und "Freq_high_word" in die Variable Frequenz.
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
Variable Variable Variable
Frequenz Freq_low Freq_high
1.Byte = 1.Byte
2.Byte = 2.Byte
3.Byte = 1.Byte
4.Byte = 2.Byte
Und genau das kann BASCOM in dem Du die Variablen so deklarierst.
Dim Frequenz as long
Dim Freq_low_word as word at Frequenz OVERLAY
Dim Freq_high_word as word at Frequenz+2 OVERLAY
Du hast nun 3 Variablen, die in Wirklichkeit aber nur eine einzige sind.
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
incr Freq_high_word
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.
Als Gerüst ergibt sich dann für Deinen Frequenzzähler...
' ## 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
Mach was draus!
Ich hab den Code nicht getestet, ich kann etwas ultra wichtiges vergessen haben, ich kann Fehler drin haben.
Ciao
Werner
teslanikola
21.03.2005, 16:59
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?
## 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
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.)
Würde dich nie so dermasen beleidigen!!!!!!!!!
Hier mein Code MIT Kommentar:
$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
Hatte doch noch ein paar Fehlerchen korrigiert!
Jetzt versteht man meinen Code besser.
Gruß teslanikola
Werner_Just
21.03.2005, 20:57
Hallo Teslanikola,
toller code, aber warum hast du alles geändert , war meins den so sch***.
ich hab doch fast nix verändert.
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.
ich glaube, ich hab jetzt verstanden Worum es Kommentare im Quellcode gibt! Damit andere auch verstehen was ich meine.
Stimmt, ich hätte einige Kommentare einfügen sollen. Ich hab aber ehrlich nicht damit gerechnet, daß Du noch Schwierigkeiten damit haben könntest.
Zugegeben dein Code ist echt kompliziert, geht das echt nicht einfacher?
Das der Code komplizierter ist als Deiner würde ich rundweg abstreiten, aber der selbstgeschriebene Code erscheint immer 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
Werner_Just
23.03.2005, 10:59
Hallo Tesnikola,
hast Du das interesse am Frequenzzähler verloren oder grübelst Du noch über dem Code?
Ciao,
Werner
teslanikola
23.03.2005, 11:35
sorry hatte wenig Zeit, immer diese Arbeiten in der Schule. Brenne heute mal den Code ins Flash und mache mak nen kl. Test.
teslanikola
23.03.2005, 12:00
servus, irgendwas geht nicht, wenn der Timer0 oder timer1 voll ist, springt der nicht zu Test1 oder 2 ( in der Sim )
Werner_Just
23.03.2005, 12:03
Hallo Teslanikola,
schick mal Deinen Code.
Ciao,
Werner
teslanikola
23.03.2005, 12:26
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!!!
teslanikola
23.03.2005, 12:28
$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
teslanikola
23.03.2005, 12:35
servus Werner haste ICQ
Werner_Just
23.03.2005, 14:09
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
teslanikola
23.03.2005, 14:30
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?????????????????????????
Werner_Just
23.03.2005, 15:35
Hallo Teslanikola,
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.
tut er auch, das Problem tritt erst unmittelbar danach auf.
Lösch das 'Return' aus der IF-Abfrage in der Interrupt-Routine Test1:
[Test1: [...]
Timer0 = 126 ' ???
Timer1 = 0
Start Timer0
Start Timer1
' Return
End If
Return
dann müsste es funktionieren.
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
teslanikola
23.03.2005, 17:11
OH HAPPY DAY, OH JESUS CHRIST!!!!!
Danke Werner du bist der GRÖÖÖÖÖÖÖÖÖÖÖÖSTE Thank you!!! , 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!!!!!
Werner_Just
23.03.2005, 20:14
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
teslanikola
24.03.2005, 12:03
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.
Werner_Just
24.03.2005, 13:15
Hallo Teslanikola,
stimmt, beachte aber bitte, das die Anzahl der Timer1 Interrupts dabei 128 mal höher ist als bei Prescale=1024. Das kann irgendwann Probleme mit der Rechenleistung geben.
Zudem gilt: die 1s Messzeit ist erreicht wenn der 39. Interrupt ausgelöst wird. Zu dem Zeitpunkt stoppt der Timer aber noch nicht. Der µC führt erst noch einige Operationen aus, die allesamt Zeit brauchen.
- Die Register werden auf dem Stack gespeichet
- es wird in die Interrupt Routine gesprungen
- der Zähler wird erhöht
- die IF-Abfrage wird abgearbeitet
- der PinD.5 wird getoggelt (warum überhaupt)
Erst dann wird Timer1 ausgelesen!
Während der Zeit die für die Zwischenschritte benötigt werden misst Timer1 noch munter weiter.
Eh Du also anfängst den Messzeit-Timer zu optimieren, solltest Du Dir ein paar Gedanken machen was in welcher Reihenfolge abgearbeitet werden könnte.
Was spricht z.B. dagegen unmittelbar nach der Abfrage ob es der 39. Interrupt ist als aller erstes den Timer1 zu stoppen, damit der nichtmehr weiter misst?
Im übrigen:
Wie kommst Du auf 3906/4882 Interrupts? Ich komme auf andere Zahlen. (Zwar nicht deutlich andere aber wenn ich mit dem Holzhammer hinter Dir stehen würde, so würde ich Dir doch mit Genuß einen überbraten. :teufel: )
10E6/8/256 = 4882,8125. Was passiert zwischen 0,8125 und 1? Ein Interrupt! Die Anzahl der Interrupts lautet daher...!?
Ciao,
Werner
teslanikola
24.03.2005, 13:50
Pind.5 war nur zur Kontrolle, das ist jetzt raus!
10E6/8/256 = 4882,8125. Was passiert zwischen 0,8125 und 1? Ein Interrupt! Die Anzahl der Interrupts lautet daher...!?
4883 OK, hab ich vergessen!
Hast du schon mal mit EXt. Speicher geschaft, wenn ja scho mal auf meinen EXt. Speicher Thread, hab nähmlich nedn Problem.
Danke für deine Hilfe. Ach wie kann ich denn noch genauer ( Frequenzz. ) machen, wenn ich den von meinem Vater nehme ( schon fast 30 Jahre alt ) kommt da ne Frequenz mit einer abweichung von 10% raus! Wie kann ich meinen Frequenzz. kalibrieren??????
G
Werner_Just
24.03.2005, 14:35
Hallo Teslanikola,
zum Kalibrieren mußt Du Deinen Frequenzzähler gegen ein Frequenznormal antreten lassen. Das kann ein nach DKD der NYST kalibrierter Frequenzzähler oder ein Frequenzgenerator sein. Sowas kostet in einem Kalibierlabor 500-1000 Euro, also vergiss es.
Um zu sehen wie genau dein Frequenzzähler ist hast Du imo zwei praktikable Wege. Zum einen teste Deine Software sorgfältig im Simulator aus. Hier ist es insbesondere interessant, daß die Messzeit möglichst genau stimmt. Überpüfen kannst Du dieses anhand des Zykluszählers im Simulator und der Funktion "Running to Cursor".
Dann brauchst Du ein Oszi und überprüfst damit, ob Deine Eingangsbeschaltung irgendweche Takte verschluckt. Wenn das nicht der Fall ist, dann kannst Du eigentlich davon ausgehen, das der Frequenzzähle mit passabler Genauigkeit läuft.
Ansonsten nimm z.b. einen 2. Atmel, programmier einen Rechteckgenerator, Threads mit Codebeispielen gibts genug, und verwende den zu testen Deines Frequenzzählers.
10% Abweichung bei einem 30Jahre alten Frequenzgenerator/-zähler halte ich nicht für ungewöhnlich viel. Vermutlich ist das Teil einfach nicht mehr genauer. Bei so alten Geräte ist die Takterzeugung / Torzeiterzeugung noch analog gelöst und driftet damit entsprechend stark bei Bauteilalterung. Unser 20000DM teurer Rohde&Schwarz Generator weist eine Abweichung von fast 1% auf und der ist gerademal 10 Jahre alt und volldigital.
(Getestet gegen ein frisch kalibriertes Fluke ScopeMeter. Genauigkeit in Frequenzzählmodus laut Kalibrierprotokoll besser als 0,000005%. (0.1% der zulässigen Abweichung von 0.5%. Ich liebe Kalibrieprotokolle :-( ).
Bezüglich externem Speicher hab ich keine praktische Erfahrung.
Nur wie es theoretisch geht. Gibt 'nen schönes kleines Beispiel im Rowalt Buch (aber das hab ich Dir ja schon einige male ans Herz gelegt).
Ciao,
Werner
teslanikola
24.03.2005, 15:41
Wenn ich wieder Flüssig bin lege ich mir das Buch zu, hast die ISBN?
Werner_Just
24.03.2005, 15:59
Hallo Teslanikola,
Wenn ich wieder Flüssig bin lege ich mir das Buch zu, hast die ISBN?
ISBN gibts leider nicht. Rowalt verlegt im Eigenverlag www.rowalt.de
Das Buch ist trotzdem keine kopierte Blättersammlung. Ich war positiv überrascht. Wo man sich dran gewöhnen muß ist seine Eigenart alles was man einfach in Assembler machen kann auch in Assembler zu machen. Das hat aber den positiven Nebeneffekt, daß einem gleichzeitig die Angst vor Assembler genommen wird. Und alles was er macht, egal ob in Basic oder Assembler erklärt er schritt für schritt.
Es gibt noch eine Experimentierplatine zu Buch. Imo braucht man die aber nicht. Wenn man nichts hat hat um einen AVR zu programmieren ist sie sicher nicht verkehr, aber wenn mans eh schon kann, dann gehts auch mit 'nen Steckbrett/Lochrater oder einfach nur im Kopf.
Ciao,
Werner
teslanikola
25.03.2005, 23:56
Nicht schlecht, kaufe ich mir ( sobald die sch*** Prüfungen rum sind, weil wenn ichs hab lern ich nix mehr [Prüfungen] 8-[ )
deuterius
02.04.2005, 12:43
Hallo zusammen
In Sachen AVR und Bascom bin ich noch ein ziemlicher Anfänger. Trotzdem wollte ich einen Frequenzzähler bauen und habe folgende Lösung gefunden:
Timer/Counter0 funktioniert als Zähler, er zählt also die externen Impulse. Bei jedem Überlauf wird in einem Interrupthandler ein Byte (oder evtl. ein Word) um eins hochgezählt.
Timer/Counter1 stellt die Torzeit (z. B. eine Sekunde) zur Verfügung. Dazu wird die Taktfrequenz (4 MHz) mit dem Prescaler durch 64 geteilt und der Compare-Wert auf 65200 gesetzt. Zwischen je zwei Compare-Ereignissen vergeht so genau eine Sekunde.
In einer weiteren Interrupt-Routine wird nun bei jedem solchen Compare-Ereignis Timer0 ausgelesen. Die Frequenz ergibt sich dann aus der Anzahl Überläufe von Timer0 mal 256 plus dem Schlussstand von Timer0. Dann wird Timer0 zurückgesetzt und alles beginnt von neuem.
Diese Lösung funktioniert, soweit ich das bis jetzt getestet habe, gut. Zugegebenermassen werden bei hohen Frequenzen die Interrupts etwas häufig aufgerufen.
Falls irgendein "alter Hase" mir verborgene Schwächen dieser Methode aufzeigen könnte, würde mich das sehr interressieren
teslanikola
02.04.2005, 13:07
So funkt meiner auch, der eine Timer generiert die Torzeit, der andere zählt die Impulse, der Arbeitet recht gut!!!
Werner_Just
04.04.2005, 09:26
Hallo deuterius,
Falls irgendein "alter Hase" mir verborgene Schwächen dieser Methode aufzeigen könnte, würde mich das sehr interressieren
schwäche nicht gerade, aber eine nicht optimale Ressourcen-Ausnutzung.
Du benutzt Timer0 als externen Zähler und Timer1 als Torgenerator. Damit mußt Du für jeden Zählimpuls einen Interrupt auslösen, was bei niedriegen Frequenzen kein Problem darstellt, die maximal mögliche Frequenz aber unnötig verringert.
Benutzt Du Timer 0 als Torgenerator und Timer1 als externen Zähler, dann kannst Du die Counter-Unit des Timer1 verwenden und die Zähl-Interrupts einsparen.
Alternativ kannst Du, je nach verwendetem AVR, auch Timer2 als externen Zähler verwenden. Dieser besitzt meist ebenfalls eine Counter-Unit.
Nikolas Lösung entspricht, vom Grundprinzip Deiner her, nur daß er eben die Timer getauscht hat und die Counter-Unit nutzt. IMO ist das eleganter.
Wenn ich ihn noch dazu bringen OVERLAY zu verwenden, anstatt *256 oder +65536 zu rechnen, dann wär ich mit seinem Programm (fast) gänzlich zufrieden. :teufel:
Ciao,
Werner
teslanikola
04.04.2005, 13:08
So habs noch nen bissele Verbessert ( siehe Pulses und Sek )
$regfile = "2313def.dat"
Config Portb = Output
Config Portd = Output
Config Pind.5 = Input
Dim Var1 As Byte
Dim Freq As Long
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 Timer1 = Counter , Edge = Rising
Enable Interrupts
Enable Timer1
Portd.5 = 0
Timer0 = 216 ' Constante zum erzeugen einer "Exacten" Sek.
Timer1 = 0
Start Timer0
Start Timer1 'Auf die Pins, Fertig, Messen!
On Timer0 Sek
On Timer1 Pulses ' Anzeige Schlaufe
Do
S = Str(freq)
L = Len(s)
For X = 1 To L
S = Str(freq)
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
Waitms 2
Next X
Loop
Sek:
Incr Var1
If Var1 = 39 Then 'Wenn Timer0 39 überlief (1 Sek) dann:
Freq = W + Counter1
Var1 = 0
Timer0 = 216
Timer1 = 0
End If ' Wenn Timer0 (Gatetimer) voll, dann Var1 + 1
Return
Pulses:
W = W + 65536
Return
Das ist der Komplete Code inklusive Multiplex Ausgabe!!!
Werner_Just
04.04.2005, 13:32
Hallo Nikola
> So habs noch nen bissele verbessert ( siehe Pulses und Sek )
du bist gemein!
Da keimt Hoffnung auf in Deinem Code ein OVERLAY zu finden und dann ist da nix. ;-)
Hast Du Deinen Code mal ausprobiert?
Läuft er?
Auch noch bei der zweiten Messung?
Würde mich etwas wundern, denn "W" wird nach der 1. Messung nicht zurück gesetzt.
Ciao,
Werner
teslanikola
27.04.2005, 13:36
Werner, der läuft 1A.
Der misst und misst und misst, sell ihn bald ma auf meine HP.
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.