Bascom BASCOM ; Erste Schritte zum Ausprobieren

Ok, das If Temp = 0 ersetzt dieses If(year And &B0000_0011) = 0 Then. Trotzdem habe ich noch irgend wo einen Fehler, den Datum wird nicht geändert.
 
Hi,

Irgendwo hatte dino glaub ich mal hier ein Tut geschrieben wie man somit (fast) jeden verfusten Chip wieder Leben einhauchen kann. Leider finde ich den grade nicht. Aber vom Prinzip nur den Ausgang vom Oszillator an einen der beiden Crystal Pins, das wars.
Sollte dieses Reserved jetzt intern allerdings bewirken dass garkeine Clock mehr akzeptiert wird, Pech. Dann geht es höchstens noch mit High Voltage programmmern.



>> Hier steht die Rettung drin (Beitrag #7)

Gruß
Dino
 
  • Like
Reaktionen: TommyB
Falls es wen interessiert, hier das Selbe in LunaAVR, diesmal komplett:


CodeBox BascomAVR
' Compiler configuration
#library "library/Lcd4.interface"               ' 4 bit LCD implementation
#library "library/Sleep.interface"              ' Sleep / Idle implementation
#library "library/Wdt.interface"                ' Watchdog timer implementation
Avr.Device = atmega8
Avr.Clock  = 8000000
Avr.Stack  = 64

' Hardware configuration: LCD
Lcd4.PinDB4 = PortD.4
Lcd4.PinDB5 = PortD.5
Lcd4.PinDB6 = PortD.6
Lcd4.PinDB7 = PortD.7
Lcd4.PinRS  = PortD.2
Lcd4.PinEN  = PortD.3
'Lcd4.PinRW = PortD.1                            ' Optional, basically unused anyway
Lcd4.Config.Columns = 20
Lcd4.Config.Lines = 2

' Hardware configuration: Keys
#define Key0 As PortB.0
#define Key1 As PortB.1
Key0.Mode = Input, PullUp                       ' Key0 as Input, with PullUp enabled
Key1.Mode = Input, PullUp                       ' Key1 as Input, with PullUp enabled

' Used variables
Dim IRQ As Byte                                 ' Interrupt requests
Dim Count1 As Byte                              ' Software Counter 1 (for 200ms)
Dim Count2 As Byte                              ' Software Counter 2 (for 1s)
Dim Year As Byte                                ' Current year (tenths and ones only)
Dim Month As Byte                               ' Current month
Dim Day As Byte                                 ' Current day
Dim Hour As Byte                                ' Current hour
Dim Minute As Byte                              ' Current minute
Dim Second As Byte                              ' Current second

' Initialization ==============================================================

' Variables
IRQ = 0                                         ' We have no Interrupts yet.
Year = 19                                       ' Begin with (20)19
Month = 8                                       ' August
Day = 1                                         ' The 1st

' LCD
Lcd4.Init()                                     ' Initialize display
Lcd4.Cursor.Disable()                           ' Don't show the cursor
Lcd4.Screen.Clear()                             ' Clear the entire screen
IRQ.0 = 1                                       ' Mark screen as dirty (repaint needed)

' Timer 2 (CTC, 8ms)
Timer2.Clock = 256                              ' 8.000.000 / 256 = 32µs Ticks
Timer2.Cmp.Value = 249                          ' 8.000.000 / 256 / 249 = 8ms Interrupt
Timer2.Cmp.Clear.Enable                         ' Enable CTC mode
Timer2.Cmp.Isr = ISR_Timer2_OV                  ' Set ISR for Timer2

' Setup watchdog
' Ok, watchdog implementation is buggy right now...
'Wdt.Clock = 125ms                              ' More than enough
'Wdt.Mode = Reset                               ' Reset the chip if stucked
ASM
  PUSH  R16                                     // Save R16
  IN    R16,    WDTCR                           // Load Watchdog Timer Control Register
  ORI   R16,    (1<<WDCE) OR (1<<WDE) OR (1<<WDP2)  // Enable WDT and set time
  OUT   WDTCR,  R16                             // Write modified values
  POP   R16                                     // Restore R16
EndASM

' Set sleep mode
Sleep.Mode = idle                               ' Lowest sleep mode (we need Timer2)

' Enable interrupts
Avr.Interrupts.enable


' Main Loop ===================================================================


Do
 
  ' Handle IRQ's
  If IRQ.0 = 1 Then                             ' IRQ.0 = Display needs repainting
    Call OnIRQ0
  End If
 
  ' Kick the dog
  Wdt.Reset
 
  ' Fall asleep
  Sleep.Now
 
Loop


' Low priority handler below ==================================================


' IRQ.0 = Display is dirty, repaint it.
Procedure OnIrq0()
 
  ' Display header
  Lcd4.Cursor.Set(1, 1)
  Lcd4.Text(" Std. Min. Sek.")
 
  ' Display hours
  Lcd4.Cursor.Set(2, 2)
  Lcd4.Text(Format("00", Hour))
  Lcd4.Text(" : ")
 
  ' Display minutes
  Lcd4.Text(Format("00", Minute))
  Lcd4.Text(" : ")
 
  ' Display seconds
  Lcd4.Text(Format("00", Second))
 
  IRQ.0 = 0                                     ' We handled IRQ0, so reset it
 
EndProc


' Interrupt service routines below ============================================


' ISR for Timer2 CTC overflow (each 8ms).
ISR ISR_Timer2_OV
 
  Incr Count1                                   ' Increment soft counter 1 (for 200ms)
  If Count1 = 25 Then                           ' Check for overflow
    Count1 = 0                                  ' Reset it
    Call ISR_Tick_200ms()                       ' Process Tick routine
  End If
 
  Incr Count2                                   ' Increment soft counter 2 (for 1s)
  If Count2 = 125 Then                          ' Check for overflow
    Count2 = 0                                  ' Reset it
    Call ISR_Tick_1s()                          ' Process Tick routine
  End If
 
EndISR

' Called by ISR_Timer2_OV each 200ms.
' Still in ISR mode, hence the prefix.
Procedure ISR_Tick_200ms()
 
  If Key0 = 0 Then                              ' If Key0 is pressed
    Incr Minute                                 ' Increment minute
    If Minute >= 60 Then                        ' Check for overflow
      Minute = 0                                ' Reset to 0
    End If
  End If
 
  If Key1 = 0 Then                              ' If Key1 is pressed
    Incr Hour                                   ' Increment hours
    If Hour >= 24 Then                          ' Check for overflow
      Hour = 0                                  ' Reset to 0
    End If
  End If
 
  If Key0 = 0 And Key1 = 0 Then                 ' If Key 0 and 1 are pressed
    Second = 0                                  ' Reset whole time
    Minute = 0                                  ' "
    Hour = 0                                    ' "
  End If
 
  Irq.0 = 1                                     ' Enforce display reset
 
EndProc

' Called by ISR_Timer2_OV each 1000ms (=1s).
' Still in ISR mode, hence the prefix.
Procedure ISR_Tick_1s()
 
  Incr Second                                   ' Increment seconds
  If Second >= 60 Then                          ' Check for overflow
    Second = 0                                  ' Reset to 0
    Incr Minute                                 ' Increment minutes
  End If
 
  If Minute >= 60 Then                          ' Check for overflow
    Minute = 0                                  ' Reset to 0
    Incr Hour                                   ' Increment hours
  End If
 
  If Hour >= 24 Then                            ' Check for overflow
    Hour = 0                                    ' Reset to 0
    Incr Day                                    ' Increment day
  End If
 
  Dim DayOv As Byte                             ' Temp storage for day overflow
  Select Case Month
  Case 1, 3, 5, 7, 8, 10, 12                    ' Months with 31 days
    DayOv = 32                                  ' Set overflow
  Case 4, 6, 9, 11                              ' Months with 30 days
    DayOv = 31                                  ' Set overflow
  Case 2                                        ' The allmighty februrary
    If Year And 0b00000011 = 0 Then             ' Check for leap year
      DayOv = 30                                ' It is, set overflow (30, cause 29 days)
    Else                                        ' No leap year
      DayOv = 29                                ' Set overflow (29, cause 28 days)
    End If
  End Select
  If Day >= DayOv Then                          ' Check for overflow
    Day = 1                                     ' Reset to 1
    Incr Month                                  ' Increment month
  End If
 
  If Month >= 13 Then                           ' Check for overflow
    Month = 1                                   ' Reset to 1
    Incr Year                                   ' Increment year
  End If
 
  If Year >= 100 Then                           ' Check for overflow (only tenths and ones)
    Year = 0                                    ' Reset to 0
  End If
 
EndProc

Man sieht, allzu viel anders ist es jetzt nicht.
Ist aber mangels Hardware (Mega8) Und (grusel) LCD ungetestet.
 
@LotadaC Btw, grade getestet. LunaAVR frisst es. Das ist nicht Bayrisch.
Hmm...
Wie kann der Controller überhaupt ein If..Then... abarbeiten?
Es muß die Bedingung geprüft werden - i.a. ein Compare (CP, CPI), und dann in Abhängigkeit eines Flags (i.a. Carry oder Zero) bedingt gesprungen werden (BREQ/BRNE oder BRLO/BRSH)...
Meiner Meinung nach kann Bascom das nur so (eben weil die Bedingung hier kein komplexer Term sein darf).

Interessant wäre also, wie andere Sprachen (z.B. Mondisch) bestimmte Fälle optimieren können.
Im Prinzip habt Ihr ja: If ((Bytevariable AND Bytekonstante)=0) Then...
Zu erwarten wäre also,
...daß das And aufgelöst wird (ANDI) - Ergebnis ist ein Byte.
...daß der Vergleich mit 0 aufelöst wird (CPI)
...daß in Abhängigkeit des Z-Flags bedingt gesprungen wird (BREQ/BRNE)

Möglicherweise versteht die Sprache aber auch: If (Bytevariable AND Bytekonstante) Then...
Im Gegensatz zum letzten mal wäre zu erwarten,
...daß das AND aufgelöst wird (ANDI), wobei automatisch das "Z" manipuliert wird.
...daß in Abhängigkeit des "Z" gesprungen wird (BRNE/BREQ).

Der Vergleich mit 0 entfällt, da AND "nebenbei" das Z im SREG manipuliert
 
Hier mal die Projektdatei, incl. .hex, .bin, .s, und report.
Du kannst da bestimmt mehr mit anfangen als ich :)

