Serieller Datenempfang im Interrupt / "Bascom"

Moin Leute,

ich fürchte, ich habt's noch nicht verstanden :) Hab jetzt wenig Zeit, aber versuche es mal an einem ganz einfachen Beispiel.

Stellt Euch vor, Ihr habt eine 8x8 Matrix, einfarbig, ums einfach zu halten. Die hat 8x8 = 64 LED's. Wenn man den Zustand jeder einzelnen LED speichern bzw. setzen möchte, benötigt man 8x8 = 64 Bit's oder besser 64/8 = 8 Bytes. Ich könnte mir also ein Byte-Array bauen, das die Größe 8 hat, also 8 Array-Elemente mit je 8 Bit. In unserem Beispiel würde also ein Array-Element einer Zeile entsprechen und die einzelnen Bits dieses Elements der jeweiligen LED.
Somit kann ich mit LED(1).0 = 1, die erste LED in der ersten Zeile aktivieren.

Dieses Prinzip übersetzt Ihr jetzt auf eine große LED-Matrix, dann wisst Ihr, wie ich das mache. Aus meiner Sicht ist das sehr effizient.

@HinterBlauenAugen: Der Zugriff erfolgt natürlich wahlfrei. Das übertragene Word beinhaltet also das Array-Element, den Index (das Bit) und die Farbe.

Sorry, bin jetzt wieder off.

Gruß
Jan
 
Stellt Euch vor, Ihr habt eine 8x8 Matrix, einfarbig, ums einfach zu halten. Die hat 8x8 = 64 LED's. Wenn man den Zustand jeder einzelnen LED speichern bzw. setzen möchte, benötigt man 8x8 = 64 Bit's oder besser 64/8 = 8 Bytes. Ich könnte mir also ein Byte-Array bauen, das die Größe 8 hat, also 8 Array-Elemente mit je 8 Bit. In unserem Beispiel würde also ein Array-Element einer Zeile entsprechen und die einzelnen Bits dieses Elements der jeweiligen LED.
Somit kann ich mit LED(1).0 = 1, die erste LED in der ersten Zeile aktivieren.
Der Teil ist eh klar.

Dieses Prinzip übersetzt Ihr jetzt auf eine große LED-Matrix, dann wisst Ihr, wie ich das mache. Aus meiner Sicht ist das sehr effizient.
In Bezug auf die benötigte Speichermenge ist das zunächst mal das naheliegende. Jede LED ist ein Bit im Speicher, mit Farbe dann 2 bit.

@HinterBlauenAugen: Der Zugriff erfolgt natürlich wahlfrei. Das übertragene Word beinhaltet also das Array-Element, den Index (das Bit) und die Farbe.
Spätestens hier hört die Effizienz auf. Wenn du für jede LED anstelle der 2 Bit 2 Byte (1 Byte pro Bit) übertragen musst, kommt da natürlich einiges zusammen. Anstelle von 16KByte für das gesamte Display (256*32*2) musst du nun 128KB übertragen.
Statt die Übertragung schneller zu machen, würde ich da ansetzen.
Wenn du nur ein einzelnes Bit setzen willst, dann macht es Sinn, es so zu machen wie du es implementiert hast.
Willst du aber z.B. ein kleines Bild von sagen wir mal 16x16 Bit übertragen, würdest du mit dieser Methode 256 Byte übertragen müssen. Du könntest auch die obere Linke Ecke (2Byte) und die Höhe (1Byte) und Breite 1Byte) übertragen. Dann wären dazu nur 256Bit * 2 Farben + 4Byte, also 68 Byte notwendig, knapp ein Viertel.
Wenn du den Speicher genau so angelegt hast wie das Display, kannst du sehr leicht die Positionen der zu setzenden Pixel berechnen.

Auch an anderen Stellen sind in deinem Programm noch einige Möglichkeiten eingebaut. Dies hier
Code:
Sub Clearmatrix
        For X = 1 To Ledbuffersize
        Ledbufferred(x) = &HFF
        Ledbuffergreen(x) = &HFF
        Next
End Sub
benötigt über 60.000 Takte, würdest du Longs (&HFFFFFFFF) schreiben anstelle von Bytes (&HFF) wären es weniger als 25.000.

