K-BUS TRanciever Melexis TH3122

ich nutze den internen regulator..
das mit dem Stromsparen ist erstmal egal,.
wie sieht dein eeprom aufbaue jetzt aus ? kannst ohne eeprom datei nich viel testen :D
 
Also mit EN auf Vs. Und die 3 Statuspins hast Du auf irgendwelche Pins des 2313 gelegt - die sollten erstmal tristate bleiben, und nicht behandelt werden(tristate ist default). Du könntest wie gesagt überwachen, bis wann der TH ordentlich angelaufen ist, aber ich sehe den Sinn nicht: entweder er arbeitet noch nicht, dann kommen keine gültigen Telegramme (ungültige interessieren uns nicht), oder es kommen gültige Telegramme (die verarbeitet werden), dann gehe ich davon aus, daß er auch ordentlich arbeitet...
Wenn man auf den Bus schreiben will, muß man natürlich zumindest den SEN/STA mit einbeziehen, hier macht dann auch eine vorherige Kontrolle Sinn, ob der Th dazu überhaupt bereit ist...
Das Eeprom-File würde ich, wie in Beitrag #66 angedeutet, durch das AVRstudio erzeugen und brennen lassen. Ich hatte ja vorher den Baum mal dargestellt, inzwischen sind allerdings die Ebenen von Quell-ID und Länge raus - root zeigt sozusagen auf die 5 Ziel-IDs. Der in #66 eingebundene Ausschnitt stellt den Teilbaum von Ziel-ID 0x68 dar (und natürlich die Wurzel selbst), die restlichen 4 Teilbäume fehlen also noch.
Außerdem sind die NEC-Codes (also das jeweilige Datenbyte) da noch unbekannt. Entweder man ersetzt den jeweiligen Text durch das entsprechende Byte, oder (was eleganter ist) man definiert den Text als Compiler-Variable mit dem entsprechenden Wert. Unter Assembler lautet die entsprechende Direktive ".equ" Syntax:
Code:
.equ name=[I]Wert[/I]
wobei Wert hier ein Byte ist (hex-Schreibweise mit 0x??) - Das erzeugt so keinen Code, beim Compilieren wird der Name dann immer durch den wert ersetzt (wie auch bei den label-Adressen).
Zum Testen: Habe auch noch keinen Weg gefunden, ein vorhandenes Eeprom-File in den Bascom-Simulator einzubringen - scheint also auf "In-System-Debugging" bzw Simulation mit dem echten Controller über ein PC-seitiges Terminalprogramm herauszulaufen...

Ich habe inzwischen etwas zu der Timer-ISR und zur UART-RX-ISR geschrieben, die Inits von Timer und UART muß ich mangels Datenblatt im Kopf nochmal durchgehen - und das dann alles mal eintippen... bisher ist das nur mit Bleistift auf ein paar A4-Seiten gekliert, während der Bahnfahrten...
Und die Auswerteroutine im Hauptprogramm - deren Ablauf ist grob in #68 beschrieben.

jaja... ich fahr den Laptop ja schon hoch...

Edit (13.02. 12:35): die ISR sollten jetzt fertig sein, init von Timer0 muß ich noch durchgehen, Auswertung im main fehlt noch komplett.
Bascom kompilierts erstmal fehlerfrei.
Derzeit bei 528 Bytes Flash.
 
Boah... ist ja mal heftig, wie die Kompilat-Größe durch das Hauptprogramm explodiert ist... sind ja locker 100-150 bytes gewesen...
egal das isses derzeit:
Code:
'(------------------------------------------------------------------------------
Bonze's K-Bus -> NEC Transciever
--------------------------------------------------------------------------------
MCU:  ATtiny2313
Takt: 8MHz intern

--K-Bus--> TH3122 --UART--> Tiny2313 --PWM--> NEC
--------------------------------------------------------------------------------
verwendete Hardware:
   -Timer1 im frequenzkorrektem Fast-PWM
      -ICU1 legt Frequenz fest
      -OCU1A als PWM-Output, IRQ modifiziert ICR1 (genau genommen PPM)
   -UART1
      -RxD für K-Bus-Empfang (IRQ-basiert)
      -TXD für Debugging (ggf später K-Bus-senden)
   -Timer0
      -Überlauf(IRQ) detektiert neues Telegramm, durch reload in RxD unterdrückt

        TH3122               ATtiny2313
    +------------+    +-----------------------+
    |       Sense|--->| ???          Reset(A2)|<------Reset
    |       Reset|--->| ???           MOSI(B5)|<---+    |
    |     SEN/STA|<-->| ???           MISO(B6)|--->+---ISP
<-->|Bus      RxD|--->|RxD(D0)         SCK(B7)|<---+
    |         TxD|<---|TxD(D1)        OC1A(B3)|--->PWM--->NEC
    +------------+    +-----------------------+

freie Pins (PortB=PC-Ints):
   A0=XTAL0    ???
   A1=XTAL1    ???

   B0=AIN0
   B1=AIN1
   B2=(OC0A)
   B4=(OC1B)

   D2=INT0
   D3=INT1
   D4=(T0)
   D5=(OC0B)
   D6=ICP1 (InputCaptureUnit durch frequenzkorrekten PWM belegt)
--------------------------------------------------------------------------------
')
'derzeit wird der UART-Transmitter fürs debugging verwendet, Fehlerbytes:
Const Nec_transmitter_overrun = &H01
Const Nec_crc_error=&H02