LunaAVR hab ich Version 2018R2 (aktuell).
 

Anhänge

  • Uhr.zip
    24,4 KB · Aufrufe: 1
Falls es wen interessiert, hier das Selbe in LunaAVR, diesmal komplett:
Aus diesem Code habe ich Zeile 190 in meinem Code reingesetzt und dafür das selbige aus meinen Dim Anweisungen rausgenommen. Eigentlich nur nur diese Zeile an einen anderen Platz versetzt compile Programm(F7) und Progamm chip(F4). Danach war nichts mehr auf dem Display zu sehen und der Atmega8 wurde nicht mehr erkannt. Dummerweise habe ich auch noch das Programm, ohne zu wissen was mit dem Chip geschehen ist, auf meinem zweiten Board geschrieben.
Was ist passiert.
 
Keine Ahnung. Ist ja nur die Position wo die Variable deklariert wird anders, was in diesem Fall in Ordnung ist, sie wird ja nur "vor Ort" gebraucht.
Da kann am Flashen nichts hindern.
Oder ist der Chip schon so alt und hat so viele Flash Prozesse hinter sich dass er nu hops ist? (ist mir persönlich noch nie passiert)...
 
Kann nicht sein. Gleich zwei Chips auf verschiedenen Board's. Kann also auch keine falsche Steckverbindung sein.
Habe jetzt nur noch den Atmega88 und halt den großen Atmega32. Nur habe ich jetzt Angst diese mit dem Code auch noch zu zerschießen.
 
