Bascom BASCOM ; Erste Schritte zum Ausprobieren

Ich habe dieses hier zusammen gestellt. Grün blinkt weiter im Sekundetakt aber in der Ausgabe wird unverändert 0Hz angezeigt.

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
Dim Countdown As Word
Dim Cnt As Word
Dim Erg As Word
Ddrb = &B_1111_1111
Portb = &B0000_0000
Ddrc = &B_11_1111
Portc = &B00_0000
Ddrd = &B_1111_0111
Portd = &B0000_1000
Rot Alias Portd.7
Gruen Alias Portc.3
Blau Alias Portd.6
Ocr2 = 249
Config Timer2 = Ctc , Prescale = 256 , Clear_timer = 1
Config Timer1 = Timer , Prescale = 256
On Timer1 Cnt_sub
On Timer1_timer_irq
On Oc2 Isr_timer2
Enable Oc2
Enable Interrupts
Do
   Print Erg ; " Hz"
   Wait 1
Loop
Isr_timer2:
   Incr Count
   If Count = 125 Then
      Count = 0
      Toggle Gruen
      If Countdown = 0 Then
         Rot = 0
      Else
         Decr Countdown
      End If
   End If
Return
Cnt_sub:
   Incr Cnt
Return
Timer_irq:
   Load Timer1 ; 62500
   Cnt = Cnt * 256
   Cnt = Timer2 + Cnt
Return
End
 
Könnte daran liegen weil du "Erg" nie zuweist ;)
Timer1 Interrupts brauchen wir (noch) überhaupt nicht, der zählt von alleine. Daher sind die 2. letzten Subs auch nicht benötigt (was du da versucht hast erschließt sich mir jetzt auch nicht).

Eigentlich ist es doch ganz einfach. Du hast eine stabile Zeitbasis auf 1Hz. Das ist da wo du Grün toggelst. Du könntest dort auch ein Gosub Tick_1s einfügen und das Toggeln extra machen, wie jetzt mit Cnt_sub:.
Jetzt musst du nur noch den Wert von Timer1 ausgeben und wieder nullen (letzteres würde ich vorerst weg lassen, nur zum Testen).

Jetzt ist das weitere Problem dass du die Hardwareeinheit "Timer/Counter1" als Timer, also selbstlaufend definierst. Das wollen wir ja nicht, er soll ja nur zählen. Also wäre es Config Timer1 = Counter , Edge = Rising.
Dann einen Taster an ICP1 (PINB0 beim Mega8) gegen Masse. Das ist der Eingang für den Timer, wenn man keine interne Taktquelle nutzt. Pegeländerung (hier steigende Flanke, also los lassen des Tasters) erhöht den Timerwert. Möglicherweise muss der Pin vorher noch auf Eingang gestellt werden. Danach per PORT den Pull-Up aktivieren oder extern einen anschließen (nur für die Tastermethode).
 
Ich komme selbst nicht mehr weiter. Habe Taster an PB0 angeschlossen, PullUp aktiviert und den Gosub eingesetzt. Kein Ergebnis im Terminal.


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
Dim Countdown As Word
Dim Erg As Word
Ddrb = &B_1111_1110
Portb = &B0000_0001
Ddrc = &B_11_1111
Portc = &B00_0000
Ddrd = &B_1111_0111
Portd = &B0000_1000
Rot Alias Portd.7
Gruen Alias Portc.3
Blau Alias Portd.6
Key Alias Pinb.0
Ocr2 = 249
Config Timer2 = Ctc , Prescale = 256 , Clear_timer = 1
Config Timer1 = Counter , Edge = Rising
On Tick_1s
On Urxc Onuartrx
Enable Urxc
On Oc2 Isr_timer2
Enable Oc2
On Timer1 Ontimer1
Enable Timer1
Enable Interrupts
Do
   Print Erg ; " Hz"
   Wait 1
Loop
Onuartrx:
   If Ischarwaiting() = 1 Then          'Wenn Zeichen Empfangen
      Zeichen = Inkey()                 'dann Zeichen aus Puffer lesen
      If Zeichen = "1" Then             'bei 0x00 PWM deaktivieren
         Rot = 1
      Elseif Zeichen = "0" Then         'bei 0xFF PWM aktivieren
         Rot = 0
      Else
         Countdown = Zeichen * 60
         Rot = 1
      End If
   End If