$crystal = 8000000
$regfile = "attiny2313.dat"
$hwstack = 25
$swstack = 25
$framesize = 20
Const Debugmode = 1                                         '1=debugmode, 0=normal mode
'****Interruptvektoren****
On Oc1a Oc1a_isr Nosave                                     'Hi->Lo-Flanke vom NEC, Pulslänge wird angepaßt
On Oc0a K_bus_timeout_isr Nosave                            'Timeout für UART
On URXC Uart_recieved_isr Nosave                            'byte empfangen, ggf CRC, BIP, IGN, CRC_OK für main
'****globale Variablen****
'für NEC-Sender
Dim Bitzaehler As Byte                                      'Zählt über NEC gesendete Bits
Dim Adress As Byte                                          'NEC-Empfängeradresse
Dim Kommando As Byte                                        'NEC-Kommando
'für K-Bus-Empfänger
Dim Bytezaehler As Byte                                     ' (restliche) Bytes des Telegrammes
Dim K_rec_buff As Byte                                      'RxD-ISR übergibt Byte hier
Dim Nec_tree_ptr As Byte                                    'zeigt auf aktuellen Knoten im Eeprom
Dim Xnor As Byte                                            'führt CRC-Byte mit
'GPIOR0 wird als universellesFlagRegister verwendet (default alle Bits=0)
Bip Alias Gpior0.0                                          'neues Byte im Puffer
Ign Alias Gpior0.1                                          'Rest-Telegramm ignorieren!
Crc_ok Alias Gpior0.2                                       'CRC-Check war ok
Nec_busy Alias Gpior0.3                                     'der sendet noch
'****************Subs***************
Declare Sub Initnec(byval Zieladresse As Byte)
Declare Sub Sendnec(byval Kommandobyte As Byte)
Declare Sub Initkbus()
Call Initnec(&B10011101)                                    'NEC-Interface mit Adresse initialisieren
Call Initkbus()                                             'K-Bus-Interface initialisieren
Enable Interrupts                                           'Interrupts freigeben
dim temp as  Byte
dim temp2 as byte
'***********Hauptschleife***********
Do
   'Bip pollen, und Bytes im Eeprom suchen, bei CRC_OK korrespondierenden NEC senden********************
   if bip=1 then                                            'neues relevantes Byte?
      bip=0
      readeeprom temp, Nec_tree_ptr                         'NEC-Code laden
      if crc_ok=1 then                                      'CRC_ok?
         call sendnec(temp)                                 'NEC senden
      else
          do
          incr Nec_tree_ptr
            readeeprom temp2, Nec_tree_ptr                   'Knotenwert laden
            incr Nec_tree_ptr                                'zeigt auf Adresse
            if temp2=temp then
               exit do
            end if
            decr temp
            if temp=0 then                                   'nicht gefunden
               ign=1                                         'Ignore-Flag
               exit do
            end if
          loop
      end IF
   end if
Loop

'*****************Subroutinen*******
Sub Initnec(zieladresse As Byte)
   Tccr1a = 2                                               'für normale I/O und WGM=14
   Ocr1a = 17999
   Icr1 = 17999
   Ddrb.3 = 1                                               'PortB.3 (OC1A) ist Ausgang
   Bitzaehler = 38
   Adress = Zieladresse
   Enable Oc1a
End Sub
Sub Sendnec(kommandobyte As Byte)
   If Nec_busy = 1 Then
      #if Debugmode = 1
       Udr = Nec_transmitter_overrun                        'Fehlercode senden(UART)
      #endif
   Else
      Kommando = Kommandobyte                               'zu sendendes CMD übernommen
      Tccr1b = 25                                           'Timer läuft (->IRQs)
      SBI PORTB, PORTB3                                     'Startburst
      #if Debugmode = 1
       Udr = Kommando                                       'NEC-Code (Byte) über UART gesendet
      #endif
      Nec_busy = 1
   End If
End Sub
Sub Initkbus()
   Bytezaehler = 255                                        'beginn eines Telegrammes
   Nec_tree_ptr = 0                                         '->Wurzel
   Xnor = 0
   'Timer0 ->CTC mit IRQ und 1,696ms (OCR0A)
   OCR0A=52
   tccr0a=&b00000010                                        'CTC Mode
   TCCR0B=&b00000100                                        'Timer0 mit Prescaler 256 gestarted
   enable Oc0a                                              'IRQ aktivieren (TIMSK)
   'UART vorbereiten 9600 Baut ,8DB, 1SB, gerade Parität
   sbi UCSRC,upm1                                           'gerade Parität, der Rest ist default
   Ubrrl = 51                                               '9600baud bei 8MHz, U2X=0 Error:0,16%
   #if Debugmode = 0
      Ucsrb = &B10010000                                    'Reciever mit IRQ aktiv
   #else
      Ucsrb = &B10011000                                    'Reciever mit IRQ aktiv, Transmitter ohne
   #endif
End Sub

'*****Interrupt Service Routinen****
K_bus_timeout_isr:
  $asm                                                      'bei Timeout (1,7ms) auf init zurücksetzen
  push r16                                                  'R16->Stack
  LDI r16, 255
  STS {Bytezaehler}, R16                                    'Bytezaehler = 255
  LDI r16, 0
  STS {nec_tree_ptr}, r16                                   'nec_tree-Ptr = 0
  STS {xnor}, r16                                           'XNOR = 0
  CBI GPIOR0, 1                                             'IGN-Flag gelöscht
  pop r16                                                   'R16<-Stack
  $end Asm
