Hilfe - Küchentimer

Hicki

Mitglied
25. Feb. 2009
44
2
8
58
Sangerhausen/OT Grillenberg
Sprachen
  1. BascomAVR
Hallo,

ich möcht mein neues Projekt "Küchentimer" vorstellen. Der Schaltplan ist soweit fertig, aber das Problem welches ich habe, ist die Software. Da ich mit Bascom noch sehr wenig Ahnung habe, wende ich mich an Euch.
Der Küchentimer ist mit 6 großen 7 Segmentanzeigen ausgestattet. Zum Stellen des Timers habe ich mir einen Drehimpulsgeber ausgesucht(beim Drehen Zeit einstellen und drücken jeweils Sek./Min./Std. einstellen) und zum Starten und Stoppen des Timers einen seperaten Taster. Nach Ablauf der Zeit soll ein akustisches Signal ausgegeben werden sowie ein Piepen bei den letzten 10 Sekunden.
Schaltplan und erste Bascomversuche habe ich angehängt. Über Hilfe würde ich mich sehr freuen.

Gruß Andreas
 

Anhänge

  • test1.bas
    6,2 KB · Aufrufe: 37
  • Küchentimer.png
    Küchentimer.png
    35,1 KB · Aufrufe: 80
Hi
Nun, ich bin kein BASCOM Experte, aber der Blick in dein Listing verwirrt mich etwas.
Beispiel :
Code:
If Sek_einer >= 10 Then                                  'Wenn Sekunde-Einer größer 10
      Sek_einer = 0                                         'dann Sekunde Einer-Stelle Null setzen
      Decr Sek_zehner                                       'und Sekunde Zehner-Stelle runterzählen
   End If

Es ist doch ein Count-Down, oder irre ich da ?
Außerdem packst du viel Code in die ISR. Ich würde da etwas anders vorgehen:
In der IST setzt du nur ein Bit. Ist dieses Bit gesetzt, dann weißt du, das eine Sekunde vergangen ist und rufst die Bearbeitung auf. In der Bearbeitung löscht du das Sekundenbit.
Ok, mag vielleicht etwas unlogisch sein, doch mit einem Sekundenereignis kannst du einiges machen.
Kommen wir zum Countdown. Du zählst von oben nach unten, das heißt, 3 ...2 ... 1 .. 0 .. 9 .. 8 usw.
Der Übergang bei Decr x und bei X=0. Entweder x wird <0 oder x fängt wieder bei 255 an. In Bascom schätz ich mal das x negativ wird. Daher lautet die Abfrage

Code:
If Sek_einer < 0 Then                                  'Wenn Sekunde-Einer kleiner 0
      Sek_einer = 9                                         'dann Sekunde Einer-Stelle auf 9  setzen
      Decr Sek_zehner                                       'und Sekunde Zehner-Stelle runterzählen
   End If

Gruß oldmax
 
Hi
Nun, ich bin kein BASCOM Experte, aber der Blick in dein Listing verwirrt mich etwas.
Beispiel :
Code:
If Sek_einer >= 10 Then                                  'Wenn Sekunde-Einer größer 10
      Sek_einer = 0                                         'dann Sekunde Einer-Stelle Null setzen
      Decr Sek_zehner                                       'und Sekunde Zehner-Stelle runterzählen
   End If

Es ist doch ein Count-Down, oder irre ich da ?
Außerdem packst du viel Code in die ISR. Ich würde da etwas anders vorgehen:
In der IST setzt du nur ein Bit. Ist dieses Bit gesetzt, dann weißt du, das eine Sekunde vergangen ist und rufst die Bearbeitung auf. In der Bearbeitung löscht du das Sekundenbit.
Ok, mag vielleicht etwas unlogisch sein, doch mit einem Sekundenereignis kannst du einiges machen.
Kommen wir zum Countdown. Du zählst von oben nach unten, das heißt, 3 ...2 ... 1 .. 0 .. 9 .. 8 usw.
Der Übergang bei Decr x und bei X=0. Entweder x wird <0 oder x fängt wieder bei 255 an. In Bascom schätz ich mal das x negativ wird. Daher lautet die Abfrage

Code:
If Sek_einer < 0 Then                                  'Wenn Sekunde-Einer kleiner 0
      Sek_einer = 9                                         'dann Sekunde Einer-Stelle auf 9  setzen
      Decr Sek_zehner                                       'und Sekunde Zehner-Stelle runterzählen
   End If

Gruß oldmax

Guten Morgen oldmax,

Du hast vollkommen Recht. Vielen Dank. Ich kann es leider noch nicht testen, da die Hardware noch nicht fertig ist. Der geänderte Code in der Anlage.

Gruß Andreas
 

Anhänge

  • test2.bas
    6,3 KB · Aufrufe: 4
Hallo Hicki!

Wenn du deinen Programmcode hier direkt einstellen würdest, so dass ihn nicht jeder erst herunterladen muss, dann würden bestimmt einige User mehr drüber schauen..... und es gibt bestimmt mehr Hilfe bzw. Anregungen. :wink:

Gibt es einen speziellen Grund, warum du dein Programm hier nur als "Download" einstellst? :hmmmm:


Grüße,
Cassio
 
Hallo Hicki!

Wenn du deinen Programmcode hier direkt einstellen würdest, so dass ihn nicht jeder erst herunterladen muss, dann würden bestimmt einige User mehr drüber schauen..... und es gibt bestimmt mehr Hilfe bzw. Anregungen. :wink:

Gibt es einen speziellen Grund, warum du dein Programm hier nur als "Download" einstellst? :hmmmm:


Grüße,
Cassio

Hi Cassio,

eigentlich gibt es da keinen Grund. Danke für den Hinweis.

Gruß Andreas
Code:
'*** Küchentimer ***************************************************************
'*** mit Atmega8 und 6 x LED 7 Segment-Anzeigen ********************************
'*** Andreas Hickmann
'*** Anregung und Grundlagen von http://www.elektronik-radio.de ****************


'*** Hardware ******************************************************************
$regfile = "m8def.dat"
$crystal = 3686400                                          '3,6864 MHz

'*** Ports konfigurieren********************************************************
Ddrb = &B00110000                                           'PB => 1=Ausgang / 0=Eingang
Portb = &B00000011                                          '1=PullUp eingeschaltet
Ddrc = &B11111111                                           'PC => Multiplexen der Anzeige
Ddrd = &B11111111                                           'PD => 7-Segmente

'Sekundentakt erzeugen
On Timer1 Ontimer1
Config Timer1 = Timer , Prescale = 64                       '=1Hz
Enable Timer1

'Multiplexfrequenz erzeugen
On Timer0 Ontimer0
Config Timer0 = Timer , Prescale = 64                       '=400Hz
Enable Timer0

Enable Interrupts

'*** Variablen *****************************************************************
Dim Wert As Byte                                            'Ziffer die ausgegeben wird
Dim Multiplex As Byte                                       'Stellenwert (1,2,4,8,16,32)
Dim Sek_einer As Byte
Dim Sek_zehner As Byte
Dim Min_einer As Byte
Dim Min_zehner As Byte
Dim Std_einer As Byte
Dim Std_zehner As Byte

