Bascom BASCOM ; Erste Schritte zum Ausprobieren

TIFR ist das Timer Interrupt Flag Register - ein Rahmen mit acht Lämpchen an Deinem Panel. Tifr.tov1 ist ein Bit in diesem Register, eines der acht Lämpchen.

Jedesmal wenn der Timer null wird, setzt er dieses Bit - schaltet er das Lämpchen an.
Derzeit mit einer Frequenz von 15Hz.

If TIFR.TOV1 = 1 Then - Unser Hauptprogramm prüft regelmäßig, ob die Lampe brennt (1= brennt, 0= ist aus). Nur wenn Die Lampe brennt (=1), dann (=THEN) wird der Code bis zum End if ausgeführt.
Meistens ist die Lampe aus, der Code wird ignoriert/übersprungen. Nur ganz selten (15Hz) wird er ausgeführt.
So aus dem Stehgreif würde ich sagen, anstatt =1 nehme ich einfach =256.
Damit würdest Du das Zahnrad quasi größer machen wollen, das geht so nicht, wie Du bemerkt hast. Du mußt ein weiteres Zahnrad einbauen... später...
und dann das TIFR.TOV1=1 ausführen lassen.
mit TIFR.TOV1=1 schaltest Du die Lampe aus (nachdem Du mit If gesehen hast, daß sie brennt), damit Du beim nächsten mal wieder sehen kanns, daß der Timer null erreicht hat und die Lampe erneut angeschaltet hat.
Das abschalten von TIFR.TOV1 würde ich sogar vor dem Toggeln machen lassen.

Eine Idee hätte ich noch, mit einer For...Next Schleife könnte man auch bis 256 zählen lassen
Von der Idee her nicht schlecht (das ist das weitere Zahnrad), aber Du nimmst keine For..Next-Schleife, sondern zählst eine Byte-Variable hoch. Wenn Du bereits bei 245 reagierst hättest Du sogar ziemlich genau ein Hertz (die 256 wären noch einfacher zu realisieren aber eben weiter weg vom einem Hertz)...
bis 245 zählen lassen und dann...
die Grüne LED toggeln
 
Ich habe eine Variable als Byte gesetzt und diese dann mit Elseif versucht zählen zu lassen. Dabei habe ich alle Möglichen Varianten ausprobiert. Bascom hat zeigte dann auch keine Fehlermeldungen an, aber nach dem ich es dann auf den µC geschrieben hatte, blieb alles unverändert.
Wie lässt man eine Byte-Variable im Programm hochzählen?
 
Wert = Wert + 1
oder kürzer (ich weiß nur nicht ob Bascom es unterstützt):
Wert += 1
Wenn es nur um + 1 geht:
Incr Wert
 
Wenn Du uns keinen Code zeigst, können wir Dir keinen Fehler zeigen...

Der geforderte Ablauf wäre:
  • Wenn ein Überlauf stattfand (Tifr.Tov1 gesetzt)
    • Flag zurücksetzen (Tifr.Tov1 setzen)
    • Zählvariable inkrementieren (+1)
    • Wenn Zählvariable=245
      • Zählvariable auf 0 (zurück)setzen
      • LED toggeln
    • Ende Wenn
  • Ende Wenn
Wie Thomas sagte kannst Du entweder 'ne Eins addieren, oder Inkrementieren (letzteres ist effizienter, da es eine Maschineninstruktion gibt, die dann genutzt wird.)

Beim Inkrementieren kannst Du entweder die Bascom-Instruktion Incr oder die Assembler-Instruktion INC nehmen - wird wahrscheinlich beides den selben Maschinencode 1001010ddddd0011 erzeugen (wobei ddddd das verwendete Rechenregister (Blatt auf Deinem Schreibtisch) codiert)
 
Es funktioniert. Gruen toggelt im Sekunden Takt.

CodeBox BascomAVR
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32
$baud = 19200

Dim Zeichen As Byte
Dim Z As Word

Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down

Rot Alias Portd.7
Config Rot = Output
Rot = 1
Gruen Alias Portc.3
Config Gruen = Output
Gruen = 1

