K-BUS TRanciever Melexis TH3122

so, mal zum testen, wie ich mir das vorstelle, hab ich mit dem readeeprom nen fehler gemacht, oder mag das der Simulator einfach nicht?

Code:
Load_adr:
   For I = 1 To 8
      Readeeprom Eepromdata(1) , I
      Readeeprom Eepromdata(2)
      Readeeprom Eepromdata(3)
      Readeeprom Eepromdata(4)
      Readeeprom Eepromdata(5)
      'Print Eepromdata(1) ; " " ; Eepromdata(2) " " ; ; Eepromdata(3) " " ; ; Eepromdata(4) " " ; ; Eepromdata(5)
      If Eepromdata(4) = Recieved(3) And Eepromdata(5) = Recieved(4) Then    'prüfen ob empfanegens = gespeichertes ist
         'nec senden....
      End If
    Next
Return

$eeprom
1:                                                          'vol +
Data &B00101000 , &H68 , &H32 , &H11 , &H1F
2:                                                          'vol -
Data &B10101000 , &H68 , &H32 , &H10 , &H1E
3:                                                          'Next pressed
Data &B00101000 , &H68 , &H3B , &H01 , &H06
4:                                                          'next 1s
Data &B00101000 , &H68 , &H3B , &H11 , &H16
5:                                                          'Prev pressed
Data &B11100001 , &H68 , &H3B , &H08 , &H0F
6:                                                          'Prev 1s
Data &B00101000 , &H68 , &H3B , &H18 , &H1F
7:                                                          'SES anderer empfaenger
Data &B00101000 , &HB0 , &H3B , &H80 , &H5F
8:                                                          'RT wählen dr
Data &B00101000 , &HC8 , &H3B , &H80 , &H27
$data

also egal wie ich das readeeprom nutze, es geht nicht, glaube es liegt an meiner version 2.0.7.1
 
so hab die daten mal so ins eeprom gelegt wie du vorgeschlagen hast,.
versuch mich an der ausleseroutine, aber glaube bekomm das nich hin :D
Code:
Data 0 , 3                                                  'pointer, anzahl der Kinder
Data &H68 , &H0008                                          'erster Knoten, Anfangsadr
Data &HB0 , &H0A08                                          'zweites Knoten, Anfangsadr
Data &HC8 , &H0A0C                                          'dritter Knoten, Anfangsadr

Data &H32 , 2                                               'erstes Kind vom ersten Knoten,Anzahl Kinder 2
Data &H11 , &B00101000                                      'erstes  vom ersten
Data &H10 , &B10101000                                      'zweites vom ersten
Data &H3B , 5                                               'zweites Kind vom ersten Knoten,Anzahl Kinder 4
Data &H01 , &B00101000                                      'erstes  vom zweiten
Data &H11 , &B00101000                                      'zweites  vom zweiten
Data &H08 , &B11100001                                      'drittes  vom zweiten
Data &H18 , &B11100001                                      'viertes  vom zweiten

Data &H3B , 1                                               'ertes Kind vom zweiten Knoten,Anzahl Kinder 2
Data &H80 , &B00101000                                      'erstes vom dritten

Data &H3B , 1                                               'zweites Kind vom dritten Knoten,Anzahl Kinder 2
Data &H80 , &B00101000                                      'zweites vom dritten

$data

EDIT: die adressen oben sind falsch, wie geb ich da werte größer 16 an, da ja dann 0001 und 1 (speicherplatz adr im eeprom) im geb rauch sind ?
geht das mit bascom ueberhaupt oder brauch dazu dann 2 bytes?
 
So Aktueller Stand,LotadaC , hoffe hab deine idee mit der speicherung der Daten richtig umgesetzt!
es besteht noch ein kleiner optimierungsbedarf ..
probiert es ruhig mal aus,.
hier mal 3 codes, welche u.a. verarbeitet werden sollen
'vol + |50| 04 | 68 | 32 | 11 | 1F
'vol - |50| 04 | 68 | 32 | 10 | 1E
'Next pressed |50| 04 | 68 | 3B | 01 | 06

Code:
$crystal = 8000000
$regfile = "ATtiny2313.dat"
$hwstack = 30                                               ' default use 32 for the hardware stack
$swstack = 20                                               'default use 10 for the SW stack
$framesize = 20                                             'default use 40 for the frame space
$baud = 9600
$sim

Dim Empfangszaehler As Byte

'Dim Serial_flag As Bit At Empfangszaehler + 7 Overlay
Dim Serial_flag As Bit
Dim Recieved(35) As Byte
Dim Code(6) As Byte
'empfangende daten
Dim Startadress As Byte At Recieved + 1 Overlay
Dim Messagelength As Byte At Recieved + 2 Overlay
Dim Zieladress As Byte At Recieved + 3 Overlay
Dim Data_1 As Byte At Recieved + 4 Overlay
Dim Data_2 As Byte At Recieved + 5 Overlay
Dim Xorbyte As Byte At Recieved + 6 Overlay
Dim Nxor As Byte
Dim Inhaltlength As Byte
Dim I As Byte
Dim I1 As Byte
Dim Eepromdata(7) As Byte