Return
Isr_timer2:
   Incr Count
   If Count = 125 Then
      Count = 0
      Gosub Tick_1s
      If Countdown = 0 Then
         Rot = 0
      Else
         Decr Countdown
      End If
   End If
Return
Tick_1s:
   Toggle Gruen
Return
Ontimer1:
   If Key = 0 Then
      Count = Count + 1
   End If
Return
End
 
Wegen dem Uhrenquarz
  • Cylindrical 2 * 6mm (32.768KHz) for the quartz crystal 32768 passive crystal.
  • Load Capacitance: 12.5pF.
  • Equivalent resistance: 35KΩ.
  • Frequency tolerance: +20 PPM.
ist dieser geeignet?
Quarzoszillatoren habe ich diese zur Hand
Quarz_Oszi.jpg
 
Meine Gedankenzüge mit Count=Count+1 sind falsch. Ich will doch die genaue Frequenz haben, mit der die Grüne LED blinkt. Also muss ich den Timer1 eine Rechenaufgabe stellen. Liege ich damit richtig? Wenn ja, weiß ich immer noch nicht, wie ich da vorgehen soll.
 
Wie kommst du drauf dass der Timer/Counter1 was machen soll?
Das macht der schon von ganz alleine, sonst wäre er doch sinnlos. Dann könntest du genau so gut INT0 und eine Variable nehmen.

Warum hast du das alte Main: Prinzip wieder verworfen?

Warum gibst du den Wert nicht in Tick_1s aus statt in der Main Loop? Zumal dort mit Wait... Wait ist böse, sollte vermieden werden wo es nur geht. Erst recht Genauigkeit erreichst du so nicht. Der Befehl verheizt zwar CPU Zeit, aber du weißt nicht wie genau, dazu kommt noch was davor und danach kommt, auch wenn es nur ein Loop/Goto ist. Und treten Interrupts ein wird die Warteschleife halt dafür unterbrochen und später fortgesetzt, ist also länger als geplant.
Wenn man das jetzt mit Hardware benutzt, wie LCD Displays, ok. Da ist es aber auch WaitUs oder WaitMs.

Warum gibst du Erg aus, setzt es aber nirgends? Ich vermute mal dass das in OnTimer1 geschehen sollte, so war es aber nicht geplant.
Geb den Wert vom Timer/Counter1 aus. Also Print Timer1 ; " Hz"
So ists noch kein Frequenzzähler, aber ist erstmal sinnvoller zum testen. So würde er die Tastendrücke zählen, unabhängig von Zeit. Später in die Tick_1s Timer1 = 0 um wieder von 0 anzufangen zu zählen.
 
Warum hast du das alte Main: Prinzip wieder verworfen?
Ich habe gedacht, das ist im Prinzip das gleiche und weil in Erläuterungen (Internet) diese Do Schleifen immer wieder verwende werden.
Irgendwie muss ich mir ein paar Beispiele holen um auf gut Glück etwas zusammen stellen zu können. Ich habe halt immer noc nicht begriffen, wie der µC arbeitet.
Also kann der ganze Quatsch in #543 raus und welches Grundgerüst, von dem du mal gesprochen hast, soll ich nehmen, um weiter arbeiten zu können?
 
Vom Prinzip ist Do - Loop und Main: - Goto Main das Selbe, ja. Mit Grundprinzip meinte ich eher dessen Inhalt. Also Sleep und Watchdog reset.
Wo steckst du denn fest, also was verstehst du nicht?
 
Ich bin davon ausgegangen, die Frequenz der Grünen LED zu ermitteln -> falsch. Dass das Wait ein Störfaktor ist, auch klar. Ich dachte nur, in der Printausgabe hat das kein Problem.
Entweder habe ich die Aufgabe nicht verstanden oder ich schau mich im Internet falsche Beispiele an, an denen ich dann wie ein Zug in der Schiene läuft und nicht vom Weg abkomme, weil keine Weiche (in diesen Fall einer erleuchtender Lösungsweg) kommt.
 