Do
If Ischarwaiting() = 1 Then
   Inputbin Zeichen
   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 "t Led aendert Zustand"
   Elseif Zeichen = "?" Then
         If Rot = 0 Then
            Print "Led aus"
         Elseif Rot = 1 Then
            Print "Led an"
         End If
   End If
End If

   If Tifr.tov1 = 1 Then
      Set Tifr.tov1
      Incr Z
   Elseif Z = 245 Then
      Z = 0
      Toggle Gruen
   End If
Loop
End

Ich kann auch Prescale = 8 einstellen und hab dann mehr Spielraum in Zeile 44
 
Zuletzt bearbeitet:
Gratuliere :yahoo:

Verstehst du denn was jede Zeile tut oder sind noch Fragen offen bis hierher?
 
Diesen Teil hab ich so halbwegs verstanden. Nur mit den Registern hab ich noch keinen Durchblick. wenn z.B. ein andere Aufgabe gestellt wird, bei dem ein anderes Register in Frage käme, wüsste ich nicht wie, wo und welches gesetzt werden müsste.
 
Geht auch, aber derzeit prüft Dein Programm in Zeile 44 bei jedem Schleifendurchlauf, ob 245 erreicht ist, außer das erste mal nach einem Timerüberlauf.
(Das erste mal nach einem Timerüberlauf ist die erste If-Bedingung erfüllt, also wird dieser Teil ausgeführt und nicht der Else Zweig.)
Z kann sich ja nur nach einem Timerüberlauf geändert haben (Zeile 43), also kann da dann auch gleich geprüft werden, ob beim Inkrementieren 245 erreicht wurde.
In Zeile 44 wäre statt dem Elseif ein weiterer If-Block in dem anderen If-Block (ab Zeile 41) aufzuspannen. So, wie das auch mit der Ausgabe nach einem empfangenen "?" im UART-Teilprogramm geschah...

wenn z.B. ein andere Aufgabe gestellt wird, bei dem ein anderes Register in Frage käme, wüsste ich nicht wie, wo und welches gesetzt werden müsste.
Deswegen hab ich Dir ja eigentlich immer die nötigen Register und Bits in die Hand gedrückt, hier zum Beispiel:
Jetzt habe ich Dir gesagt, daß Du mit der Abfrage des Zählers selbst (TCNT1 bzw unter Bascom auch Timer1) auf dem Holzweg bist (das ist so, als wenn Du im Auto ununterbrochen auf den Tacho/Kilometerzähler starrst, und siehst daß der "0000" anzeigt oder eben nicht). Der Timer hat aber neben seinem "Kilometerzähler" noch 'ne Lampe (Flag/Fähnchen) die jedesmal wenn er auf "0000" umschaltet angeht, und dann anbleibt bis irgendwer sie wieder deaktiviert..
Dann bleibt sie auch aus, wenn der Timer weiterhin auf "0000" steht - erst wenn er wieder auf "0000" umschaltet, geht sie wieder an.

Diese Lampe ist das Überlaufflag des Timers, TOV1. Es befindet sich beim Mega8 im allgemeinen "Timer and Counter Flag Register". TIFR.
Das "Empfangspuffer enthält Daten"-Bit (UCSRA.RXC) hatte ich auch irgendwo erklärt, und daß Ischarwaiting genau dieses abfragt. Ob Du selbst I/O-Register bzw deren Bits prüfst/manipulierst, oder ob Du das durch höhere Bascom-Instruktionen erledigen läßt ist egal, aber Dir sollte klar sein, daß alle Interaktionen zwischen Programm und Peripherie immer über die Register (Panel mit Lämpchen, Schaltern usw am Schreibtisch) laufen. Selbst das Toggeln der Led, die Config Timer Zeile manipuliert sogar mehrere Register...
 
