und schrittweise durchgehen...
mit "Step into Code".
"Memory-Window" aktivieren, und dort den SRAM anzeigen lassen.
Als erstes fällt auf, daß Bascom den gesamten SRAM mit 0x00 initialisiert, was im Simulator 'ne weile braucht. Über den Sinn kann man sich streiten - ob da nun 0x00 oder 0xFF oder irgendwas zufälliges steht; im allgemeinen sind es eh nicht die zu erwartenden Bytes, initialisiert man die verwendeten Variablen eh selbst.
Man kann Bascom per Direktive anweisen, das ganze zu unterlassen: nach den anderen Direktiven in Zeile 6 also
$NORAMCLEAR
Ok, für das grundsätzliche Init braucht der Simulator trotzdem etwas Zeit, irgendwann (nach 3157808 Takten) ist jedenfalls Zeile 11 erreicht, wo die ID des Sensors im SRAM abgespeichert wird (zeigt Bascom in einem Rutsch an, im Hintergrund wird natürlich jedes der acht Bytes einzeln abgelegt (8*3=24 Takte))
DSID wurde in Zeile 9 dimensioniert, und zwar als ByteArray mit 48 Bytes. Was heißt das?
Bascom allokiert "irgendwo" im SRAM (konkret bei Adresse 0x0100 beginnend) 48 Bytes Speicher, DSID ist ein Zeiger auf diese Speicheradresse, ein Griff dran...
(und zwar bis Adresse 0x012F, ich hatte den Code so von Dir übernommen, ich brauche natürlich nur acht der 48 Bytes, egal...)
Dasselbe geschieht dann in Zeile 54 mit dem Testdatensatz identisch (final würde 1wread entsprechende Daten liefern, und in AR1() ablegen, für AR1 wurden in Zeile 19 neun Bytes allokiert, Bascom hat den entsprechenden Griff also an Speicherzelle 0x135 "dranngeschraubt".
Nach der Ausführung von Zeile 54 also:
Das Least Significant Byte der Testdaten ist also 0x31, das Most Significant Byte ist 0x00, oder als 16bit Zahl 0x0031, und zwar unter Beachtung des Vorzeichens -> Integer.
0x0031 entspricht dezimal 49. Da ein Bit für ein halbes Kelvin steht, entspricht das also 24,5°C.
Außerdem ist hier das Least Significant Bit auch gesetzt 0x0031 entspricht &B0000_0000_0011_000
1 (ein halbes Kelvin halt, sehr schön...-> folgt gleich).
Auf die folgende CRC-Prüfung gehe ich hier nicht ein, das könnte bei 1wread mit quasi_null_Aufwand miterledigt werden, wird aber von Bascom leider nicht so gemacht. (Mir juckts in den Fingern, die Leseroutinen aus der mcs.lib in eine neue Bibliothek zu kopieren und modifizieren).
Ok...
Was sollen die Zeilen 58 und 59?
Das letzte Bit steht für halbe Kelvin, einen (gerundeten) Nachkommaanteil also, und der soll ja jetzt genauer berechnet werden, und deswegen willst Du ihn da raus bekommen, soweit klar.
Aber was machst Du genau?
Das LSByte wird in eine neue Speicherzelle (0x013E) kopiert, mittels bitweisem logischen AND werden die oberen sieben Bits wegmaskiert, anschließend prüfst Du, ab das Ergebnis 'ne eins ist, ist das der Fall, wird das LSByte dekrementiert.
Also nochmal:
Wenn das Bit gesetzt ist, wird es am Ende dekrementiert, also genau dieses Byte auf null gesetzt.
Und wenn es nicht gesetzt ist/war? Dann wird nichts gemacht. Aber wenn es nicht gesetzt war, kann es vorher nur "0" gewesen sein, also ist in allen Fällen hinterher das letzte Bit "0".
Dann kannst Du es also auch ohne jegliche Prüfung (zehn Takte weniger) einfach löschen:
Reset Ar1(1).0
Was macht Makeint?
Die Inhalte der beiden Bytevariablen AR1(1) und AR1(2) werden in die Integervariable T1 kopiert, nach zehn Takten also in T1 dasselbe wie in AR1(1:2):
Mal vorsichtig gefragt:
Brauchst Du die Originalen Werte in AR1(1:2) noch für irgendwas?
Warum nicht gleich dort/mit denen weiterrechnen?
Statt für T1 neuen Speicher (0x013F..0x0140) zu allokieren, kannst Du den T1-Griff auch einfach an die Speicherzelle(n) von AR1(1:2) (0x0135..0x0136) schrauben lassen. Die Dimensionierung von T1 in Zeile 24 also einfach ändern auf:
Dim T1 As Integer At Ar1(1) Overlay
, und Zeile 60 fliegt auch raus...
Die Zeilen 61..68 entsprechen mehr oder weniger der Formel aus dem Datenblatt, nur daß mit verhundertfachten Werten (also quasi Centigraden) gerechnet wird, um einen Teil der Operationen ganzzahlig durchführen zu können.
Bei T1 wird die verhundertfachung durch Multiplikation mit 50 erreicht, da durch die Halbkelvin-Darstellung bereits verdoppelt wurde.
In dem anderen Thread (den ich anfangs mal verlinkt hatte), hatte ich mir die nötigen Takte mal beispielhaft angesehen, der Rechenweg ist ja exakt derselbe gewesen...
Der ganzzahlige Anteil (also hier die Zeilen 58..67) erforderte damals etwa 715 Takte, wobei die beiden Integerdivisionen (hier 65 und 67) je etwa 280 Takte kosteten. Die Single-Division (hier 68) kostete dann nochmal fast dasselbe: 680 Takte.
Extrem Aufwändig außerdem das fusen des Ergebnisses: 6500 Takte.
Ergibt also folgenden Code:
CodeBox BascomAVR
$regfile = "m128def.dat"
$crystal = 12000000 'Quarzfrequenz festlegen
$hwstack = 100 ' default use 32 for the hardware stack
$swstack = 128 ' default use 10 for the SW stack
$framesize = 288 ' default use 40 for the frame space
$NORAMCLEAR
'Config 1wire = Porte.1 '## eingang Temperaturen
Dim Dsid(48) As Byte 'Sensor-IDs je acht Bytes
'Die ausgelesenden DS1820 Adressen
Dsid(1) = &H10 : Dsid(2) = &Hc0 : Dsid(3) = &H8f : Dsid(4) = &Ha2 : Dsid(5) = &H03 : Dsid(6) = &H08 : Dsid(7) = &H00 : Dsid(8) = &Hfc
'Die ermittelten und berechneten Temperaturen, wegen der späteren Darstellung als String mittels "Fusing" werden hier zwingend
'Single-genaue Variablen benötigt
Dim Temp1 As Single
'Hier landen die ausgelesenen Bytes des Sensor-Scratchpads.
'LSB, MSB, USER1, USER2, RES1, RES2, CNT_REMAIN, CNT_PER_C, CRC
Dim Ar1(9) As Byte
' (unnötiges) temporäres Hilfsbyte
Dim Tmp1 As Byte
'Hilfsinteger für Temperaturberechnung
Dim T1 As Integer At Ar1(1) Overlay
Dim T2 As Integer
Do
Gosub Temp
'(
1wreset
1wwrite &HCC 'alle Sensoren ansprechen
1wwrite &H44
')
Waitms 300
If Err = 1 Then
Locate 1 , 15 : Lcd "Sensor Fehler "
Else
Locate 1 , 1 : Lcd "T1 "
Lcd Fusing(temp1 , "##.#") ; " "
End If
Loop
End
'-------------------------------------------------------------------------------
Temp:
'(
1wreset
1wwrite &H55
1wwrite Dsid(1) , 8
1wwrite &HBE
Ar1(1) = 1wread(9)
')
'Testdatensatz 24,3125°C
Ar1(1) = &H31 : Ar1(2) = &H00 : Ar1(3) = &H4B : Ar1(4) = &H46 : Ar1(5) = &HFF : Ar1(6) = &HFF : Ar1(7) = &H07 : Ar1(8) = &H10 : Ar1(9) = &H8D
If Ar1(9) = Crc8(ar1(1) , 8) Then
'1wreset
Reset Ar1(1).0
T1 = T1 * 50
T1 = T1 - 25
T2 = Ar1(8) - Ar1(7)
T2 = T2 * 100
T2 = T2 / Ar1(8)
T1 = T1 + T2
T1 = T1 / 10
Temp1 = T1 / 10
End If
Return
Es gibt übrigens Genauigkeitsverluste, Bascom liefert hier statt der erwarteten 24,3125°C 24,2999992...°C
Da die eine Fließkommadivision eh drinn ist, kann man die Formel auch gleich entsprechend umstellen, und bei Fließkomma bleiben.
Alternativ geht auch ganz ohne Fließkomma, aber dann muß auch auf Fusing verzichtet werden...