Declare Sub Minute
Declare Sub Stunde

Multiplex = 1                                               'Startwert
Timer1 = 7936                                               'Für den Start des Counters nach 1 Sekunde

'*** Main (Zeit einstellen) ****************************************************
Do
   Debounce Pinb.0 , 0 , Minute , Sub                       'Minuten einstellen
   Debounce Pinb.1 , 0 , Stunde , Sub                       'Stunden einstellen
Loop

'*** Sub-Routinen (Zeit einstellen) ********************************************
Sub Minute
    Incr Min_einer                                          'Minute um 1 erhöhen
    Sek_einer = 0                                           'Nullen der Sekunde (Einer)
    Sek_zehner = 0                                          'Nullen der Sekunde (Zehner)
End Sub

Sub Stunde                                                  'Stunde um 1 erhöhen
    Incr Std_einer
End Sub

'*** Interrupt-Routinen ********************************************************
Ontimer1:                                                   'Aufruf im Sekundentakt
   Timer1 = 7936                                            '=> 1Hz
   Decr Sek_einer                                           'Sekunde Einer-Stelle runterzählen
   'Die Sekunden-Einer runterzählen => 0,9,8,7,6,5,4,3,2,1
   If Sek_einer < 0 Then                                    'Wenn Sekunde-Einer kleiner 0
      Sek_einer = 9                                         'dann Sekunde Einer-Stelle auf 9  setzen
      Decr Sek_zehner                                       'und Sekunde Zehner-Stelle runterzählen
   End If                                                   '
  'Die Sekunden-Zehner runterzählen => 0,5,4,3,2,1
   If Sek_zehner < 0 Then                                   'Wenn Sekunde-Zehner kleiner 0               '
      Sek_zehner = 5                                        'dann Sekunde Zehner-Stelle auf 5 setzen
      Decr Min_einer                                        'und Minute Einer-Stelle runterzählen
   End If
   'Die Minuten-Einer runterzählen => 0,9,8,7,6,5,4,3,2,1
   If Min_einer < 0 Then                                    'usw.
      Min_einer = 9
      Decr Min_zehner
   End If

   If Min_zehner < 0 Then
      Min_zehner = 5
      Decr Std_einer
   End If

   If Std_einer < 0 Then
      Std_einer = 9
      Decr Std_zehner
   End If

   If Std_zehner < 0 Then
      Std_zehner = 3
   End If

   If Std_zehner >= 2 And Std_einer >= 4 Then               'Wenn 24 Uhr alles 00:00:00 setzen
         Std_zehner = 0
         Std_einer = 0
   End If
Return

Ontimer0:                                                   'Der Multiplexer!
   Timer0 = 112                                             '= 400Hz

   'Hier wird die Umschaltsequenz (Multiplexen) der 6 Segmente erzeugt!
   Multiplex = Multiplex * 2                                '1,2,4,8,16,32,(64)
   If Multiplex = 64 Then Multiplex = 1

   '400Hz/6Segmente=> 66Hz. Die kpl. Anzeige wird also mit 66Hz gemultiplext!

   Portd = &B11111111                                       'Alle Segmente vor dem Umschalten ausschalten
   Portc = Multiplex                                        'Das anzusteuernde Segment auswählen

   If Multiplex = 1 Then Wert = Sek_einer                   'Ab hier erfolgt die Zuordnung von Anzeige und Wert
   If Multiplex = 2 Then Wert = Sek_zehner
   If Multiplex = 4 Then Wert = Min_einer
   If Multiplex = 8 Then Wert = Min_zehner
   If Multiplex = 16 Then Wert = Std_einer
   If Multiplex = 32 Then
      If Std_zehner = 0 Then                                'Wenn 0 soll die Anzeige dunkel bleiben
         Wert = 10                                          '10 bedeutet => kein Segment ist an.
      Else
         Wert = Std_zehner
      End If
   End If

   'Hier erfolgt die die Auswahl (Dekodierung) welche Segmente leuchten sollen
   Select Case Wert
      Case 0
         Portd = &B11000000                                 '0
      Case 1
         Portd = &B11111001                                 '1
      Case 2
         Portd = &B10100100                                 '2
      Case 3
         Portd = &B10110000                                 '3
      Case 4
         Portd = &B10011001                                 '4
      Case 5
         Portd = &B10010010                                 '5
      Case 6
         Portd = &B10000010                                 '6
      Case 7
         Portd = &B11111000                                 '7
      Case 8
         Portd = &B10000000                                 '8
      Case 9
         Portd = &B10010000                                 '9
      Case Else
         Portd = &B11111111                                 'Anzeige dunkel schalten
   End Select
Return
 
Hallo,

Code:
   'Hier erfolgt die die Auswahl (Dekodierung) welche Segmente leuchten sollen
   Select Case Wert
      Case 0
         Portd = &B11000000                                 '0
      Case 1
         Portd = &B11111001                                 '1
      Case 2
         Portd = &B10100100                                 '2
      Case 3
         Portd = &B10110000                                 '3
      Case 4
         Portd = &B10011001                                 '4
      Case 5
         Portd = &B10010010                                 '5
      Case 6
         Portd = &B10000010                                 '6
      Case 7
         Portd = &B11111000                                 '7
      Case 8
         Portd = &B10000000                                 '8
      Case 9
         Portd = &B10010000                                 '9
      Case Else
         Portd = &B11111111                                 'Anzeige dunkel schalten
   End Select
Return

diesen Teil könnte man auch wesentlich schneller ablaufen lassen wenn man statt der ganzen Case-Sachen ein Array verwendet. Nimm ein Byte-Array mit 10 Einträgen. Da legst du die Muster drin ab. Dann kannst du sozusagen schreiben ...

Portd = Muster(Wert)

... und hast das ganze ohne einen einzigen Vergleich erledigt. Natürlich auf Kosten des Speicherverbrauchs ;)
Das einzige was dann fehlt ist das die Anzeige bei allen anderen Werten dunkel ist. Aber das sollte normalerweise nicht passieren wenn der Rest richtig programmiert ist :p

Gruß
Dino
 
Deine Stellen sind alles Bytes. Bytes sind vorzeichenlos, können Werte zwischen (inklusive) 0 und (inklusive) 255 annnehmen. Also nie kleiner als 0 werden.
Dekrementierst Du ein Byte was 0 ist, läuft es auf 255 über.
(ASM: DEC beeinflußt dabei nicht das Carry-Flag, SUBI mit 1 (also 1 subtrahieren) schon)
 
Hallo,

Code:
   'Hier erfolgt die die Auswahl (Dekodierung) welche Segmente leuchten sollen
   Select Case Wert
      Case 0
         Portd = &B11000000                                 '0
      Case 1
         Portd = &B11111001                                 '1
      Case 2
         Portd = &B10100100                                 '2
      Case 3
         Portd = &B10110000                                 '3
      Case 4
         Portd = &B10011001                                 '4
      Case 5
         Portd = &B10010010                                 '5
      Case 6
         Portd = &B10000010                                 '6
      Case 7
         Portd = &B11111000                                 '7
      Case 8
         Portd = &B10000000                                 '8
      Case 9
         Portd = &B10010000                                 '9
      Case Else
         Portd = &B11111111                                 'Anzeige dunkel schalten
   End Select