In #146 wird mir gratuliert, aber vielleicht meint TommyB auch, na endlich haste es geschafft.
Wie dem auch sei, ich hatte zumindestens mal ein gutes Gefühl.
Dann werde ich wieder kritisiert. Kannst Du mir nicht einfach die Auflösung und Zeilenweise den aufklärenden Kommentar schreiben.
Die vergleichsweise Erklärungen mit dem Schreibtisch oder Tacho bringen mich ganz durcheinander.
Übrigens habe ich (auf einem anderen Rechner) das Datenblatt vom ATmega8 geöffnet. Allerdings gibt Google unterschiedliche Suchergebnisse aus, wobei ich dann das Datenblatt vom ATmega8/L hatte. Es geht darum, wenn ein Hinweis gegeben wird (Datenblatt Seite xxx), dann sind diese unterschiedlich. Kannst Du mir dein Datenblatt (als Link oder PDF) schicken. Wäre Super.
 
Viele Wege führen nach Rom, der Eine ist besser, der andere nicht. Das Wichtigste ist ja erst mal dass es funktioniert :)
Was er meint ist dass du bei (fast) jedem Schleifendurchgang überprüfst (Zeile 44) statt nur nach dem erhöhen. Funktionieren wird beides, nur der Controller hat bei seiner Methode etwas weniger zu tun ;)
Optimiert wäre es:


CodeBox BascomAVR
...
   If Tifr.tov1 = 1 Then
      Set Tifr.tov1
      Incr Z
      If Z = 245 Then ' kein ElseIf, eigenständige Abfrage
         Z = 0
         Toggle Gruen
      End If
   End If
...


p.s.: Ich hab mich für dich gefreut...
 
Wie Du selbst mitbekommen hast, geht Deine Lösung (auch). #148 war wenn überhaupt als konstruktive Kritik zu verstehen, was Du besser machen kannst.

Wenn Dich der bildhafte Vergleich stört:
  • Alle Rechen- und Vergleichsoperationen führt der Controller in seinen Rechenregistern durch (und fast alle davon auf Byte-Ebene). Von den Rechenregistern bekommst Du in Bascom selbst fast gar nichts mit
  • Variablen sind im SRAM abgespeichert, und werden für die Operationen vorher aus selbigem geladen, und hinterher ggf wieder dahin abgespeichert. (Wiederholte Zugriffe auf dieselben SRAM-Adressen könnten geschickt die 32 Rechenregister ausnutzen - Bascom macht das im allgemeinen aber nicht.)
  • Die Schnittstelle zu den peripheren Modulen ("Außenwelt": ADC, AC, Timer, Kommunikationsschnittstellen (I²C, UART, SPI, …), Beine direkt) läuft grundsätzlich über I/O-Register. Für viele Peripheriemodule gibt es diverse Zugriffs- und Konfigurationsmöglichkeiten in Bascom - aber nicht für alle. Grundsätzlich steht Dir aber immer die Möglichkeit zur Verfügung, die I/O-Register selbst zu manipulieren, wenn Du mit Bascom-Mitteln nicht weiterkommst.
