Bascom BASCOM ; Erste Schritte zum Ausprobieren

Frequenzzähler, dafür hast du ja eigentlich schon alles fertig :)
Nimm erst mal wieder den Mega, allein schon wegen UART.
Außerdem hast du da mehrere Timer drin.

UART: Hatten wir schon.

Timer für Sekundentakt: Hatten wir schon. Ich würde hierfür aber Timer 0 oder besser 2 nutzen.
Warum Timer 2: Den kannst du extern asynchron mit einem Uhrenquartz (32,768KHz) versorgen, der Genauigkeit wegen. Der wird dann an die XTAL Anschlüsse angeklemmt. Falls du keinen solchen hast, dann könntest du in defekten Routern, Mainboards etc. fündig werden. An Sonsten, die kosten nicht viel.

Warum nicht Timer 1?
Es ist der einzige 16bitter, also kostbare Hardware. Außerdem: Diese Komponente heißt nicht umsonst Timer/Counter. Man kann ihn also auch als Zähler nutzen, das auch automatisch per High/Low am Pin.

Sagen wir jetzt mal, Ausgabe per UART. Du nutzt Timer 2 für den Sekundentakt. Timer 1 wird extern per Pegeländerung erhöht.
Schon eine Idee die Hz zu ermitteln?
 
Bascom für Windows 10

EDIT:
Bitte keine urheberrechtlich geschützte Software im Forum hochladen. Am besten einen Link zum Hersteller setzen. Ich habe mal den Anhang entfernt. Dirk :)
 
Zuletzt bearbeitet von einem Moderator:
Das ist nur der Compiler, der crasht ja nicht, sondern die IDE ;)

Und jo, alles so wie du es gelernt hast.
Nachher nur geringfügig anders.

Probier es mal. Das Grundgerüst kennst du ja.
Nehmen wir erst mal Timer 0, den kennst du ja schon. Ist beim Mega das Gleiche wie beim Tiny. Zumal ich nicht weiß ob du einen Uhrenquartz hast.
Mach mal ein Programm was jede Sekunde einen Wert (Byte reicht, also 0..255) über UART ausgibt (dezimal) und dann um 1 erhöht.
Eine Zahl (hier Byte) in String zu verwandeln war in Bascom glaube ich Str(Variable).
 
Es gibt Probleme mit der Berechnung von Timer0. Da ich so eine Seite für die Timerberechnung kenne, mit der man aber bei 1Mhz Taktfrequenz nur auf eine Wunschzeit von 100ms kommt. Ich glaubte ja zu wissen, wie die Berechnung geht, aber
  1. der Timer ein ist ein 16Bit
  2. es wird aber eine Phasenkorekte 8Bit-PWM angegeben (das sind die 510 Schritte)
  3. Timer0 ist ein 8Bit und zählt auch 0-255 und Phasenkorrekt sind 510.
Irgendwo habe ich einen Denkfehler.
 
Ich habe aus einem Router zwei Quarze entnehmen können. Könnte der untere ein Uhrenquarz sein?
 

Anhänge

  • 2019-06-23 17.40.59.jpg
    2019-06-23 17.40.59.jpg
    21,3 KB · Aufrufe: 7
Nutz mal lieber die 8MHz hierfür ;)
Und... Mein Fehler. Im Mega8 ist der Timer 0 dafür etwas ungeeignet. Wusste ich nicht. Aber ist ja nur eine Zahl die man tauschen muss. Wir gehen also direkt auf Timer 2.

Du brauchst hier kein PWM mehr, nur den Timer als solches.
Nur die Berechnung ist jetzt etwas "tricky".

Bestimmt auch hilfreich:

Schauen wir mal in's Datenblatt.
Unter Timer 2 - Register description. Du musst nicht alles verstehen, aber auf Seite 116 stehen die möglichen Vorteiler.
Kein Prescaler, /8, /32, /64, /128, /256, /1024
Nicht jeder AVR unterstützt alle, daher nachschaun.

Jetzt ist es ja so, dass du 8MHz hast, die 8 Bit Timer können maximal 256 Schritte zählen. Wobei bei Timern die im CTC Modus laufen können (beim Mega8 kann es Timer 0 nicht, daher 2) kannst du selbst den Maximalwert festlegen, aber halt nur im Rahmen 0..255.

Macht also eine niedrigste Frequenz von 8.000.000 / 1.024 (Prescaler) / 256 (Maximalwert) = 30,517578125 Hz
Das sind immer noch 29 Überläufe + n bissl Wechselgeld zu viel.
Fazit: Der Timer wird immer zu schnell laufen. Und krumme Werte sind blöd.