Return
Uart_recieved_isr:
  $asm                                                      'empfangenes Byte abholen, auswerten, ggf CRC, Flags für main setzen
  push R16                                                  'R16->Stack
  LDI R16, 0
  Out Tcnt0 , R16                                           'Timer reset
  in r16, UDR                                               'Empfangenes Byte->R16
  SBIC UCSRA, UPE
  SBI GPIOR0, 1                                             'Paritätsfehler -> setze IGN-Flag
  SBIC GPIOR0, 1                                            'IGN gesetzt?
  RJMP rx_isr_restore_R16                                   'dann ignoriere Byte
  PUSH R17                                                  'R17->Stack
  IN R17, SREG
  PUSH R17                                                  'SREG->Stack
  LDS R17, {Bytezaehler}
  PUSH R18                                                  'R18 ->Stack
  LDS R18, {Xnor}
  DEC R17                                                   'decr Bytezaehler
  BRNE notCRC                                               'nur bei Zaehler=0...
  CP R16, R18                                               'CRCcheck
  #if debugmode=0
  BRNE Restore_r18_sreg_r17                                 'CRC-ERROR->nix zu tun
  #else
  brne crcerror
  #endif
  SBI GPIOR0, 0                                             'setze BIP
  SBI GPIOR0, 2                                             'setze CRC_OK
  RJMP Restore_r18_sreg_r17
  #if debugmode=1
 crcerror:
   ldi R16,Nec_crc_error
   out udr, R16                                             'Fehlercode senden
   RJMP Restore_r18_sreg_r17
  #endif
 Notcrc:                                                    '...sonst
  CPI R17, 253                                              'wenn Längenbyte empfangen
  BRNE notlength                                            'dann
  STS {Bytezaehler}, R16                                    'Bytezaehler=neues Byte
  RJMP calccrc
 Notlength:
  BRCS calccrc                                              'wenn Bytezaehler>253 überspringe, sonst...
  STS {K_rec_buff}, R16                                     'neues Byte->Puffer
  STS {Bytezaehler}, R17                                    'Bytezaehler abgespeichert
  SBI GPIOR0, 0                                             'BIP gesetzt
 Calccrc:
  EOR R18, R16                                              'xnor=xnor EOR neues Byte
  STS {Xnor}, R18                                           'XNOR abgespeichert
 Restore_r18_sreg_r17:                                      'R18, SREG, R17 zurückholen
  POP R18
  POP R17
  out sreg, R17
  pop R17
 Rx_isr_restore_r16:                                        'R16 zurückholen
  pop R16
  $end Asm
Return

Oc1a_isr:                                                   'PWM-Frequenz anpassen (PPM)
      $asm                                                  'Assemblerblockanfang
      PUSH XH
      PUSH XL
      PUSH R16
      IN R16, SREG
      PUSH R16                                              'Register und SREG gesichert
      Loadadr Bitzaehler , X                                'X Enthält Bitzaehler -speicheradresse
      LD R16, X                                             'R16=Bitzähler
      DEC R16                                               'R16 dekrementiert
      ST X+, R16                                            'Bitzähler zurückgespeichert, X enthält Adress-Adresse
      BREQ naechstesVorbereiten                             'final wurde gesendet, Sprung (nächstes vorbereiten)
      CPI R16, 34                                           'Z=1 <==> Bitzaehler (jetzt)= 34
      BREQ burstAbschalten                                  'dann springe burstAbschalten
      cpi R16, 33                                           'Z=1<==>Bitzaehler=33
      BREQ pauseEnde                                        'dann -> Pause Ende
      BRSH dasWars                                          '>33->dasWars (0,33,34 wurden bereits behandelt, bleiben die 32 Bits)
      CPI R16, 17                                           'Carry bei den letzten 17 als einem Endburst (R16=0) plus 16  Bits(R16=16..1)
      BRCC AdresseStimmt                                    'sonst überspringe
      inc XL                                                'X =Kommandoadresse

   Adressestimmt:
      LD R16, X
      LSL R16                                               'einmal nach links schieben, MSB wandert ins Carry
      BRCS EinsSenden                                       'bei 1 springe, bei 0 bleibe
      INC R16                                               'links wurde ne 0 rausgeschoben, deswegen wird die 0 hinten zur 1 invertiert
      ST X, R16                                             'Byte zurückgespeichert
      LDI R16, hbyte(8999)
      Out Icr1h , R16
      LDI R16, lbyte(8999)
      Out Icr1l , R16                                       'Icr Angepaßt
      RJMP dasWars                                          'Fall 0 erledigt

   Einssenden:
      ST X, R16                                             'die hinten eingeschobene 0 ist bereits invers zur 1 - Byte zurückgespeichert
      LDI R16, hbyte(17999 )
      Out Icr1h , R16
      LDI R16, lbyte(17999 )
      Out Icr1l , R16                                       'Icr Angepaßt
      RJMP dasWars                                          'Fall 1 erledigt

   Pauseende:
      LDI R16, hbyte(4499)
      Out Ocr1ah , R16
      LDI R16, lbyte(4499)                                  'Ocr wieder Auf 562,5 µs
      Out Ocr1al , R16                                      'wird erst nach dem nächsten TOV aktiv
      LDI R16, 130
      Out Tccr1a , R16                                      'B3 wird PWM (lo->hi beim nächsten TOV)
      RJMP dasWars                                          '->dasWars

   Burstabschalten:
      CBI PORTB, PORTB3                                     'B3 -> lo
      RJMP dasWars                                          '->dasWars

   Naechstesvorbereiten:
      LDI R16 , 24
      Out Tccr1b , R16                                      'Timer Steht
      LDI R16, hbyte(17999)
      Out Ocr1ah , R16
      Out Icr1h , R16
      LDI R16, lbyte(17999)
      Out Ocr1al , R16
      Out Icr1l , R16                                       'Ocr1a Und Icr1 Für Nächsten Start Vorbereitet
      LDI R16, 38
      STS {Bitzaehler},R16                                  'Bitzäehler reinitialisiert (38)
      LDI R16,0
      Out Tcnt1h , R16
      Out Tcnt1l , R16                                      'Timer = 0 (Reload, ggf anpassen)
      LDI R16, 2
      Out Tccr1a , R16                                      'B3 ist wieder I/O

   Daswars:
      POP R16
      Out Sreg , R16
      POP R16
      POP XL
      POP XH                                                'SREG und Register (R16, XH, XL) wiederhergestellt
   $end Asm
   Nec_busy = 0
