Sie sind hier: Home » Zentraler SE » Programm zSE » Prg zSE

'*******************************************************************************
'**************   Zentraler Sende/Empfangspunkt mit ATmega328P    **************
'**************         und dem Funkmodul RFM12 (5V)              **************
'*******************************************************************************

'name                     : ZSE_v0.5.bas
'copyright                : (c) 07.07.2017 jep
'purpose                  : Zentraler S/E-Punkt mit Protokoll via SW-SPI
'micro                    : Atmel328P
'
'Changelog:               : V0.2 mit neuer LEN-Definition
'                         : V0.3 mit neuer TWI-Interruptroutine (aus Internet)
'                         : V0.4 aufgeräumt
'                         : V0.5 weiter aufgeräumt, kleine Tests
'offene Probleme          :
'-------------------------------------------------------------------------------

'Bemerkung: Es wird mit einem Temperatursensor gearbeitet.

'Bei der Adressfestlegung bei mehreren Sensoren ist die Adresse des Sensors nicht bekannt.
'Man weiss deshalb nicht, welcher Sensor welcher ist, wenn man sie einfach anschliesst.
'Das Programm sucht mit 1wsearchfirst und gibt die Adresse über den seriellen Port aus.
'


' HF-Tx-Protokoll:

'                       1    2    3    4    5    6    7         x   y
'                    +----+----+----+----+----+----+----+----+----+----+
'                    |              Ausgangsbytes            |    |    |
'+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
'| AA | AA | 2D | D4 |LEN |DAB |SAB |CDB |  Data1  | n Data  |CRC2|CRC1|
'+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
'
'============================================================================================================

$regfile = "m328Pdef.dat"
$crystal = 16000000                                         '16MHz-Oszillator
$hwstack = 80
$swstack = 80
$framesize = 100
$baud = 19200

$include "MyTWIj.bas"

Declare Sub Twi_show_state(byref State As Byte)

Declare Sub Rfm12_init
Declare Function Decigrades(byval Sc(9) As Byte) As Integer
Declare Function Spitransfer(byval Dataout As Word) As Word
Declare Sub Twi_init_slave

'################################## ADRESSEN  ##################################
'                                                                             ##
Dim Zse_adresse As Byte                                     '                 ##
Zse_adresse = 5                                             'ist fix          ##
Dim Zentralenadresse As Byte                                '                 ##
Zentralenadresse = 85                                       'ist fix          ##'                                                                             ##
'###############################################################################


'================  Atmel328P als SPI MASTER und TWI-Slave  =====================

A0 Alias Pinc.0
Config A0 = Input
Set Portc.0
A1 Alias Pinc.1
Config A1 = Input
Set Portc.1
A2 Alias Pinc.2
Config A2 = Input
Set Portc.2
A3 Alias Pinc.3
Config A3 = Input
Set Portc.3
Ledg Alias Portb.0                                          'grüne LED
Config Ledg = Output
Set Portb.0
Ledr Alias Portb.1                                          'rote LED
Config Ledr = Output
Set Portb.1


'======================== SPI des ATmega328P ====================================

Ss Alias Portb.2
MISO Alias Pinb.4
MOSI Alias Portb.3
Sck Alias Portb.5
Nirq Alias Pind.2                                           'Interrupt-Eingang

Config Ss = Output                                          'Slave select
Config Sck = Output                                         'SCK  ----> SCK (RFM12B)
Config Mosi = Output                                        'MOSI ----> SDI (RFM12B)
Config MISO = Input                                         'MISO <---- SDO (RFM12B)
Config Nirq = Input
Set Portb.2                                                 'Pullup
Portd.2 = 1                                                 'Pullup

'(
'====================== SPI konfigurieren ======================================
Config Spihard = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = Low , Phase = 0 , Clockrate = 64 , Noss = 1 , Spiin = 255
Spiinit

'CONFIG SPI = soft , Din = PinB.4 , Dout = PortB.3 , clock = PortB.5 , SS = PortB.2 , Mode = 1
')