Dies hier
Code:
'Übertragung:      arrayIndexInput = serialInput and &b0000011111111111
     bitIndexInput =   serialInput and &b0011100000000000
     colorInput =      serialInput and &b1100000000000000

     Shift bitIndexInput , Right , 11
     Shift colorInput , Right , 14                 
     arrayIndex = arrayIndexInput
     color = colorInput
     bitIndex = bitIndexInput
wird in 231 Takten berechnet, das äquivalente

Code:
     Color = Serialinput_ovly And &B11000000
     Bitindex = Serialinput_ovly And &B00111000
     Shift Bitindex , Right , 3
     Serialinput_ovly = Serialinput_ovly And &B00000111
in 50. Bei diesen "Tricks" werden Overlays verwendet, die häufig zu dramatisch besseren Ausführungszeiten führen.

Du siehst, dass man für viele Verbesserungen nicht unbedingt ASM machen muss, wobei es dort noch schneller geht.
Schau mal, ob du diese Dinge umsetzen kannst und melde dich dann wieder.

Grüße

Sebastian
 
Moin Sebastian,

ich kann Deinen Einwand nachvollziehen, aber ich möchte einzelne Pixel explizit ansteuern können, z.B. für mein VU-Meter oder auch für's Game-of-Life. Dort wäre der Overhead mit Deiner Variante wieder zu hoch.
Ich stimme Dir zu, dass die Anzahl der zu übertragenen Bytes natürlich geringer wäre, würde ich ein statisches und vorallem "fest-definiertes" Bild übertragen, aber beim angesprochenen wahlfreien Zugriff würde das zu langsam sein. Außerdem wäre die Rechenlogik dahinter aufwändiger. Ich müsste ja zuerst den Startpunkt, dann die Höhe und Breite übermitteln und dann automatisch die folgenden Daten als "Pixel-Daten" interpretieren. Ist natürlich machbar, aber ich glaube, dass wäre bei meinen Anforderungen nicht der richtige Ansatz.

Kannst Du mir Deinen Overlay-Code mal erklären? Wie sieht die Variablen-Deklaration aus? Und wo wird die Variable 'arrayIndexInput' gefüllt?

btw. Wie schreibe ich Longs in mein Byte-Array? Geht das? Um das Array neu zu initialisieren geht doch bestimmt auch was mit Overlay...man müsste doch einfach den Speicher mit 1en überschreiben können.

Danke und Gruß
Jan
 
Moin Sebastian,

ich kann Deinen Einwand nachvollziehen, aber ich möchte einzelne Pixel explizit ansteuern können, z.B. für mein VU-Meter oder auch für's Game-of-Life. Dort wäre der Overhead mit Deiner Variante wieder zu hoch.
Ich stimme Dir zu, dass die Anzahl der zu übertragenen Bytes natürlich geringer wäre, würde ich ein statisches und vorallem "fest-definiertes" Bild übertragen, aber beim angesprochenen wahlfreien Zugriff würde das zu langsam sein. Außerdem wäre die Rechenlogik dahinter aufwändiger. Ich müsste ja zuerst den Startpunkt, dann die Höhe und Breite übermitteln und dann automatisch die folgenden Daten als "Pixel-Daten" interpretieren. Ist natürlich machbar, aber ich glaube, dass wäre bei meinen Anforderungen nicht der richtige Ansatz.
Du musst auch nicht bei jedem Befehl das Gleiche tun. Willst du ein Pixel setzen, nimmst du deine Methode. Ist es ein Feld, nimmst du die andere. Was gerade kommt musst du dem Empfänger natürlich mitteilen.
Der Rechenaufwand ist gering. Du schaltest ja immer nur einfach zum nächsten Pixel weiter (+1bit) oder du springst um eine Zeile(+32*8bit) tiefer. Für beides ist die Operation klar.

Kannst Du mir Deinen Overlay-Code mal erklären? Wie sieht die Variablen-Deklaration aus?
Dim Serialinput_ovly as Byte at Serialinput +1 overlay 'ist das MSB von Serialinput
D.h. wenn du in diese Variable etwas schreibst, landet dies im MSB von SerialInput. Da du nur dort Änderungen vornimmst, reicht dies.
Dann sind diese beiden Befehle äquivalent:
colorInput = serialInput and &b1100000000000000 'ist ein Befehl auf Word Typen, die nachher noch auf Byte gesetzt wird
Color = Serialinput_ovly And &B11000000 'ist ein Befehl auf Byte Typen, die direkt richtig steht