Return
686 Bytes
Fehlt noch das Eeprom-File. Vielleicht sollte man für den Simulator einen Teil des Baumes "zu Fuß" mit einbauen...
 
Code:
$eeprom
Wurzel:
Data &H03 , &H68 , &H0007 , &HB0 , &H001E , &HC8 , &H0024   '3 kinder, Ibusbyte, unterkat,Ibusbyte, unterkat, Ibusbyte, unterkat,
Lb_68:
Data &H02 , &H32 , &H000C , &H3B , &H0011                   '2 kinder, Ibusbyte, nec , Ibusbyte, nec
Lb_68_32:
Data &H02 , &H11 , &H28 , &H10 , &HA8                       '2 kinder, volup, nec , Ibusbyte, voldown
Lb_68_3b:
Data &H04 , &H01 , &HD0 , &H11 , &HD0 , &H21 , &HFF , &H08 , &HA1 , &H18 , &HFF , &H28 , &HFF       'Nextp , Next1s , Nextre ,  Prev ,  Prev1s , Prevre

Lb_b0:
Data &H01 , &H3B , &H0021                                   '1 kinder, Ibusbyte, unterkat
Lb_bo_3b:
Data &H01 , &H80 , &B00000000                               'anzahl, Ibusbyte, nec

Lb_c8:
Data &H01 , &H3B , &H0027                                   '1 kinder, Ibusbyte, unterkat
Lb_c8_3b:
Data &H01 , &H80 , &HC8                                     'anzahl, Ibusbyte, nec
$data
erzeugt folgende eeprom file,.

in bascom lässt sich nix andres fgescheites erzeugen, anstatt den labels, nutze ich die direkte adresse im eeprom,.
oder muss ich an der stelle des labels, den kompleten inhalt des "labels einfuegen?
"
 

Anhänge

  • eeprom.png
    eeprom.png
    5,9 KB · Aufrufe: 3
In etwa, aber:
  • Du hast natürlich nur einen Teil; root hat in Wirklichkeit 5 Kinder (die 5 Ziel-IDs)
  • 50-04-68-3B hat 6 Kinder, bzw erfordert 6 Vergleiche (Du hast ja auch 6 Werte + 6 Codes= 12 Bytes dazustehen), aber Du hast vorn trotzdem nur 4 angegeben (es werden also nur die ersten 4 Vergleiche abgearbeitet, die letzten beiden Knoten werden nie getroffen)
  • bei 50-04-C8-3B hast Du auch erst den ersten Teilbaum, oder?
  • einige der unterschiedlichen Telegramme führen zu identischen NECs - ist das korrekt?

Wie Du siehst, wird das mit dem Adressen-ausrechnen ganz schön unübersichtlich - leider kenne ich keine Lösung für-mit labeln unter Bascom
Hast Du damit schon mal irgendwas simuliert? (also im Simulator immer ein Byte des Telegrammes in das UDR schreiben, und dann per Hand den RX-Interrupt auslösen - irgendwie so muß das gehen...)
 
Update: 2 Fehler in der UART-RX-ISR gefunden:
-nach dem Dekrementieren des Bytezaehlers muß das Ergebnis natürlich noch in den SRAM zurückgeschrieben werden (auf meinem Zettel steht das... muß ich übersehen haben)
-nach dem Vergleich des Zählers mit 253 sollen natürlich alle Bytes größer als 253 ignoriert werden, das BIP ist bei Zähler kleiner als 253 zu setzen (Zähler = 253 wurde eh separat abgehandelt). Im Prinzip Relationszeichen falschrum. Hatte da BRCS statt BRCC geschrieben.

Hier mal der korrigierte
Code:
'(------------------------------------------------------------------------------
Bonze's K-Bus -> NEC Transciever
--------------------------------------------------------------------------------
MCU:  ATtiny2313
Takt: 8MHz intern

--K-Bus--> TH3122 --UART--> Tiny2313 --PWM--> NEC
--------------------------------------------------------------------------------
verwendete Hardware:
   -Timer1 im frequenzkorrektem Fast-PWM
      -ICU1 legt Frequenz fest
      -OCU1A als PWM-Output, IRQ modifiziert ICR1 (genau genommen PPM)
   -UART1
      -RxD für K-Bus-Empfang (IRQ-basiert)
      -TXD für Debugging (ggf später K-Bus-senden)
   -Timer0
      -Überlauf(IRQ) detektiert neues Telegramm, durch reload in RxD unterdrückt

        TH3122               ATtiny2313
    +------------+    +-----------------------+
    |       Sense|--->| ???          Reset(A2)|<------Reset
    |       Reset|--->| ???           MOSI(B5)|<---+    |
    |     SEN/STA|<-->| ???           MISO(B6)|--->+---ISP
<-->|Bus      RxD|--->|RxD(D0)         SCK(B7)|<---+
    |         TxD|<---|TxD(D1)        OC1A(B3)|--->PWM--->NEC
    +------------+    +-----------------------+

freie Pins (PortB=PC-Ints):
   A0=XTAL0    ???
   A1=XTAL1    ???

   B0=AIN0
   B1=AIN1
   B2=(OC0A)
   B4=(OC1B)

   D2=INT0
   D3=INT1
   D4=(T0)
   D5=(OC0B)
   D6=ICP1 (InputCaptureUnit durch frequenzkorrekten PWM belegt)
--------------------------------------------------------------------------------
')
'derzeit wird der UART-Transmitter fürs debugging verwendet, Fehlerbytes:
Const Nec_transmitter_overrun = &H01
Const Nec_crc_error = &H02