'======================= TWI-Konfiguration, HW-TWI-Bus =========================
                                                            'sie sind HW-mässig festgelegt
'Adressen (es wird IMMER nur geschrieben)
'Zentraler S/E-Punkt im Analyzer: H3B
'Zentrale im Analyzer:            H39

Const TWI_Zentrale = &H72                                   'Write TWI-Addresse der Zentrale (ATmega1284P)
Const TWI_ZSE = &H76                                        'Write TWI-Adresse des ZSE (Atmega328)
Twi_slv_addr = TWI_ZSE                                      'lokale TWI-Adresse

Dim Fehlerstatus as Byte
Dim State_TWI as Byte
Dim TWI_Status as Byte
Dim Timeout as Byte
Dim TWI_merker As Byte
TWI_merker = 0

Dim TWI_Sendedaten(70) As Byte                              'TWI-Sendespeicher (60 Daten, 4 Vor, 2 CRC)
Dim Zaehler as Byte at TWI_Sendedaten(5) Overlay
Zaehler = 0
Dim Bytecount_s As Byte                                     'Index für TWI-Sendespeicher
Bytecount_s = 1                                             'und initialisieren

Dim TWI_Empfangsdaten(70) As Byte                           'TWI-Empfangsspeicher (60 Daten, 4 Vor, 2 CRC)
Twi_sr_data = Varptr(TWI_Empfangsdaten(1))                  'Pointer auf Datenbuffer Empfang
Dim Bytecount_e As Byte                                     'Index für TWI-Empfangsspeicher
Bytecount_e = 1                                             'und initialisieren
Dim Total_TWI As Byte                                       'TWI, zu übertragende Anzahl Bytes

Twar = Twi_slv_addr + 1                                     'TWI Adress + GCA
Config Twi = 200000                                         'TWI Speed
On Twi Twi_mst_slv_isr , Nosave                             'ISR für TWI


'===================== ADC für Betriebsspanung messen ======================

Config Adc = Single , Prescaler = Auto , Reference = Internal_1.1
Const Adc_multiplier = 5.75964                              ''(1.1 * 1470) /(1024.0 * 270) * 1000

Dim Adcwert As Word                                         'Wandlerwert
Dim Betriebsspannung As Single                              'Betr_spg siehe bei 1-Wire Konfiguration


'============= Timerinterupt für Zeitbegrenzung Interruptempfang einstellen =================
Config Timer0 = Timer , Prescale = 1024
Const Timer0_preload = 255 -(8 * 16000000 / 4800 * 1024)    'für 2 Bytes: gilt für 16 MHz und 4800 Baud
On Timer0 Timer0_irq                                        'beim Interrupt Empfang stoppen
Enable Timer0                                               'Timer0 Interrupt freigeben
Stop Timer0


'==========================  Zeit-Konfiguration  ===============================
$external _soft_clock                                       'Dieser Befehl bindet den Code der Original-Uhrenroutine ein

Config Clock = User                                         'Teilt dem Compiler mit, daß eine eigene Uhrenroutine verwendet wird
                                                            'Die internen Variablen _hour, _min, _sec, _day, _month, _year werden erzeugt
Const _sectic = 0                                           'Keine Sectic Sub verwenden

Config Date = Dmy , Separator = .                           'Datum auf deutsches Format einstellen

Config Timer1 = Timer , Prescale = 256 , Clear Timer = 1    'Clear Timer setzt Timer1 bei Erreichen des Comparewertes auf 0 zurueck
Const Ctc_value =(_xtal / 256) - 1                          'Berechnen des Compare-Wertes, bei dem Timer1 zuruecksetzt
Compare1a = Ctc_value                                       'Comparewert setzen
Enable Compare1a                                            'Compare-ISR erlauben
On Compare1a Timer1_clock_isr Nosave                        'Definitition des Labels fuer Timer1 Compare-ISR

Time$ = "20:00:00"                                          'Stellen der Uhrzeit auf einen Initialwert
Date$ = "01.01.17"                                          'Stellen des Datums auf einen Initialwert