Also, geplant war jetzt nicht die grüne LED zu messen. Schon gar nicht die Eigene, das würde ja gar nichts bringen. Grün dient nur als Indikator dass es "ungefähr" läuft. Erst mal nur einen Taster. Hat den Hintergrund, du kannst n paar mal öfters die Sekunde drauf drücken.
Und du bist ja schon kurz vorm Ziel. Init steht, Main auch, wenn du wieder auf Sleep und WDR zurück gehst. Timer2 feuert alle 8ms. Darin ist ein Zähler wodurch jede Sekunde Tick_1s ausgeführt wird. Jetzt musst du nur noch da drin den Timer Wert ausgeben, wie oben gesagt.

Jetzt sollte er immer jeden Tastendruck zählen (ggf. ein paar mehr, Taster prellen gerne mal).
Da noch nichts zurück gesetzt wird ist es natürlich noch kein Frequenzzähler. Aber, Schritt für Schritt.
 
Ja. Timer1.
Oder in Hardware (Assembler) TCNT1.
 
Macht nichts mehr

CodeBox BascomAVR
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32
$baud = 19200
Dim Zeichen As Byte
Dim Count As Byte
Dim Countdown As Word
Ddrb = &B_1111_1110
Portb = &B0000_0001
Ddrc = &B_11_1111
Portc = &B00_0000
Ddrd = &B_1111_0111
Portd = &B0000_1000
Rot Alias Portd.7
Gruen Alias Portc.3
Blau Alias Portd.6
Key Alias Pinb.0
Ocr2 = 249
Config Timer2 = Ctc , Prescale = 256 , Clear_timer = 1
Config Timer1 = Counter , Edge = Rising
Config Watchdog = 2048
Start Watchdog
On Tick_1s
On Urxc Onuartrx
Enable Urxc
On Oc2 Isr_timer2
Enable Oc2
On Timer1 Ontimer1
Enable Timer1
Enable Interrupts
Enable Interrupts
Main:
   Reset Watchdog
   Config Powermode = Idle
   Goto Main
Onuartrx:
   If Ischarwaiting() = 1 Then
      Zeichen = Inkey()
      If Zeichen = "1" Then
         Rot = 1
      Elseif Zeichen = "0" Then
         Rot = 0
      Else
         Countdown = Zeichen * 60
         Rot = 1
      End If
   End If
Return
Isr_timer2:
   Incr Count
   If Count = 125 Then
      Count = 0
      Gosub Tick_1s
      If Countdown = 0 Then
         Rot = 0
      Else
         Decr Countdown
      End If
   End If
Return
Tick_1s:
   Toggle Gruen
Return
Ontimer1:
Print Timer1 ; " Hz"
Return
 
Ist ja auch klar, OnTimer1 wird (wenn überhaupt, weil ja als Counter genutzt) nur bei einem Überlauf ausgelöst.
Das Print gehört schon in Tick_1s.
 
Timer/Counter1 macht das wozu du ihn konfiguriert hast. Als Counter.
Config Timer1 = Counter , Edge = Rising
Bei jeder rising edge, also steigender Flanke, wird der Wert um 1 erhöht. Ganz ohne Quelltext (abgesehen vom Init). Wenn Pullup und Taster gegen GND also bei jedem loslassen. Dafür muss das Signal (der Taster) aber an ICP1 hängen.
 
Alternative Pin Belegung.
8082
PB0 ist also schon richtig. (beim Mega8, andere Chips haben den vielleicht wo anders)
 
ICP1 ist eine Spezialfunktion des Beins B0 beim Mega8.
ICP1 steht für "Input Capture Pin von Timer 1"
Du kennst die alten Stoppuhren, wo man auf irgendeinem Weg sowas wie 'ne Rundenzeit messen konnte, während die Uhr weiterläuft?
ICP1 macht genau das bei Timer1. Je nach Konfiguration wird bei einer fallenden oder steigenden Flanke an diesem Pin der Inhalt des Zählers von Timer1 (TCNT1) in ein spezielles Register, das Input Capture Register 1 (ICR1) kopiert. Die Rundenzeit sozusagen...

ICP1 kann außerdem einen Interrupt auslösen...
 

Ü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)