$crystal = 8000000
$regfile = "attiny2313.dat"
$hwstack = 25
$swstack = 25
$framesize = 20
Const Debugmode = 1                                         '1=debugmode, 0=normal mode
'****Interruptvektoren****
On Oc1a Oc1a_isr Nosave                                     'Hi->Lo-Flanke vom NEC, Pulslänge wird angepaßt
On Oc0a K_bus_timeout_isr Nosave                            'Timeout für UART
On Urxc Uart_recieved_isr Nosave                            'byte empfangen, ggf CRC, BIP, IGN, CRC_OK für main
'****globale Variablen****
'für NEC-Sender
Dim Bitzaehler As Byte                                      'Zählt über NEC gesendete Bits
Dim Adress As Byte                                          'NEC-Empfängeradresse
Dim Kommando As Byte                                        'NEC-Kommando
'für K-Bus-Empfänger
Dim Bytezaehler As Byte                                     ' (restliche) Bytes des Telegrammes
Dim K_rec_buff As Byte                                      'RxD-ISR übergibt Byte hier
Dim Nec_tree_ptr As Byte                                    'zeigt auf aktuellen Knoten im Eeprom
Dim Xnor As Byte                                            'führt CRC-Byte mit
'GPIOR0 wird als universellesFlagRegister verwendet (default alle Bits=0)
Bip Alias Gpior0.0                                          'neues Byte im Puffer
Ign Alias Gpior0.1                                          'Rest-Telegramm ignorieren!
Crc_ok Alias Gpior0.2                                       'CRC-Check war ok
Nec_busy Alias Gpior0.3                                     'der sendet noch
'****************Subs***************
Declare Sub Initnec(byval Zieladresse As Byte)
Declare Sub Sendnec(byval Kommandobyte As Byte)
Declare Sub Initkbus()
Call Initnec(&B10011101)                                    'NEC-Interface mit Adresse initialisieren
Call Initkbus()                                             'K-Bus-Interface initialisieren
Enable Interrupts                                           'Interrupts freigeben
Dim Temp As Byte
Dim Temp2 As Byte
'***********Hauptschleife***********
Do
   'Bip pollen, und Bytes im Eeprom suchen, bei CRC_OK korrespondierenden NEC senden********************
   If Bip = 1 Then                                          'neues relevantes Byte?
      Bip = 0
      Readeeprom Temp , Nec_tree_ptr                        'NEC-Code laden
      If Crc_ok = 1 Then                                    'CRC_ok?
         Call Sendnec(temp)                                 'NEC senden
      Else
          Do
            Incr Nec_tree_ptr
            Readeeprom Temp2 , Nec_tree_ptr                 'Knotenwert laden
            Incr Nec_tree_ptr                               'zeigt auf Adresse
            If Temp2 = Temp Then
               Exit Do
            End If
            Decr Temp
            If Temp = 0 Then                                'nicht gefunden
               Ign = 1                                      'Ignore-Flag
               Exit Do
            End If
          Loop
      End If
   End If
Loop

'*****************Subroutinen*******
Sub Initnec(zieladresse As Byte)
   Tccr1a = 2                                               'für normale I/O und WGM=14
   Ocr1a = 17999
   Icr1 = 17999
   Ddrb.3 = 1                                               'PortB.3 (OC1A) ist Ausgang
   Bitzaehler = 38
   Adress = Zieladresse
   Enable Oc1a
End Sub
Sub Sendnec(kommandobyte As Byte)
   If Nec_busy = 1 Then
      #if Debugmode = 1
       Udr = Nec_transmitter_overrun                        'Fehlercode senden(UART)
      #endif
   Else
      Kommando = Kommandobyte                               'zu sendendes CMD übernommen
      Tccr1b = 25                                           'Timer läuft (->IRQs)
      SBI PORTB, PORTB3                                     'Startburst
      #if Debugmode = 1
       Udr = Kommando                                       'NEC-Code (Byte) über UART gesendet
      #endif
      Nec_busy = 1
   End If
End Sub
Sub Initkbus()
   Bytezaehler = 255                                        'beginn eines Telegrammes
   Nec_tree_ptr = 0                                         '->Wurzel
   Xnor = 0
   'Timer0 ->CTC mit IRQ und 1,696ms (OCR0A)
   Ocr0a = 52
   Tccr0a = &B00000010                                      'CTC Mode
   Tccr0b = &B00000100                                      'Timer0 mit Prescaler 256 gestarted
   Enable Oc0a                                              'IRQ aktivieren (TIMSK)
   'UART vorbereiten 9600 Baut ,8DB, 1SB, gerade Parität
   sbi UCSRC,upm1                                           'gerade Parität, der Rest ist default
   Ubrrl = 51                                               '9600baud bei 8MHz, U2X=0 Error:0,16%
   #if Debugmode = 0
      Ucsrb = &B10010000                                    'Reciever mit IRQ aktiv
   #else
      Ucsrb = &B10011000                                    'Reciever mit IRQ aktiv, Transmitter ohne
   #endif
End Sub

'*****Interrupt Service Routinen****
K_bus_timeout_isr:
  $asm                                                      'bei Timeout (1,7ms) auf init zurücksetzen
  push r16                                                  'R16->Stack
  LDI r16, 255
  STS {Bytezaehler}, R16                                    'Bytezaehler = 255
  LDI r16, 0
  STS {nec_tree_ptr}, r16                                   'nec_tree-Ptr = 0
  STS {xnor}, r16                                           'XNOR = 0
  CBI GPIOR0, 1                                             'IGN-Flag gelöscht
  pop r16                                                   'R16<-Stack
  $end Asm