Dim Curr_sec As Byte                                        'Hier wird die aktuelle Sekunde gemerkt
Curr_sec = 255                                              'Initialisieren mit einem fuer _Sec nicht vorkommenden Wert
Dim Neue_sekunde As Bit                                     'Flag
Dim Alte_minute As Byte                                     '
Alte_minute = 0
Dim Wochentag As Byte                                       '0..6
Dim Jahr As Byte                                            'für Manipulationen nötig
Dim Monat As Byte                                           'für Manipulationen nötig
Dim Tag As Byte                                             'für Manipulationen nötig
Dim Stunden As Byte                                         'für Manipulationen nötig
Dim Minuten As Byte                                         'für Manipulationen nötig
Dim Sekunden As Byte                                        'für Manipulationen nötig


'=== Hier werden die funkseitig zu SENDENDEN BYTES (max TOTAL 66 möglich) abgelegt ===

'   1     2     3     4     5                           x     y     z
'+-----+-----+-----+-----+-----+   +-----+-----+-----+-----+-----+-----+
'|                           Sendebytes                                |
'+-----+-----+-----+-----+-----+   +-----+-----+-----+-----+-----+-----+
'| LEN | DABs| SABs| CDB |      max. 60 Byte               |  CRCs_16  |
'+-----+-----+-----+-----+-----+   +-----+-----+-----+-----+-----+-----+

Dim Sendebytes(70) As Byte


'=== Hier werden die funkseitig zu EMPFANGENDEN BYTES (max TOTAL 66 möglich) abgelegt ===

'                       1    2    3    4    5    6    7    8    9   10                max 66
'                    +----+----+----+----+----+----+----+----+----+----+----+----+----+----+
'                    |                  IRQ_Empfangsbytes / Empfangsbytes                  |
'+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
'| AA | AA | 2D | D4 |LENe|DABe|SABe|CDBe| D1 | D2 | D3 | D4 | D5 | .. | Dx | Dy |CRC2|CRC1|
'+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
'                    |    |                                                                |
'                    |    |<------------ LEN = Anzahl Daten und CRC OHNE LEN  ------------>|
'                    |<--------------- Totale Anzahl zu empfangende Bytes ---------------->|

Const Maxanzahlempfangsbytes = 70                           'Datenmenge (maximal total 66 Byte)
Dim Irq_anzahlempfangsbytes As Byte                         'Zähler für die empfangenen Bytes
Dim Empfangsbytes(maxanzahlempfangsbytes) As Byte           'Empfangspuffer nach Empfang
Dim Irq_empfangsbytes(maxanzahlempfangsbytes) As Byte       'Empfangspuffer während Empfang
Dim Lene As Byte At Empfangsbytes(1) Overlay                'Längenbyte
Dim Irq_anzahlbytemax as Byte
Dim Irq_Akt_byte As Byte
Dim Funkdaten_vorhanden As Bit

Config Int0 = Falling
On Int0 Rfm_funkirq
Enable Int0


'=========================== 1-Wire Konfiguration ==============================
Config 1wire = Portd.7                                      '1-Wire-Port bei Version 2
'Config 1wire = Portd.6                                      '1-Wire-Port bei Version 1

Dim Dg As Integer                                           'DECIgrades, I call it, cause I have no space for commas on the display....
Dim Degr As Single                                          'zur Darstellung umgewandelt
Dim B As Byte
Dim I As Byte

Dim Temp_id1(8) As Byte                                     'Sensor 1 Adresse 64 bits incl CRC
Dim Sc(9) As Byte                                           'Scratchpad 0-8 72 bits incl CRC für die Daten
Dim Messintervall as Byte
Messintervall = 1
Dim Mi As Byte
Mi = Messintervall

'   1     2     3     4     5     6     7     8     9    10    11    12
'+-----+-----+-----+-----+-----+-----+-----------+-----+-----+-----+-----+
'|                                Sendebytes TA                          |
'+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
'|LENs |DABs |SABs |CDBs | Temperatur|  Feuchte  | Betr.Spg  |  CRC_16s  |
'+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
'                                                            |CRC_h|CRC_l|
'                                                            +-----+-----+

