Bascom BASCOM ; Erste Schritte zum Ausprobieren

Ok, wie bereits per PN beschrieben, hast Du zwei wesentliche Baustellen:
  • Durch Stop Timer wird der Timer nur angehalten, aber die LEDs nicht zwingend abgeschaltet. Dazu wäre der Compare Output Mode umzuschalten.
  • Du hast versucht, zwei für sich funktionierende Teilprogramme zusammenzufassen - beide verwendeten aber Warteschleifen. Das beeinträchtigt sich jetzt gegenseitig.
Mein Vorschlag war, auf die Warteschleifen komplett zu verzichten, und stattdessen aus der PWM-Frequenz eine geeignete Zeitbasis abzuleiten, die in der Hauptschleife gepollt werden kann.
Die Schrittfrequenz des Timers hatte ich oben bereits bestimmt, der Teimer läuft im phasenkorrekten PWM, also im dual Slope. Er läuft zwischen 0 und 255 hin und her, erreicht alle 510 Schritte die Null, wo das Überlauf-Flag gesetzt wird.125000Hz/510≈245Hz PWM-Frequenz, das sind 4,08ms pro Überlauf.

Deine Flacker-Effekt-Programmschleife war diese:

CodeBox BascomAVR
Do
    Fla = Rnd(200)
    Fla = Fla + 55
    Pwm0a = Fla
    Waitms Pause
    Pwm0b = 255 - Fla

    Pause = Rnd(10)
    Pause = Pause * 25
    Waitms Pause
Loop
Versuchen wir das mal ohne wait/mithilfe des Timerüberlaufs möglichst genau so nachzubauen (egal, obs genau so sein muß oder nicht).
Kern des Flackerns ist unter anderem, daß die Dauer gleicher Intensität einer LED der Summe zweier Zufallszahlen (je 0..10) multipliziert mit 25 in Millisekunden ist. Außerdem sind beide LEDs um eine dieser Zeiten verschoben. Die 25 werden durch 6 Timerüberläufe realisiert, das entspräche 24,48ms (hinreichend genau, denk ich).

CodeBox BascomAVR
$regfile = "m8adef.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

'Programmschleife******************* 

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

Wäre jetzt mal locker aus dem Handgelenk geschüttelt, und nicht weiter getestet. Sollte eigentlich dauerhaft genau so flackern. Kannst Du das mal testen?