Declare Function Read_eeprom_data(byref Pos As Byte)as Byte

$eeprom
Data 0 , 3
'WurzelKnoten                                                  'pointer, anzahl der Kinder
Data &H68 , &H0008                                          'erster Knoten, Anfangsadr
Data &HB0 , &H018                                           'zweites Knoten, Anfangsadr
Data &HC8 , &H01C                                           'dritter Knoten, Anfangsadr
'Kinder 1.Ordnung
Data &H32 , &H014 , 2                                       'erstes Kind vom ersten Knoten,adresse der Kinder, Anzahl Kinder 2
Data &H3B , &H010 , 4                                       'zweites Kind vom ersten Knoten,adresse der Kinder,Anzahl Kinder 4
Data &H3B , &H01B , 1                                       'ertes Kind vom zweiten Knoten,adresse der Kinder,Anzahl Kinder 2
Data &H3B , &H020 , 1                                       'erstes Kind vom dritten Knoten,adresse der Kinder,Anzahl Kinder 1
'Kinder 2.Ordnung
'H68->H32
Data &H11 , &B00101000                                      'erstes  vom ersten
Data &H10 , &B10101000                                      'zweites vom ersten
'H68->H3B
Data &H01 , &B00101000                                      'erstes  vom zweiten
Data &H11 , &B00101000                                      'zweites  vom zweiten
Data &H08 , &B11100001                                      'drittes  vom zweiten
Data &H18 , &B11100001                                      'viertes  vom zweiten
'HB0->H3B
Data &H80 , &B00101000                                      'erstes vom dritten
'HC8->h3B
Data &H80 , &B00101000                                      'zweites vom dritten

$data

Empfangszaehler = 1
Nxor = 0

'Hardware
Config Timer0 = Timer , Prescale = 256                      'Prescale = 256
Enable Timer0
Stop Timer0
Timer0 = 203

'INTs
Enable Interrupts
On Timer0 Timer0_isr

Enable Urxc
On Urxc Uart_isr                                            ' Keine automatische Register-Rettung

'PROGRAMM
Do
  If Serial_flag = 1 Then
     While Ischarwaiting() = 1
        Inhaltlength = Messagelength - 1
        Recieved(empfangszaehler) = Inkey()                 'empfangenes abholen

        If Empfangszaehler > 0 And Empfangszaehler < Inhaltlength Then       'es soll ja nur die checksumme von laenge bis zur checksumme gebildet werden
           Nxor = Nxor Xor Recieved(empfangszaehler)
           'Print "CRC CHeck " ; Hex(nxor)
        End If
        Incr Empfangszaehler
     Wend
     Serial_flag = 0
  End If

  'nachricht komplett empfangen
  If Ischarwaiting() <> 1 And Empfangszaehler > 4 Then
     If Nxor = Xorbyte Then                                 'pausibilitätsprüfung der empfangenenen daten
        'Print "CRC Prüfung i.O."
        For I = 2 To Empfangszaehler                        'in verarbeotungsrray rueberholen, die ersten 3 bytes werden nicht benoetigt,. sender/empfanger/laenge
           I1 = I - 2
           Code(i1) = Recieved(i)
        Next
        Gosub Load_adr:
     End If

     'Print Hex(recieved(1)) ; " | " ; Hex(recieved(2)) ; " | " ; Hex(recieved(3)) ; " | " ; Hex(recieved(4)) ; " | " ; Hex(recieved(5)) ; " | " ; Hex(recieved(6)) ; " | " ; Hex(nxor)
  End If


  'Gosub Load_adr
Loop
End


'_______________________________________________________________________________
Uart_isr:
   Start Timer0
   Serial_flag = 1
Return

Timer0_isr:
   Stop Timer0
   Timer0 = 203                                             'Nach 1,7ms den empfangszaehler wieder nullen= neue nachricht empfangen
   Empfangszaehler = 1                                      '
Return

Load_adr:
         I = 2
         Lesen:
         Eepromdata(1) = Read_eeprom_data(i)                'Knoten
         If Eepromdata(1) <> Code(1) Then
            Incr I
            Goto Lesen:
         Else
            Incr I
            Eepromdata(2) = Read_eeprom_data(i)             'adresse der Kinder 1:ordnung
         End If
         Print "1." ; "Wurzelknoten " ; Hex(eepromdata(1))

         Wurzel_ok:                                         'Kind 1Ordnung
         I = Eepromdata(2)
         Eepromdata(3) = Read_eeprom_data(i)
         If Eepromdata(3) <> Code(2) Then
            Incr I
            Goto Wurzel_ok:
         Else
            Incr I
            Eepromdata(4) = Read_eeprom_data(i)             'adresse der Kinder 1:ordnung
         End If
         Print "2." ; "Knoten " ; Hex(eepromdata(3))


         I = Eepromdata(4)                                  'Kind 2Ordnung
         Kind_ok:
         Eepromdata(5) = Read_eeprom_data(i)
         If Eepromdata(5) <> Code(3) Then
            Incr I
            Goto Kind_ok:
         Else
            Incr I
            Eepromdata(6) = Read_eeprom_data(i)             'adresse der Kinder 1:ordnung
         End If
         Print "3." ; "Adresse " ; Hex(eepromdata(5))
         Print "4." ; "NEC Adresse " ; Bin(eepromdata(5))