Und wo wird die Variable 'arrayIndexInput' gefüllt?
Gar nicht. Annahme ist, dass du die nur als Zwischenwert brauchst. Die Adresse steht nach
Serialinput_ovly = Serialinput_ovly And &B00000111
in SerialInput zur weiteren Benutzung.

btw. Wie schreibe ich Longs in mein Byte-Array? Geht das? Um das Array neu zu initialisieren geht doch bestimmt auch was mit Overlay...man müsste doch einfach den Speicher mit 1en überschreiben können.
So ist das ja gemacht.

Code:
Const Ledbuffersize_4 = Ledbuffersize / 4
Dim Ledbufferred_ovly(Ledbuffersize_4) as Long at Ledbufferred(1) Overlay 'jetzt liegen über den 1024 Byte 256 Long drüber
Dim Ledbuffergreen_ovly(Ledbuffersize_4) as Long at Ledbuffergreen(1) Overlay
For X = 1 To Ledbuffersize_4
    Ledbufferred_ovly(x) = &HFFFFFFFF
    Ledbuffergreen_ovly(x) = &HFFFFFFFF
Next

Grüße

Sebastian
 
Moin!

Hab jetzt mal alles so umgebaut und auch die Mux-Routine optimiert. Hat allerdings nix gebracht, bei 57.600 ist Schluss. Egal, ob ich den UART mit Interrupt fahre oder nicht (Config SerialIn = Buffered).

Es liegt daran, dass die Mux-Routine einfach zuviel Zeit braucht, die Grütze rauszuhauen. Somit ist meine Hauptroutine nicht in der Lage zwei Bytes sauber zu empfangen. Wenn ich die Pixel 'per Hand', also langsam setze, geht's natürlich, ist aber ja nicht Sinn der Sache.

Kann ich die Mux-Routine noch optimieren oder bringt das nix...ggf. macht es auch Sinn, das mit nem xMega zu probieren und die SPI-Clock zu erhöhen. Habe jetzt nen Teiler von 4, beim xMega könnte ich nen Teiler von 2 nehmen und 32MHz fahren.

Anbei mal mein jetziger Code.

Gruß
Jan

Code:
$regfile = "m1284pdef.DAT"
$crystal = 22118400
$hwstack = 128
$swstack = 128
$framesize = 128
$baud = 115200

Ddrb = &B11111111

strobe Alias Portb.1

Declare Sub SetLED(Byval ledX As Integer , Byval ledY As Integer , Byval color As Byte)
Declare Sub ClearMatrix

'Config Serialin = Buffered , Size = 255

Config Spi = Hard , Interrupt = Off , Data Order = msb , Master = Yes , Polarity = High , Phase = 1 , Clockrate = 4 , Noss = 1 , Spiin = 0

Spiinit

On Timer1 Mux
Config Timer1 = Timer , Prescale = 1
Enable Timer1

Enable Interrupts

Const physicalDisplayHeight = 16
Const physicalDisplayWidth = 512
Const overallPixelCount = physicalDisplayWidth * physicalDisplayHeight
Const ledBufferSize = overallPixelCount / 8
Const numberOfModulesPerRow = physicalDisplayWidth / 8

Dim ledBufferRed(ledBufferSize) As Byte
Dim ledBufferGreen(ledBufferSize) As Byte

'Used in timer-isr...
Dim currentRow As Byte
Dim startIndex As Integer

Dim x as Integer
'Fill buffer cause display's inverted (0 = LED ON, 1 = LED OFF)
For x = 1 To ledBufferSize
    ledBufferRed(x) = &HFF
    ledBufferGreen(x) = &HFF
Next

Dim serialInput As Word
Dim Serialinput_ovly as Byte at Serialinput +1 overlay

Dim arrayIndex As Integer
Dim color As Byte
Dim bitIndex As Byte

Dim ByteIsWaiting as Byte

print "GO"

'(
call setled(65 , 31 , 3)
call setled(65 , 33 , 3)
call setled(65 , 32 , 3)
call setled(128 , 31 , 3)
call setled(128 , 33 , 3)
call setled(128 , 32 , 3)
')