Return
Uart_recieved_isr:
  $asm                                                      'empfangenes Byte abholen, auswerten, ggf CRC, Flags für main setzen
  push R16                                                  'R16->Stack
  LDI R16, 0
  Out Tcnt0 , R16                                           'Timer reset
  in r16, UDR                                               'Empfangenes Byte->R16
  SBIC UCSRA, UPE
  SBI GPIOR0, 1                                             'Paritätsfehler -> setze IGN-Flag
  SBIC GPIOR0, 1                                            'IGN gesetzt?
  RJMP rx_isr_restore_R16                                   'dann ignoriere Byte
  PUSH R17                                                  'R17->Stack
  IN R17, SREG
  PUSH R17                                                  'SREG->Stack
  LDS R17, {Bytezaehler}
  PUSH R18                                                  'R18 ->Stack
  LDS R18, {Xnor}
  DEC R17                                                   'decr Bytezaehler
  STS {Bytezaehler}, R17
  BRNE notCRC                                               'nur bei Zaehler=0...
  CP R16, R18                                               'CRCcheck
  #if Debugmode = 0
  BRNE Restore_r18_sreg_r17                                 'CRC-ERROR->nix zu tun
  #else
  brne crcerror
  #endif
  SBI GPIOR0, 0                                             'setze BIP
  SBI GPIOR0, 2                                             'setze CRC_OK
  RJMP Restore_r18_sreg_r17
  #if Debugmode = 1
 Crcerror:
   ldi R16,Nec_crc_error
   Out Udr , R16                                            'Fehlercode senden
   RJMP Restore_r18_sreg_r17
  #endif
 Notcrc:                                                    '...sonst
  CPI R17, 253                                              'wenn Längenbyte empfangen
  BRNE notlength                                            'dann
  STS {Bytezaehler}, R16                                    'Bytezaehler=neues Byte
  RJMP calccrc
 Notlength:
  BRCC calccrc                                              'wenn Bytezaehler>253 überspringe, sonst...
  STS {K_rec_buff}, R16                                     'neues Byte->Puffer
  STS {Bytezaehler}, R17                                    'Bytezaehler abgespeichert
  SBI GPIOR0, 0                                             'BIP gesetzt
 Calccrc:
  EOR R18, R16                                              'xnor=xnor EOR neues Byte
  STS {Xnor}, R18                                           'XNOR abgespeichert
 Restore_r18_sreg_r17:                                      'R18, SREG, R17 zurückholen
  POP R18
  POP R17
  Out Sreg , R17
  pop R17
 Rx_isr_restore_r16:                                        'R16 zurückholen
  pop R16
  $end Asm
Return

Oc1a_isr:                                                   'PWM-Frequenz anpassen (PPM)
      $asm                                                  'Assemblerblockanfang
      PUSH XH
      PUSH XL
      PUSH R16
      IN R16, SREG
      PUSH R16                                              'Register und SREG gesichert
      Loadadr Bitzaehler , X                                'X Enthält Bitzaehler -speicheradresse
      LD R16, X                                             'R16=Bitzähler
      DEC R16                                               'R16 dekrementiert
      ST X+, R16                                            'Bitzähler zurückgespeichert, X enthält Adress-Adresse
      BREQ naechstesVorbereiten                             'final wurde gesendet, Sprung (nächstes vorbereiten)
      CPI R16, 34                                           'Z=1 <==> Bitzaehler (jetzt)= 34
      BREQ burstAbschalten                                  'dann springe burstAbschalten
      cpi R16, 33                                           'Z=1<==>Bitzaehler=33
      BREQ pauseEnde                                        'dann -> Pause Ende
      BRSH dasWars                                          '>33->dasWars (0,33,34 wurden bereits behandelt, bleiben die 32 Bits)
      CPI R16, 17                                           'Carry bei den letzten 17 als einem Endburst (R16=0) plus 16  Bits(R16=16..1)
      BRCC AdresseStimmt                                    'sonst überspringe
      inc XL                                                'X =Kommandoadresse

   Adressestimmt:
      LD R16, X
      LSL R16                                               'einmal nach links schieben, MSB wandert ins Carry
      BRCS EinsSenden                                       'bei 1 springe, bei 0 bleibe
      INC R16                                               'links wurde ne 0 rausgeschoben, deswegen wird die 0 hinten zur 1 invertiert
      ST X, R16                                             'Byte zurückgespeichert
      LDI R16, hbyte(8999)
      Out Icr1h , R16
      LDI R16, lbyte(8999)
      Out Icr1l , R16                                       'Icr Angepaßt
      RJMP dasWars                                          'Fall 0 erledigt

   Einssenden:
      ST X, R16                                             'die hinten eingeschobene 0 ist bereits invers zur 1 - Byte zurückgespeichert
      LDI R16, hbyte(17999 )
      Out Icr1h , R16
      LDI R16, lbyte(17999 )
      Out Icr1l , R16                                       'Icr Angepaßt
      RJMP dasWars                                          'Fall 1 erledigt

   Pauseende:
      LDI R16, hbyte(4499)
      Out Ocr1ah , R16
      LDI R16, lbyte(4499)                                  'Ocr wieder Auf 562,5 µs
      Out Ocr1al , R16                                      'wird erst nach dem nächsten TOV aktiv
      LDI R16, 130
      Out Tccr1a , R16                                      'B3 wird PWM (lo->hi beim nächsten TOV)
      RJMP dasWars                                          '->dasWars

   Burstabschalten:
      CBI PORTB, PORTB3                                     'B3 -> lo
      RJMP dasWars                                          '->dasWars

   Naechstesvorbereiten:
      LDI R16 , 24
      Out Tccr1b , R16                                      'Timer Steht
      LDI R16, hbyte(17999)
      Out Ocr1ah , R16
      Out Icr1h , R16
      LDI R16, lbyte(17999)
      Out Ocr1al , R16
      Out Icr1l , R16                                       'Ocr1a Und Icr1 Für Nächsten Start Vorbereitet
      LDI R16, 38
      STS {Bitzaehler},R16                                  'Bitzäehler reinitialisiert (38)
      LDI R16,0
      Out Tcnt1h , R16
      Out Tcnt1l , R16                                      'Timer = 0 (Reload, ggf anpassen)
      LDI R16, 2
      Out Tccr1a , R16                                      'B3 ist wieder I/O

   Daswars:
      POP R16
      Out Sreg , R16
      POP R16
      POP XL
      POP XH                                                'SREG und Register (R16, XH, XL) wiederhergestellt
   $end Asm
   Nec_busy = 0