Kannst Du mir dein Datenblatt (als Link oder PDF)
Hier, und dann auf Documents klicken. Es gibt ein komplettes und ein gekürztes Datenblatt. Ich denke, daß sich nach Version "AA" (die sind tatsächlich einmal durch's Alphabet) nochmal nenneswert was ändern wird..

Nachdem Thomas den entsprechenden Teil bereits aufgelöst hat, hier mal mein vollständiges Programm mit folgenden Änderungen als neuen Ausgangspunkt für Dich:
  • Kommentare
  • Reihenfolge bei der Beinkonfiguration
  • Inkey statt Inputbin
  • Z ist bei mir (erstmal) 'n Byte - spielt aber keine Rolle
  • Abfrage ob Z=245 verschachtelt
  • End in der letzten Zeile entfernt (Die Hauptschleife terminiert nie. End erzeugt selbst 'ne leere Endlosschleife, nachdem vorher Interrupts global gesperrt wurden. Dieser Code wird aber nie ausgeführt.)


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 Z As Byte                                               'Timerüberlaufzähler

Rot Alias Portd.7                                           'Namen für LED-Beine
Gruen Alias Portc.3
Config Rot = Output                                         'Ausgänge
Config Gruen = Output
Rot = 1                                                     'LEDs erstmal an
Gruen = 1

'Phasenkorrekter 8-Bit-PWM, PWM-Frequenz=245Hz
Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down

Do                                                          'Hauptschleife Begin
   'erstes Teilprogramm - UART Empfang und auswerten
   If Ischarwaiting() = 1 Then                              'Wenn Zeichen Empfangen
      Zeichen = Inkey()                                     'dann Zeichen aus Puffer lesen
      If Zeichen = "1" Then                                 'Wenn Zeichen = "1"
         Rot = 1                                            '...
         Print "Led An"
      Elseif Zeichen = "0" Then                             'Wenn Zeichen = "0"
         Rot = 0                                            '...
         Print "Led Aus"
      Elseif Zeichen = "t" Then                             'Wenn Zeichen = "t"
         Toggle Rot                                         '...
         Print "Toggle Led"
      Elseif Zeichen = "?" Then                             'Wenn Zeichen = "?"
         If Rot = 0 Then                                    'Dann wenn Led an ist...
            Print "Led ist aus"
         Elseif Rot = 1 Then                                'sonst wenn Led aus ist...
            Print "Led ist an"
         End If
      End If

   End If

   'zweites Teilprogramm - LED durch timer blinken lassen
   If Tifr.tov1 = 1 Then                                    'wenn Timer übergelaufen ist
      Tifr.tov1 = 1                                         'Überlaufflag zurücksetzen
      Incr Z
      If Z = 245 Then                                       'Überläufe zählen (245)
         Z = 0                                              'Zähler zurücksetzen
         Toggle Gruen                                       'LED toggeln
      End If
   End If

Loop                                                        'Hauptschleife Ende
 
Ich habe langsam das Gefühl, dass es dem Kerzenlicht näher kommt. Ich nehme an, dass das erste Programm so umgestellt werden kann, um das Kerzenlicht nach einer bestimmten Zeit an bzw. ausgeschaltet wird.


CodeBox BascomAVR
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 32
$swstack = 32
$framesize = 64

Config Timer1 = Pwm , Prescale = 64 , Compare_a_pwm = Clear_down , Compare_b_pwm = Clear_down

Dim Fla As Byte
Dim Pause As Byte
Dim Pausex2 As Byte
Dim Tov1cnt As Byte

Do
   If Tifr.tov1 = 1 Then      'Auf Überlauf prüfen
      Set Tifr.tov1           'Überlaufflag zurücksetzen
      Incr Tov1cnt            'überlaufzähler inkrementieren

      If Pause = Tov1cnt Then 'entspricht dem 2ten "waitms pause"
         Fla = Rnd(200)
         Fla = Fla + 55
         Pwm1a = Fla
      End If
      If Pausex2 = Tov1cnt Then       'entspricht dem ersten "waitms pause"
         Pwm1b = 255 - Fla
         Pause = Rnd(10)
         Pause = Pause * 6
         Pausex2 = Pause
         Shift Pausex2 , Left 'pausex2=pause*2
         Tov1cnt = 0
      End If
   End If
Loop
 
Ich habe langsam das Gefühl, dass es dem Kerzenlicht näher kommt.
Das hast Du ja bereits, aber...
nach einer bestimmten Zeit an bzw. ausgeschaltet wird
genau darum geht's, und zwar in kleinen (teilweise letztendlich unnötigen) Schritten.

So, im Code (#152) wird in Zeile 19 der Timer als PWM initialisiert und gestartet - PWM läuft also bereits. Wir fragen bisher aber nur die "Überläufe" ab (Zeile 45).
Jetzt schauen wir uns die PWM-Ausgabe an. Timer1 hat zwei PWM-Kanäle (A und B), die fest an den Beinen B1 und B2 anliegen. dort schließen wir also zwei weitere LEDs (nebst geeigneten Vorwiderständen) an:
8046
Da hier über PWM gedimmt werden soll, habe ich kleinere Widerstände gewählt - den LED-Strom etwa auf 15mA oder so dimensioniert.
Wie gesagt, die PWM-Ausgabe läuft nach Zeile 19 bereits. Das On-Off-Verhältnis (die Schaltschwelle) wird jeweils in einem 16Bit-Register vorgegeben: OCR1A und OCR1B. (16Bit ? Tatsächlich sind es je zwei Register: OCR1AH und OCR1AL, OCR1BH und OCR1BL - jeweils ein Low- und ein High-Byte).
Bascom kennt diese sechs Namen, Bascom kennt zusätzlich noch die Namen PWM1A und PWM1B, die Du bisher verwendet hast (am Ende landet alles in denselben vier Byte-Registern, klar).
Der Timer läuft wie gesagt im Phasenkorrekten 8-Bit-PWM.
Die Reichweite ist also auf 8 Bit beschränkt - 0..255.
Phasenkorrekt bedeutet, daß der Timer nicht inkrementiert und (nach 255) überläuft, sondern je nach 0 und 255 umkehrt (deswegen ergeben sich 510 Schritte pro Periode).
PWM = Clear Down bedeutet, daß beim Raufzählen im Vorgegebenen Wert an, und beim Runterzählen im Vorgegebenen Wert abgeschaltet wird. Oder anders gesagt: je kleiner der Wert, desto heller; je größer, desto dunkler. Grundsätzlich machen wegen den 8 Bit nur Werte zwischen 0 und 255 (Bytes eben) Sinn.
Setze also nach der Timer-Konfiguration einfach mal... PWM1A auf 200, und PWM1B auf 100.
Die LEDs sollten konstant unterschiedlich leuchten, Grün sollte weiterhin mit 0,5Hz blinken, Rot auf den UART reagieren.

nächste Teilaufgabe wäre nun, das erste Teilprogramm so zu erweitern, daß jedes andere Zeichen als "1", "0", "t" und "?" die Helligkeit von Kanal B steuert.
"Sonst" heißt auf Englisch "Else" (ohne If dahinter)
Der UART basiert auf Bytes. Das Bascom-Terminal hingegen auf ASCII-Codes. Wenn Du also 'ne "1" eintippst, wird nicht &B00000001 bzw &H01 bzw 1dezimal gesendet, sondern &B00110001 bzw &H31 bzw 49dezimal. Der ASCII eben. Zeichen hat also dann den Wert &B00110001. In Zeile 25 wird ebenso nicht mit 1 verglichen, sondern mit dem ASCII-Code von "1".
Du kannst mit Deiner Tastatur direkt nicht alle Codes eingeben, nur die Zahlen, Buchstaben und ein paar Zeichen. Du kannst im Bascom-Terminal allerdings auch den Wert ("value") eines ASCII senden lassen (Terminal->send ASCII Character->Zahl zwischen 0..255 eingeben und Enter).
Etwas komfortabler ist, im Terminal die ALT-Taste gedrückt zu halten, auf dem NumPad der Tastatur den Wert vierstellig einzugeben (also mit führenden Nullen), und dann die ALT-Taste loszulassen.
Wert heißt hier dezimal (also 0..255)
 
Das ist eine sehr gute Aufklärung. Wenn ich das bis hier her richtig verstanden habe, kann ich den Timer1 mehrfach verwenden, denn einmal blinkt die Grüne Led und die weißen Led's an OC1A und OC1B aber alles noch an Timer1.
Die weißen Led's leuchten unterschiedlich hell. Habe auch die Werte mal verändert.
daß jedes andere Zeichen als "1", "0", "t" und "?" die Helligkeit von Kanal B steuert.
Da muss ich passen bzw. erst einmal ein bisschen googeln. Bis jetzt hab ich noch keinen Anfang gefunden.
 
kann ich den Timer1 mehrfach verwenden
Jain...
der Timer läuft hin und her, mit der durch den Vorteiler (Prescaler) angegebenen Schrittfrequenz. Das TOV1-Flag wird autonom immer beim erreichen von null gesetzt. Das prüft das Hauptprogramm, ohne den Timer zu beeinflussen. Ebenso wird jedesmal, wenn der durch die OCR1-Vorgaben läuft (PWM1A bzw PWM1B) ein ähnliches Flag gesetzt - interessiert uns hier nicht.
Durch den gewählten Timer-Modus und (Timer1=PWM) und die gewählten Waveform Generation Modi (Compare … pwm = clear down) ist der Timer außerdem so eingestellt, daß automatisch PWM an den beiden Beinen erzeugt wird. Quasi unabhängig von weiteren Aktionen Deines Hauptprogrammes. Das PWM-Tastverhältnis wird dabei durch die OCR-Vorgaben (PWM1A/B) festgelegt - wenn Du die verändern läßt, verändert sich das Tastverhältnis, und damit die scheinbare Lichtintensität.
Und genau das sollst Du tun.

Dein in Zeile 24 empfangenes Zeichen ist ein Byte, eine Zahl von 0..255. Die kannst Du also testweise nach dem Empfang PWM1B zuweisen.
In Zeile 25 wird geprüft, ob der in "Zeichen" abgespeicherte Zahlenwert gleich dem ASCII-Code von "1" ist, also 49.
Nur dann wird die LED angeschaltet, und der Text gesendet.
Wenn Zeichen nicht 49 ist, wird geprüft (Elseif in Zeile 28), ob Zeichen "0", also = 48 ist. Nur dann wird die LED abgeschaltet und ein entsprechender Text gesendet.
Wenn Zeichen auch nicht 49 war - … usw.
Wenn Zeichen (weder "1" noch "0" noch "t" und) auch nicht "?" war, dann (else) soll ohne weitere Prüfung (ohne weiteres If) die Zuweisung an Kanal B erfolgen.
 
Ich brauche noch einmal eine kurze Zusammenfassung in einfachen Worten, so wie Du das hier
PWM = Clear Down bedeutet, daß beim Raufzählen im Vorgegebenen Wert an, und beim Runterzählen im Vorgegebenen Wert abgeschaltet wird. Oder anders gesagt: je kleiner der Wert, desto heller; je größer, desto dunkler. Grundsätzlich machen wegen den 8 Bit nur Werte zwischen 0 und 255 (Bytes eben) Sinn.
beschrieben hast.
Was ist der Unterschied zwischen Input, Inputbin und Inkey?
Was macht das Ischarwaiting() und was bedeutet die Klammer?
Mit der Übersetzung aus der Bascom Hilfe komme ich nicht klar. Ist mir zu fachmänisch beschrieben.
 
Hmm...
Wo fang ich an?

Schau mal ins Datenblatt des Mega8 Lesezeichen->UART->Overview (Seite 129). Da ist in Figure 61 das Block-Diagramm des UART-Moduls.
Du siehst drei Blöcke in gestrichelten Linien eingerahmt. Das erste ist die Taktung, das zweite der Transmitter (Sender). Uns interessiert der dritte Block - der Receiver, der Empfänger.

Grundsätzlich werden die Daten seriell empfangen, bitweise nacheinander. Man erhält also 'ne binäre Zahl. Üblicherweise 8 Bits (möglich sind zwischen 5 und 9, aber wir bleiben bei 8 ).
Wie dieses Byte interpretiert werden soll (als Sammlung von Bits, als Byte, als vorzeichenbehaftetes Halbbyte, als Teil einer mehr-bytigen binären Zahl, als Character/ASCII-Zeichen, als Teil eines Strings, …) ist Sache des Programmes - übertragen werden... Bytes (bitweise).

Rechts am Empfänger Block ist mit RxD das gleichnamige Bein des Controllers angedeutet, von dort kommen also die Bits.
Sie werden vereinfacht gesagt in ein Empfangs-Schieberegister eingetaktet (Receive Shift Register).
Wurde ein komplettes Byte eingetaktet, wird es in den Empfangspuffer kopiert (UDR (receive) - UDR steht für UART Data Register).
Der Empfangspuffer kann bis zu zwei Bytes aufnehmen.

Der Controller (Dein Programm) kann die Bytes aus dem Empfangspuffer auslesen (über den Datenbus, in Rechenregister, und da dann ggf irgendwie verarbeiten und z.B. irgendwohin (SRAM/Variablen) abspeichern).
Wie die Bytes in den Empfangspuffer gelangen ist also klar, wie man sie auslesen kann auch.
Aber was ist, wenn der Puffer leer ist, und trotzdem ausgelesen wird?
Dann erhält man 'ne Null (also &B00000000 bzw &H00 bzw ASCII-Null bzw 0 dezimal). Diese Null kannst Du aber nicht von einer tatsächlich übermittelten Null unterscheiden.
Dazu müßtest Du vor dem lesen aus dem Schieberegister wissen, ob überhaupt (noch/schon) Daten drin sind.

Ganz unten sind drei Kontroll- und Statusregister dargestellt (auf die auch über den Datenbus zugegriffen werden kann) - UCSRA..UCSRC.
Im UCSRA gibt es das Bit RXC "USART receive Complete". Dieses Bit zeigt an, ob ungelesene Daten im Empfangspuffer sind.

Inkey() liest einfach nur ein Byte aus dem Empfangspuffer aus, und weist es der Zielvariable zu. Sind keine Daten im Empfangspuffer, wird 'ne Null überwiesen.
Waitkey() wartet (wenn nötig) solange, bis (mindestens) ein Byte im Empfangspuffer liegt (indem in einer Schleife das RXC-Bit in UCSRA abgefragt wird), liest diese Byte dann aus und weist es der Zielvariable zu.
Inputbin kann mehrere Zielvariablen haben (sogar unterschiedlichen Typs (Byte/Integer/Strings/…), und wartet dann auf jedes zuzuweisende Einzelbyte).
(Außerdem kann hinter jeder Zielvariable ein numerischer Wert angegeben werden, um z.B. Arrays zu füllen. Ob an der Stelle Arraygrößen kontrolliert werden ist Unklar - wahrscheinlich wird einfach die Schreibadresse im SRAM inkrementiert, blind gespeichert)
Input wartet nicht nur auf einzelne Bytes, die in der Zielvariable/Zielstring abgelegt werden, sondern terminiert erst, wenn ein Carriage Return empfangen wurde. Input betrachtet die empfangenen Zeichen als ASCII, und wandelt sie passend zur Zielvariable um. - wenn also zB im Empfangspuffer &B00110111 (55 dezimal) liegt, und Du das mit Input in eine Stringvariable auslesen läßt, landet in der Speicherzelle auch &B00110111. Läßt Du es aber in eine Bytevariable auslesen, landet dort &B00000111 (7dezimal).
Das Byte 55 wird als ASCII-Code 55 verwertet, und das ist das Zeichen "7".
Ischarwaiting() schaut nur, ob Daten im Empfangspuffer liegen oder nicht (RXC-Bit in UCSRA), und liefert entsprechend 'ne 1 oder 'ne 0 (als Byte) zurück. Ischarwaiting() wartet auf nichts, und liest auch nichts aus dem Empfangspuffer.

Waitkey(), Inputbin und Input warten also je auf mindestens ein Zeichen - das Programm stoppt also solange, bis die entsprechende Zeichenanzahl bzw bei Input sogar ein CR empfangen wurde.
Da das unser Hauptprogramm unterbrechen würde, wollen wir das nicht.
Inkey() stoppt zwar nicht, würde aber jedesmal 'ne null liefern wenn nichts gesendet wurde.
Also schauen wir mit Ischarwaiting() nach ob was empfangen wurde, und holen nur empfangene Zeichen ab.
Wenn wir aber eh (nach Ischarwaiting()) wissen, daß ein Zeichen im Puffer ist, muß das nicht nochmal durch die Leseinstruktion überprüft werden (waitkey(), Inputbin)

was bedeutet die Klammer?
Ischarwaiting() ist eine Funktion, also ein Teilprogramm, welches irgendwas zurückliefert. Irgendwas ist hier ein Byte (welches den Zustand des Empfangspuffers repräsentiert).
Ischarwaiting() muß also einer Bytevariable zugewiesen werden bzw einer Variable, die eine Bytevariable aufnehmen kann (numerische Variablen, also word/integer/Long).
In den Klammern können der Funktion Parameter übergeben werden. Hier werden keine benötigt, deswegen sind die Klammern leer. Bei einem Controller mit mehreren Hardware-UARTs müßtest Du hingegen angeben, von welchem UART du wissen willst, ob in dessen Empfangspuffer Daten sind - indem Du den als Parameter in den Klammern mitangibst. (Wahrscheinlich wird bei leeren Klammern einfach der erste Hardware-UART verwendet)
 
Ich glaube so langsam fällt der Groschen.
Die UART ist die serielle Schnittstelle des RS-232 (mein Maxx232).
Der USART ist die universelle synchrone und asynchrone serielle Empfänger und Sender ist ein hochflexibler serieller Baustein.

Das sind Begriffe, mit denen ich nicht ganz klar kam und mich endlich mal damit auseinandersetzten musste.
Nach der Arbeit werde ich mal ein paar Test's mit den Input, Inpubin und Inkey durchführen. Ich habe die Vermutung, dass die Eingabe über die Tastatur und Ausgabe über das Terminal eine Abhängigkeit besteht.
Ich wünsche einen schönen Tag.
 
Zuletzt bearbeitet:
RS232 ist der empfohlene Standard (Recommended Standard 232) einer seriellen Schnittstelle. Das betrifft einerseits die elektrische Codierung der einzelnen Bits (NRZ - No Return to Zero - eine "0" wird durch 3..15V, eine "1" durch -3..-15V repräsentiert), als auch wie die Bits zu einem "Wort" zusammengefaßt und verpackt werden (zulässig sind 5..9 Datenbits, die in einen Rahmen aus einem Startbit (="0") und mindestens einem Stopbit ("1") eingebettet. Optional kann vor dem Stopbit ein Paritäts-prüf-bit vereinbart werden.
RS232 ist asynchron - beide Seiten müssen sich an eine vereinbarte Übertragungsgeschwindigkeit (Baudrate - übertragene Bits pro Sekunde) halten. Der Empfänger synchronisiert dabei immer auf die Flanke zwischen Idle/Stopbit und dem Startbit.

USART heißt "Universal Synchronous and Asynchronous serial Receiver and Transmitter". Dieses Modul ist Bestandteil Deines Mikrocontrollers. Es kann als getaktete Schnittstelle (synchronous), als auch als ungetaktete Schnittstelle (asynchronous) betrieben werden.
Der Controller arbeitet aber nur mit TTL-Pegeln (1=Vcc, 0=Gnd). Soll mit RS232 (Pegeln) kommuniziert werden, müssen die Pegel entsprechend gewandelt werden. Das macht Dein MAX232 (der beinhaltet 'ne Ladungspumpe/-inverter, die etwa +/-10V generiert, "Invertierer", die die Pegel entsprechend wandeln. Siehe Datenblatt Seite 17 Figure 5 ).

Der USART kann also synchron und asynchron - wir verwenden ihn aber nur synchron, also als UART.

(Mein USB-Adapter wandelt übrigens nicht auf RS232, sondern arbeitet mit den 5V-TTL-Pegeln, und übermittelt die entsprechenden Signale via USB an einen virtuellen seriellen Port im PC)

Das Terminal (zB von Bascom oder auch hterm) erlaubt Dir, irgendwelche Daten über eine serielle Schnittstelle (bei Dir die echte RS232, bei mir die virtuelle über USB) zu senden oder zu empfangen.

Terminal heißt ja nur Endstück/Endstelle - so gesehen ist jede Software die PCseitig (zB Thomas' Digitalmultimetertool oder auch mein STK500-Programm) oder controllerseitig (zB auch unser Programm im Controller) 'n Terminal...
 

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