Der Code kann dir nichts zerschossen haben. Das können höchstens falsche Fuses. Oder Spannungen.
Wird ISP aktiviert geht der Chip in Reset Status und bleibt dort, also wird keinerlei Code ausgeführt.
Und Code kann auf die Fuses nicht zugreifen (höchstens Read-Only, aber selbst da bin ich nicht sicher).
 
Jetzt bin ich gerade dabei, das TIFR beim Atmega88a zu suchen (im Datenblatt). Ich habe doch das Grundgerüst Sekundentakt, wo nur die Grüne Led blinkt, weiter nichts. Wenn ich jetzt "m88adef.dat" stehen habe. meckert Bascom die Zeile/n mit
If Tifr.tov1 = 1 Then
Tifr.tov1 = 1 an. Also müssen ein paar Veränderungen ran.
 
Bei den neueren Controllern hast Du kein allgemeines "Timer and Counter Interrupt Flag Register" (TIFR) mehr, stattdessen gibt es für jeden Timer ein eigenes TIFR (TIFR0 für Timer0, TIFR1 für Timer1 und TIFR2 für Timer2).
Jeder der drei Timer besitzt je zwei Output-Compare-Interrupts und einen Überlaufs-Interrupt, Timer1 zusätzlich einen Input-Capture-Interrupt. Wären insgesamt also zehn Interrupt-Flags, die eh nicht mehr in ein Register passen. Bei Controllern mit vier..fünf Timern und noch mehr OC-Units pro Timer usw erst recht nicht.
Also wurde der "Aufbau" irgendwann umgekrempelt - jeder Timer besitzt ein eigenes TIFR.
Selbiges gilt für das Interrupt Mask Register (TIMSK).
 
jeden Timer ein eigenes TIFR (TIFR0 für Timer0, TIFR1 für Timer1 und TIFR2 für Timer2).
Dann müsste das doch einfach so geändert werden, um einen ein Sekundentakt zu erzeugen.

CodeBox BascomAVR
If Tifr0.tov0 = 1 Then            'wenn Timer übergelaufen ist
         Tifr0.tov0 = 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
 
Aber was wird mit der Timer Config
Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
 