Return
Also jetzt 690 Bytes :p
 
Code:
$eeprom
Wurzel:

Data &H01 , &H68 ,                                          'Lb_68 ,lb_68:
Data &H02 , &H32 ,                                          'Lb_68_32 :
Data &H02 , &H11 , &B00101000 , &H10 , &B10101000,
Data &H3B ,                                                 'Lb_68_3b:
Data &H06 , &H01 , &B00101000 , &H11 , &B00101000 , &H21 , &B00101000 , &H08 , &B11100001 , &H18 , &B00101000 , &H28 , &B00101000

$data

muesste so stimmen,
wen ich 50 04 68 32 11 1F per UART raushaue, dann geht der nec three pointer auf 2 ..
egal was ich sende der nec three pointer kennt nur den zustand 0 und 2,.
vl is doch das eeprom file im arsch,.
 
So stimmt das File auch wieder nicht, da fehlen doch diverse Adressen... da war das erste besser, nur eben bei lb_68_3B muß am Anfang die &H06 hin
Code:
$eeprom
Wurzel:
Data &H03 , &H68 , &H0007 , &HB0 , &H001E , &HC8 , &H0024   '3 kinder, Ibusbyte, unterkat,Ibusbyte, unterkat, Ibusbyte, unterkat,
Lb_68:
Data &H02 , &H32 , &H000C , &H3B , &H0011                   '2 kinder, Ibusbyte, nec , Ibusbyte, nec
Lb_68_32:
Data &H02 , &H11 , &H28 , &H10 , &HA8                       '2 kinder, volup, nec , Ibusbyte, voldown
Lb_68_3b:
Data &H06 , &H01 , &HD0 , &H11 , &HD0 , &H21 , &HFF , &H08 , &HA1 , &H18 , &HFF , &H28 , &HFF       'Nextp , Next1s , Nextre ,  Prev ,  Prev1s , Prevre

Lb_b0:
Data &H01 , &H3B , &H0021                                   '1 kinder, Ibusbyte, unterkat
Lb_bo_3b:
Data &H01 , &H80 , &B00000000                               'anzahl, Ibusbyte, nec

Lb_c8:
Data &H01 , &H3B , &H0027                                   '1 kinder, Ibusbyte, unterkat
Lb_c8_3b:
Data &H01 , &H80 , &HC8                                     'anzahl, Ibusbyte, nec
$data
Die Label brauchst Du natürlich auch nicht, da das ja in Bascom so nicht geht - der Übersichtlichkeit könnte man hier Kommentare nehmen.

Die fehlenden Adressen werden zum Fehler beitragen, aber der Vergleich "IF temp2 = temp Then" ist natürlich auch Quark... da gehört natürlich "If temp2 = K_rec_buff" hin... (*peinlich*)

P.S.: unsicher bin ich mir auch dabei, daß Du manchmal 2stellige Hex-Schreibweise (&H68), manchmal vierstellige(&H0021) verwendest. Ok, vorn stehen Nullen, aber wird das jetzt als Byte eingebaut, oder als Word (wobei das erste Byte 0 ist)? Schreib mal konsequent nur mit HEX ohne die nullen, binär sollte natürlich kein Problem sein.
 
muss dich enttäusche, so geht der nec tree pointer erst nach dem 3 oder 4 ten senden des bytes höher als 0
das is noch irgendwo der wurm drin,.
werd am wochenende das mal in echt testen ,.
und schauen was passiert, kannst du mal das eeprom file mit avr studio erstellen?
 
Die ersten beiden Bytes habe auf den Eeprom-Pointer keinen Einfluß (Sender-ID, Längenbyte) - beide werden aber in der Empfangsroutine ausgewertet. Zumindest der Bytezaehler sollte sich ändern. Beim Empfang der Sender-ID von 255 auf 254, beim Empfang des Längenbytes von 254 auf die empfangene Länge (bei Deinen Telegrammen 4). Erst das 3te Byte (Ziel) hat einen Einfluß auf den Zähler...

Wie und womit testest Du? Direkt im Simulator, durch Manipulation des UDR und den Interrupt?
 