Return

diesen Teil könnte man auch wesentlich schneller ablaufen lassen wenn man statt der ganzen Case-Sachen ein Array verwendet. Nimm ein Byte-Array mit 10 Einträgen. Da legst du die Muster drin ab. Dann kannst du sozusagen schreiben ...

Portd = Muster(Wert)

... und hast das ganze ohne einen einzigen Vergleich erledigt. Natürlich auf Kosten des Speicherverbrauchs ;)
Das einzige was dann fehlt ist das die Anzeige bei allen anderen Werten dunkel ist. Aber das sollte normalerweise nicht passieren wenn der Rest richtig programmiert ist :p

Gruß
Dino

Guten Morgen Dino,

hast Du das so gemeint?

Code:
Dim Anzeigesegmente(11) As Byte

Anzeigesegmente(1) = &B11000000                             'Zahl 0
Anzeigesegmente(2) = &B11111001                             'Zahl 1
Anzeigesegmente(3) = &B10100100                             'Zahl 2
Anzeigesegmente(4) = &B10110000                             'Zahl 3
Anzeigesegmente(5) = &B10011001                             'Zahl 4
Anzeigesegmente(6) = &B10010010                             'Zahl 5
Anzeigesegmente(7) = &B10000010                             'Zahl 6
Anzeigesegmente(8) = &B11111000                             'Zahl 7
Anzeigesegmente(9) = &B10000000                             'Zahl 8
Anzeigesegmente(10) = &B10010000                            'Zahl 9
Anzeigesegmente(11) = &B11111111                            'Anzeige dunkel


Portd = Anzeigesegmente(1)
Portd = Anzeigesegmente(2)
Portd = Anzeigesegmente(3)
Portd = Anzeigesegmente(4)
Portd = Anzeigesegmente(5)
Portd = Anzeigesegmente(6)
Portd = Anzeigesegmente(7)
Portd = Anzeigesegmente(8)
Portd = Anzeigesegmente(9)
Portd = Anzeigesegmente(10)
Portd = Anzeigesegmente(11)

Gruß Andreas
 
Hi
Das mit den Byte-Format kann ich trotz fehlender BASCOM-Kenntnis auch erklären.:cool:
Also, in einem Byte kannst du 8 Bit darstellen, welches im Binärsystem einem Zahlenbereich von 0 bis 255 bedeutet. das sind 256 Werte. Decrementierst du ein Byte ist klar, der Wert läuft nach unten und wird irgendwann einmal 0. Beim nächsten Decrement müßte die Zahl ein negatives vorzeichen bekommen, das gibt es aber nicht. Daher fängt die Zählerei auch wieder bei 255 an, weil alle Bits "1" sind. Also mußt du deine Abfragen etwas umstellen, denn deine Werte werden niemals <0 sondern tatsächlich > 10.
Also der Teil deiner Abfrage
Code:
Decr Sek_einer                                           'Sekunde Einer-Stelle runterzählen
   'Die Sekunden-Einer runterzählen => 0,9,8,7,6,5,4,3,2,1
   [COLOR="#FF0000"]If Sek_einer < 0 Then                                    [/COLOR]'Wenn Sekunde-Einer kleiner 0
      Sek_einer = 9                                         'dann Sekunde Einer-Stelle auf 9  setzen
      Decr Sek_zehner                                       'und Sekunde Zehner-Stelle runterzählen
   End If
muß
Code:
Decr Sek_einer                                           'Sekunde Einer-Stelle runterzählen
   'Die Sekunden-Einer runterzählen => 0,9,8,7,6,5,4,3,2,1
   [COLOR="#FF0000"]If Sek_einer > 10 Then                                    [/COLOR]'Wenn Sekunde-Einer größer 10
      Sek_einer = 9                                         'dann Sekunde Einer-Stelle auf 9  setzen
      Decr Sek_zehner                                       'und Sekunde Zehner-Stelle runterzählen
   End If
wobei es unerheblich ist, ob du nun 10 oder einen höheren Wert eingibst, solange dieser <254 ist.
Einen Fehler in deiner Zähllogig glaube ich noch entdeckt zu haben:
Code:
If Std_einer < 0 Then
      Std_einer = 9
      Decr Std_zehner
   End If

If Std_zehner < 0 Then
      Std_zehner = 3
   End If

   If Std_zehner >= 2 And Std_einer >= 4 Then               'Wenn 24 Uhr alles 00:00:00 setzen
         Std_zehner = 0
         Std_einer = 0
   End If
Du setzt den Std_einer immer auf 9. Irgendwann bekommst du damit einen Wert von 39. Könnte Absicht sein, glaub ich aber nicht.
Nun zum Aufbau der Ausgaben für die Anzeige. Was Dino meinte, ist, das die Zahlencodes in einer Art Tabelle angelegt werden. Nennt sich in Bascom glaub ich "Array". Dort hinterlegst du die Bit-Werte beginnend mit 0.
Möchtest du eine 4 anzeigen, holst du dir aus dem Array das Byte mit dem Index 4 und gibst es aus. Somit entfallen alle Case-Anweisungen.. Die Dunkelschaltung kannst du ja z.B. auf ein 11. Feld im Array legen. Und was den Speicherplatz betrifft, na ja, ich glaub nicht, das diese 10 oder 11 Bytes da groß ins Gewicht fallen....:rolleyes:
Also, der Vorgang ist grob beschrieben:
Du hast einen Zählpuffer. Hier werden deine Zahlenwerte berechnet. Für die Ausgabe nimmst du nun die Zahl, indizierst damit dein Array und holst den Code für die Anzeige aus dem entsprechenden Arrayfeld. Das gibst du aus und fertig.
So, nun muß ich aber zur Arbeit.....:bad:
Gruß oldmax
 
...Nun zum Aufbau der Ausgaben für die Anzeige. Was Dino meinte, ist, das die Zahlencodes in einer Art Tabelle angelegt werden. Nennt sich in Bascom glaub ich "Array". Dort hinterlegst du die Bit-Werte beginnend mit 0.
Möchtest du eine 4 anzeigen, holst du dir aus dem Array das Byte mit dem Index 4 und gibst es aus. Somit entfallen alle Case-Anweisungen.. Die Dunkelschaltung kannst du ja z.B. auf ein 11. Feld im Array legen. Und was den Speicherplatz betrifft, na ja, ich glaub nicht, das diese 10 oder 11 Bytes da groß ins Gewicht fallen....:rolleyes:..

Eigentlich hatter das ja da schon zu stehen. Ob er das Array in einer Schleife, oder zu Fuß (also für jeden Index einzeln) mit Werten füllt, ist hierbei Wurscht (ersteres kostet weniger Flash, letzteres ist schneller, aber eigentlich jeweils nur eine Winzigkeit...)
Was noch fehlt: Wenn man einen festgelegten diskreten Zustand ausgeben will, bringt das noch keine Vorteile, da kann man weiterhin Portb=0b01001011 oder so schreiben - Der Vorteil ist, daß sich genau das richtige Bitmuster einer darzustellenden Zahl genau im Array-Element mit dem Index derselben Zahl befindet. Du kannst jetzt also jetzt z.B. insbesondere auch schreiben:
Code:
Portd=Anzeigesegmente(sek_einer)

