Hallo,
ich möchte Daisy Chain mit mehreren AVRs machen. Aufbau wie hier
http://www.mikrocontroller.net/articles/SPI_Daisychain
Der Master ist hier nicht das Problem. Den habe ich bereits mit
Shiftregistern getestet.
SS low
alle Daten schicken
SS high
Nun ist aber die Frage, wie ich bei den Slaves am besten vorgehe. Jeder
Slave soll 3 Byte erhalten.
Gibt es dazu einen kleinen Code für HardwareSPI`?
So, habe einen kleine Teilerfolg. Nun kommen die Werte schon einmal
richtig an. Stellt sich die Frage, wohin mit data[2] damit dieser am
MISO wiederbereitsteht für den nächsten MOSI am folgenden AVR.
Werde gleich noch anstatt der Abfrage in der while Schleife einen
Interrupt mit steigender Flankenerkennung einbauen. Der Attiny macht nur
eine PWM für 3 Leds. Ansonsten ist er dauerhaft im Leerlauf.
Auch wenn ich nicht dazu beitragen kann, so ist das schon mal was, das
ich in der Zukunft auch machen möchte.
Danke für deinen Beitrag. Hoffe ich lerne so eine Menge darüber.
Nochmal einen Nachtrag. Der Master funktioniert soweit korrekt. Sendet
je angehängten Controller 3 Bytes.
Nur macht mir die ISR zu schaffen.
Wie läuft die ISR genau ab?
Sobald ein Byte empfangen ist?
Wenn ja, wie muss ich die ISR anpassen damit das ganze richtig
weitergeleitet wird.
1
ISR(SPI_vect)
2
{
3
data[3]=data[2];// Ueber MISO an den nächsten MOSI.
Sebastian schrieb:> Wie läuft die ISR genau ab?>> Sobald ein Byte empfangen ist?
Genau.
> Wenn ja, wie muss ich die ISR anpassen damit das ganze richtig> weitergeleitet wird.
Dein Problem ist ein ganz anderes.
Die SPI EInheit kann entweder Master oder Slave sein.
Natürlich könnte man die laufend umkonfigurieren. Aber ob das so schlau
ist? Denn während die SPI Einheit als Master sendet, sollte sie ja als
Slave eingangsseitig weiterhin auf Empfang bleiben.
Ich würde mir die Master Seite jedes Slaves in der Chain selbst
ausprogrammieren. Ist ja keine Raketentechnik.
1
#define SEND_PORT PORTB
2
#define SEND_DATA_PIN PB6
3
#define SEND_DATA_CLOCK PB7
4
#define SEND_SS PB5
5
6
#define SEND_DELAY 5
7
8
voidsendStart()
9
{
10
SEND_PORT&=~(1<<SEND_SS);
11
}
12
13
voidsendFinished()
14
{
15
SEND_PORT|=(1<<SEND_SS);
16
}
17
18
voidsendByte(uint8_tbyte)
19
{
20
uint8_ti;
21
for(i=0;i<8;i++)
22
{
23
if(byte&0x80)// High Bit zuerst
24
SEND_PORT|=(1<<SEND_DATA_PIN);
25
else
26
SEND_PORT&=~(1<<SEND_DATA_PIN);
27
28
_delay_us(SEND_DELAY);// Datenbit liegt an. Gib dem Empfänger ein
29
// bisschen Zeit.
30
31
SEND_PORT|=(1<<SEND_CLOCK);
32
_delay_us(SEND_DELAY);
33
SEND_PORT&=~(1<<SEND_CLOCK);
34
35
byte<<=1;
36
}
37
}
Damit hast du eine Software-SPI, mit der du Bytes an den nächsten Slave
weiterschicken kannst (aber bitte nicht aus der ISR heraus).
Karl Heinz schrieb:> Die SPI EInheit kann entweder Master oder Slave sein.> Natürlich könnte man die laufend umkonfigurieren. Aber ob das so schlau> ist? Denn während die SPI Einheit als Master sendet, sollte sie ja als> Slave eingangsseitig weiterhin auf Empfang bleiben.
Dazu kommt natürlich dann ja auch, dass du ja nur einen Satz an
Hardware-SPI Pins hast. Aus Sicht eines deiner Slaves benötigst du aber
2 'Anschlüsse'. Auf dem einen Satz von Leitungen kommen die Bytes vom
jeweiligen Vorgänger in der Chain rein, auf dem anderen Satz von
Leitungen gehen die Bytes an den jeweiligen Nachfolger raus.
Sebastian schrieb:> Nochmal einen Nachtrag. Der Master funktioniert soweit korrekt. Sendet> je angehängten Controller 3 Bytes.>> Nur macht mir die ISR zu schaffen.>> Wie läuft die ISR genau ab?>> Sobald ein Byte empfangen ist?>> Wenn ja, wie muss ich die ISR anpassen damit das ganze richtig> weitergeleitet wird.>>
1
>ISR(SPI_vect)
2
>{
3
>data[3]=data[2];// Ueber MISO an den nächsten MOSI.
4
>data[2]=data[1];
5
>data[1]=data[0];
6
>data[0]=SPDR;
7
>}
8
>
etwa so:
temp = data[2];
data[2] = data[1];
data[1] = data[0];
data[0] = SPDR;
SPDR = temp;
Das würde gehen, wenn der Master eine kleine Pause alle 8 Bits macht,
damit der Slave die ISR ausführen kann.
Das nächste Problem ist, wann weiß der Slave das alle Daten Übertragen
sind.
Das SS-Signal wird zwar von de SPI-Einheit ausgewertet, aber die
Software kommt da nicht ran.
Man brauch eine weitere Interrupt-Quelle die erkennt, dass das SS-Signal
OFF geht (logisch HI). Entweder man legt das SS-Signal zusätzlich an
einen INT-Eingang, oder man nimmt einen PIN-Change-Interrupt der die
meisten TINYs und MEGAs an allen Pins haben.
EDIT:
Da es Zeitkritisch ist, SPDR zu früh wie möglich neu schreiben:
Sebastian schrieb:> Nun ist aber die Frage, wie ich bei den Slaves am besten vorgehe. Jeder> Slave soll 3 Byte erhalten.
Exakt die gleiche Frage gabs doch vor einigen Tagen schonmal, such mal
danach.
An der Gültigkeit der damaligen Antworten hat sich zwischenzeitlich
nichts geändert.
Hab den Thread durchgelesen, aber da wird in allen Richtungen spekuliert
:(
Das senden ist bei mir kein Problem. Es werden 6 Bytes rausgesendet (hab
dem ganzen mal ein paar µs Zeit gegegben.
Nur bekomme ich es nicht hin, dass wenn nun SS LOW ist, dass die Bytes
durch alle Slaves geschoben werden.
Wenn ich 255, 255, 255, 0, 0, 255 als Bytes sende, soll es in Slaves
sobald SS wieder HIGH ist, wie folgt aussehen.
Slave1
255, 255, 255
Slave2
0, 0, 255
SPDR=buffer[i];// Writing to the register initiates data transmission.
6
while(!(SPSR&(1<<SPIF)));// waiting for SPI Interrupt Flag
7
_delay_us(50);
8
}
9
PORTA|=(1<<PORTA7);//SS to Hi
10
}
Welchen AVR Controller verwendest du, im Masterbetrieb MUSS der SS-Pin
als Output konfiguriert werden, auch wenn du einen anderen Pin benutzt
um die Slaves zu selektieren.
Wie sieht dein Code jetzt in den Slaves aus?
Schein an sich alles richtig zu sein.
Der Tiny kann die SPI-Leitungen wahlweise auf andere Pins Mappen:
Standard ist PA4 bis 7
A4 / A3 ist dein SCK
A5 / A0 ist dein SPI Output
A6 / A1 ist den SPI Input
A7 / A2 ist SS
und auf B1 ist ebenfalls das SS-Signal?
in deinen //.. versteckt sich hoffentlich das sei()
Welchen tackt haben die Controller und welche SPI Clock gibt der Master
vor?
@Karl Heinz das sollte alles problemlos mit der Hardware-SPI gehen.
und jetzt hast du deinen Beitrag gelöscht
Christian K. schrieb:> @Karl Heinz das sollte alles problemlos mit der Hardware-SPI gehen.> und jetzt hast du deinen Beitrag gelöscht
Ja, weil ich meinen Irrtum erkannt habe.
Christian K. schrieb:> Schein an sich alles richtig zu sein.>> Der Tiny kann die SPI-Leitungen wahlweise auf andere Pins Mappen:>> Standard ist PA4 bis 7>> A4 / A3 ist dein SCK> A5 / A0 ist dein SPI Output> A6 / A1 ist den SPI Input> A7 / A2 ist SS> und auf B1 ist ebenfalls das SS-Signal?>> in deinen //.. versteckt sich hoffentlich das sei()>> Welchen tackt haben die Controller und welche SPI Clock gibt der Master> vor?>> @Karl Heinz das sollte alles problemlos mit der Hardware-SPI gehen.> und jetzt hast du deinen Beitrag gelöscht
Hallo Christian,
was möchtest du mit dem Remap mir erzählen? Dass ich die SPI
Schnittstelle umlegen kann, ist mir bekannt, aber ich sehe da keinen
nutzen drin.
Also auf B1 habe ich das SS-Signal gelegt und es mittels Interrupt
abgefragt. SS ist ansonsten nirgends angeschlossen.
Die Master sendet mit FCK/16. Alle Tinys laufen mit den internen 8MHz.
Christian K. schrieb:> Sebastian schrieb:>> DDRB &= ~(1<<PORTB1);>> PORTB |= (1<<PORTB1);>> Willst du da den internen PullUp aktivieren?
Ja, aber mir fällt gerade auf, das geht bei den neuen Attinys ja über
ein gesondertes Register PUExn
Sebastian schrieb:> was möchtest du mit dem Remap mir erzählen? Dass ich die SPI> Schnittstelle umlegen kann, ist mir bekannt, aber ich sehe da keinen> nutzen drin.
Gut, hätte ja sein gekonnt das du das übersehen und die falschen Pins
genommen hast.
> Also auf B1 habe ich das SS-Signal gelegt und es mittels Interrupt> abgefragt. SS ist ansonsten nirgends angeschlossen.
Wie meinst du dass, SS geht nur an B1 oder zusätzlich zu B1 nirgendwo
anders?
Die Hardware-SPI der Slaves brauch auf jeden Fall das SS-Signal, fest
auf GND geht nicht, da sie im Gegensatz zu 0815 Schieberegistern
Byte-orientiert arbeiten, und sonst nicht wissen wann das erste Bit los
geht.
Einem 74x595 wäre das egal, da kann man es fest ah GND legen.
Ein externe PullUP von 10KOhm für das SS-Signal wäre optimal.
Die SPI Pins hatte sich soweit schon richtig. Brauch diese ja auch für
das Programmieren. Bei den Alternative Port geht das nicht.
Ich werde dass mit SS noch einmal abändern.
Ich schaue gerade schon, ob es bei mir nicht sogar Sinn macht, dass
ganze über USART in SPI Mode (synchron) zu machen. Da müsste ich doch
dann 2 getrennte Hardware Systeme haben, die sich nicht in die Querre
kommen. Ich muss halt nur darauf achten, dass ich das ganze so belegte,
dass ich später noch Platz für 3 PWM (16 Bit-Timer) überhalte.