Do

  ByteIsWaiting = IsCharWaiting()

  If ByteIsWaiting = 1 Then

     Inputbin serialInput

     Color = Serialinput_ovly And &B11000000
     Bitindex = Serialinput_ovly And &B00111000
     Shift Bitindex , Right , 3
     Serialinput_ovly = Serialinput_ovly And &B00000111
     arrayIndex = serialInput

     'If arrayIndex = 0 Then
        'For x = 1 To ledBufferSize
        '    ledBufferRed(x) = &HFF
        '    ledBufferGreen(x) = &HFF
        'Next
     'Else
        Select Case color
               Case 0
                  ledBufferRed(arrayIndex).bitIndex = 1
                  ledBufferGreen(arrayIndex).bitIndex = 1
               Case 64                                      '1
                  ledBufferRed(arrayIndex).bitIndex = 0
                  ledBufferGreen(arrayIndex).bitIndex = 1
               Case 128                                     '2
                  ledBufferRed(arrayIndex).bitIndex = 1
                  ledBufferGreen(arrayIndex).bitIndex = 0
               Case 192                                     '3
                  ledBufferRed(arrayIndex).bitIndex = 0
                  ledBufferGreen(arrayIndex).bitIndex = 0
        End Select
     'End If

  End If

Loop

 Sub ClearMatrix

        For x = 1 To ledBufferSize
        ledBufferRed(x) = &HFF
        ledBufferGreen(x) = &HFF
        Next

End Sub


Sub SetLED(Byval ledX As Integer , Byval ledY As Integer , Byval color As Byte)

      Local ledBitIndex As Byte
      Local ledArrayIndexOffset As Integer                  'Must be integer!!!
      Local ledArrayIndex As Integer

      'Variante NEU2, 4 Display's , 128x64
      If ledY > 48 Then
         ledY = ledY - 48
         ledX = ledX + 256
      ElseIf ledY > 32 Then
         ledY = ledY - 32
      ElseIf ledY > 16 Then
         ledY = ledY - 16
         ledX = ledX + 384
      ElseIf ledX < 129 Then
         ledX = ledX + 128
      End If

      ledArrayIndexOffset = ledX / 8

      ledBitIndex = ledX Mod 8

      If ledBitIndex > 0 Then
         ledBitIndex = 8 - ledBitIndex
      Else
          Decr ledArrayIndexOffset
      End if

      Decr ledY

      ledArrayIndex = ledY * numberOfModulesPerRow
      ledArrayIndex = LEDArrayIndex + ledArrayIndexOffset

      Incr ledArrayIndex

      Select Case color
            Case 0
                 ledBufferRed(ledArrayIndex).ledBitIndex = 1       '0
                 ledBufferGreen(ledArrayIndex).ledBitIndex = 1       '0
            Case 1
                 ledBufferRed(ledArrayIndex).ledBitIndex = 0       '1
                 ledBufferGreen(ledArrayIndex).ledBitIndex = 1       '0
            Case 2
                 ledBufferRed(ledArrayIndex).ledBitIndex = 1       '0
                 ledBufferGreen(ledArrayIndex).ledBitIndex = 0       '1
            Case 3
                 ledBufferRed(ledArrayIndex).ledBitIndex = 0       '1
                 ledBufferGreen(ledArrayIndex).ledBitIndex = 0       '1
      End Select
End Sub

Mux:
   timer1 = 39000

   If currentRow = 16 Then currentRow = 0

   startIndex = currentRow * numberOfModulesPerRow

   Spiout ledBufferGreen(startIndex + 1) , numberOfModulesPerRow
   Spiout ledBufferRed(startIndex + 1) , numberOfModulesPerRow

   Spiout currentRow , 1

   Set strobe                                               'Latch data to output
   Reset strobe

   Incr currentRow
Return
 
Wenn ich die Mux-Routine splitte, schaffe ich wieder 115.200 bps...

Code:
Mux:
   TIMER1 = 52267

   If ISR_Helper = 0 Then

      Spiout ledBufferGreen(startIndex + 1) , numberOfModulesPerRow

      Incr ISR_Helper
   Else
       Spiout ledBufferRed(startIndex + 1) , numberOfModulesPerRow

       Spiout currentRow , 1

       Set strobe                                           'Latch data to output
       Reset strobe

       Incr currentRow

       Incr ISR_Helper
       If ISR_Helper > 1 Then ISR_Helper = 0
   End If