Zum Byte: danke für die bessere Erklärung, oldmax. Strenggenommen ist das natürlich kein Überlauf, sondern ein Unterlauf:p
kommt ja auch überall woanders vor. BeimTacho zB...
 
Hallo,

Was noch fehlt: Wenn man einen festgelegten diskreten Zustand ausgeben will, bringt das noch keine Vorteile, da kann man weiterhin Portb=0b01001011 oder so schreiben - Der Vorteil ist, daß sich genau das richtige Bitmuster einer darzustellenden Zahl genau im Array-Element mit dem Index derselben Zahl befindet. Du kannst jetzt also jetzt z.B. insbesondere auch schreiben:
Code:
Portd=Anzeigesegmente(sek_einer)
genau so. :cool: Tabellen können richtig viel Arbeit sparen wenn man sie mit ein wenig Hirn und System anlegt :p In Assembler geht das natürlich noch um einiges besser. Kannst dir ja mal meine Assembler-Listings (Mega32 Daddelboard) ansehen. Da hab ich über eine Tabelle die verwürfelten Zeilen des LCDs in die richtige Reihenfolge gebracht und Zeilenüberläufe verarbeitet.

Gruß
Dino
 
Hi Leute,

ich danke Euch erst einmal für die Tipps und Hilfe.
Was ich aber nicht verstehe ist das mit dem Array. Geht das vielleicht für mich bitte noch etwas ausführlicher?

Gruß Andreas
 
Hi Andreas,

Was ich aber nicht verstehe ist das mit dem Array. Geht das vielleicht für mich bitte noch etwas ausführlicher?

also ... eine normale Bytevariable kann ein Byte fassen.

dim a as Byte
a=255

ein Byte-Array kann mehrere Bytes fassen (stell es dir als Liste vor).

dim a(5) as Byte
a(1)=0
a(2)=43
a(3)=128
a(4)=255
a(5)=192

Die Variable "A" hat sozusagen 5 Plätze für Werte zur Verfügung so wie eine Schloßallee auch mehrere Hausnummern hat.

Gruß
Dino
 
Guten Morgen Dino,

hast Du das so gemeint?

Code:
Dim Anzeigesegmente(11) As Byte

Anzeigesegmente(1) = &B11000000                             'Zahl 0
Anzeigesegmente(2) = &B11111001                             'Zahl 1
Anzeigesegmente(3) = &B10100100                             'Zahl 2
Anzeigesegmente(4) = &B10110000                             'Zahl 3
Anzeigesegmente(5) = &B10011001                             'Zahl 4
Anzeigesegmente(6) = &B10010010                             'Zahl 5
Anzeigesegmente(7) = &B10000010                             'Zahl 6
Anzeigesegmente(8) = &B11111000                             'Zahl 7
Anzeigesegmente(9) = &B10000000                             'Zahl 8
Anzeigesegmente(10) = &B10010000                            'Zahl 9
Anzeigesegmente(11) = &B11111111                            'Anzeige dunkel

Gruß Andreas

Hi Dino,

dann war das ja schon mal richtig.
Und wie geht es weiter?

Gruß Andreas
 
Hi,

bevor ich gleich ... :sleep:
dann war das ja schon mal richtig.
Und wie geht es weiter?
am besten wäre jetzt eine fertige Hardware :rolleyes: aber die ist ja glaube ich noch in Arbeit.
Am Simulator fehlt leider der "Aha-Effekt".

Du könntest jetzt zB auf einem der Displays mal Ziffern anzeigen. Also ungefähr die Vorgehensweise die ich dir in der PN vorgeschlagen habe ...

Ich mache das immer folgendermaßen:

1. Grundstruktur aufbauen.
also die Einstellungen für den Chip (regfile, crystal, hwstack, swstack, framesize),
dann alle Portdefinitionen (DDRx, PullUps, ...) mit Bemerkungen zu den Portfunktionen,
dann eine Endlosschleife dahinter.
Damit hat man dann ein Grundgerüst.

2. Initialisierung der Sonderfunktionen
ich baue hinter den Portdefinitionen die Zeilen für zB LCD-Initialisierung, UART-Geschwindigkeit, I2C-Definition (Taxtrate,...) ein. Also alles was die Schnittstellen zum Leben benötigen. Das sind auch nur wenige Zeilen

3. Hardwaretest
ich baue erste kleine Zeilen in die Grundstruktur rein mit denen ich die Hardware testen kann.
Also Leds zum blinken bringen, Testtext aufs LCD, Testtext beim UART über RS232 an den PC senden. All sowas um die Lebensfähigkeit der Schaltung und der Komponenten die man verbaut hat zu testen. Kleine stinknormale Print-Befehle oder für LEDs Toggle-Befehle. Damit es nicht zu schnell geht mach ich in die Endlosschleife nen WAIT 1 rein.

4. schrittweises Einbauen der Funktionen
danach setze ich nach und nach die einzelnen Funktionen um. Zuerst die Basisfunktionen.

Bei deiner Uhr also zuerst mal eine Zeichentabelle für die Segmente bauen und auf einem Display statisch verschiedene Ziffern anzeigen lassen.

Dann mal einen Timer zum laufen bringen um eine Basis für ein sauberes Multiplexing zu haben. Etwa so 100-300Hz (also 3-10ms Ablaufzeit) Als Test könntest du mit dem Timerinterrupt zB eine Variable hochzählen deren letzte Stelle du auf einer der Anzeigen darstellst. Die Umarbeitung von Dezimal auf 7Segment hast du ja schon mit der Zeichentabelle am laufen.

Wenn du nun weißt das der Timer und die Zeichendarstellung läuft, baust du mit dem Timer ein Multiplexing für die Anzeige auf. Die Stellen werden also der Reihe nach durchgeschaltet. Damit kannst du dann schon mehrstellige Werte anzeigen lassen.

Danach kommt die Uhr. Also eine Softclock zum laufen bekommen (mit Uhrenquarz) und die Werte auf der Anzeige darstellen. Sch... egal was die Uhr für eine Zeit anzeigt.

Zum Schluß machst du die Steuerung (bei dir ja mit Drehencoder) und damit du die Uhr stellen kannst.

Danach noch Feinschliff und Kleinigkeiten.

Bei dem Ablauf kommen dann ab und zu bei jedem Abschnitt wieder diese Aha-Effekte. Ah ... so geht das. Außerdem baut man das Programm strukturiert auf und hat nicht zu viele Baustellen auf einmal.

Das mit dem Array ist jetzt eine Alternative wie man einen Teil dieser Vorgehensweise umsetzen kann. Es würde auch mit dem Select-Case gehen. Mit einem Array ist es aber "schöner". Es gibt immer mehrere Möglichkeiten ein Teil umzusetzen. Wenn du ein Programm modular aufbaust, dann kannst du später recht streßfrei einzelne Teile optimieren oder durch andere Vorgehensweisen ersetzen ohne den Rest anfassen zu müssen.