Wir stehen jetzt also vor der Aufgabe: 8.000.000 / y / z = (grade Zahl)
Kann man bestimmt berechnen, ich probiere aber immer aus.
Ich nutze hier gerne den Timer Calculator von @Dirk:
8077

Hier ein bisschen mit den Werten herum probiert um auf 0% Fehlerquote zu kommen.
Prescaler 256 ist vorhanden, also hätten wir alle 8ms einen Interrupt.
Kurz nachgerechnet, um auf 1 Sekunde zu kommen 1 / 0,008 = 125.
Grader Wert, passt. Krummer Wert wäre jetzt etwas blöd ;)
Unser Interrupt feuert also nachher alle 8ms. Dann müssen wir noch selber zählen, nämlich bis 125, dann haben wir genau* eine Sekunde.
Aber: Der Timer darf nur bis 249 zählen, nicht bis 255.

Wir nutzen jetzt also statt PWM den CTC Modus. CTC heißt eigentlich nur dass du den Höchstwert des Timers selber festlegen kannst.


CodeBox BascomAVR
OCR2 = 249 ' Maximalwert von Timer2 setzen (Output Compare Register, Timer 2)
Config Timer2 = Ctc , Prescale = 256 , Clear_timer = 1, Compare A = Disconnect
On Compare2 OnCompare2
Enable Compare2

Komplett ungetestet, musst du ggf. noch anpassen.

Jetzt die ISR erstellen wie früher. Vorher einen Zähler DIMensionieren (z.B. delay). Byte reicht. In der ISR diesen erhöhen. Wenn er 125 erreicht hat: Auf 0 setzen und den eigentlichen Inhalt ausführen, sonst nicht.

In die ISR kommt erst mal nur ein Print("Test") oder ähnliches rein, damitt man sehen kann ob es läuft.


*) Genau hängt natürlich von der Genauigkeit der Clock ab.

Und leider nicht. Die Quartze sind definitiv verwendbar, aber keine Uhrenquartze. Die sind typischerweise rund und bedeutend kleiner, beschriftet mit 32k oder 32.768.
 
Ich habe heute hin und her gerätselt und bin dann auf dieses Ergebnis gekommen. Nur um erst einmal einen Sekundentakt mit Timer2 zu realisieren.
In der Schleife steht jetzt noch das drin, was im Grundgerüst eben stand und auch noch funktioniert. Ganz ohne der Schleife blinkt auch keine Grüne LED.
Zufrieden bin ich nicht damit, da es zwar 1Hz sein sill, aber blinken tut sie in 60 Sekunden 50 mal. Gebe ich mich nicht zufrieden.

CodeBox BascomAVR
$regfile = "m8def.dat"
$crystal = 1000000
$hwstack = 40
$swstack = 16
$framesize = 32
$baud = 19200
Dim Zeichen As String * 1
Dim C As Byte
Ddrb = &B_1111_1111
Portb = &B0000_0000
Ddrc = &B_11_1111
Portc = &B00_0000
Ddrd = &B_1111_1111
Portd = &B0000_0000
Rot Alias Portd.7
Gruen Alias Portc.3
Const Timer2_preload = 194
Config Timer2 = Timer , Prescale = 64
Enable Timer2
Timer2 = Timer2_preload
On Timer2 Isr_timer2
Enable Interrupts
Do
   If Ischarwaiting() = 1 Then          'Wenn Zeichen Empfangen
      Zeichen = Inkey()                 'dann Zeichen aus Puffer lesen
      If Zeichen = "1" Then
         Rot = 1
         Print "Led An"
      Elseif Zeichen = "0" Then
         Rot = 0
         Print "Led Aus"
      Elseif Zeichen = "t" Then
         Toggle Rot
         Print "Toggle Led"
      Elseif Zeichen = "?" Then
         If Rot = 0 Then
            Print "Led ist aus"
         Elseif Rot = 1 Then
            Print "Led ist an"
         End If
      End If
   End If
Loop
Isr_timer2:
   Timer2 = Timer2_preload
   If Tifr.ocf2 = 1 Then
      Set Tifr.ocf2
      Incr C
      If C = 194 Then                   'Überläufe zählen
         C = 0                          'Zähler zurücksetzen
         Toggle Gruen                   'LED toggeln
      End If
   End If
Return
Jetzt probiere ich Deine Version.
 
Die sind typischerweise rund und bedeutend kleiner, beschriftet mit 32k oder 32.768.
Be der suche des einen Quarzes (TXC 17.BQDEF) hab ich die Uhrenquarze gesehen. Aber hätte ja sein können, weil auf irgendeiner Internetseite für Quarze es auch welche mit "TXC" vorhanden waren.
 
So kenne ich die (den Schwarzen zwar nicht, egal):
8078
8079
 