Return
 
An der Mux-Routine sehe ich nur Kleinigkeiten, die du verbessern kannst. Geschätzte 90% der Zeit geht in die beiden SPIOut Befehle, bei denen ich nicht weiß, wie man sie verbessern kann.
Klarere Möglichkeiten sehe ich beim Empfangen der beiden Bytes. Dein Ischarwaiting() reagiert sofort auf das erste übertragene Byte. Dann wird gewartet, bis das zweite Byte empfangen wurde. Das würde ich in der Regel anders machen.
Und zwar direkt mit dem URXC Interrupt. Das geht etwa so:
Code:
Dim SerialInput As Word
Dim SerialInput_ovly(2) as Byte at SerialInput Overlay
On URXC URXC_Isr
Enable URXC
...
Do
   ...
   If Flag = 1 Then
      'SerialInput wie vorher verarbeiten
      Flag = 0
   End If
   ...
Loop

End

URXC_isr:
   Incr count
   SerialInput_ovly(count)=UDR
   If count = 2 Then
      Flag = 1
      count = 0
   End If
Return
Ist jetzt nichts von getestet und nur aus der Erinnerung heraus. Also bestimmt irgendwelche Kleinigkeiten übersehen.
Um die Routine so kurz wie möglich zu halten, kann man die Isr noch mit der NoSave Option aufrufen. Dazu muss man analysieren, welche Register in ihr benutzt werden.

Grüße

Sebastian
 
Moin!

Werd' ich mal ausprobieren.

btw. Habe mal die Anzahl der Displays erhöht, fahre jetzt 8 anstatt 4, also DisplayWidth ist 1.024 statt 512. Er muss jetzt also statt 64 Bytes 128 Bytes per SPI raushauen. Läuft ebenfalls sauber mit 57.600. Denke, an den SPIOut's kanns irgendwie auch nicht liegen.

Gruß
Jan
 
Da der Empfang nach meinem Vorschlag mit ISR arbeitet, ist es evtl. angebracht, die Ausgabe über SPIOut nicht unterbrechbar zu machen. Dazu wäre es aber vielleicht sinnvoll, nicht zu große Blöcke rauszuschieben. Sonst kann es passieren, dass das Zeichen nicht rechtzeitig abgeholt wird.
Wie sind denn jetzt deine aktuellen Parameter von

Const physicalDisplayHeight = 16
Const physicalDisplayWidth = 512

Grüße

Sebastian
 
Habe ja schon mit verschiedenen Blockgrößen experimentiert, siehe #35 und #39. Wenn ich mehrere Blöcke schicke, muss ich natürlich auch die entsprechende Array-Position vorher ausrechnen. Alles in allem bringt es nix, daher habe ich die Blöcke so gross wie möglich gemacht, um so wenig wie möglich rechnen zu müssen.

Und gerade das "Unterbrechen" bewirkt, dass ich auf die höhere Baudrate gehen kann, auch wenn es sich anscheinend nur um µS handelt.

btw. Die Werte sind aktuell. Habe 4 Displays dran. Ein Display besteht physikalisch aus 128 x 16 Pixeln, die allerdings in 64 x 32 aufgebaut sind. Sie haben jeweils 2 Eingänge für Rot und Grün, nutzen aber denselben 4 nach 16 Demuxer für die Zeilen.

Gruß
Jan
 
Da der Empfang nach meinem Vorschlag mit ISR arbeitet, ist es evtl. angebracht, die Ausgabe über SPIOut nicht unterbrechbar zu machen.
War eh Quatsch, da die Mux Routine ja die ISR vom Timer1 ist, wird also eh nicht unterbrochen.
Und gerade das "Unterbrechen" bewirkt, dass ich auf die höhere Baudrate gehen kann, auch wenn es sich anscheinend nur um µS handelt.
Wie gesagt, er musste vorher warten, bis das nächste Zeichen kommt. Mit dem Interrupt ist das weg.
Deine Mux-Isr dauert jetzt etwas mehr als 1/10000s. In der Zeit schaffst du 80Kbaud.
Wenn der UART in der Zeit mehr als 2 Zeichen sendet, geht eins verloren.