Edit @Dirk : Schau mal Zeile 14... die vielen Sterne im Kommentar werden durch irgendwelche "B"-Tags ersetzt... bekommst Du das hin?
(eigentlich stand da 'Programmschleife*******************)
 
Zuletzt bearbeitet von einem Moderator:
Hab getestet und funktioniert.
Verstehe nur die Anweisungen Zeile 17 "Tifr.tov" und die Zeile 19 "Tov1cnt" nicht. Sehe so etwas zum ersten mal.
Ist zwar als Variable deklariert, aber was soll das bedeuten.
Zeile 31 "Shift Pausex2" kann ich ebenfalls nicht verstehen.
 
Datenblatt vom ATmega8A Seite 149:

TIFR ist das Timer/Counter Interrupt Flag Register. Beim Mega8(A) befinden sich darin die Interrupt-Flags aller Timer, insbesondere auch die vom Timer1.
Uns interessiert das Überlaufs-Flag: Timer/Counter 1 Overflow Flag (TOV1). Dieses wird quasi bei jedem Überlauf automatisch gesetzt (bzw im hier verwendeten Phasenkorrektem PWM jedesmal beim erreichen der "0"). An dieses Flag könnte man einen Interrupt koppeln - ist aber nicht nötig.
In Zeile 17 wird also geprüft, ob das TOV1-Bit im TIFR-Register gesetzt ist. (In Bascom kannst Du ein Bit in einem Byte/Register so referenzieren, mit dem Punkt. Hat Cassio bereits im ersten Code-Block so verwendet, bei den LEDs an PortD Zum Beispiel).

Wenn das Bit gesetzt ist, hat irgendwann mal ein "Überlauf" stattgefunden. In Zeile 18 wird das Flag sofort gelöscht, damit der nächste Überlauf erkannt werden kann.
Tov1cnt ist eine von mir hinzugefügte Byte-Variable, die die Überläufe (von Timer1) zählt (CNT für Count).
Deine Konstruktion mit den Zufallswerten für die PWM-Register und die Pause hab ich weitgehend übernommen/angepaßt. Nur daß eben nicht 25..250ms gewartet wird, sondern nach jedem Timerüberlauf geprüft wird, ob tov1cnt den Zufallswert zwischen 6 und 60 erreicht hat (6 * 4,08ms=24,48..60 * 4,08=244,8ms).
Im Gegensatz zur vorher verwendeten Wait-Instruktion wird also nur mal kurz geschaut ob ein Überlauf stattfand, und dann nur kurz geschaut, ob jetzt gehandelt werden muß. Das Programm wartet also nicht mehr, und es können weitere Inhalte in die Schleife eingesetzt werden.
Insgesamt muß aber beachtet werden, daß tov1cnt keine Schritte "verlieren" darf. (Ok, Aussetzer im Flackern sollten auch nicht weiter stören).
Zwischen zwei Überläufen macht der Timer ja 510 Schritte, und die mit einem 64stel (=gewählter Prescaler) des Systemtaktes. Also reichlich 32000 Takte Zeit...

Pausex2 soll Pause mal zwei heißen. die Variable wird für den zweiten Vergleich benötigt. Auch wenn der Mega multiplizieren kann (ein Tiny könnte es nicht) - verdoppeln oder halbieren geht im Binärsystem (Zweiersystem) so schneller. Ich verschiebe die Zahl einfach um eine binäre Stelle nach links (oder das gedachte Komma um eine Stelle nach rechts): aus zB &B00101011 wird &B01010110. Rechne nach...
Du würdest im Dezimalsystem (Zehnersystem) ebensoeinfach verzehnfachen können: aus 25436 wird 254360.

Wie gesagt: die waits sind jetzt eleminiert - es kann weiterer Code in die Schleife eingefügt werden, ohne daß der Flackereffekt betroffen ist (unter Beachtung der maximalen 32000 Takte, klar)
Entweder direkt in der Loop, oder auch im If Block, der in Zeile 17 aufgespannt wird (aber außerhalb der da bereits befindlichen If-Blöcke).
Im ersten Fall wird der bei jedem Durchlauf der Loop ausgeführt (mit variierender Frequenz), im zweiten nur nach jedem Timer-Überlauf, also konstant etwa alle 4,08ms.

Du könntest Dich jetzt also mal daran versuchen, 'nen Taster und 'ne LED hinzuzufügen - nach jedem Timerüberlauf soll jetzt zusätzlich der Taster überprüft werden: ist er gedrückt, wird die LED angeschaltet, ist er nicht gedrückt, wird sie ausgeschaltet.

P.S.: Ich initialisiere keine Beine - Config Timer in Zeile 7 macht die beiden verwendeten PWM-Beine automatisch zum Ausgang (im Datenrichtungsregister), der gewählte PWM-Mode übersteuert außerdem die beiden PORT-Bits.
Um die Initialisierung der verwendeten Beine für Taster und LED mußt Du Dich aber selbst kümmern.
 
Zuletzt bearbeitet:
jetzt wird' ja richtig kompliziert. Leider hab ich bis jetzt noch keine Zeit gehabt, etwas auszuprobieren. Mein Max232 ist heute gekommen. Konnte ich ebenfalls noch nicht testen. Müsste wohl erst einmal ein Programm raussuchen, mit dem ich das Gerät ausprobieren kann.
 
Dann könntest Du mit dem Programm aus #21 erstmal unterbrechen, und 'n einfaches "Hallo Welt Programm" mit dem UART angehen.

Aufgabe: Erstelle ein Programm, das nach einem Reset/Power On über den UART einmal den Text "Moin Moin" ausgibt, und lasse das durch ein Terminalprogramm auf dem PC empfangen.
nach der Ausgabe muß das Programm irgendwie "gestoppt" bzw terminiert werden.
 


CodeBox BascomAVR
Print "Moin Moin"                                           'gibt "Moin Moin" aus
End                                                         'generiert leere Endlosschleife (stoppt Programm)
Das wars.
Das setzt natürlich voraus, daß bei Menu → Optionen → Compiler → Kommunikation die tatsächliche Taktfrequenz des Controllers und die tatsächliche Baudrate des Empfängers angegeben ist, außerdem natürlich bei Menu → Optionen → Compiler → Chip der tatsächlich verwendete Controller. Ist das einmal dort eingetragen, kann man im Reiter mit dem Chip den Button ADD to Code klicken (vorher Cursor an den Anfang des Programmes setzen).
Dann werden diese Einstellungen als Direktiven in den Code eingefügt:

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

Was fehlt ist die Baudrate, die wäre per Hand einzufügen: $baud = 9600
Warum die Direktiven?
Sind keine vorhanden, verwendet Bascom die vorgegebenen Einstellungen aus dem Optionen-Menü - egal, was da steht, und ob's Sinn macht. Verwendest Du Direktiven, gilt was im Code steht, und das siehst Du im Code (bzw derjenige, der Dir helfen soll).

Nächste Aufgabe:
Schreibe ein Programm, daß je ein einzelnes Zeichen über den UART entgegennimmt, und dieses zurücksendet.
Eine Endlosschleife bietet sich an
 
  • Like
Reaktionen: Ditron
Guten Morgen
Aufgabe #25
Ich zerbreche mir den Kopf, suche nach allen Möglichen Befehlen auch im Lehrbuch, dabei ist es so einfach.
Verwirrt hat mich Reset/Power On.
Aufgabe #26
Hab ich mir so vorgestellt.


CodeBox BascomAVR
$regfile = "m8def.dat"
$crystal = 8000000
$baud = 19200

Dim Zahl As Byte

Main:

   Input "Eine Zahl eingeben:" , Zahl


   Select Case Zahl

      Case 1
      Print "Zahl ist 1"

      Case 2 To 10
      Print "Die Zahl liegt zwischen 2 und 10"

      Case Is > 10
      Print "Die Zahl ist groesser 10"

   Case Else

      Print "Die Zahl ist Null"

   End Select

Goto Main


Für diese Aufgabe hatte ich schon im Lehrbuch etwas gefunden.
Was
Nur mit dem "Echo" komm ich nicht klar.
Auf jeden Fall funktioniert mein Max232 aus China.
 
Ist aber mehr als die Aufgabe.
Aufgabe war, genau ein Zeichen einzulesen und genau dieses auch wieder auszugeben.
Print und Input arbeiten mit Strings (ASCII) bzw wandeln das intern bei Bedarf in Strings um. Wenn Du in Deinem Code also nacheinander die Tasten 2, 3 und 5 betätigst, werden in Wirklichkeit drei(!) Bytes über den UART gesendet: 0x32, 0x33 und 0x35. Ggf. wirst Du zusätzlich noch Enter drücken müssen, was CR (0x0D) oder CR und LF (0x0D, 0x0A) dazufügt.
Input nimmt diese einzelnen ASCII entgegen (bis das Enter empfangen wurde), und "setzt" die drei ASCII zu der entsprechenden Byte-Variable 235dezimal zusammen (das entspräche also 0xEB oder dem ASCII "Ù" (je nach Codepage, klar).

Deswegen hatte ich oben auch Zeichen geschrieben, also im Sinne von ASCII-Zeichen: Strings der Länge 1.

Du verwendest als Endlosschleife ein unbedingtes Goto - üblich ist eigentlich 'ne Do-Loop-Schleife. Da die aber ohne Abbruchbedingung verwendet wird, sollte genau derselbe Maschinencode erzeugt werden (strenggenommen wäre also Goto sogar die logischere Variante).
Nur mit dem "Echo" komm ich nicht klar.
Wenn ich das richtig in Erinnerung habe, sendet Input default automatisch alle übertragenen Zeichen zurück.
When you use INPUT to retrieve values for variables, all info you type can be echoed back. In this case you will see each character you enter. When ECHO is OFF, you will not see the characters you enter.
In versions 1.11.6.2 and earlier the ECHO options were controlled by an additional parameter on the INPUT statement line like : INPUT "Hello " , var NOECHO
This would suppress the ECHO of the typed data. The new syntax works by setting ECHO ON and OFF. For backwards compatibility, using NOECHO on the INPUT statement line will also work. In effect it will turn echo off and on automatic.
By default, ECHO is always ON.



CodeBox BascomAVR
$regfile = "m8adef.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32
$baud = 9600
Dim Zeichen As String * 1
Do
   Input Zeichen Noecho
   Print Zeichen
Loop
 
So, jetzt geht nichts mehr.
Die erste Auflösung sah so einfach aus, dass ich sie nicht testen musste.
Bei der zweiten Auflösung habe ich noch einmal im Lehrbuch nachgesehen. Leider habe ich nichts von "Echo" entdecken können.
Wie ich das in Erinnerung habe, wird das in der Arduino-Schreibweise verwendet. Ich glaube das ist C+.
Also, mein Terminal hat weder bei der ersten noch bei der zweiten Lösung irgend etwas angezeigt.
Ich bleib wieder hängen.
 
Moment mal...
Dein Code aus #27 geht?
Meine Codes aus #28 und #30 gehen nicht?

Welches Terminalprogramm nutzt Du?
Das setzt natürlich voraus, daß bei Menu → Optionen → Compiler → Kommunikation die tatsächliche Taktfrequenz des Controllers und die tatsächliche Baudrate des Empfängers angegeben ist
Was fehlt ist die Baudrate, die wäre per Hand einzufügen: $baud = 9600
Meine beiden Codes gehen von einer Empfänger-Baudrate von 9600Baud aus (bzw beim ersten Beispiel von dem, was in den Optionen eingestellt ist, wenn Du die $baud-Direktive eben nicht hinzugefügt hast.)
Dein Code aus #27 erwartet hingegen vom Empfänger:


CodeBox BascomAVR
$baud = 19200
Was erwartet Dein Terminalprogramm?
 
Ich habe es mit $baud = 19200 und $baud = 9600 versucht. Beides funktioniert nicht, aber warum nicht?
Wenn es bei meinem Code geht, habe ich doch alles richtig angeschlossen und eingestellt.
Bei meinem Code kann ich bis $baud = 4800 runter gehen.
 
Stopp, habe etwas falsches geschrieben. Ich nehme meine Behauptung im Bezug auf die Baudrate zurück.
Diese Baudrate funktioniert bei meinem Code #27 nur mit $Baud=19200
 
Welches Terminalprogramm nutzt Du?
Und welche Baudrate ist da eingestellt?
Im Code aus #18 hast Du:
$regfile = "m8adef.dat"
In #27 hingegen:
$regfile = "m8def.dat"
Welchen Controller hast Du denn wirklich?
Ob das 'ne Rolle spielt (also insbesondere bei Bascom) kann ich nicht sagen (Fakt ist: ich hab hier 'nen Mega88 (ohne A), den Bascom als A identifiziert hatte, und der nach einem Brennversuch definitiv nicht mehr ordentlich beschrieben werden kann (auch mit dem AVR-Studio kann ich gesetzte Fuses nicht mehr löschen) - Ich verwende zum flashen seitdem grundsätzlich(!) das AVR/ATMEL-Studio)
 
Zuletzt bearbeitet:
Ich benutze das Terminal von Bascom AVR.
Der Code $regfile = "m8adef.dat" ist das Lernobjekt von Cassio. Ich benutz den Atmega 8-16PU, welches in meinen Programmen auch immer eingetragen wird.
Ich habe auch noch einen Atmega88A-PU. Soll ich diesen lieber benutzen?
 
Ah ok, und der Mega8 muß das natürlich können...
So, ich hab dann auch mal'n Mega8 rausgesucht und den auf'n Steckbrett gepappt:print1_fritz.png
Gemäß dem Gesetz der größtmöglichen Gemeinheit war das natürlich ein Controller, der bereits auf 'nen externen Takt gefused war... was ich natürlich erst nach einigem rumprobieren im STK500 herausbekommen habe... Grml...
Ok, Fuses korrigiert und zurück aufs Steckbrett.
Signature lesen klappt.
Also den (vollständigen) Code aus #27 in Bascom auf Mega8 und 19200Baud geändert und compiliert.
Dann das .hex mit dem aktuellen ATMEL Studio geflasht.
Das orangene Kabel auf Gnd gesteckt (deswegen das extra Kabel).
HTerm gestartet, auf 19200Baud eingestellt und verbunden.
Orangenes Kabel aus Gnd herausgezogen (dreimal, wie man sieht):

print1.png

Print sendet übrigens CR und LF, ich habs in HTerm beiNewline at entsprechend ausgewählt und das Häkchen bei Show Newline Characters entfernt.

Also zumindest bei mir geht's...
 
Kann es möglich sein, dass ich die Max232 Platine direkt an den PC angesteckt habe. Bei einem 9-poligen Kabel kreuzen sich die Tx und Experten vom weiblichen zum männlichen Stecker.
 
Kann es möglich sein,
Gute Frage... Normalerweise gilt:
  • Handelt es sich um eine Verbindung von Terminal bzw. Rechner (DTE) (meistens mit Stecker) zu einem Modem (DCE) (meistens mit Buchse), ist ein 1:1-Kabel nötig.
  • Handelt es sich dagegen um eine Verbindung zweier Geräte gleichen Typs (z. B. zweier PCs), so sind die Leitungen zu kreuzen. Ein solches Kabel nennt man Nullmodem-Kabel, da kein Modem (also '0 Modems') eingesetzt wird.
Quelle
Stellt sich also die Frage, ob Dein Adapter eher wie ein PC, oder wie ein Modem verschaltet ist. Für letzteres spricht auch die verwendete Buchse. Außerdem schriebst Du:
funktioniert bei meinem Code #27 nur mit $Baud=19200
Also sollte die Hardware grundsätzlich stimmen.
Ansonsten mußt Du Dir Dein Adapter genau ansehen/durchklingeln und mit dem Datenblatt des MAX232 abgleichen.
Der MAX hat je zwei Kanäle in beide Richtungen (also insgesamt vier).
TxD des Controllers muß auf einen TTL-Eingang des MAX, der korrespondierende RS232-Ausgang (also desselben Kanals) muß dann am RS232-Stecker des PC an Pin2 (RxD) ankommen. Das sollte auch Pin2 Deines Adapters sein.
Pin3 des RS232-Steckers am PC (und am Adapter) muß auf einen RS232-Eingang des MAX laufen, der korrespondierende Ausgang (des Kanals) dann auf RxD des AVR geschaltet werden.

Das nicht verwendete Kanal-Paar könntest Du bei Bedarf mit etwas Geschick dann an die Handshake-Signale löten...

Bei meinem USB-TTL-UART-Adapter ist das etwa eindeutiger: Die USB-seitige Verdrahtung gibt's so nicht da das ja auf dem PC ein virtuelle Comport ist, und zum Controller hin sind die Signale aus Sicht des Adapters benamst. Ums noch eindeutiger zu machen sogar mit RXI (RX In) und TXO (TX Out).
 
Wenn es bei meinem Code #27 funktioniert und du der Meinung bist, dass die Hardware in Ordnung ist, dann will ich gar nicht erst irgend etwas zu verändern.
Das war nur so ein Gedanke mit dem Kabel.8011
 
Beim Beispiel in #35 hab ich wie gesagt (nach dem Flashen) den Controller erstmal im Reset gehalten (indem ich den Reset-Pin über die orangene Leitung mit Gnd verbunden habe).
Der Controller ist zwar im Reset (gefangen), hat aber Strom. Insbesondere hat auch der Pegelwandler/Adapter Strom.
Dann am PC mit HTerm 'ne Verbindung zum Adapter hergestellt, und zuletzt den Reset freigegeben.
aber keine Ahnung, wie ich damit umgehen soll.
Schau mal in #35 das Bild.
Nach dem Start erstmal oben die Grundeinstellungen festlegen, also den richtigen seriellen Port wählen, Baudrate (hier 19200), Anzahl der Datenbits (üblicherweise 8), Anzahl der Stop-Bits (1), kein Paritätsbit (None).
Wenn das fertig ist, und der Controller+Adapter Strom hat, kannst Du die Verbindung mit "Connect" links oben herstellen.
Wenn Du Am Controller den Reset freigibst (also das Kabel zu Gnd entfernst), startet dessen Programm - dann sollte im Received-Fenster der empfangene Text erscheinen.
Ich habe direkt darüber nur ASCII ausgewählt - die empfangenen Bytes werden also als ASCII-Text dargestellt. Du kannst beliebig dezimal, Hexadezimal und/oder Binärdarstellung dazuklicken.
Bascom hängt an Print automatisch CR+LF an (also Wagenrücklauf+Zeilenvorschub).
Diese Steuerzeichen werden Dir bei Received erstmal auch angezeigt.
Oben kannst Du das auch bei "Newline at" auswählen, dann wird entsprechend im Received Fenster umgebrochen.
Wenn Du den Haken bei "Show newline Characters" rausnimmst, werden die auch nicht mehr dargestellt.
Natürlich nur Kosmetik...

Zu senden wäre ja hier noch nichts...
 

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