Ja genau. Die müssten eventuell auch in alten Weckern drin sein. Heutzutage sind die meisten auf Funkuhr eingestellt, aber müssten auch noch einen Quarz haben...
 
Ich habe aus einem Router zwei Quarze entnehmen können. Könnte der untere ein Uhrenquarz sein?

Die Bauform ist HC-49S, der hat wahrscheinlich 17MHz. Quarze mit 32,768kHz gibt es in der Bauform nicht, zumindest nicht von TXC, habe ich aber auch sonst in dieser Bauform so noch nie gesehen.

 
Config Timer2 = Ctc , Prescale = 256 , Clear_timer = 1, Compare A = Disconnect
Noch nichts weiter im Code stehen und schon Fehlermeldung
Unknow Config Parameter [CAMPARE A]
Unknow statement [ONCOMPARE2]
Da stimmt etwas nicht


CodeBox BascomAVR
$regfile = "m8def.dat"                  'Controllerdefinitionsdatei einbinden
$crystal = 8000000                      'Systemtakt angeben (Baudrate)
$hwstack = 40                           'Stacks
$swstack = 16
$framesize = 32
$baud = 19200                           'Baudrate UART
'Dim Zeichen As Byte                     'UART-Empfang
Dim Count As Byte
Ddrb = &B_1111_1111
Portb = &B0000_0000
Ddrc = &B_11_1111
Portc = &B00_0000
Ddrd = &B_1111_1111
Portd = &B0000_0000
Rot Alias Portd.7
Gruen Alias Portc.3
Ocr2 = 249
Config Timer2 = Ctc , Prescale = 256 , Clear_timer = 1 , Compare A = Disconnect
On Compare2 Oncompare2
Enable Compare2
On Timer2 Isr_timer2
Enable Interrupts
Main:
 Oncompare2
Goto Main
 
Kann gut sein dass die das Compare aus dem Config raus geschmissen haben. Lustigerweise stammte die Zeile aus deren Hilfe...
Also das ", Compare A = Disconnect" ist eh unnötig, ist ja kein PWM.
In der Main steht nichts drin. Wobei, gewöhn dir an da immer ein Reset Watchdog rein zu setzen, auch wenn du ihn nicht nutzt.
Und dir fehlt noch die Sprungadresse, also die ISR für OnCompare2. Klar dass er da dann meckert, weil, wohin soll er springen? ;)

Edit: Isr_Timer2 fehlt auch. Wozu überhaupt?
 
Edit: Isr_Timer2 fehlt auch. Wozu überhaupt?
Ich habe doch On Timer2 Isr_timer2 stehen. Ist das nicht das, was es sein soll?
Den Compare2 meckert er immer noch an. Also hab ich es erst einmal auskommentiert, um irgend ein Ergebnis zu sehen.
Bei diesen Code kommen keine Fehlermeldungen aber auch nichts anderes. Da blinkt nichts, es leuchte rein gar nichts.


CodeBox BascomAVR
$regfile = "m8def.dat"                  'Controllerdefinitionsdatei einbinden
$crystal = 8000000                      'Systemtakt angeben (Baudrate)
$hwstack = 40                           'Stacks
$swstack = 16
$framesize = 32
$baud = 19200                           'Baudrate UART
'Dim Zeichen As Byte                     'UART-Empfang
Dim Count As Byte
Ddrb = &B_1111_1111
Portb = &B0000_0000
Ddrc = &B_11_1111
Portc = &B00_0000
Ddrd = &B_1111_1111
Portd = &B0000_0000
Rot Alias Portd.7
Gruen Alias Portc.3
Ocr2 = 249
Config Timer2 = Ctc , Prescale = 256 , Clear_timer = 1       ', Compare A = Disconnect
'On Compare2 Oncompare2
'Enable Compare2
On Timer2 Isr_timer2
Enable Interrupts
Main:
   Reset Watchdog
   Goto Main
Isr_timer2:
   If Ocr2 = 0 Then
      Toggle Gruen
   End If
Return
 
Jetzt ist wenigstens die ISR drin.
Die wird aber nie ausgeführt, weil dein Timer nie überläuft (255->0) sondern per Compare bei einem gewissen Wert zurück gesetzt wird (OCR2).

*verschiedene Flüche über Bascom die teilweise nicht jugendfrei sind*
Es gibt nur "Compare1". Was Anderes kennt der nicht. Musst "OC2" als Interruptnamen verwenden, also den AVR Namen -.-

OCR2 bleibt beim eingestellten Wert. Keine If, nur Toggeln
 
Doch, hast du.

Wie jetzt


CodeBox BascomAVR
Isr_timer2:
   ...
Return


Das ist der Teilcode der aufgerufen wird wenn ein (aktivierter) Interrupt auftritt.
Den definierst du per On [Interruptname] [NameDerISR] Befehl.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)