Grüße

Sebastian
 
Hallo,

versuche möglichst in zeitkritischen Bereichen keine Division oder Multiplikation zu verwenden. Versuch es irgendwie auf Schiebeoperationen umzuarbeiten. Zum Beispiel ...
x/2 ... => ... um 1 Bitposition nach rechts schieben
x/8 ... => ... um 3 Bitpositionen nach rechts schieben
x*4 ... => ... um 2 Bitpositionen nach links schieben
usw.
Versuch nur Ganzzahl-Operationen auszuführen und deine Operationen irgendwie auf logische Operationen zurückzuführen die auch im Assembler-Befehlssatz existieren. Das beschleunigt ganz erheblich.

Gruß
Dino
 
Moin!

Nachdem ich jetzt noch mehr Displays (192x96) dran hab, kann ich das über RS232 eh vergessen. Meine Idee ist jetzt, einen weiteren AVR einzusetzen, der die Daten per RS232 empfängt und dann per SPI an meinen "Display"-AVR schiebt, der den Inhalt wiederum direkt in die LEDBuffer schreibt.
Da ich für die Displays ja nur den MOSI nutze, kann ich den MISO bestimmt für die Dateneingabe nutzen. Somit übernimmt dann ein anderer Avr den Datenempfang und wird nicht dauernd durch die Multiplex-ISR unterbrochen.

Habe das o.a. jetzt noch nicht probiert; meine Frau k*tzt schon rum, weil ich ständig vor dem Kram hänge, daher ist meine Zeit start begrenzt :) Hat jemand ggf. einen Codeschnipsel, der sowohl Sender als auch Empfänger beinhaltet?
Konkret geht es ja darum, während der Display-AVR das Display per SPI befeuert, auf dem selben SPI Daten zu empfangen und passend in die Buffer zu kippen. Der Sender muss ja nur ständig die Daten, die er per RS232 bekommt, per SPI rausrotzen.

Habe mit dem SPI-Empfang leider noch nie was gemacht, daher meine Unwissenheit. Ggf. geht das ja auch per I²C, aber das ist zu langsam, denke ich?!

Danke und Gruß
Jan
 
Hi Jan,

Konkret geht es ja darum, während der Display-AVR das Display per SPI befeuert, auf dem selben SPI Daten zu empfangen und passend in die Buffer zu kippen. Der Sender muss ja nur ständig die Daten, die er per RS232 bekommt, per SPI rausrotzen.

Habe mit dem SPI-Empfang leider noch nie was gemacht, daher meine Unwissenheit. Ggf. geht das ja auch per I²C, aber das ist zu langsam, denke ich?!
also I2C ist glaube ich maximal 400kHz (also mit Protokolloverhead bei 300-350kBit/s Nettovolumen Eher weniger).

Der SPI sendet und empfängt gleichzeitig. Das heißt ... ein 8Bit-Schieberegister sendet und empfängt die Daten gleichzeitig. Das auf dem einen Ende rausgeschoben (gesendet) wird und gleichzeitig auf dem anderen Ende Bits im Schieberegister angenommen werden. Wenn du also ein Byte gesendet hast, dann ist es aus dem Register verschwunden. Es wurde durch das ersetzt was du gleichzeitig empfangen hast.

Es gibt aber nur einen einzigen Master auf dem SPI-Bus. Wenn du also mit dem einen Atmel die Daten über SPI an die ICs des Displays sendest, dann mußt du mit dem identischen Taktsignal die Daten aus dem anderen Atmel (der mit der RS232) rausholen. Du empfängst also jedesmal ein Byte vom RS232-Atmel wenn du ein Byte zum Display schiebst.

[RS232-Atmel]----->------[Display-Atmel]----->-----[Display-Register]

Der Takt muß wegen der Displaysteuerung dabei zwangsweise vom Display-Atmel kommen. ... herzlichen Glückwunsch :rolleyes:

Hast du schonmal an Assembler gedacht um Zeit im Programmablauf zu sparen ? :p ;)
Eventuell würde ich nen Atmel einsetzen der notfalls mit 20MHz Takt laufen kann.
Dann ist schonmal etwas Reserve da.