Gruß
Dino
 
Hi Dino, :goodnight:

die Harware ist leider noch nicht fertig. Ich denke mal Ende nächster Woche(ich habe momentan viel zu tun).
Wir machen es so, dass ich mich wieder melde, wenn die Hardware fertig ist.
Macht ja auch Sinn, etwas gleich in der Praxis zu testen.

Ich danke erst einmal Allen die bis jetzt geholfen haben.

Gruß Andreas
 
Hi
Manchmal sagt ein Bild mehr wie tausend Worte....
Anzeige.PNG
Du siehst die Zahl, die du darstellen willst. Hier hat sie mal 4 Stellen, aber es dürfen auch mehr sein.
Der Stellenzähler und das Select-Byte arbeiten eng miteinander. Um die "1" darin zu verschieben, gibt es entsprechende Befehle. Das heißt, jedesmal, wenn du den Stellenzähler erhöhst, muß auch das Bit geschoben werden, um die richtige Anzeige zu selektieren. Dan holst du den Zahlenwert von der Stelle und indizierst damit deinen Tabelleneintrag, wo der 7-Segment-Code für die Zahl steht. Den gibst du dann aus. Damit du keine "Geisterzeichen" bekommst (nachleuchten der Segmente) nutzt du den Timer - Interrupt. In jeder msek. erzeugst du diesen. Davon leitest du deinen Zeitzähler ab und versorgst dann den Multiplexer
Interrupt:
Alle Segmentanzeigen aus. ( Select-Byte mit "00000000" verunden)
Stellenzähler incrementieren
Select_Byte weiterschieben
Stellenzähler auf Überlauf prüfen -> wenn Überlauf
Stellenzähler 0
Select-Byte ="00000001"
Zahl der Stelle laden
Segmentcode adressieren
Segmentcode laden
Auf 7 Segmentanzeige schalten (gemeinsame)
Select-Byte ausgeben

Das ist mal völlig ohne Festlegung auf eine Sprache die Vorgehensweise.
Gruß oldmax
 
Hi
Manchmal sagt ein Bild mehr wie tausend Worte....
Anhang anzeigen 5155
Du siehst die Zahl, die du darstellen willst. Hier hat sie mal 4 Stellen, aber es dürfen auch mehr sein.
Der Stellenzähler und das Select-Byte arbeiten eng miteinander. Um die "1" darin zu verschieben, gibt es entsprechende Befehle. Das heißt, jedesmal, wenn du den Stellenzähler erhöhst, muß auch das Bit geschoben werden, um die richtige Anzeige zu selektieren. Dan holst du den Zahlenwert von der Stelle und indizierst damit deinen Tabelleneintrag, wo der 7-Segment-Code für die Zahl steht. Den gibst du dann aus. Damit du keine "Geisterzeichen" bekommst (nachleuchten der Segmente) nutzt du den Timer - Interrupt. In jeder msek. erzeugst du diesen. Davon leitest du deinen Zeitzähler ab und versorgst dann den Multiplexer
Interrupt:
Alle Segmentanzeigen aus. ( Select-Byte mit "00000000" verunden)
Stellenzähler incrementieren
Select_Byte weiterschieben
Stellenzähler auf Überlauf prüfen -> wenn Überlauf
Stellenzähler 0
Select-Byte ="00000001"
Zahl der Stelle laden
Segmentcode adressieren
Segmentcode laden
Auf 7 Segmentanzeige schalten (gemeinsame)
Select-Byte ausgeben

Das ist mal völlig ohne Festlegung auf eine Sprache die Vorgehensweise.
Gruß oldmax

Hi Oldmax,

vielen Dank erst einmal.
So, ich habe die Schaltung erst einmal auf ein Testboard aufgebaut. Jetzt kann die Programmiererei beginnen.
Fangen wir von oben an. Sind die Eistellung des Chip´s soweit richtig?

Code:
'*** Hardware ******************************************************************
$regfile = "m8def.dat"
$crystal = 3686400                                          '3,6864 MHz

'*** Ports konfigurieren********************************************************
Ddrb = &B00110000                                           'PB => 1=Ausgang / 0=Eingang
Portb = &B00000011                                          '1=PullUp eingeschaltet
Ddrc = &B11111111                                           'PC => Multiplexen der Anzeige
Ddrd = &B11111111                                           'PD => 7-Segmente

'Sekundentakt erzeugen
On Timer1 Ontimer1
Config Timer1 = Timer , Prescale = 64                       '=1Hz
Enable Timer1

'Multiplexfrequenz erzeugen
On Timer0 Ontimer0
Config Timer0 = Timer , Prescale = 64                       '=400Hz
Enable Timer0

Enable Interrupts

Gruß Andreas
 
Hi Andreas,

So, ich habe die Schaltung erst einmal auf ein Testboard aufgebaut. Jetzt kann die Programmiererei beginnen.
Fangen wir von oben an. Sind die Eistellung des Chip´s soweit richtig?

Code:
'*** Hardware ******************************************************************
$regfile = "m8def.dat"
$crystal = 3686400                                          '3,6864 MHz

'*** Ports konfigurieren********************************************************
Ddrb = &B00110000                                           'PB => 1=Ausgang / 0=Eingang
Portb = &B00000011                                          '1=PullUp eingeschaltet
Ddrc = &B11111111                                           'PC => Multiplexen der Anzeige
Ddrd = &B11111111                                           'PD => 7-Segmente

'Sekundentakt erzeugen
On Timer1 Ontimer1
Config Timer1 = Timer , Prescale = 64                       '=1Hz
Enable Timer1

'Multiplexfrequenz erzeugen
On Timer0 Ontimer0
Config Timer0 = Timer , Prescale = 64                       '=400Hz
Enable Timer0

Enable Interrupts

1. Fang nicht gleich mit der Initialisierung der Interrupts und dem Einschalten der Interrupts an. Das kommt noch früh genug. Mach erstmal die grundlegenden Sachen wie ne Ziffer auf eines deiner Displays zu zaubern.

2. Schreib das Ddrb = &B00110000 lieber so Ddrb = &B0011_0000 damit du dich bei den Bits nicht so schnell verzählst.

3. Schreib bei deiner Portinitialisierung auch dabei welches Bit du für was verwendet hast. Zum Beispiel so ...
Code:
' ################################
' ##### DEFINITION DER PORTS #####
' ################################
'
' PD0 --<---- RxD | UART
' PD1 ---->-- TxD | TTL-Pegel
'
' PD2 --<---- INT0
' PD3 --<---- INT1
'             ____________
'            |            |
' PD4 ---->--|D4          |
' PD5 ---->--|D5 LCD 4Bit |
' PD6 ---->--|D6 HD44780  |
' PD7 ---->--|D7 2x16Chr  |
'            |            |
' PB0 ---->--|E / Sys-LED |
' PB1 ---->--|RS          |
'            |____________|
'
' PB2 ---->-- /SS  |
' PB3 ---->-- MOSI | SPI-Bus
' PB4 --<---- MISO |
' PB5 ---->-- SCK  |
'
' PB6 -- XTAL1 | Systemquarz
' PB7 -- XTAL2 | 16,000MHz
'
' ===== PortB =================================================================
' I=7=  I=6=  O=5= I=4= O=3= O=2= O=1= O=0=  => 00101111 => DDRB
' XTAL2 XTAL1 SCK  MISO MOSI /SS   RS   E    => 00010000 => PORTB (init)
'   |     |    |    |    |    |    |    |
'
Ddrb = &B0010_1111
Portb = &B0001_0000