Return

Function Read_eeprom_data(byref Pos As Byte)as Byte
      Local Tmp As Byte
      Readeeprom Tmp , Pos
      Read_eeprom_data = Tmp
End Function

das einzigste was noch fehlt, it diefehlerüberprüfung,.
d.h. wenn er die angegebenen daten nicht findet,.
 
Ich hab mir das mal ausgedruckt, und gehe das morgen in der Bahn durch.
Irgendwie habe ich es in Bascom nicht geschafft, in einer Data-Zeile eine Label-Adresse einzubauen (Also die Adresse, auf die der Label zeigt als feste Zahl, als Datum (=Datenwert?)). Wenn ich das mit eingebettetem ASM versuche, gibts zwar keinen Fehler, aber es erscheint (zumindest im Simulator) auch nix im Eeprom. Es wird auch keine .eep-Datei erzeugt (nur, wenn zusätzlich noch eine Data-Anweisung dabei ist, die Datei ist für mich nicht lesbar/interpretierbar)
Also hab ich's nochmal direkt im Studio versucht:
eepromtest2.png
Wenn man sich die erzeugte .eep ansieht, findet man die Werte wieder:
Code:
00: 0x03
01: 0x01
02: 0x07 <- lb_1 = Speicherzelle 07 (Adresse)
03: 0x02
04: 0x08 <- lb_2 = Speicherzelle 08
05: 0x03
06: 0x09 <- lb_3 = Speicherzelle 09
07: 0xFF
08: 0xFF
09: 0xFF
sollte also so passen, auch wenn der Simulator das nicht richtig anzeigt.

Edit: Na dann - los gehts...
 