Dim Ta(12) As Byte
Dim Lens As Byte At Ta(1) Overlay                           'Längenbyte
Lens = 11                                                   'Datenmode, fix 12 Bytes Daten - 1 (LEN)
Dim Dabs As Byte At Ta(2) Overlay                           'Adresse an den die Daten geschickt werden (DAB)
Dabs = Zentralenadresse                                     'Zentralenadresse ist 85
Dim Sabs As Byte At Ta(3) Overlay                           'eigene Adresse (SAB)
Sabs = Zse_adresse
Dim Cdbs As Byte At Ta(4) Overlay                           'Kommandobyte fix
Cdbs = &B00100000                                           'Datenmode, ohne ACK
Dim Temp_daten1 As Integer At Ta(5) Overlay
Dim Feuchte As Integer At Ta(7) Overlay                     'Platzhalter für Feuchte
Feuchte = &HAAAA                                            'Dummywert
Dim Betr_spg As Word At Ta(9) Overlay
Dim Crc_16s As Word At Ta(11) Overlay                       'CRC16
Dim Paketzaehler As Byte
Paketzaehler = 0

Dim Temp As Byte
Dim D As Word
Dim M As Byte
Dim N As Byte
Dim R As Word
Dim X As Byte                                               'wird im Interrupt genutzt
'________________________________________

Const Printerausgabe = 1                                    '1 = Printerausgabe; 0 = keine Ausgabe
Const LED_anzeigen = 1                                      '1 = schaltet die LED; 0 = ohne LED


'_______________________________________________________________________________

'                              ***************
'                     **********************************
'          ********************************************************
'*******************************************************************************
'***************************** PROGRAMMSTART ***********************************
'*******************************************************************************

Programmstart:

Enable Interrupts
Print
Print
Print "File: " ; Version(3)
Print

'Temperatur-Sensor suchen und Adresse seriell ausgeben

Temp_id1(1) = 1wsearchfirst()                               'sucht die Adresse des 1. Temp.Bausteins
Print "1Wire-Adresse ID1: " ;
For I = 1 To 8
    Print Hex(temp_id1(i)) ; " " ;
Next I
Print
Print
Gosub Twi_sense                                             'Aktivieren Slave-Funktion

Ss = 1
Sck = 0
Rfm12_init                                                  'RFM12B initialisieren
waitms 5

Irq_akt_byte = 0
Funkdaten_vorhanden = 0
Eifr.intf0 = 1                                              'Eventuell anstehenden Interrupt löschen

'Auf neue Anfangssequenz warten
r = Spitransfer(&H82c8)                                     'Empfänger aktivieren
r = Spitransfer(&Hca83)                                     'FIFO einstellen/aktivieren

Enable Interrupts

     Print "Start"
     Print


'###############################################################################
'##############################   Hauptprogramm   ##############################
'###############################################################################

Do
'-------------------
' Sekunde nachführen
'-------------------

   If Curr_sec <> _sec Then                                 'Sec-Tick nachführen
      Curr_sec = _sec
      If Alte_minute <> _min Then
         Gosub Mintic
         Alte_minute = _min
      End If
   End If