' ===== PortD =================================================================
' O=7= O=6= O=5= O=4= I=3= I=2= O=1= I=0=  => 11110010 => DDRD
' LCD7 LCD6 LCD5 LCD4 INT1 INT0 TxD  RxD   => 00001101 => PORTD (init)
'   |    |    |    |    |    |    |    |
'
Ddrd = &B1111_0010
Portd = &B0000_1100

... sonst verwickelst du dich früher oder später bei der Programmierung.

4. Mach mal als erstes ne Endlosschleife ans Ende (Mainloop, Hauptschleife, ... wie auch immer man sie nennen will). Ich mache zusätzlich noch ne 8Bit oder 16Bit-Variable als Schleifenzähler rein für irgendwelche Testaufgaben oder was weiß ich noch. Also so ...
Code:
Dim Loopcount As Word
Loopcount = 0
' ###############################################
' ##### Hauptschleife Start #####################
' ###############################################
Do

...
...

Incr Loopcount

Loop
' ###############################################
' ##### Hauptschleife Ende ######################
' ###############################################

Wenn du schon Interrupts reinpackst, dann vergiß wenigstens nicht die ISRs (Interrupt Service Routinen) hinter die Hauptschleife zu packen. Sonst bekommst du entweder Compilerfehler weil deine Labels für die angegebenen Interruptvektoren (zB ... On Ovf0 Tim0_isr) nicht existieren oder dein Atmel springt in den Interruptvektor und findet da die ersten Befehle deines Hauptprogramms und rennt Amok. Also wenn du etwas reinpackst, dann mach es so das es komplett drin ist und nicht nur einen Teil davon.

Sieh dir mal die Struktur und die ganzen Bemerkungen im folgenden Programm an ...
Code:
' ####################################################
' ##### Zisternensensor mit AVR ATtiny2313 ###########
' ####################################################
' (c) 26.06.2012 by Dino
'
' Frequenzmessung und Temperaturmessung fuer
' Zisternenanzeige (Fuellstand und Innentemperatur)
' BASCOM 2.0.7.3
' 69% Flash used
' File: Zisternensensor_Tiny2313_v3.bas
'
'Hardware:  PD5/T1 : Oszillatoreingang
'           PD4    : 1Wire-Sensor DS18S20 (Temperatur)
'           PD0/RxD: Kommandos empfangen 1k2 8n1
'           PD1/TxD: Daten senden 1k2 8n1
'
' e = Mess-Ende
' a = Mess-Anfang

' Stecker Pin 1+2 = Sensor, heißes Ende (Osc)
' Stecker Pin 3+G = Sensor, kaltes Ende (GND)

' RJ45 Pin 1  = ws/or ------- TxD
' RJ45 Pin 2  = or    - GND
' RJ45 Pin 3  = ws/gn ------- RxD
' RJ45 Pin 4  = bl    - GND
' RJ45 Pin 5  = ws/bl ---- +UB
' RJ45 Pin 6  = gn    - GND
' RJ45 Pin 7  = ws/bn ---- +UB
' RJ45 Pin 8  = bn    ---- +UB
' RJ45 Schirm = Draht - GND

' Prozessor ATtiny2313
$regfile = "ATtiny2313.DAT"
' Systemtakt von 20MHz (externer Quarz)
$crystal = 20000000

$hwstack = 48
$swstack = 8
$framesize = 28
$noramclear




' ####################################
' ##### DEFINITION DER VARIABLEN #####
' ####################################
'
' Array fuer den 1Wire-Sensor
Dim Ds18s20(9) As Byte                                      ' Array fuer Scratchpad

' Variablen fuer DS18S20 Temperatur
Dim Ds_count As Byte                                        ' Zaehler fuer Scratchpad bearbeiten                                 '
Dim Deg_lo As Byte                                          ' unteres Temperaturbyte
Dim Deg_hi As Byte                                          ' oberes Temperaturbyte

' Variablen fuer Frequenzmessung
Dim Ticks As Word                                           ' Zaehler fuer Messinterfall in 1ms-Ticks
Dim Cnt_lo As Byte                                          ' Wert des Low-Bytes vom 16Bit-Timer 1
Dim Cnt_hi As Byte                                          ' Wert des High-Bytes vom 16Bit-Timer 1
Dim Cnt_ovf As Word                                         ' Wert vom 16-Bit Ueberlaufzaehler fuer 16Bit-Timer 1
Dim T1ovf As Word                                           ' 16-Bit Ueberlaufzaehler fuer 16Bit-Timer 1

Dim Temp As Byte                                            ' Temporaere Byte-Variable fuer alles moegliche
Dim Tmpchr As Byte                                          ' Temporaere Variable fuer ein Byte



' ################################
' ##### DEFINITION DER PORTS #####
' ################################
'
' DDR  =>  0-Bit = Eingang / 1-Bit = Ausgang
' PORT =>  0-Bit = PullUp aus / 1-Bit = PullUp an (bei Eingang)


' PD0 -------<---- UART RxD | UART
' PD1 --------->-- UART TxD | TTL-Pegel
' PD2/INT0 --
' PD3/INT1 --
' PD4/T0 ----<->-- 1Wire-Bus (Timer0 = 8Bit)
' PD5/T1 ----<---- Mess-Oszillator (Timer1 = 16Bit)
' PD6/ICP1 --
'
' ===== PortD =================================================================
' I=7= I=6= I=5= I=4= I=3= I=2= O=1= I=0=  => 00000010 => DDRD
' ---- ----  T1  1Wir ---- ---- TxD  RxD   => 11111101 => PORTD (init)
'  |    |    |    |    |    |    |    |
'
Ddrd = &B0000_0010
Portd = &B1111_1101


' PB0 --
' PB1 --
' PB2 --
' PB3 --
' PB4 --
' PB5/SDA -------- MOSI |
' PB6 ------------ MISO | ISP-Port
' PB7/SCL -------- SCK  |
'
' ===== PortB =================================================================
' I=7= I=6= I=5= I=4= I=3= I=2= I=1= I=0=  => 00000000 => DDRB
' ISP  ISP  ISP  ---- ---- ---- ---- ----  => 11111111 => PORTB (init)
'  |    |    |    |    |    |    |    |
'
Ddrb = &B0000_0000
Portb = &B1111_1111


' PA0 -- XTAL1 | Systemquarz
' PA1 -- XTAL2 | 20,000MHz
' PA2 -- RESET
'
' ===== PortA =================================================================
' I=7= I=6= I=5= I=4= I=3= I=2= I=1= I=0=  => 00000000 => DDRA
' ---- ---- ---- ---- ---- Rst  XTl1 XTl2  => 11111111 => PORTA (init)
'  |    |    |    |    |    |    |    |
'
Ddra = &B0000_0000
Porta = &B1111_1111