Du verwendest einen anderen Weg als ich (vorschlug) - alles davon ist mir noch nicht klar. Außerdem bin ich jetzt mit dem Interrupt-Flag etwas ins schwimmen gekommen (wann wird es gelöscht? Wenn der korrespondierende Interrupt executiert wird (=UART-RXC-ISR), oder wenn das UDR ausgelesen wird (=Inkey)? Scheint (abweichend vom sonst üblichen Mechanismus eher letzteres zu sein... hat mich bisher nie konkret interessiert, weil ich üblicherweise das UDR in der entsprechenden ISR auslesen lasse). Egal erstmal...

Wenn Du beim überprüfen des kompletten Telegrammes eh auf die Absender-ID und die Länge (die interessiert nur bei Empfang) verzichtest, muß das auch nicht ins Eeprom. Dann ändert sich aber auch der Baum (Root hat 5 Kinder).
Da ich das mit den labeln im Eeprom unter Bascom irgendwie nicht hinbekommen habe (keine Ahnung ob das an Bascom oder mir liegt), würde ich die .eep von AVRStudio erzeugen und brennen lassen. In Assembler sollte das dann so aussehen (ich Denke, Du kannst das trotzdem lesen - ersetze .db durch Data, und label sind label...):
Code:
.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, next1s, 0x21, nextre, 0x08, prev, 0x18, prev1s, 0x28, prevre

lb_B0:
...
Die Label in den Data-Zeilen ersetzt der Assembler selbst - kann man also einfach später noch was einfügen...
vol_up, vol_down usw stehen für den entsprechenden NEC-Code (könnte man natürlich auch vorher als Compiler-Konsatnte definieren.
Ich würde allerdings auch bei der Verarbeitung der einzelnen empfangenen Bytes was ändern - hoffentlich komm ich morgen dazu, mehr zu schreiben...
 
ich wllte direkt auf die register zugreifen des eeproms, ohne zu wissen wie die label heissen, und mit einem algorythmuss, immer zeichen fuer zeichen durchgehen..
das funktioniert eigentlich auch, es waere nur gut, wenn ich aus den 3 schleifen jetzt noch eine machen koennte..-
das ist auch möglich,.
ich lese einmal die anzahl der Kinder,
die Startadresse der kinder im eeprom aus,.
dann lese ich adresse fuer adresse aus und vergleiche es mit meinem empfangenen,.


das is wie ein vergleich..



EDIT: dein vorschlag versteh ich auch immernochnich ganz :D
vl ein kleines stueckchen der auswertung?
 
Ich würde das so angehen:
als globale Variablen:
Der Bytezähler, der Eeprompointer, ein Puffer für das grade empfangene Byte, ein Byte für das mitführen der Checksumme.
Außerdem ein Byte für diverse Flags. (Dafür würde ich GPIOR0 verwenden.
Bits:
BIP - neues Byte im Puffer
IGN - ignoriere restliches Telegramm
CRC_OK - korrekte Checksumme empfangen

In der Vergleichsroutine werden dann sicher noch ein paar Hilfsbytes benötigt (in ASM würde man da einfach die Rechenregister freischaufeln)
Initialwert des Bytezählers ist 255, der wird bei mir dekrementiert
Eeprompointer = 0 (da steht im Eeprom die Anzahl der Kinder der Wurzel)
NXOR sollte 0 sein, klar
Die Flags da oben auch.

In der Timer-ISR werden diese Initialwerte wiederhergestellt, ob der Timer im CTC oder mit reload läuft ist erstmal egal.

Der Empfang wird in der UART-Recieve-ISR abgewickelt.
Als erstes wird der Timer zurückgesetzt, sodaß er nicht überläuft.
Dann wird das IGN geprüft - wenn es gesetzt ist, wird direkt zum Return/Reti gesprungen.
Das UDR wird gelesen, und in den Puffer geschrieben (inkey quasi).
Der Bytezähler wird dekrementiert.
Ist er jetzt 0, wird das empfangene Byte mit NXOR verglichen. Bei Gleichheit werden CRC_OK und BIP gesetzt, bei Ungleichheit das IGN, danach wird zum Return gesprungen.
Wurde der Zähler 253, wird das empfangene Byte in den Bytezähler geschrieben.
Jetzt wird geprüft, ob der Bytezähler<252 Wenn ja, wird BIP gesetzt.
Jetzt wird das NXOR mit dem neuen empfangenen Byte verXORrt.
(Einsprungpunkt von Zähler=0)
Return (from Interrupt)

Im Hauptprogramm pollst Du das BIP (IF...then...end if). Ist es gesetzt, also ein reguläres Byte im Puffer, quittierst Du dessen Abarbeitung durch löschen des BIP, und prüfst, ob auch das CRC_OK gesetzt ist. Wenn ja, wird die Zelle aus dem Eeprom (in ein Hilfsbyte) geladen, auf die der Eeprompointer zeigt. Dieses Byte ist der zu sendende NEC-Code, dessen senden Du hier veranlassen kannst. Sicherheitshalber kann man hier jetzt noch das IGN setzen. Danach wird der If-Then-Block verlassen.
War das CRC_OK nicht gesetzt, befindet sich ein, zu prüfendes Byte im Puffer(byte). Jetzt wird erstmal Die Zelle aus dem Eeprom geladen, auf die der Pointer zeigt. Das ist die maximale Anzahl der vergleiche (Hilfsbyte).danach wird der Pointer um eins inkrementiert (erster Vergleichswert).
(Hier ist ein Einsprung-Label)
EepromZelle(Pointer) laden, und mit Puffer vergleichen -> wenn verschieden, wird das Hiflfsbyte dekrementiert (wird es dabei 0, wird das IGN gesetzt, da der Wert im Puffer nicht gefunden wurde, und anschließend der IF-Block verlassen), der Pointer um 2 erhöht (nächstes Kind), und zum Einsprung-Label zurückgesprungen.
->wenn gleich, wird der Pointer um eins erhöht (zeigt jetzt also auf die Adresse des gefundenen Kindes), und der IF-Block verlassen

Das sollte es eigentlich gewesen sein ... hoffe ich;)
 
wie prüfts du das crc fuer jedes byte ?

Der Empfang wird in der UART-Recieve-ISR abgewickelt.
Als erstes wird der Timer zurückgesetzt, sodaß er nicht überläuft.
Dann wird das IGN geprüft - wenn es gesetzt ist, wird direkt zum Return/Reti gesprungen.
Das UDR wird gelesen, und in den Puffer geschrieben (inkey quasi).
Der Bytezähler wird dekrementiert.
Ist er jetzt 0, wird das empfangene Byte mit NXOR verglichen. Bei Gleichheit werden CRC_OK und BIP gesetzt, bei Ungleichheit das IGN, danach wird zum Return gesprungen.
Wurde der Zähler 253, wird das empfangene Byte in den Bytezähler geschrieben.
Jetzt wird geprüft, ob der Bytezähler<252 Wenn ja, wird BIP gesetzt.
Jetzt wird das NXOR mit dem neuen empfangenen Byte verXORrt.
(Einsprungpunkt von Zähler=0)
Return (from Interrupt)
Das ist quasi die Auswertung des XOR-Bytes des gesamten Telegrammes (bis auf das XOR-Byte selbst, klar).
...
Ahh... Hemi hat in #27 zur UART-Konfiguration geschrieben: "9600, 8-E-1" -> Gerade Parität, 1 Stop-Bit?
Dann sollte genau das auch beim UART eingestellt werden (Uart Parity Mode=2, USBS=0 in UCSRC). Empfängt die UART-Hardware jetzt ein Byte mit falschem Paritätsbit, wird das UPE-Bit in UCSRA gesetzt. Dieses müßte also vor dem lesen des UDR geprüft werden. Ist es gesetzt, würde ich das UDR lesen (löscht UPE), das IGN setzen, und die ISR verlassen - das komplette Telegramm wird also ignoriert.

P.S.: UCSRA ist I/O-Register 0x0B -> in ASM könnte man auf UPE direkt mit SBIS/SBIC reagieren, ohne UCSRA laden zu müssen.
 
sag ich doch...
...Da ich das mit den labeln im Eeprom unter Bascom irgendwie nicht hinbekommen habe (keine Ahnung ob das an Bascom oder mir liegt)...
Ich würde (angenommen ich würde das Programm selbst überhaupt unter Bascom programmieren) jedoch zumindest die .eep-Datei (also die Eeprom-Daten) vom Studio erzeugen und brennen lassen - mit den Labeln.
Der Vorteil ist, daß man nahezu problemlos Knoten/Äste/Teilbäume einfügen/manipulieren kann, und sich um Adressen und so praktisch keine Gedanken mehr machen muß. Er muß halt nur an der entsprechenden Stelle mit einem Label eingefügt werden, der referenzierende Knoten muß um Wert und Labelname ergänzt werden, und die Zahl der Kinder angepaßt, klar.
 
puhh....

so hab verusucht nochn bisschen dran zu drehen,.
Code:
$crystal = 8000000
$regfile = "ATtiny2313.dat"
$hwstack = 25                                               ' default use 32 for the hardware stack
$swstack = 25                                               'default use 10 for the SW stack
$framesize = 20                                             'default use 40 for the frame space
$baud = 9600
$sim

'Blobale Var
Dim Status As Byte
Dim Empfangszaehler As Byte
Dim Recieved(35) As Byte
Dim Code(6) As Byte

'empfangende daten
Dim I As Byte
Dim I1 As Byte
Dim Recieved_alle As Byte At Recieved + 35 Overlay
Dim Startadress As Byte At Recieved + 1 Overlay
Dim Messagelength As Byte At Recieved + 2 Overlay
Dim Zieladress As Byte At Recieved + 3 Overlay
Dim Data_1 As Byte At Recieved + 4 Overlay
Dim Data_2 As Byte At Recieved + 5 Overlay
Dim Xorbyte As Byte At Recieved + 6 Overlay
Dim Nxor As Byte
Dim Inhaltlength As Byte

'EEprom lesen
Dim Schleifenzaehler As Byte
Dim Kinder_anz As Byte
Dim Eeprom_pointer As Byte
Dim Eepromdata(7) As Byte                                   'enthaelt die werte
Dim Nec As Byte At Eepromdata + 4 Overlay
Dim Kinder_zaehler As Byte

Declare Function Read_eeprom_data(byval Pos As Byte)as Byte

$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

'Hardware
Config Timer0 = Timer , Prescale = 256                      'Prescale = 256
Enable Timer0
Stop Timer0
Timer0 = 203

'INTs
Enable Interrupts
On Timer0 Timer0_isr

Enable Urxc
On Urxc Uart_isr                                            ' Keine automatische Register-Rettung

'Variablen init
Empfangszaehler = 1
Nxor = 0
Status.0 = 0                                                'fehlerbit

'PROGRAMM

Do

  If Status.7 = 1 Then                                      'Serial_flag prüfen
       While Ischarwaiting() = 1
          If Status.0 = 0 Then                                 'ignoreflag prüfen nur auswerten und absoeichern falls kein fehler aufgetreten ist
             If Ucsra.upe = 0 Then                             'paritätsprüfung
               Recieved(empfangszaehler) = Inkey()             'zeichen abholen
             Else
               Status.0 = 1                                    'ingorebit/fehlerbit setzen
             End If

             If Empfangszaehler >= 3 Then                      'ab dem 3 zeichen prüfen, empfaenger, sender, und laenge werden abgeschnitten
                Nxor = Nxor Xor Recieved(empfangszaehler)      'es soll ja nur die checksumme von laenge bis zur checksumme gebildet werden
                Gosub Load_adr:
             End If

             Incr Empfangszaehler
          End If
       Wend
     Status.7 = 0                                           'Serial flag zuruecksetzen
  End If

  'wenn nachricht komplett empfangen
  If Ischarwaiting() <> 1 And Empfangszaehler > 4 Then
     If Nxor = Xorbyte Then                                 'pausibilitätsprüfung der empfangenenen daten
        'Print "CRC Prüfung i.O."
        For I = 2 To Empfangszaehler                        'in verarbeotungsrray rueberholen, die ersten 3 bytes werden nicht benoetigt,. sender/empfanger/laenge
           I1 = I - 2
           Code(i1) = Recieved(i)
        Next
     End If

     'Print Hex(recieved(1)) ; " | " ; Hex(recieved(2)) ; " | " ; Hex(recieved(3)) ; " | " ; Hex(recieved(4)) ; " | " ; Hex(recieved(5)) ; " | " ; Hex(recieved(6)) ; " | " ; Hex(nxor)
  End If
Loop
End


'_______________________________________________________________________________
Uart_isr:
   Start Timer0
   Status.7 = 1                                             'Serial flag setzen
Return

Timer0_isr:
   Stop Timer0
   'Standartwerte wiederherstellen, fuer naechsten Empfang vorbereiten
   Timer0 = 203
   Recieved_alle = 0
   Empfangszaehler = 1
   Status.0 = 0                                             'Ignorebit zuruecksetzen
   Status.1 = 0                                             'CRC prüfbit zuruecksetzen
   Status.2 = 0                                             'BIP nachricht komplett empfangen
   Eeprom_pointer = 0                                       'eeprompointer auf anfang setzen
   I = 0
   Schleifenzaehler = 0                                     '
   Kinder_zaehler = 0

Return

Load_adr:                                                   'schleifenzaehler = nummer des byte das geklesen werden soll
   Kinder_anz = Read_eeprom_data(eeprom_pointer)            'anzahl der kinder der gruppe lesen
   Incr Schleifenzaehler
   Incr Eeprom_pointer
   Eepromdata(schleifenzaehler) = Read_eeprom_data(eeprom_pointer)       '1. Adresse der Kinder der Wurzel

   Anfang:
   Eepromdata(schleifenzaehler) = Read_eeprom_data(eeprom_pointer)       '1. Adresse der Kinder der Wurzel
   If Eepromdata(schleifenzaehler) <> Recieved(empfangszaehler) Then       'Vergleich mit empfangenem
      If Kinder_zaehler <= Kinder_anz Then                  'wenn mehr schleifen als Kinder gelsen werden soll
         Incr Kinder_zaehler                                'anzahl der "durchforsteteten" kinder_zaehler erhöhen
         Incr Eeprom_pointer
         Incr Eeprom_pointer
         Goto Anfang
      Else
         Status.0 = 1                                       'fehlerbit setzen,.
         Print "anzahl versuche ueberschritten"
      End If
   'bei erfolgreichem vergleich, dann ..
   Else
      'passenden NEC lesen
   If Schleifenzaehler = 3 Then                             'beim 3 durchgang =>eeprom_pointer 1 erhoehen und dazu passende Nec lesen
      Incr Eeprom_pointer                                   'auf nec speicheradresse setzen, eeprompointer um 1 erhöhen
      Nec = Read_eeprom_data(eeprom_pointer)                'lese nec adresse des Kindes aus
      Status.0 = 1
   Else
      Kinder_zaehler = 0                                    'anzahl der "durchforsteteten" kinder_zaehler zuruecksetzen
      Incr Eeprom_pointer                                   'auch eeprompointerauf adressbereich der Kinder setzen(2./3.)
      Eeprom_pointer = Read_eeprom_data(eeprom_pointer)     'lese adresse des Kindes aus
   End If
End If
Return

Function Read_eeprom_data(byval Pos As Byte)as Byte
      Local Tmp As Byte
      Readeeprom Tmp , Pos
      Read_eeprom_data = Tmp
End Function

bestimmt kann man noch einiges optimieren, aber nach ersten Tests läufts so wies soll,.
Könnte sich das bitte jemand anschauen der ein bisschen ahnung hat, und ein paar optimierungen vornhemen, brauche jetzt 61% des flashs,. mit dem nec -senden code wirds knapp, sehr knapp,.
mir gefaellt ausserdem die Schleife nicht so gut, in der such routine, alternative hier waere wohl ne for, oder while schleife,. ?!
 
Das ist immer noch nicht ganz der Weg, den ich vorgeschlagen hatte.
Ich habe zwischenzeitlich mal den Code vom NEC-Transmitter aus dem anderen Thread hervorgeholt - bei mir compiliert der mit 18% Flash oder so.
Ein wenig von meinem Konzept hab ich auch schon dazugepinselt, insbesondere aber erstmal Kommentare - vielleicht kann ich das nachher mal hochladen...
Frage:
Zur Fehlerbehandlung/Debugging würde ich gern nebenbei über den TxD ein-byte-Nachrichten verschicken, dazu wäre also der UART-Transmitter mitscharfzumachen (neben dem Reciever, den wir eh brauchen). Uner Assembler würde ich mir am Programmanfang jetzt 'ne Assembler-Konstante definieren (DebugMode oder so), und bei der UART-Init dann in Abhängigkeit dieser Konstante bedingt entwder nur RXEN, oder auch zusätzlich TXEN aktivieren (bedingte compilierung) Gibts sowas unter Bascom auch?
2tens: wenn ich derartige Fehlerbytes ausgeben lasse, und zusätzlich den gesendeten NEC über UART ausgeben lasse (also nur das Kommando), laßt sich das eventuell schlecht interpretieren - hattest Du hier irgendwo eigentlich schon die NEC-Kommandos zu den K-Bus-Telegrammen aufgelistet?
3tens: Wenn Du das über ein Terminalprogramm simulieren willst, muß ein Telegramm ja quasi als zusammenhängender Text im Terminal eingegeben sein. Wie willst Du das mit den Unterbrechungen zwischen 2 Telegrammen (die "Prio-Pausen") testen? (könnte interessant werden, um die Auslastung/Überlastung des NEC-Transmitters zu testen (dieweil der ja erheblich langsamer als der UART ist...)

Ich bin also noch drann - auch wenns vielleicht nicht so aussieht...

Edit: bedingte compilierung unter Bascom erfolgt mit
Code:
#if Bedingung
 [Codeblock]
#else
 [Codeblock]
#endif
also mit"#" statt "."

Neues Problem: Beim Einstellen einiger I/O-Register ist mir aufgefallen, daß nach dem Start praktisch alle (I/O-Register) 0x00 sind. Bis auf den Stackpointer, und einige Statusflags (zB Z in SREG oder UDRE in UCSRA) alle Bits 0...
Was macht Bascom da mit den Initial values???
Oder ist das bloß der Simulator?
2tens:Wird im CTC-Mode eigentlich überhaupt ein TOV-IRQ ausgelöst? Der Timer läuft ja dann nicht mehr von MAX nach BOTTOM über, sondern von TOP (=OCR0A)

Soweit siehts bisher aus, da fehlt aber bei den vielen Stern-Kommentaren noch einiges:
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

$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
'UART-Rx und Timer0-Überlauf****************************************************************************
'****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
'******Hauptschleife******
Do
   'Bip pollen, und Bytes im Eeprom suchen, bei CRC_OK korrespondierenden NEC senden********************
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
      Udr = Nec_transmitter_overrun                         'Fehlercode senden(UART)
   Else
      Kommando = Kommandobyte                               'zu sendendes CMD übernommen
      Tccr1b = 25                                           'Timer läuft (->IRQs)
      SBI PORTB, PORTB3                                     'Startburst
      'soll der gesendete NEC (Byte) zum debugging auch über den UART ausgegeben werden???**************
      'udr=Kommando
      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,7ms (OCR0A), ISR oben deklarieren, unten implementieren******************
   sbi tccr0a, wgm01                                        'CTC Mode, Rest=default

   '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
   'RxD mit IRQ, ISR oben deklarieren, TxD ohne IRQ (senden über UDR=Byte) für debugging****************
End Sub

'*****Interrupt Service Routinen****
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
Belegt bisher 406 bytes im Flash, also ca 19%...
 
mit hterm, kann man senden, zeichenketten und diese dann in ner schleife, bzw anzahl der wiederholungen einstellbar

wie willst du das nun machen ? byte empofangen, und gleich im eeprom auslesen , vergleichen und dann verwerfen, oder naechstes, und dann auf ebene 2 ...?
 
Ja, aber um zu sehen, wieviel Traffic auf dem Bus der Adapter verkraftet, mußte man verschiedene Szenarien testen. Worst Case wäre wenn ein verwertbares Telegramm nach dem anderen eintrudelt - mit der Pause für maximale Priorität dazwischen. also:
Telegramm1
Pause 1,7ms
Telegramm2
Pause 1,7ms
usw
(da alleine das senden eines NEC-Telegrammes (also mit Adresse, Kommando, jeweils invertiert und den entsprechenden Conditions am Anfang und ende) immer 65ms (oder was war das nochmal?) dauert, geht das definitiv nicht - wie willst Du da verfahren? neu eintrudelnde s-Telegramme ignorieren?)

Zu der anderen Frage:
Steht eigentlich in #68 (nur daß da der Paritätscheck noch fehlt). Die UART-ISR liefert an das Hauptprogramm, ob ein aus dem Baum zu suchendes Byte empfangen wurde (ByteImPuffer), bzw stattdessen das durch den NecTreePointer indizierte Byte im Eeprom zu senden ist (CRC_ok).
Nach dem Reset und jedem Timeout (1,7ms durch Timer0) beginnt das Hauptprogramm sich so Ebene für Ebene (also Byte für Byte) durch den Baum zu Suchen. wird es in der Jeweiligen Ebene des Teilbaumes nicht fündig, wird abgebrochen (IGN). Ansonsten ist die gefundene Position Ausgangspunkt für das nächste empfangene Byte (bzw der gesuchte NEC-Code.
Die Interrupt-Service-Routinen und das Hauptprogramm fehlen halt noch...
 
mhh vl, müssen wir ne warteschlange einbauen?
wenn wir gleich filtern auf die ersten 2 empfangerbytes, also die empfangsadr, und sendeadresse,
dann kann man direkt schon die nachrichten löschen, soviele tasten werden am lenkrad, welche ja sender ist, nicht direkt gleichzeitig gedrueckt,.
 
Verstehe ich jetzt grad nicht.
Was meinst Du mit "gleichzeitig gedrückt"?
Auf dem Bus kann ja immer nur ein K-Telegramm nach dem anderen kommen, Wenn 'ne Kollision droht, wird entweder ein Telegramm abgewürgt, oder das Neue wartet - die Detektion des abgewürgten haben wir mit der Prioritätspause drinn, ist hier also kein Problem.
Bleibt das Problem, daß das NEC-Senden wesentlich (!!!) langsamer geht, als das K-Bus-Empfangen. Ok, Telegramme, die nicht im Baum enthalten sind, oder deren Parität oder Checksumme nicht stimmt, ignorieren wir. Aber was passiert, wenn Du länger eine Taste am Lenkrad gedrückt hälst? Werden dann entsprechend viele Telegramme über den Bus gesendet (die dann via NEC weiterzuleiten wären)?
Mein Vorschlag: erstmal ohne weitere Pufferung umsetzen, aber im Debugmode diverse Status-/Fehlerbytes über den UART->PC/etc senden lassen. Wenn das Hauptprogramm soweit ist, daß ein Telegramm zu senden wäre, der NEC-Transmitter aber noch busy ist, wird das zu sendende Telegramm verworfen, und ein (1) Fehlerbyte über den UART gesendet. Wenn das dann mal laufen sollte, kann man Immer noch einen Ringpuffer mit dem freien SRAM umsetzen - statt im If-Bip-Block den NEC zu senden, wird der dort in den Ringpuffer eingefügt, außerhalb des Blockes (also bei jedem Durchlauf der main, insbesondere auch wenn kein neues Byte im Puffer ist) wird, sofern der Puffer nicht leer ist, wenn der NEC-Transmitter frei ist, ein NEC-Telegramm gesendet.

Dieser Puffer verschafft Dir natürlich nur etwas mehr Zeit, irgendwann isser auch voll, wenn ständig relevante K-Bus-Telegramme eintrudeln. Und von den 128 Bytes SRAM haben wir und Bascom bereits einige verwendet - ggf muß man dann mal sehen, ob sich die stacks und der Framesize weiter reduzieren lassen...
 
Welche?
SEN/STA liefert Infos über den Zustand (frei/besetzt) des Busses wenn der µC den als Eingang (Tristate) schaltet - wie das ist, wenn man den (Controllerseitig) als Ausgang verwendet, ist mir noch nicht ganz klar... Was bedeutet, daß der Transmission Path disabled ist (bei einem logisch-High)? Kann man dann munter seriell senden, ohne daß das einen Einfluß auf auf den Bus hat? Hemi?
Sense informiert Dich (Deinen Controller) darüber, ob die Versorgungsspannung des TH... eine Mindestgrenze erreicht hat,
Reset ähnlich, nur das hier entscheidend ist, daß der interne Regulator für Vcc stabil arbeitet. Insbesondere läßt sich also auch erkennen, ob er im standby ist, oder Durch den Bus wieder aufgeweckt wurde.
Hemi hatte ja bereits mal gefragt, ob Du den Regulator überhaupt verwendest (hattest Du da geantwortet?) - eine fallende Flanke am EN-Pin scheint den Regulator in den Standby zu schicken (wodurch dann der Controller ohne Saft wäre/sich abschalten würde), Aktionen auf dem Bus würden den Regulator aktivieren (wenn ich das recht verstanden habe eine steigende Flanke am EN auch, aber die kann ein spannungsloser Controller ja nicht erzeugen)
Ich denke aber, daß EN bei Dir fest auf Vs liegt, der Regulator, und somit auch der Controller permanent laufen, sobald auch der TH... unter Spannung steht.

SEN/STA sollte also eigentlich nur für's Senden von Interesse sein, ob man damit sicher den Schreibzugriff des TH... auf den Bus unterbinden kann, weiß ich wie gesagt nicht...
also erstmal alle 3 Pins tristate lassen, und ggf auslesen (PIN-Register)
Wenn der Controller eine eigene Spannungsversorgung besitzt, könnte man über den Sense detektieren, ob der TH... überhaupt läuft/aktiv ist (wenn der Controllerpin interruptfähig ist, könnte man den Controller ggf schlafen schicken, und über diesen Pin aufwecken, oder den UART deaktivieren/aktivieren, Stromsparmaßnahmen ergreifen/aufheben usw...).
Ähnliches bei dem Reset.
Im Dauerbetrieb sollte sich an den beiden Pins also ein high-Pegel auslesen lassen - darauf könnte man in der Init-Phase warten/im Hauptprogramm prüfen - aber... was soll der Controller tun, wenn eines der beiden Signale low geht?

Aber erstmal interessieren Dich diese Pins beim Empfang nicht. Entweder der TH... ist aktiv, und leitet Dir an den Controller weiter, was er vom Bus empfängt, oder er ist's nicht, dann tut ers nicht, wodurch also am Controller auch nichts ankommt.
 

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