'------------------------------------------------------------------------
' Ergebnis als Slave auswerten;   Vorsicht, der Bus ist solange blockiert
'------------------------------------------------------------------------

   If Twi_slv_flag <> 0 Then
      Select Case Twi_slv_flag
         Case &H60
            #if Printerausgabe = 1
               Print "SLAVE recv"
            #endif
            Total_TWI = TWI_Empfangsdaten(1) + 1
            If Total_TWI <> Twi_sr_cntr then                'Soll und Ist stimmen nicht überein
               Twi_slv_flag = 0                             'löschen marker
               Twi_slv_stat = 0                             'löschen marker
               Gosub Twi_sense                              'alles wieder enablen und Bus freigeben
               goto Ende1
            end if
            If TWI_Empfangsdaten(2) = TWI_ZSE Then
               Twi_slv_flag = 0                             'löschen marker
               Twi_slv_stat = 0                             'löschen marker
               Gosub Twi_sense                              'alles wieder enablen und Bus freigeben
               gosub Fuer_zse                               'für den ZSE
             else
               D = Memcopy(TWI_Empfangsdaten(1) , Sendebytes(1) , Total_TWI)       'alles andere zum Funk-Sendepuffer umkopieren
               Twi_slv_flag = 0                             'löschen marker
               Twi_slv_stat = 0                             'löschen marker
               Gosub Twi_sense                              'alles wieder enablen und Bus freigeben
               Gosub Funk_transfer                          'und umkopierte Daten senden
            end if
         Case &HA8
            #if Printerausgabe = 1
               Print
               Print "SLAVE tran:"                          'es ist was abgeholt worden
            #endif
         Case &H70
            #if Printerausgabe = 1
               Print
               Print "SLAVE GCA :"                          'ein General Call ist gekommen
            #endif
         Case Else:
            #if Printerausgabe = 1
               Print Chr(7) ;                               'Irgendein Fehler
               Call Twi_show_state(twi_slv_flag)            'Print status-text
            #endif
      End Select
      #if Printerausgabe = 1
          Print
      #endif
      Twi_slv_flag = 0                                      'löschen marker
      Twi_slv_stat = 0                                      'löschen marker
      Gosub Twi_sense                                       'alles wieder enablen und Bus freigeben
   End If

   '-------------------------------------
' Ergebnis vom Funkempfänger auswerten
'-------------------------------------

   If Funkdaten_vorhanden = 1 Then                          'vom Funk sind Daten vorhanden
      #if LED_anzeigen = 1
         Ledr = 0                                           'rote LED ein
      #endif
      Total_TWI = Empfangsbytes(1) + 1                      'LENe dazuzählen damit alles übertragen wird

      #if Printerausgabe = 1
         Print "vom Funk: ";
         For M = 1 To Total_TWI
             Print Hex(Empfangsbytes(m)) ; " " ;
         Next M
         Print
      #endif

      D = Memcopy(empfangsbytes(1) , TWI_Sendedaten(1) , Total_TWI)       'zum TWI-Sendepuffer umkopieren
      Funkdaten_vorhanden = 0                               'Merker löschen
      Gosub Master_transmit                                 'und an die Zentrale weiterleiten
      Gosub Twi_sense                                       'nachher wieder aktivieren der Slave-Funktion
      waitms 1
      #if LED_anzeigen = 1
         LEDr = 1                                           'rote LED aus
      #endif
   End If

   Ende1:

Loop

'###############################################################################
'###############################################################################
'###############################################################################


'*******************************************************************************
'********************* Alles was einmal pro Minute abläuft ********************

Mintic:
   #if Printerausgabe = 1
      Print Time$
   #endif
   Mi = Mi - 1                                              'Messintervallzeit decrementieren
   If Mi = 0 Then
      Mi = Messintervall
      Gosub Temperaturmessung                               'Messungen durchführen
      Adcwert = Getadc(7)                                   'Wandlerwert als Word
      Betriebsspannung = Adcwert * Adc_multiplier           'als Single konvertieren und multiplizieren
      Betr_spg = Betriebsspannung                           'zum Senden wieder in ein Word umwandeln
      Crc_16s = Crc16(Ta(1) , 10)                           'CRC16 rechnen über 10 Bytes
      Total_TWI = 12                                        'es sind total 12 Bytes über TWI zu senden
      D = Memcopy(Ta(1) , TWI_Sendedaten(1) , Total_TWI)    'zum TWI-Sendepuffer umkopieren

      #if Printerausgabe = 1
         Print "vom ZSE:  ";
         for I = 1 to 12
            Print Hex(Ta(i)) ; " " ;
         next i
         Print
      #endif

      Gosub Master_transmit                                 'und los
      Gosub Twi_sense                                       'nachher wieder aktivieren der Slave-Funktion
   End If
Return


'*******************************************************************************
'*******************************************************************************

'===================== Alles was den ZSE betrifft ==============================

Fuer_zse:                                                   'hier die entsprechende Aktion ausführen
                                                            'zum Beispiel Zeit übertragen