' ===== UART (TTL) initialisieren =============================================
Config Com1 = 1200 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
' Config Serialin = Buffered , Size = 4                       ' Buffer kostet wertvolles SRAM
Open "com1:" For Binary As #1
' Clear Serialin                                              ' Braucht man ohne Buffer auch nicht


' ===== 1Wire-Bus DS18S20 Temperatursensor ====================================
Config 1wire = Portd.4


' ===== Timer Initialisieren ==================================================
Config Timer0 = Timer , Prescale = 256                      ' Timer0 liefert die Messzeit (1sec)
On Ovf0 Tim0_isr

Config Timer1 = Counter , Edge = Falling , Prescale = 1     ' Timer1 zaehlt die Eingangstakte
On Ovf1 Tim1_isr

Enable Timer0                                               ' Timer starten
Enable Timer1                                               ' Timer starten

Waitms 300                                                  ' kleine Wartezeit

Print #1 , "00000000000000000000000000"                     ' Startmeldung ueber UART senden

Waitms 100                                                  ' nochmal etwas warten

Temp = 0                                                    ' Flag Auf "Messung läuft nicht" setzen
' Temp 0 = Messung läuft nicht
'      1 = Messung läuft
'      2 = Mesungen abgeschaltet

' ###############################################
' ##### Hauptschleife Start #####################
' ###############################################
Do


  ' Damit man mit dem "Wait 1100" nicht unnoetig Zeit verbrennt habe ich das Messende nun ueber ein Flag
  ' anzeigen lassen. Nun kann man waehrend der Messzeit auch noch was anderes machen.
  If Temp = 0 Then                                          ' Test ob die Messung zu Ende ist
    ' Frequenz-Messung ist zu Ende

    Gosub Ds18s20_temp                                      ' 1Wire Temperatur abfragen (vom letzten Messzyklus)
    Gosub Ds18s20_mess                                      ' 1Wire Messung starten - der Chip arbeitet alleine weiter

    ' Uebertragung der Daten ueber UART (1k2 8n1) im Hexformat mit crlf (0D 0A) als Endmarke
    ' gesamt : 13 Byte => 26 Chr in Hex ... + Ende-Zeichen crlf (0d 0a)
    ' Wegen der besseren Debug-Moeglichkeit ueber ein Terminal habe ich mich gegen die Binaeruebertragung
    ' entschieden. Die Gegenstelle liest dann die Daten ueber ...
    ' INPUTHEX [" prompt" ] , var[ , varn ]
    ' ... in numerische Variablen ein. Ueber das CRLF als Zeilenende ist die Trennung der Datentelegramme
    ' gegenueber Binaertelegrammen auch einfacher.

    '    __LSB
    '  //  __MSB       __CntRemain     uuuu = Userdefined Bytes im EEPROM
    ' || //          //  __Cnt/deg     ffff = Reserved Bytes (FF FF)
    ' ||||          || //  __CRC
    ' llmm uuuuffff |||| cc  _________Freq
    ' AA00 4B46FFFF 0C10 87 DBD9E53F
    ' 3200 4B46FFFF 0E10 FA 00045946  <=== Leerzeichen im Texteditor eingefuegt um die
    ' 3200 4B46FFFF 0D10 AF 000459DD       Lesbarkeit der Datentelegramme zu verbessern
    ' Ready
    ' AA00 4B46FFFF 0C10 87 000459DD
    ' 3200 4B46FFFF 0D10 AF 000459DA
    ' 3200 4B46FFFF 0D10 AF 000459D6

    ' === Ohne eingefügte Leerzeichen (so kommt es ueber die Leitung) ===
    ' Ready
    ' AA004B46FFFF0C1087DBD9E537
    ' 34004B46FFFF0F10AD00045B12
    ' 34004B46FFFF0F10AD00045B79
    ' 34004B46FFFF0E106900045B72

    ' Daten des Temperatursensors (Scratchpad des DS18S20) ausgeben (9 Byte => 18Cht r in Hex)
    For Ds_count = 1 To 9
'      Printbin #1 , Ds18s20(ds_count);                      ' Scratchpad auf UART ausgeben
      Print #1 , Hex(ds18s20(ds_count));                    ' Scratchpad auf UART als HEX ausgeben
    Next

    ' 32Bit Frequenzmessung ausgeben (4 Byte => 8Chr in Hex)
    Temp = High(cnt_ovf)
'    Printbin #1 , Temp;                                     ' Frequenzmessung auf UART ausgeben (Bits 31-24)
    Print #1 , Hex(temp);                                   ' Frequenzmessung auf UART als HEX ausgeben (Bits 31-24)
    Temp = Low(cnt_ovf)
