Hi,
ich versuche grade ein 16bit Zeichen von einem Atmega88 auf einen
Attiny2313 zu übertragen. Mit 8bit funktioniert es soweit auch.
Mein Ansatz ist zwei 8bit Zeichen von dem mega88 zusenden und dann im
2313 immer zwei 8bit zu einem 16bit Zeichen zusammen zusetzen.
Das Problem ist, dass er jedes 8bit Zeichen ca. 6mal empfängt oder
sendet.
Wie kommt es dazu? Muss ich auf irgendwas achten, damit es nur einmal
gesendet wird?
Momentan sende ich nur ein 8bit Zeichen und zähle wie oft es empfangen
wurde.
Atmega88:
Also auf den Sender läuft sonst nur noch das irmp Programm hier aus dem
Forum, aber das hat so weit ich weiß nichts mit dem SPI zu tun, oder
etwa doch?
Die Tasten von der IR sind entprellt. Das er also mehr mals die
Sendefunktion aufruft kann sein.
Hardware seitig ist das es ohne SS, also nur Clock MOSI und MISO sind
verbunden.
Bei dem Empfänger läuft sonst noch ein Timer interrupt und ein UART
interrupt und sonst noch ein code um zwei Siebensegmet anzeigen
anzusteuern.
Wie kann denn die "ISR (USI_START_vect)" noch aufgerufen werden? Oder
brauch der µC hardwareseitig so lange um das interrupt bit wieder zu
löschen, dass er das ganze noch 6 mal aufruft, denn wenn ich den counter
zu Testzwecken verzögert in der main zählen lasse, dann zählt er
richtig, also folgen die 5 ungewollten interrupts unmittelbar nach der
Sendung.
Ein "volatile" vor der Variablen initaliesierung hab ich auch beim
counter.
Erich schrieb:> Muss man nicht e r s t abfragen, ob das (vorherige) Byte rausgegangen> ist?
Muss man! Erst SPSR einlesen und wenn SPIF gesetzt ist, dann SPDR
schreiben. Dies löscht dann auch SPIF. Das allererste Byte schreibt man
direkt, weil ja erst nach dessen Übertragung SPIF das erste Mal gesetzt
wird.
Ja ist es, aber ich brauche es nur in ein Richtung.
Hab es jetzt aber auch mal so Probiert:
Sender:
1
voidSPI_MasterTransmit(uint8_tcData)
2
{
3
SPDR=cData;
4
while(!(SPSR&(1<<SPIF))){};
5
returnSPDR;
6
}
Empfänger:
1
ISR(USI_START_vect)
2
{
3
while(!(USISR&(1<<USISIF)));
4
SPI_Register=USIDR;
5
USISR|=(1<<USISIF);
6
while(!(USISR&(1<<USISIF)));
7
USIDR=12;
8
counter++;
9
}
Dann bleibt er aber im zweiten "while" in der ISR hängen und ohne while
macht er gar nichts.
Mir ist aufgefallen, das er je nach dem welches Zahl ich sende, er
unterschiedlich viele Zyklen macht aber jedes mal ungefähr die gleiche
Anzahl bei der selben Zahl.
@Dshing
Hallo,
kann es sein, das von IRMP der Tastenrepeat als mehrmaliges Drücken der
entsprechenden Taste weitergegeben wird, und der Sender deshalb den Code
mehrmals sendet?!
Sascha
Also ich bin mir nicht ganz sicher, was du meinst, aber beim Sender
kommt er ja nur in die switch Anweisung, wenn der list.schalter1==0. Den
lasse ich ja aber dann gleich wieder auf 1 setzen und brauch er 0,7s bis
er es wieder auf 0 setzt.
Gibt es denn noch eine andere Möglichkeit ein Zeichen mit >=16bit zu
übertragen als mit so einer counter Variante?
Dshing Sung schrieb:> Also ich bin mir nicht ganz sicher, was du meinst
Was er meint ist:
Hast du eigentlich schon mal überprüft, ob der Sender 6 mal empfängt,
weil der Sender 6 mal sendet? Denn das wäre die naheliegenste Erklärung
für dein beobachtetes Verhalten am Empfänger.
Infrarot-Fernsteuerungen senden bei einem Tastendruck normalerweise
mehrmals die Tastenbetätigung.
Dshing Sung schrieb:> Gibt es denn noch eine andere Möglichkeit ein Zeichen mit >=16bit zu> übertragen als mit so einer counter Variante?
also der Counter allein ist Mist, da du keine Syncronisierung hast wann
das 1. Byte kommt.
Du must in deiner SPI noch eine Leitung als SlaveSelect hinzufügen. Wenn
die sagen wir mal L-Active ist, dann weiß der Empfänger das nach einem
Übergang von H->L als nächstes das ERSTE von n-Byte kommt. Nachdem alle
Bytes übertragen sind wird die select-Leitung wieder deaktiviert.
bisher sehe ich in deinem Code aber nicht's zur Übertragung von
16Bit-Werten.
Sascha
Also ich hab auf der Senderseite jetzt mal das IRMP komplett
rausgenommen.
Und nur das notwendigste gelasen. Aber es bleibt beim Alten. Also muss
der Fehler doch im Empfänger liegen oder, nur wo?
Also ich hab jetzt mal die CLK-Frequenz geändert, wenn ich sie
verdopple, dann halbiert es sich von ca. 6 auf 3 und wenn ich die
Frequenz halbiere bekomme ich ca. 13 Durchläufe.
Also scheint der Fehler eine Zeit basierend zu sein, aber leider hilft
mir das nicht weiter :(
also dein Problem liegt im Empfänger
Datenblatt tn2313
<Zitat>
• Bit 7 – USISIF: Start Condition Interrupt Flag
When Two-wire mode is selected, the USISIF flag is set (to one) when a
start condition is detected. When output disable mode or Three-wire mode
is selected and (USICSx =0b11 & USICLK = 0) or (USICS = 0b10 & USICLK =
0), any edge on the SCK pin sets the flag.
</Zitat>
zum Empfang verwendest du die USI_START_ISR - wann wird die ausgelöst?!
Mit deiner Init des USI ist die Bedingung (USICS = 0b10 & USICLK = 0)
erfüllt, und damit bekommst du mit jeder Taktflanke an SCK einen
Interrupt -> also 16x pro Byte!
Sascha
Achso, da ist mein Englisch wohl einfach zu schlecht, ich dachte nicht
das das heißt, dass er bei JEDER CLK-Flanke auslöst. Also muss ich jetzt
bei jeder Sendung nach der ersten Flanke den Interrupt ausschalten und
danach wieder einschalten? Gibt es da nicht eine elegantere Lösung? So
wie auch beim UART?