Return

'===============================================================================

'****************************** Temperaturmessung ******************************

Temperaturmessung:                                          'die Temperaturmessung anstossen (Konvertierung starten)

   #if Printerausgabe = 1
      Print "1-W Messung"
      Print
   #endif
   1wreset                                                  '1-Wire-Bus zurücksetzen
   1wwrite &HCC                                             'Adressrom´s überspringen
   1wwrite &H44                                             'Temperaturkonverion für alle anstossen
   Wait 1                                                   'Konvertierzeit
   1wverify Temp_id1(1)                                     '1. Sensor, sendet "Match ROM "
   If Err = 1 Then                                          'Error = 1: Fehler aufgetreten
      Temp_daten1 = 9999                                    'damit die Stelle nicht leer bleibt
    Else                                                    'Sensor hat geantwortet
      1wwrite &HBE
      Sc(1) = 1wread(9)                                     '9 Bytes in Array einlesen
      If Sc(9) = Crc8(sc(1) , 8) Then                       'CRC-Check
         If Temp_id1(1) = &H10 Then                         '1. Byte bestimmt Family Code; hier 18S20
            Temp_daten1 = Decigrades(sc(9))                 'Umwandlung in ein Integer-Word (-32768...32767) zum abspeichern
            #if Printerausgabe = 1
               Print "---> Sensor ist 18S20"
            #endif
         End If
         If Temp_id1(1) = &H28 Then                         '1. Byte bestimmt Family Code; hier 18B20
            Temp_daten1 = Makeint(sc(1) , Sc(2))            'Umwandeln in Integerwert,
            Temp_daten1 = Temp_daten1 * 10                  'und
            Temp_daten1 = Temp_daten1 / 16                  'Umrechnung in ein Integer-Word (-32768...32767) zum abspeichern
            #if Printerausgabe = 1
               Print "---> Sensor ist 18B20"
            #endif
         End If
      Else
          Temp_daten1 = 9999                                'damit bei CRC-Fehler die Stelle nicht leer bleibt
      End If
   End If
Return

'----------------------------------------------------------

Function Decigrades(byval Sc(9) As Byte)
   Dim Tmp As Byte , T1 As Integer , T2 As Integer

   Tmp = Sc(1) And 1                                        '0.1C Genauigkeit, Bit 0 ausmaskieren
   If Tmp = 1 Then Decr Sc(1)                               'wenn 1 dann 1 abziehen
   T1 = Makeint(sc(1) , Sc(2))                              'Umwandeln in Integerwert, Anzahl 1/2° (Temp-Schritt ist 0.5°C)
   T1 = T1 * 50                                             'x50, da 1/100°-Schritte
   T1 = T1 - 25                                             'gemäss DS18S20 data sheet 0.25(*100) abziehen
   T2 = Sc(8) - Sc(7)
   T2 = T2 * 100
   T2 = T2 / Sc(8)
   T1 = T1 + T2
   Decigrades = T1 / 10
End Function


'###############################################################################

'==================== Sendet das Datenpaket über Funk ==========================
'Die Senderoutine ist für Polling des Senders geschrieben,
'es wird gewartet bis ein Byte gesendet ist!

Funk_transfer:

   D = Spitransfer(&H8238)                                  'Enable Transmitter; enable Synthesizer ;enable Crystal Osc
   Gosub Rfm12_warten
   D = Spitransfer(&Hb8aa)
   Gosub Rfm12_warten
   D = Spitransfer(&Hb8aa)
   Gosub Rfm12_warten
   D = Spitransfer(&Hb82d)
   Gosub Rfm12_warten
   D = Spitransfer(&Hb8d4)
   For N = 1 To Sendebytes(1)
      Gosub Rfm12_warten
      D = &HB800 + Sendebytes(n)                            'Daten senden
      D = Spitransfer(d)
   Next N
   Gosub Rfm12_warten
   D = Spitransfer(&Hb8aa)                                  'Dummy
   Gosub Rfm12_warten
   D = Spitransfer(&Hb8aa)                                  'Dummy
   Gosub Rfm12_warten
   D = Spitransfer(&H82d9)                                  'Sender aus, Empfänger ein