Danach sollten wir mal zusammen die gesammelten Daten des Projektes auf den Tisch legen und drübersehen (Vor allem Schaltplan) um zu sehen wo man von der Hardware optimieren kann und dadurch Engstellen umschiffen kann.
Oder ob man irgendwo grundsätzlich am Konzept was optimieren kann. So könnte es bei den Datenraten über kurz oder lang auf nen Hammer laufen.

Dann würde ich weitersehen.

Gruß
Dino
 
Der SPI sendet und empfängt gleichzeitig.

Heißt also, dass ich die Daten in der Mux-Routine auch wieder empfangen muss. Und mein RS232-AVR dabei als SPI-Slave fungiert.

Hast du schonmal an Assembler gedacht um Zeit im Programmablauf zu sparen ?

Den Code hat Sebastian schon optimiert, mehr ist da wohl ohne Assembler nicht drin. Leider kann ich das nicht. Hat nur für Basic gereicht, hehe...

Eventuell würde ich nen Atmel einsetzen der notfalls mit 20MHz Takt laufen kann.

Der Atmel läuft schon übertaktet mit 22,1184MHz.

Bzgl. der Hardware hab ich m.E. schon alles rausgeholt. Die Schaltung ist so einfach, dass es keinen Plan gibt :) Wenn ich mal Luft habe, male ich aber gern einen.
Im Prinzip steuert nen ganzer A*schvoll HC595er die Spalten und ein 4->16-Decoder (2 x HC138) die Zeilen. Der einzige Trick an der Geschcihte ist, dass ich für die Zeilen auch nen HC595 nehme, um alles per SPI machen zu können. Heißt also, dass die 4 Demuxer-Eingänge auf die ersten 4 Ausgänge des HC595er gehen und der Overflow auf den Dateneingang des ersten Displays. Um nun die korrekte Zeile zu wählen, sende ich als letztes ein Byte per SPI, das eben diese Zeile enthält. Kann man im Code schön sehen.
 
Heißt also, dass ich die Daten in der Mux-Routine auch wieder empfangen muss. Und mein RS232-AVR dabei als SPI-Slave fungiert.
Nein.

Das Register (Schieberegister) des SPI-Interfaces hat zwei Enden (wie ne Wurst). Das eine Ende liegt am Pin MOSI und das andere Ende am Pin MISO. Das ist so als wenn du bei der Wurst den Finger an einem Ende in die Pelle drückst. Dann quillert am anderen Ende der ganze Inhalt raus und dein Finger steckt an Stelle des Inhalts in der Wurst :cool: :rolleyes:

Finger --->---- Wurst ---->--- ehemaliger Inhalt der Wurst.

Entweder du läßt den Inhalt einfach auf den Boden fallen oder du stellst ne Schüssel drunter wenn du es weiterverarbeiten willst. Wenn du die Wurst statt mit dem Finger mit was sinnvollerem (Senf/Ketchup) füllen willst dann drückst du nicht den Finger in die Pelle sondern steckst die Tülle der Tube an der Stelle rein. Der ehemalige Inhalt fällt aber trotzdem raus und du hast jetzt statt des Fingers Senf oder Ketchup in der Wurstpelle.:hahaha: :stupid: :tomato:

Gruß
Dino
 
Ja, das hab ich schon begriffen, aber trotzdem ne super Erklärung, hehe...

Ich meinte damit, dass ich die Daten des RS232-AVR im selben Moment einlesen muss, also wie Du schon sagtest, mit dem selben Taktsignal...Die Daten, die ich ans Display rausrotze brauche ich ja am Ende nicht mehr, die fallen also auf den Boden, quasi ;)

Gruß
Jan
 
Hi Jan,

Ich meinte damit, dass ich die Daten des RS232-AVR im selben Moment einlesen muss, also wie Du schon sagtest, mit dem selben Taktsignal...
nur ...
- woher weiß der Atmel mit der RS232 wann er die Daten in sein SPI-Register für den Versand reinschreiben soll ?
- Woher weiß der Display-Atmel das er ein gültiges Byte von RS232-Atmel bekommen hat ?
- Woher weiß der Display-Atmel das der RS232-Atmel evtl noch nichts neues in das Datenregister geschrieben hat und er dadurch nicht bloß Blödsinn empfängt ?

Fragen über Fragen ... Aber wir wollen ja Lösungen suchen ;) :cool:

Gruß
Dino
 

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