Interessant wäre also, wie andere Sprachen (z.B. Mondisch) bestimmte Fälle optimieren können.
Im Prinzip habt Ihr ja: If ((Bytevariable AND Bytekonstante)=0) Then...
Zu erwarten wäre also,
...daß das And aufgelöst wird (ANDI) - Ergebnis ist ein Byte.
...daß der Vergleich mit 0 aufelöst wird (CPI)
...daß in Abhängigkeit des Z-Flags bedingt gesprungen wird (BREQ/BRNE)
Der GCC macht aus

CodeBox C
    if ((zeit.sec & 0x03) == 0) // Die Klammern sind in C zwingend
                // der Vergleich hat höhere Priorität, als das bitweise UND
folgendes:

CodeBox Assembler
00000359 MOVW R26,R14        Copy register pair 
0000035A LD R24,X            Load indirect 
0000035B ANDI R24,0x03       Logical AND with immediate 
0000035C BRNE PC+0x0B        Branch if not equal 
Die ersten beiden Zeilen holen der Sekundenwert aus einer Zeitstruktur (ich habe die Sekunden genommen, da sieht man schneller eine Veränderung als bei den Jahren…), dann folgt vor dem BRNE nur noch ein ANDI.
Wenn man den Vergleich in der Anweisung wegläßt

CodeBox C
    if (zeit.sec & 0x03)
wird nur das BRNE durch ein BREQ ersetzt.
Das Ergebnis ist in beiden Fällen (eigentlich nicht nur in C) eindeutig: entweder es ist null oder nicht.

In Bascom und LunaAVR wird das nicht wesentlich anders umgesetzt sein. Und für diese Sprachen gibt es sicher auch eine Prioritätenliste, in der der Vorrang der Operatoren eindeutig geregelt ist.
 
  • Like
Reaktionen: TommyB
In VB.Net würde If Year And 0b00000011 = 0 Then sogar als Compilerwarnung angezeigt, da die Schreibweise unklar ist (blau grün zuerst oder grün orange?). Daher ist hier auch die Klammer nötig. (und umwandeln in Dezimal oder Hex, weil VB.Net keine Binärform erkennt).
 
Hi

Nun, eigentlich wollte ich mich raushalten, aber hier muss ich Mal etwas sagen. Heini14, du bekommst Codeblock für Codeblock. Schade ist, du verstehst es nicht. Da können sich deine Tutoren die Finger wundschreiben. Vielleicht hilft dir der Hinweis, nicht alles mit Copy und Paste zu machen. So lernst du nie, wie ein Programm konstruiert werden muß und jede Abweichung zwischen deinem Aufbau und dem des "Tutoren" zwingt dich auf dem Bretter. Oft nimmst du einfach nur kleine Abschnitte und fügst sie ein und wunderst dich, das nix mehr läuft. Das liegt daran, das du weder den Codeblock verstehst noch irgendeinen Bezug zu deinem Programm hast. Also, zu mal so, als wenn es keine Kopierfunktion gibt und schreib den Code ab. Vielleicht merkst du dann eher, wenn etwas falsch ist und kannst dir gleich an diesen Stellen Gedanken machen, warum der Editor meckert. Du musst verstehen lernen, warum der Controller nicht das tut, was du von ihm erwartest. Der kann nur deinen Anweisungen folgen und das tut er auch mit einer ausgesprochen nervigen Sturheit. Er weiß ja nicht, das du anders denkst wie er. Also mußt du lernen, die "Denkweise" eines Controllers zu verstehen. Also, schreibe jede Zele selbst, auch wenn C&P so verführerisch sind.

Gruß oldmax
 
  • Like
Reaktionen: TommyB
Also, schreibe jede Zele selbst, auch wenn C&P so verführerisch sind.
Ok, ich werde in Zukunft nur noch das kopieren, was ich selbst schon geschrieben habe bzw. gelernt und verstanden. Wenn ich also beim Atmega88a den Timer0 im CTC Modus verwenden möchte, kann ich das in Bascom einfach so schreiben. Will ich aber nachschlagen und das Datenblatt sehe, fällt mir auf, dass die Schreibweise ganz anders erfolgt, wie in Bascom.
Wenn Du helfen möchtest, bräuchte ich mal ein Erklärung hierzu. Für mich wäre Timer0 = CS00.

Timer_Auswahl.JPG
Am Ende wird es so // Timer 0 konfigurieren TCCR0 = (1<<CS01); // Prescaler 8 // Overflow Interrupt erlauben TIMSK |= (1<<TOIE0); geschrieben.
Warum das 1<<CS01.
Da ich schon von Anfang an Probleme habe, tue ich mich mit Copy/Paste leichter, aber verstehe zum Schluß auch nicht ganz, wenn es funktioniert oder auch nicht.
 

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