Return

Rfm12_warten:
   Ss = 0
   Do
    Print "l"
   Loop Until MISO = 1
   Ss = 1
Return

'_______________________________________________________________________________

'*****************  Interrupt vom Funkmodul RFM12B  ****************************

Rfm_funkirq:

   Disable Int0
   Timer0 = Timer0_preload
   Start Timer0                                             'Start Zeitüberwachung                                         'Empfangsinterrupt-Ueberwachung starten
   Incr Irq_akt_byte                                        'aktueller Bytezähler erhöhen (Startwert ist 0)
   Irq_empfangsbytes(irq_akt_byte) = Spitransfer(&Hb000)    'Empfangsbyte holen und abspeichern
   If Irq_akt_byte = 1 Then
      Irq_anzahlbytemax = Irq_empfangsbytes(1) + 1          'im ersten Byte steht die Anzahl folgender Datenbytes
   End If
   If Irq_akt_byte = Irq_anzahlbytemax Then                 'max. Anzahl Bytes erreicht
       Stop Timer0
       R = Memcopy(irq_empfangsbytes(1) , Empfangsbytes(1) , Irq_anzahlbytemax)       'umkopieren
       Funkdaten_vorhanden = 1                              'Merker setzen
       Irq_akt_byte = 0                                     'Bytezähler löschen
       R = Spitransfer(&Hca81)                              'FIFO FILL zurücksetzen
       R = Spitransfer(&Hca83)                              'FIFO FILL aktivieren
       Eifr.intf0 = 1                                       'Eventuell anstehenden Interrupt löschen
   End If
   Enable Int0
Return

Timer0_irq:
   Stop Timer0                                              'Interrupt-Ueberwachung ausgelaufen --> Stop
   Irq_akt_byte = 0                                         'Bytezähler löschen
   Funkdaten_vorhanden = 0                                  'Eventuellen Merker löschen
   R = Spitransfer(&Hca81)                                  'FIFO FILL zurücksetzen
   R = Spitransfer(&Hca83)                                  'FIFO FILL aktivieren
   Eifr.intf0 = 1                                           'Eventuell anstehenden Interrupt löschen
   #if Printerausgabe = 1
      Print "Timeout"
   #endif
Return

'_______________________________________________________________________________

' Initialisiere Funkmodul

Sub Rfm12_init
    Local Wert As Word
    Local E As Word
    Local D As Word
    E = 0
    Restore Datainit3                                       'Initialisierungsfolge
    Do
      Read Wert
      D = Spitransfer(wert)
      Incr E
    Loop Until Wert = 0
    Waitms 10
End Sub


'###############################  TWI Senden  ##################################

Master_transmit:

   Twi_mst_addr = TWI_Zentrale                              'TWI Zieladresse (Zentrale)
   Twi_mt_cntr = TWI_Sendedaten(1) + 1                      'S_Puffer(1) beinhaltet die Länge-1
   Twi_mt_data = Varptr(TWI_Sendedaten(1))                  'Daten-Adresse
   Twi_mr_cntr = 0                                          'danach kein Empfang
   Gosub Run_wait_master                                    'und los
Return

Run_wait_master:
      Gosub Mst_start                                       'Aufruf
      Select Case Twi_mst_flag                              'Ergebnis ?
         Case Twi_m_sent:                                   'gesendet
            #if Printerausgabe = 1
               Print "nach TWI: ";
               For Temp = 1 To Twi_mt_cntr
                  Print Hex(TWI_Sendedaten(temp)) ; " " ;
               Next
               Print : Print
            #endif
         Case Twi_m_recv:                                   'abgeholt; keine Aktion
         Case Else:                                         'irgendein Problem
            Call Twi_show_state(twi_mst_flag)
            Print
      End Select
      Twi_mst_flag = 0
Return


'_______________________________________________________________________________

'################################ Timer Interruptroutine #######################