...kannst du mal das eeprom file mit avr studio erstellen?
Kannst Du das vielleicht selbst machen? Brennen mußt Du es möglicherweise selbst mit dem Studio - es gibt bei Bascom und dem Studio wohl unterschiedliche Eeprom-Files. Hier mal der Code, den ich heute Vormittag in der Bahn zusammengetippt habe:
Code:
.include "tn2313def.inc"		;ATtiny2313
;********* NEC-Codes benamsen... Bitte überprüfen und vervollständigen!!! ***
.equ name=wert
.equ vol_up = 0x28
.equ vol_down = 0xA8
.equ next = 0xD0
.equ next_1s = 0xD0
.equ next_re = 0xFF
.equ prev = 0xA1
.equ prev_1s = 0xFF
.equ prev_re = 0xFF
.equ ses = 0x00
.equ rt_dr = 0xC8
.equ rt_1s =
.equ rt_1_s =
.equ rt_aus =
.equ pdc_on =
.equ pdc_off =
.equ fb_close =
.equ fb_open =
.equ light =
;********** Tabelle *************
.eseg     ;ins Eeprom
.org 0x00   ;ab Adresse 0
wurzel:
.db 0x05, 0x68, lb_68, 0xB0, lb_B0, 0xC8, lb_C8, 0x60, lb_60, 0xBF, lb_BF
lb_68:
.db 0x02, 0x32, lb_68_32, 0x3B, lb_68_3B
lb_68_32:
.db 0x02, 0x11, vol_up, 0x10, vol_down
lb_68_3B:
.db 0x06, 0x01, next, 0x11, next_1s, 0x21, next_re, 0x08, prev, 0x18, prev_1s, 0x28, prev_re
lb_B0:
.db 0x01, 0x3B, lb_B0_3B
lb_B0_3B:
.db 0x01, 0x80, ses
lb_C8:
.db 0x01, 0x3B, lb_C8_3B
lb_C8_3B:
.db 0x04, 0x80,rt_dr,0x90,rt_1s,0xA0,rt_1_s,0x40,rt_aus 
lb_60:
.db 0x01, 0x0C, lb_60_0C
lb_60_0C:
.db 0x02, 0x80,pdc_on,0x40,pdc_off
lb_BF:
.db 0x02, 0x72,lb_BF_72,0x76,lb_BF_76
lb_BF_72:
.db 0x02, 0x16, fb_close, 0x26, fb_open
lb_BF_76:
.db 0x01, 0x02, light
.cseg
Die fehlenden NEC-Codes sind oben noch zu ergänzen, dann sollte sich das ganze im AVR-Studio compilieren lassen (als neue ASM-Datei). Die Dabei erzeugte .eep-Datei ist dann in das Eeprom zu brennen, Flash ist nicht zu beschreiben. Kommst Du damit klar?
(Welche AVR-Studio-Version kannst Du verwenden, welchen Programmer?)
 
ses ist ein Assembler-Mnemonic (Set Signed Flag), und somit reserviert. Ich hab jetzt "se_s" genommen.
Die 2te Zeile sollte ein Kommentar sein (; fehlte).
Die offenen NEC-Codes hab ich erstmal mit 0xFF initialisiert.

Code:
.include "tn2313def.inc"		;ATtiny2313
;********* NEC-Codes benamsen... Bitte überprüfen und vervollständigen!!! ***
;.equ name=wert
.equ vol_up = 0x28
.equ vol_down = 0xA8
.equ next = 0xD0
.equ next_1s = 0xD0
.equ next_re = 0xFF
.equ prev = 0xA1
.equ prev_1s = 0xFF
.equ prev_re = 0xFF
.equ se_s = 0x00
.equ rt_dr = 0xC8
.equ rt_1s = 0xFF
.equ rt_1_s = 0xFF
.equ rt_aus = 0xFF
.equ pdc_on = 0xFF
.equ pdc_off = 0xFF
.equ fb_close = 0xFF
.equ fb_open = 0xFF
.equ light = 0xFF
;********** Tabelle *************
.eseg     ;ins Eeprom
.org 0x00   ;ab Adresse 0
wurzel:
.db 0x05, 0x68, lb_68, 0xB0, lb_B0, 0xC8, lb_C8, 0x60, lb_60, 0xBF, lb_BF
lb_68:
.db 0x02, 0x32, lb_68_32, 0x3B, lb_68_3B
lb_68_32:
.db 0x02, 0x11, vol_up, 0x10, vol_down
lb_68_3B:
.db 0x06, 0x01, next, 0x11, next_1s, 0x21, next_re, 0x08, prev, 0x18, prev_1s, 0x28, prev_re
lb_B0:
.db 0x01, 0x3B, lb_B0_3B
lb_B0_3B:
.db 0x01, 0x80, se_s
lb_C8:
.db 0x01, 0x3B, lb_C8_3B
lb_C8_3B:
.db 0x04, 0x80,rt_dr,0x90,rt_1s,0xA0,rt_1_s,0x40,rt_aus 
lb_60:
.db 0x01, 0x0C, lb_60_0C
lb_60_0C:
.db 0x02, 0x80,pdc_on,0x40,pdc_off
lb_BF:
.db 0x02, 0x72,lb_BF_72,0x76,lb_BF_76
lb_BF_72:
.db 0x02, 0x16, fb_close, 0x26, fb_open
lb_BF_76:
.db 0x01, 0x02, light
.cseg
belegt (die ersten) 73 Eeprom-Register (57%)

Bitteschön: Anhang anzeigen Tree.zip
 
...(Welche AVR-Studio-Version kannst Du verwenden, welchen Programmer?)
Ich hatte selbst zu meinen Bascom-Zeiten zum Brennen immer das Studio verwendet, auch die Einstellung der Fuses und so fand ich da besser... egal.
Erstellt habe ich das File mit der Version 4.? (5.? ist auf meinem CoreDuo deutlich unperformanter, an 6.? hab ich mich deswegen noch gar nicht rangetraut... abgesehen davon gibt die Festplatte keine weitere Version mehr her.)
Im Programm wird die Kompilerkonstante "debugmode" definiert und verwendet. Ist die =1, werden die, in den Kommentaren erwähnten Fehlercodes über den UART (TX) gesendet - Einstellungen wie beim BUS-Empfang. Sollten sich also über einen Pegelwandler (MAX232 oä) und ein Terminalprogramm am PC auslesen lassen. Außerdem wird, wenn über den PWM ein NEC-Code ausgegeben wird, derselbe auch über UART gesendet.
 

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