Alf_Wuffi
20.11.2004, 02:20
Ich bin begeistert. Das ist genau das, was ich gesucht habe. Hatte schon Angst, dass das nie was wird mit dem Funk, nachdem ich hier all die Berichte über Manchester usw gelesen und nur Bahnhof verstanden habe. Kenn die zwar vom Fuball her, aber in diesem Zusammenhang? Nee, das war nichts für mich. Ich wollte schon immer nur etwas mit Print hin und Print zurück... So eine Black-Box, die ich mit einfachen Befehlen beherrschen kann. Genau das ist RN-Funk!
Ich habe hier soviel gelernt - mache diese Mikrocomputer-Dinge erst seit drei Monaten - , möchte ich jetzt auch einen Beitrag leisten. Hier ist der Code zum Senden und Empfangen der Dallas DS 18S20 Temperaturdaten. Hoffe, dass ich nichts vergessen habe, da ich den Code aus einem über 12 KByte großen Projekt ausschneiden musste.
Hardware: RT868F4 an RN-Mega8 als Sendemodul mit dem Dallas dran. Über RS 232 Kabel dreiadrig verbunden. Befindet sich momentan im Keller und sendet munter vor sich hin. 2 Stockwerke drüber ist das RN Control Mega 32 mit RT..empfänger. Ebenfalls mit RS232 verbunden. Hier ist eine Anzeige mit dem SAA 1064 angeschlossen. Dieses Modul fragt alle 12 Sec nach Daten, die er dann beim Sender anfordert.
Das Sendemodul erzeugt alle 5 Sec Messdaten, so dass gewährleistet ist, dass bei der Anfrage auch Daten vorhanden sind.
Hier also der Code:
Sender
' ----------------------------------------------------------------
' Temperatur mit Dallas DS1820,
' mit 0.1 C Auflösung
' ----------------------------------------------------------------
$regfile = "m8def.dat"
$crystal = 7372800 'Quarzfrequenz
$baud = 9600
'***** DS1820 Befehle
Const Read_rom = &H33
Const Skip_rom = &HCC
Const Convertt = &H44
Const Read_ram = &HBE
Const Write_ram = &H4E
Const Copy_ram = &H48
Const Recall_ee = &HB8
Const Read_power = &HB4
Const Match_rom = &H55
Declare Sub 18s20_auslesen
Declare Sub Temperatur
Dim Bd(9) As Byte
Dim I As Byte , Tmp As Byte
Dim Crc As Byte
Dim T As Integer , T1 As Single , Grad As Single
Dim V As Byte
Dim Temp_anzeige As String * 7 , Zeichen As Byte
Dim Temp As Word
Dim Messen As Bit , Empfang As Byte
Config 1wire = Portb.2 ' DS18s20 an Pin b.2
Config Pind.2 = Output
Config Timer1 = Timer , Prescale = 1024
Sende_led Alias Portd.2
On Timer1 Timer_irq
Const Timervorgabe = 29536 '**** 5 sec
Const True = 1
Const False = 0
Enable Timer1
Enable Interrupts
Reset Sende_led
'***** alle 5 sec messen
'***** Temperaturstation sendet ein Zeichen als Signal, dass
'***** er auf die Daten wartet
'***** wenn Befehl "!" kommt senden
Do
If Messen = True Then
Toggle Sende_led
Temperatur
Messen = False
Toggle Sende_led
End If
Zeichen = Inkey()
If Zeichen > 0 Then '***** läuft durch, wenn kein Zeichen
'If Zeichen = 33 Then '***** Ascii für "!"
Temp_anzeige = "A" + Temp_anzeige + "#"
Printbin Temp_anzeige '*** ohne crlf
Waitms 100
'End If
End If
Loop
End
'//////////////////////////////////////////////////////////////////////////////
Sub Temperatur
1wwrite Skip_rom
1wwrite Convertt ' Messung starten
'**** warten bis abgeschlossen
Do
Temp = 1wread()
Loop Until Temp.7 = 1 '***** Bit 8 muss 1 sein!
18s20_auslesen ' 9 bytes einlesen
If Err = 1 Then ' if there is no sensor
'Print "kein Sensor"
Temp_anzeige = "----"
Else
Temp_anzeige = Fusing(grad , "##.#" ) '**** um aufzurunden!
End If
End Sub
'//////////////////////////////////////////////////////////////////////////////
Sub 18s20_auslesen
1wreset ' Reset
1wwrite Skip_rom ' Chip ansprechen
1wwrite Read_ram ' Befehl zum Auslesen des Rams
Bd(1) = 1wread(9) ' 9 Bytes lesen
1wreset 'Reset
Temp = Bd(2)
Shift Temp , Left , 8
Temp = Temp + Bd(1)
T = Temp
T = T / 2
Grad = Bd(8) - Bd(7)
Grad = Grad / Bd(8)
Grad = Grad + T
Grad = Grad - 0.25
End Sub
Timer_irq:
Messen = True
Return
Empfänger:
'***** ----------------------------------------------------------------
'***** Thermometer mit DS18S20,
'***** mit 0.1 C Auflösung und CRC-Abfrage
'***** Anzeige mit SAA 1064
' ----------------------------------------------------------------
$regfile = "m32def.dat" ' Mega 32
$baud = 9600
$crystal = 16000000
'$sim
'***** für Anzeige
Const Befbyte = 0
Const Displays = 4
Const Sensoren = 2
Const Digit_dezpunkt = 3 '**** 3. Stelle Dez.Punkt
Const Kontrollbyte = &B00110111 '**** 9 ma Segmentstrom,Mux-Betrieb, alle Digits aktiv
Const Slave = &B01110000 '***** Adr.Pin an GND
'**** Allgemein
Const True = 1
Const False = 0
Const Interrupt_intervall = 3 '***** ca 12 sec
Dim Zeichen As String * 1 , Länge As Byte
Dim Zähler As Byte , Z As Byte
Dim I As Byte , Tmp As Byte
Dim Interrupt_zähler As Byte
'***** SAA64
Dim Saa64_bytes(7) As Byte
Dim Display_zeichen(displays) As String * 1
Dim Funk_anzeige As String * 7
Dim Temp As Word , Wert As Word
'**** für Temperatur
Declare Sub Temperatur_holen
'**** für SAA Anzeige
Declare Sub Schicke_bytes(byval Anz As Byte)
Declare Function Bitmuster_saa1064(byval Digitnr As Byte , Byval Zeichen As String ) As Byte
Declare Sub Wert_anzeigen_saa
Declare Sub Display_zeichen_bilden(byval Beginn As Byte , Byval Ende As Byte , Byval Zeichen As String)
'***** für LEDs
Config Pinc.2 = Output '**** Interrupt-LED
Config Pinc.3 = Output '**** Sende/EmpFANGS-LED
LED_interrupt Alias Portc.2
LED_empfang Alias Portc.3
Const Timervorgabe = 3036 '**** 4 sec
'**** Anzeige mit saa 1064
'**** Beide Pins haben Pullup!!(auf dem RN-Control 1.4)
'**** sonst selbst einsetzen, wichtig
Config Scl = Portc.0
Config Sda = Portc.1
'***** Timer und der Teiler festgelegt
Config Timer1 = Timer , Prescale = 1024
On Timer1 Timer_irq
'**** am Anfang aus, dann kann durch toggle an aus gemacht werden
Set Led_interrupt
Set Led_empfang
Enable Timer1
Enable Interrupts
Do
If Interrupt_zähler = Interrupt_intervall Then '**** 12 sec
Interrupt_zähler = 0
'****** Interrupt-LED an
Toggle LED_interrupt
Temperatur_holen
'****** Interrupt-LED aus
Toggle LED_interrupt
End If
Loop
End
'//////////////////////////////////////////////////////////////////////////////
Sub Temperatur_holen
'***** sende Anforderung
Zeichen = "!"
Printbin Zeichen
Waitms 100
Toggle LED_empfang
'**** Temperatur empfangen mit Inputbin
'**** Klasse Befehl!, sehr schnell und roblemlos, ohne crlf
'**** Bytefolge: A-Grad-#
'**** Länge ist unterschiedlich!
'**** passt aber alles, weil dimensioniert mit 7 Bytes
Inputbin Funk_anzeige
Länge = Len(funk_anzeige)
If Left(funk_anzeige , 1) = "A" Then
If Right(funk_anzeige , 1) = "#" Then
Länge = Länge - 2
Funk_anzeige = Mid(funk_anzeige , 2 , Länge)
Else
Funk_anzeige = "FFFF"
End If
Else
Funk_anzeige = "FFFF"
End If
'***** verzögern, sonst sieht man nicht das Flackern
Waitms 300
Toggle LED_empfang
'***** Aufbereitung der Zeichen für die 4stellige Anzeige
'***** sehr aufwändig, um die Blanks vor den Ziffern hinzubekommen
'***** auch das Minus-Zeichen muss sitzen
Display_zeichen_bilden 1 , 4 , Funk_anzeige
Wert_anzeigen_saa
End Sub
'//////////////////////////////////////////////////////////////////////////////
Sub Schicke_bytes(byval Anz As Byte)
I2cstart
For Zähler = 1 To Anz
I2cwbyte Saa64_bytes(zähler)
Next
I2cstop
Waitms 10
End Sub
'//////////////////////////////////////////////////////////////////////////////
Sub Wert_anzeigen_saa
Saa64_bytes(1) = Slave
Saa64_bytes(2) = Befbyte
Saa64_bytes(3) = Kontrollbyte '**** wird von LDR gesteuert!
For Z = 1 To Displays
Saa64_bytes(z + 3) = Bitmuster_saa1064(z , Display_zeichen(z))
Next
Schicke_bytes 7
End Sub
'//////////////////////////////////////////////////////////////////////////////
Sub Display_zeichen_bilden(byval Beginn As Byte , Byval Ende As Byte , Byval Zeichen As String * Displays )
Local Temp_zeichen As String * 1
'**** erst Array löschen
For Z = Beginn To Ende
Display_zeichen(z) = ""
Next
'***** rückwärts den TempWert durchgehen
Zähler = Ende
For Z = Len(zeichen) To 1 Step -1
Temp_zeichen = Mid(zeichen , Z , 1)
'*** nur wenn kein Dez.Punkt, übernehmen
If Temp_zeichen <> "." Then
Display_zeichen(zähler) = Temp_zeichen
Decr Zähler
End If
Next
'**** fehlende Zeichen sind nun leere Strings!!!
End Sub
'//////////////////////////////////////////////////////////////////////////////
Function Bitmuster_saa1064(byval Digitnr As Byte , Byval Zeichen As String * 1 ) As Byte
Local Segmente As Byte
Select Case Zeichen
Case "0"
Segmente = &B00111111
Case "1"
Segmente = &B00000110
Case "2"
Segmente = &B01011011
Case "3"
Segmente = &B01001111
Case "4"
Segmente = &B01100110
Case "5"
Segmente = &B01101101
Case "6"
Segmente = &B01111101
Case "7"
Segmente = &B00000111
Case "8"
Segmente = &B01111111
Case "9"
Segmente = &B01101111
Case "-"
Segmente = &B01000000
Case "" '**** leer
Segmente = &B00000000
Case Else
Segmente = &B01110001 '**** F
End Select
If Digitnr = Digit_dezpunkt Then
'***** oberstes Bit auf 1
Segmente = Segmente Or 128
End If
Bitmuster_saa1064 = Segmente
End Function
'//////////////////////////////////////////////////////////////////////////////
Timer_irq:
Timer1 = Timervorgabe
Incr Interrupt_zähler
Return
Das Ganze läuft jetzt seit über 24 Stunden. Habe noch keinen einzigen Aussetzer auf dem Display entdeckt. An den Funkboards wurde nichts eingestellt, verstellt. Es war wirklich so: Strom und Datenkabel dran, funktionierte auf Anhieb.
Wolfgang
Ich habe hier soviel gelernt - mache diese Mikrocomputer-Dinge erst seit drei Monaten - , möchte ich jetzt auch einen Beitrag leisten. Hier ist der Code zum Senden und Empfangen der Dallas DS 18S20 Temperaturdaten. Hoffe, dass ich nichts vergessen habe, da ich den Code aus einem über 12 KByte großen Projekt ausschneiden musste.
Hardware: RT868F4 an RN-Mega8 als Sendemodul mit dem Dallas dran. Über RS 232 Kabel dreiadrig verbunden. Befindet sich momentan im Keller und sendet munter vor sich hin. 2 Stockwerke drüber ist das RN Control Mega 32 mit RT..empfänger. Ebenfalls mit RS232 verbunden. Hier ist eine Anzeige mit dem SAA 1064 angeschlossen. Dieses Modul fragt alle 12 Sec nach Daten, die er dann beim Sender anfordert.
Das Sendemodul erzeugt alle 5 Sec Messdaten, so dass gewährleistet ist, dass bei der Anfrage auch Daten vorhanden sind.
Hier also der Code:
Sender
' ----------------------------------------------------------------
' Temperatur mit Dallas DS1820,
' mit 0.1 C Auflösung
' ----------------------------------------------------------------
$regfile = "m8def.dat"
$crystal = 7372800 'Quarzfrequenz
$baud = 9600
'***** DS1820 Befehle
Const Read_rom = &H33
Const Skip_rom = &HCC
Const Convertt = &H44
Const Read_ram = &HBE
Const Write_ram = &H4E
Const Copy_ram = &H48
Const Recall_ee = &HB8
Const Read_power = &HB4
Const Match_rom = &H55
Declare Sub 18s20_auslesen
Declare Sub Temperatur
Dim Bd(9) As Byte
Dim I As Byte , Tmp As Byte
Dim Crc As Byte
Dim T As Integer , T1 As Single , Grad As Single
Dim V As Byte
Dim Temp_anzeige As String * 7 , Zeichen As Byte
Dim Temp As Word
Dim Messen As Bit , Empfang As Byte
Config 1wire = Portb.2 ' DS18s20 an Pin b.2
Config Pind.2 = Output
Config Timer1 = Timer , Prescale = 1024
Sende_led Alias Portd.2
On Timer1 Timer_irq
Const Timervorgabe = 29536 '**** 5 sec
Const True = 1
Const False = 0
Enable Timer1
Enable Interrupts
Reset Sende_led
'***** alle 5 sec messen
'***** Temperaturstation sendet ein Zeichen als Signal, dass
'***** er auf die Daten wartet
'***** wenn Befehl "!" kommt senden
Do
If Messen = True Then
Toggle Sende_led
Temperatur
Messen = False
Toggle Sende_led
End If
Zeichen = Inkey()
If Zeichen > 0 Then '***** läuft durch, wenn kein Zeichen
'If Zeichen = 33 Then '***** Ascii für "!"
Temp_anzeige = "A" + Temp_anzeige + "#"
Printbin Temp_anzeige '*** ohne crlf
Waitms 100
'End If
End If
Loop
End
'//////////////////////////////////////////////////////////////////////////////
Sub Temperatur
1wwrite Skip_rom
1wwrite Convertt ' Messung starten
'**** warten bis abgeschlossen
Do
Temp = 1wread()
Loop Until Temp.7 = 1 '***** Bit 8 muss 1 sein!
18s20_auslesen ' 9 bytes einlesen
If Err = 1 Then ' if there is no sensor
'Print "kein Sensor"
Temp_anzeige = "----"
Else
Temp_anzeige = Fusing(grad , "##.#" ) '**** um aufzurunden!
End If
End Sub
'//////////////////////////////////////////////////////////////////////////////
Sub 18s20_auslesen
1wreset ' Reset
1wwrite Skip_rom ' Chip ansprechen
1wwrite Read_ram ' Befehl zum Auslesen des Rams
Bd(1) = 1wread(9) ' 9 Bytes lesen
1wreset 'Reset
Temp = Bd(2)
Shift Temp , Left , 8
Temp = Temp + Bd(1)
T = Temp
T = T / 2
Grad = Bd(8) - Bd(7)
Grad = Grad / Bd(8)
Grad = Grad + T
Grad = Grad - 0.25
End Sub
Timer_irq:
Messen = True
Return
Empfänger:
'***** ----------------------------------------------------------------
'***** Thermometer mit DS18S20,
'***** mit 0.1 C Auflösung und CRC-Abfrage
'***** Anzeige mit SAA 1064
' ----------------------------------------------------------------
$regfile = "m32def.dat" ' Mega 32
$baud = 9600
$crystal = 16000000
'$sim
'***** für Anzeige
Const Befbyte = 0
Const Displays = 4
Const Sensoren = 2
Const Digit_dezpunkt = 3 '**** 3. Stelle Dez.Punkt
Const Kontrollbyte = &B00110111 '**** 9 ma Segmentstrom,Mux-Betrieb, alle Digits aktiv
Const Slave = &B01110000 '***** Adr.Pin an GND
'**** Allgemein
Const True = 1
Const False = 0
Const Interrupt_intervall = 3 '***** ca 12 sec
Dim Zeichen As String * 1 , Länge As Byte
Dim Zähler As Byte , Z As Byte
Dim I As Byte , Tmp As Byte
Dim Interrupt_zähler As Byte
'***** SAA64
Dim Saa64_bytes(7) As Byte
Dim Display_zeichen(displays) As String * 1
Dim Funk_anzeige As String * 7
Dim Temp As Word , Wert As Word
'**** für Temperatur
Declare Sub Temperatur_holen
'**** für SAA Anzeige
Declare Sub Schicke_bytes(byval Anz As Byte)
Declare Function Bitmuster_saa1064(byval Digitnr As Byte , Byval Zeichen As String ) As Byte
Declare Sub Wert_anzeigen_saa
Declare Sub Display_zeichen_bilden(byval Beginn As Byte , Byval Ende As Byte , Byval Zeichen As String)
'***** für LEDs
Config Pinc.2 = Output '**** Interrupt-LED
Config Pinc.3 = Output '**** Sende/EmpFANGS-LED
LED_interrupt Alias Portc.2
LED_empfang Alias Portc.3
Const Timervorgabe = 3036 '**** 4 sec
'**** Anzeige mit saa 1064
'**** Beide Pins haben Pullup!!(auf dem RN-Control 1.4)
'**** sonst selbst einsetzen, wichtig
Config Scl = Portc.0
Config Sda = Portc.1
'***** Timer und der Teiler festgelegt
Config Timer1 = Timer , Prescale = 1024
On Timer1 Timer_irq
'**** am Anfang aus, dann kann durch toggle an aus gemacht werden
Set Led_interrupt
Set Led_empfang
Enable Timer1
Enable Interrupts
Do
If Interrupt_zähler = Interrupt_intervall Then '**** 12 sec
Interrupt_zähler = 0
'****** Interrupt-LED an
Toggle LED_interrupt
Temperatur_holen
'****** Interrupt-LED aus
Toggle LED_interrupt
End If
Loop
End
'//////////////////////////////////////////////////////////////////////////////
Sub Temperatur_holen
'***** sende Anforderung
Zeichen = "!"
Printbin Zeichen
Waitms 100
Toggle LED_empfang
'**** Temperatur empfangen mit Inputbin
'**** Klasse Befehl!, sehr schnell und roblemlos, ohne crlf
'**** Bytefolge: A-Grad-#
'**** Länge ist unterschiedlich!
'**** passt aber alles, weil dimensioniert mit 7 Bytes
Inputbin Funk_anzeige
Länge = Len(funk_anzeige)
If Left(funk_anzeige , 1) = "A" Then
If Right(funk_anzeige , 1) = "#" Then
Länge = Länge - 2
Funk_anzeige = Mid(funk_anzeige , 2 , Länge)
Else
Funk_anzeige = "FFFF"
End If
Else
Funk_anzeige = "FFFF"
End If
'***** verzögern, sonst sieht man nicht das Flackern
Waitms 300
Toggle LED_empfang
'***** Aufbereitung der Zeichen für die 4stellige Anzeige
'***** sehr aufwändig, um die Blanks vor den Ziffern hinzubekommen
'***** auch das Minus-Zeichen muss sitzen
Display_zeichen_bilden 1 , 4 , Funk_anzeige
Wert_anzeigen_saa
End Sub
'//////////////////////////////////////////////////////////////////////////////
Sub Schicke_bytes(byval Anz As Byte)
I2cstart
For Zähler = 1 To Anz
I2cwbyte Saa64_bytes(zähler)
Next
I2cstop
Waitms 10
End Sub
'//////////////////////////////////////////////////////////////////////////////
Sub Wert_anzeigen_saa
Saa64_bytes(1) = Slave
Saa64_bytes(2) = Befbyte
Saa64_bytes(3) = Kontrollbyte '**** wird von LDR gesteuert!
For Z = 1 To Displays
Saa64_bytes(z + 3) = Bitmuster_saa1064(z , Display_zeichen(z))
Next
Schicke_bytes 7
End Sub
'//////////////////////////////////////////////////////////////////////////////
Sub Display_zeichen_bilden(byval Beginn As Byte , Byval Ende As Byte , Byval Zeichen As String * Displays )
Local Temp_zeichen As String * 1
'**** erst Array löschen
For Z = Beginn To Ende
Display_zeichen(z) = ""
Next
'***** rückwärts den TempWert durchgehen
Zähler = Ende
For Z = Len(zeichen) To 1 Step -1
Temp_zeichen = Mid(zeichen , Z , 1)
'*** nur wenn kein Dez.Punkt, übernehmen
If Temp_zeichen <> "." Then
Display_zeichen(zähler) = Temp_zeichen
Decr Zähler
End If
Next
'**** fehlende Zeichen sind nun leere Strings!!!
End Sub
'//////////////////////////////////////////////////////////////////////////////
Function Bitmuster_saa1064(byval Digitnr As Byte , Byval Zeichen As String * 1 ) As Byte
Local Segmente As Byte
Select Case Zeichen
Case "0"
Segmente = &B00111111
Case "1"
Segmente = &B00000110
Case "2"
Segmente = &B01011011
Case "3"
Segmente = &B01001111
Case "4"
Segmente = &B01100110
Case "5"
Segmente = &B01101101
Case "6"
Segmente = &B01111101
Case "7"
Segmente = &B00000111
Case "8"
Segmente = &B01111111
Case "9"
Segmente = &B01101111
Case "-"
Segmente = &B01000000
Case "" '**** leer
Segmente = &B00000000
Case Else
Segmente = &B01110001 '**** F
End Select
If Digitnr = Digit_dezpunkt Then
'***** oberstes Bit auf 1
Segmente = Segmente Or 128
End If
Bitmuster_saa1064 = Segmente
End Function
'//////////////////////////////////////////////////////////////////////////////
Timer_irq:
Timer1 = Timervorgabe
Incr Interrupt_zähler
Return
Das Ganze läuft jetzt seit über 24 Stunden. Habe noch keinen einzigen Aussetzer auf dem Display entdeckt. An den Funkboards wurde nichts eingestellt, verstellt. Es war wirklich so: Strom und Datenkabel dran, funktionierte auf Anhieb.
Wolfgang