Timer1_clock_isr:

 !jmp _soft_clock                                           'Ruft Bascom's Uhrenroutine auf
Return                                                      'Nur vorhanden, damit es huebscher aussieht, dieses Return wird aber nie verwendet

Getdatetime:                                                'Um Bascom's Routinen zum Stellen der Uhr, wie Time$ = ... verwenden zu koennen,
Return                                                      'muessen folgende Label als leere Subs vorhanden sein

Settime:
Return

Setdate:
Return

'_______________________________________________________________________________

' ************ Hilfsfunktionen zur Kommunikation mit Funkmodul **************
'_______________________________________________________________________________


Function Spitransfer(byval Dataout As Word) As Word         'SW-Version

   Local Nspi As Integer
   Local DMOSI As Integer
   Local DMISO As Word

   sck = 0                                                  'Clock beginnt mit 0
   ss = 0                                                   'RFM12 einschalten = 0
   DMISO = 0
   For Nspi = 1 To 16                                       '16 Bit
       DMOSI = Dataout And &H8000                           'höchstwertiges Bit maskieren
       If DMOSI = 0 Then                                    'und über  Ausgang
           MOSI = 0                                         'MOSI ausgeben
       Else
           MOSI = 1
       End If
       Dataout = Dataout * 2                                'Ausgabe um 1 Bit schieben
       DMISO = DMISO * 2                                    'Eingangsbyte schieben
       DMISO = DMISO + MISO                                 'und mit Eingangsbit verknüpfen
       sck = 1
       Waitus 2                                             'Clockpuls
       sck = 0
   Next Nspi                                                'nächstes Bit
   ss = 1                                                   'RFM12 ausschalten = 1
   Spitransfer = DMISO
End Function


'(
Function Spitransfer(byval Dataout As Word) As Word         'HW-Version
   Local Dat_in_h As Byte
   Local Dat_in_l As Byte

   Ss = 0
'   sck = 0
'   SPIinit                                                  'Ports setzen (warum auch immer)
   Dat_in_h = Spimove(high(dataout))
   Dat_in_l = Spimove(low(dataout))
   Spitransfer = Makeint(dat_in_l , Dat_in_h)
   Ss = 1
End Function
')
'----------------------------------------


$include "Twi_show_state.bas"


END                                                         ' Programmende

'********************************************************************


'Funkmodul Initialisierungsdaten für 4800 Baud Funkübertragung
Datainit3:
Data &H80E8%                                                ' Enable: 868 Mhz;XTAL cap=12pf; TX-Register; RX-Fifo
Data &H82D9%                                                ' Enable: Receiver; Crystal Osc; Base Band Block; Synthesizer, Disable Low-bat Detector; Transmitter; Wake-Up-Timer; Clock output Pin
Data &HA67C%                                                ' &Ha67c=frequenz 434,15 Mhz oder z.B. &HA538 für 433,34 Mhz
Data &HC647%                                                ' &Hc647=Datenrate '4.8kbps; C623=9600kbps; C611 =19200
Data &H95C0%                                                ' Vdi , Fast , 67 kHz , 0db , -79dbm           !!!!!!!!!!
Data &HC2AD%                                                ' Fiter=Digital; Recover Mode=Auto; Quality Threshold=4; Recovery Speed=Slow
Data &HCA81%                                                ' FIFO INT Level=8; Sync on=2;Fifo Fill Start=Sync; Reset Sensitivity=High; Disable:FIFO Fill Enabled
Data &HC483%                                                ' Enable: AFC Mode; AFC; Frequency Offset Register Disable: High Accuracy; Strobe
Data &H9820%                                                ' Frequenz Shift=POS; Power Out=0 dB; Deviation=45 khz
Data &HE000%                                                ' WakeUp-Timer=0ms
Data &HC800%                                                ' Duty Cycle = Infinity % OFF
Data &HC000%                                                ' Low batterie=2,2V; Clock Pin=1 Mhz
Data &HCED4%                                                ' Synchron Pattern
Data &HCC76%                                                ' PLL Settings
Data &H0000%                                                ' Status lesen, irqs zurückstellen
Data 0%