'    Printbin #1 , Temp;                                     ' Frequenzmessung auf UART ausgeben (Bits 23-16)
'    Printbin #1 , Cnt_hi ; Cnt_lo                           ' Frequenzmessung auf UART ausgeben (Bits 15-0)
    Print #1 , Hex(temp);                                   ' Frequenzmessung auf UART als HEX ausgeben (Bits 23-16)
    Print #1 , Hex(cnt_hi) ; Hex(cnt_lo)                    ' Frequenzmessung auf UART als HEX ausgeben (Bits 15-0)

    Temp = 1                                                ' Temp als Flag nutzen : Messung noch nicht fertig
    ' ----- Frequenz-Messung starten -----
    Ticks = 0                                               ' Timer0-Ticks initialisieren
    Enable Interrupts                                       ' Interrupts für Frequenzmessung anschalten
    ' Waitms 1100                                             ' Die Frequenzmessung sollte nach 1,1sec beendet sein.
                                                             ' und damit die Interrupts auch wieder abgeschaltet (siehe ISR)


  Elseif Temp = 1 Then                                      ' Die Messung laeuft noch

    Tmpchr = Ischarwaiting(#1)
    If Tmpchr = 1 Then
      Tmpchr = Inkey(#1)
      If Tmpchr = &H65 Then                                 ' Test auf "e"
        ' ===== Messungen ausschalten ===== Character "e" (ende)
        Disable Interrupts
        Temp = 2
        ' Senden "EE EE EE EE EE EE EE EE EE EE ...."
        Print #1 , "EEEEEEEEEEEEEEEEEEEEEEEEEE"             ' 26xE als Mess-Ende
      End If
    End If

  Else                                                      ' Messung ist ausgeschaltet

    Tmpchr = Ischarwaiting(#1)
    If Tmpchr = 1 Then
      Tmpchr = Inkey(#1)
      If Tmpchr = &H61 Then                                 ' Test auf "a"
        ' ===== Messungen einschalten ===== Character "a" (anfang)
        Waitms 300                                          ' kleine Wartezeit
        Disable Interrupts
        Temp = 1
        ' Senden "AA AA AA AA AA AA AA AA AA AA ...."
        Print #1 , "AAAAAAAAAAAAAAAAAAAAAAAAAA"             ' 26xA als Mess-Anfang
        Gosub Ds18s20_mess                                  ' 1Wire Messung starten - der Chip arbeitet alleine weiter
        ' ----- Frequenz-Messung starten -----
        Ticks = 0                                           ' Timer0-Ticks initialisieren
        Enable Interrupts                                   ' Interrupts für Frequenzmessung anschalten
        '                                                     ' Die Frequenzmessung sollte nach 1 sec beendet sein.
                                                              ' und damit die Interrupts auch wieder abgeschaltet (siehe ISR)
      End If
    End If

  End If


Loop
' ###############################################
' ##### Hauptschleife Ende ######################
' ###############################################




' ============================================
' ===== Sub fuer DS18S20 Messung starten =====
' ============================================
Ds18s20_mess:
  ' ===== Befehlsbytes =====
  ' SEARCH ROM [F0h]
  ' READ ROM [33h]
  ' MATCH ROM [55h]
  ' SKIP ROM [CCh]
  ' ALARM SEARCH [ECh]
  ' CONVERT T [44h]
  ' WRITE SCRATCHPAD [4Eh]
  ' READ SCRATCHPAD [BEh]
  ' COPY SCRATCHPAD [48h]
  ' RECALL E2 [B8h]
  ' READ POWER SUPPLY [B4h]
  1wreset                                                   ' 1Wire-Bus zuruecksetzen
  1wwrite &HCC                                              ' Alle 1Wire-Devices ansprechen
  1wwrite &H44                                              ' Temperaturmessung starten
Return




' ================================================
' ===== Sub fuer DS18S20 Temperatur einlesen =====
' ================================================
Ds18s20_temp:
  ' ===== Scratchpad =====
  ' 1. Byte 0 - Temperature LSB
  ' 2. Byte 1 - Temperature MSB
  ' 3. Byte 2 - TH Register or User Byte 1 <-> TH Register or User Byte 1
  ' 4. Byte 3 - TL Register or User Byte 2 <-> TL Register or User Byte 2
  ' 5. Byte 4 - Reserved (FFh)
  ' 6. Byte 5 - Reserved (FFh)
  ' 7. Byte 6 - COUNT REMAIN
  ' 8. Byte 7 - COUNT PER deg
  ' 9. Byte 8 - CRC8
  ' ===== Seriennummer / ROM-Code =====
  ' 8-BIT CRC , 48-BIT SERIAL NUMBER , 8-BIT FAMILY CODE (10h)
  ' ===== Temperaturberechnung =====
  ' After reading the scratchpad, the TEMP_READ value is obtained
  ' by truncating the 0.5°C bit (bit 0) from the temperature data
  ' TEMPERATURE = TEMP_READ - 0,25 + ( COUNT_PER_C - COUNT_REMAIN ) / COUNT_PER_C
  '
  1wreset                                                   ' 1Wire-Bus zuruecksetzen
  1wwrite &HCC                                              ' Alle 1Wire-Devices ansprechen
  1wwrite &HBE                                              ' Scratchpad einlesen

  Ds18s20(1) = 1wread(9)                                    ' diese Version spart etwas Flash (85% zu 87%)
'  For Ds_count = 1 To 9
'    Ds18s20(ds_count) = 1wread()                            ' Scratchpad in Array uebertragen
'  Next

  ' die naechsten 4 Zeilen brauch ich eigentlich nicht wenn ich sowieso immer das ganze Scratchpad sende
  ' dann kann auch der empfangende ATmega die CRC pruefen.
  If Ds18s20(9) = Crc8(ds18s20(1) , 8) Then                 ' Wenn CRC8 korrekt dann Temperaturwerte sichern
    Deg_lo = Ds18s20(1)                                     ' Temperatur LSB
    Deg_hi = Ds18s20(2)                                     ' Temperatur MSB
  End If

Return




' ================================================
' ===== ISR fuer Timer0 Overflow =================
' ================================================
' Timer0 ist das Gate fuer die Frequenzmessung
Tim0_isr:
  Timer0 = 178                                              ' Initialisierung fuer 1ms Takt (Prescaler 256)
  Incr Ticks                                                ' 1ms-Ticks zaehlen
  If Ticks = 1 Then                                         ' beim ersten Tick ...
    Timer1 = 0                                              ' Timer1 fuer Taktzaehlung initialisieren
    T1ovf = 0                                               ' und Timer1-Ueberlaufszaehler auf 0
  End If
  If Ticks = 1001 Then                                      ' 1sec Messzeit ist vorbei -> Werte sichern
    Cnt_lo = Tcnt1l                                         ' Frequenz LSB (Byte 1)   - Timer1 LowByte
    Cnt_hi = Tcnt1h                                         ' Frequenz     (Byte 2)   - Timer1 HighByte
    Cnt_ovf = T1ovf                                         ' Frequenz MSW (Byte 3+4) - Timer1-Ueberlaufszaehler
    Disable Interrupts
    Temp = 0                                                ' Temp als Flag nutzen : Messung ist jetzt fertig
  End If
Return




' ================================================
' ===== ISR fuer Timer1 Overflow =================
' ================================================
' Timer1 ist der Zaehler fuer die Frequenzmessung
Tim1_isr:
  Incr T1ovf                                                ' Ueberlauf vom 16Bit-Timer (Byte3+4) bearbeiten
Return




' ###############################################
' ##### Programm Ende ###########################
' ###############################################
Close #1
End

' - - - - - - - - - - - - - - - - S C H L U S S - - - - - - - - - - - - - - - - - - -

Grundsätzlich baut man ein Programm grob in der Reihenfolge im Quelltext so auf ...

  • Beschreibung des Projektes (Was soll es sein, Datum, Version, Zusatzinfos)
  • Definitionen für den Compiler (CPU-Typ, Frequenz, Stack, ...)
  • Initialisierung von allem (die 4 Sub-Punkte)
    • Variablendefinition und Initialisierungswerte setzen
    • IO-Ports initialisieren (die Standard-Funktionen)
    • IO-Ports initialisieren (die erweiterten Funktionen)
    • externe Geräte initialisieren (LCD, RTC, ...)
  • Die Interrupts möglichst spät vor der Hauptschleife aktivieren (möglichst direkt davor)
  • Hauptschleife mit Sprüngen in die einzelnen Subroutinen und Grundfunktionen
  • ISRs (Interruptsserviceroutinen) also die SUBs die durch die Interruptvektoren angesprungen werden
  • die normalen SUBs die aus der Hauptschleife angesprungen werden
  • Daten, Tabellen, Felder, ...
  • Testroutinen und Restmüll

Eventuell kann man noch den einen oder anderen Teil der Liste in der Reihenfolge vertauschen. Grundsätzlich hat man aber am Anfang erstmal die Initialisierung, dann die Hauptschleife und danach die Subroutinen.

Und mach genügend Bemerkungen rein warum du was gemacht hast. Man muß nicht jeden Fitzel mit einer Bemerkung versehen. Es sollte jedoch schnell erkennbar sein warum man da irgendein Bit setzt oder irgendwas abfragt oder ...

Gruß
Dino
 

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