Forum: Compiler & IDEs atmega8<--->SPI<--->atmega8


von dieter (Gast)


Angehängte Dateien:

Lesenswert?

hallo,

ich bin relativer mikrocontrolleranfänger, habe aber die ersten hürden
schon hinter mir.
nun versuche ich mich daran daten per spi zwischen 2 atmega8
auszutauschen, was aber nicht klappt.
der master sollte mir was (z.b.15) an den slave schicken und der sollte
sie ausgeben. aber leider schreibt schon der master in das SPDR 255 und
nicht die gewünschte 15.
vielleicht kann ja jemand helfen.
danke!

dieter

von dieter (Gast)


Lesenswert?

kann mir denn keiner helfen!
dieter

von Karl heinz B. (kbucheg)


Lesenswert?

Woher weist du eigentlich dass da 255 reingeschrieben
wird und nicht 15?

Ansonsten: Wenn du auf Byte-Ebene arbeitest, wie in diesem
Fall, dann solltest du als Datanetyp 'unsigned char' benutzen
und nicht 'int'. Ob das bei deinem konkretem Problem
was hilft kann ich nicht sagen, da ich den Compiler
so nicht kenne (ist wohl kein gcc, so wie die Initialisierungs-
Sequenz aussieht wurde die von einem IDE-Wizard generiert,
dessen Namen mir im Moment nicht einfällt.)

von dieter (Gast)


Lesenswert?

du hast recht, das weiß ich nicht, da ich mir ja nur den inhalt des SPDR
ausgeben lasse und nicht was er reinschreibt.
habe es auch mit 'unsigned char' ausprobiert, der slave gibt mir aber
dennoch nicht, wie von mir beabsichtigt die 15 aus.
ja, ist mit wizard von codevision erstellt.

von Michael Wilhelm (Gast)


Lesenswert?

Bevor du ins SPDR schreibst, frage mal ab, ob die SPI überhaupt frei ist
(irgend so ein Bit im SPSR, glaube ich),

MW

von dieter (Gast)


Lesenswert?

wenn du das SPIF im SPSR meinst, das ist null.

von Karl heinz B. (kbucheg)


Lesenswert?

Ich wuerde mal als erstes aus den while-Schleifen
die Aufrufe von   Master_init  und  Slave_init rauswerfen.
Vor allem beim Slave bin ich mir fast sicher, dass das keine
gute Idee ist, den SPI ständig neu zu initialisieren. Vor
allem dann nicht wenn gerade eine Übertragung läuft :-)
Zumal ja der Slave auch gar nicht darauf wartet, dass ihm
die SPI die Ankunft eines Zeichens signalisiert.

Initialisiert wird nur einmal. Der Codevision Wizard
hat dir die Initialisierungen bereits eingebaut. Kein
Grund das nochmal selbst zu machen, vor allem nicht in
einer Schleife.

von dieter (Gast)


Lesenswert?

klingt sehr einleuchtend und habe ich auch gemacht, aber leider gibt mir
der slave immer noch nicht das aus was ich will.

von dieter (Gast)


Lesenswert?

war ein verzwickter hardwarefehler. klappt jetzt!
trotzdem danke an alle!
dieter

von dieter (Gast)


Lesenswert?

nun habe ich schon wieder eine frage:
wie kann ich denn größere daten als 8 bit übertragen?

von Karl heinz B. (kbucheg)


Lesenswert?

Indem du die gesammte Übertragung auf mehrere
8 Bit Teile aufdröselst.

Das ist allerdings naheliegend, daher jetzt meine
Frage: Was ist dein konkretes Problem?

von dieter (Gast)


Lesenswert?

mein problem ist, dass ich leider nicht weiß, wie ich das machen kann.
ich habe ein 20 bit meßwert, den ich übergeben muß.

von Karl heinz B. (kbucheg)


Lesenswert?

20 bit

3 * 8 = 24

Also die 20 Bit in 3 Bytes aufteilen und nacheinander
senden. In welchem Datentyp hast du den die 20 Bit?
(geraten: long. da long aus 4 Bytes besteht, würde ich
der Einfachheit halber alle 4 Bytes übertragen. Dann braucht
man sich keinen Kopf darüber zerbrechen, wo jetzt das
Highbyte liegt).

Kannst du zb so machen:

  void SendLong( long DerWert )
  {
    unsigned char* pData = (unsigned char*)&DerWert;

    SendByte( *pData++ );
    SendByte( *pData++ );
    SendByte( *pData++ );
    SendByte( *pData++ );
  }

und auf der Gegenstelle setzt du alles wieder zusammen

  long ReceiveLong()
  {
    long EmpfangenerWert;
    unsigned char* pTmp = (unsigned char*)&EmpfangenerWert;

    ReceiveByte( pTmp++ );
    ReceiveByte( pTmp++ );
    ReceiveByte( pTmp++ );
    ReceiveByte( pTmp++ );
  }

EmpfangeByte muss natuerlich warten, bis auch tatsaechlich
ein Byte daherkommt.

Dazwischen würde ich noch ein Byte mit bekanntem Inhalt setzen,
damit sich die Übertragung auch synchronisieren kann. Ein
einfaches Protokoll eben.

  void SendMesswert( long Wert )
  {
    SendByte( 'M' );
    SendLong( Wert );
  }

  long ReceiveMesswert()
  {
    unsigned char Tmp;

    //
    // Warte bis das Synchronisationsbyte daherkommt
    //
    do {
      ReceiveByte( &Tmp );
    while( Tmp != 'M' );

    // Synchronisation ist da. Jetzt die eigentlichen
    // Daten

    return ReceiveLong();
  }

In der Praxis wird man das wahrschinlich nicht mit Pollen
machen, sondern über Interrupt Funktionen. Aber ich will dir
ja nur die Idee eines Protokolls nahebringen. Und ausserdem
soll für dich ja auch noch was zu tun übrig bleiben :-)

von Karl heinz B. (kbucheg)


Lesenswert?

>  long ReceiveLong()
>  {
>    long EmpfangenerWert;
>    unsigned char* pTmp = (unsigned char*)&EmpfangenerWert;
>
>    ReceiveByte( pTmp++ );
>    ReceiveByte( pTmp++ );
>    ReceiveByte( pTmp++ );
>    ReceiveByte( pTmp++ );

     return EmpfangenerWert;

>  }

von Jürgen (Gast)


Lesenswert?

Guten Tag,

hoffentlich kann mir jemand auch bei der Hitze helfen.
Ich habe leider auch ein Problem mit dem SPI.
Ich möchte 2 Bytes nacheinander vom Master an den Slave schicken und
der slave gibt mir immer nur das zweite Byte aus.
Master:

char Master_write1(unsigned char data)
{    char received=0;
  SPDR = data;
  while(!(SPSR&0x80));
  return received;
  }

char Master_write2(unsigned char data2)
{
  char received2=0;
  SPDR = data2;
  while(!(SPSR&0x80));
    return received2;
}

Slave:

unsigned char Slave_Read1(void)
{
  SPDR=0x00;
  while(!(SPSR&0x80));
   data=SPDR;
   return data;
}

unsigned char Slave_Read2()
{

   SPDR=0x00;
   while(!(SPSR&0x80));
   data2=SPDR;
   return data2;


}

Was mache ich falsch?

Gruß

Jürgen

von johnny.m (Gast)


Lesenswert?

> unsigned char Slave_Read1(void)
> {
>   SPDR=0x00;
>   while(!(SPSR&0x80));
>   data=SPDR;
>   return data;
> }

Ist data (bzw. data2) global? Wozu dann ein return? Ansonsten mal ne
ganz blöde Frage: Warum zwei Funktionen, die sich (bis auf einen
Index) überhaupt nicht unterscheiden? Da tuts auch eine Funktion...

von johnny.m (Gast)


Lesenswert?

Ach ja, mehr kann ich übrigens nur sagen, wenn ich den Rest vom Code
kenne. (Ich weiß jetzt nicht, ob wir den Witz mit der Kristallkugel
heute schon hatten, deshalb schenke ich mir den jetzt...)

von Jürgen (Gast)


Lesenswert?

Ja die sind beide global.
Die beide funktionen sind gleich, aber ich will damit auch nur testen
ob das übertragen zweier Funktionen hintereinander funktioniert. Das
tut es ja leider auch nicht.

von Jürgen (Gast)


Angehängte Dateien:

Lesenswert?

Sorry habe den Anhang vergessen.

von johnny.m (Gast)


Lesenswert?

Fällt mir doch noch was auf: Der Slave wartet in einer Funktion darauf,
dass vom Master was kommt. Woher weiß der Slave, dass er diese Funktion
aufrufen muss? Er kann ja nicht wissen, wann der Master mit ihm reden
will.

Angenommenes Szenario: Der Slave macht grad irgendwas
(Hauptprogramm...) und kümmert sich einen Dreck um alles andere.
Inzwischen hat der Master Lust bekommen, dem Slave was zu schicken,
warum auch immer. Er schickt sein erstes Byte los. Der Slave ist aber
immer noch dabei, irgendwas anderes zu machen. Da SPI nicht
Interrupt-gesteuert abgefragt wird, bekommt er gar nicht mit, dass der
Master ihm gerade was mitteilen will. In der Zwischenzeit schickt der
Master sein zweites Byte. Da der Slave noch nix gelesen hat, wird das
erste Byte überschrieben. Irgendwann später ruft das Hauptprogramm im
Slave die Read-Funktionen auf. Da das erste Byte überschrieben wurde,
wird natürlich nur das zweite gelesen...

von johnny.m (Gast)


Lesenswert?

...Und das compiliert fehlerfrei? Ich sehe im Slave-Programm nirgends
eine Deklaration von data und data2... Abgesehen davon ist es unsinnig,
mit globalen Variablen in den Funktionen rumzuspielen. 'return SPDR;'
tut das selbe und Du schreibst nicht die selbe Variable zwei mal
hintereinander (und Du brauchst nur eine Funktion). Aber das ist nur
unsauberes Programmieren. Funktionieren dürfte es aus o.g. Gründen auch
mit den Änderungen nicht!

von Jürgen (Gast)


Lesenswert?

Danke!
Habe es jetzt mit einem Interrupt gemacht und es funktioniert
einwandfrei.
Danke!
Jürgen

von Jürgen (Gast)


Angehängte Dateien:

Lesenswert?

Leider zu früh gefreut. Zwei Byte ausgeben funktioniert, bei drei
hingegen nicht mehr. Es ist zum Verzweifeln....
Das erste und das dritte werden ausgegeben, das in der Mitte nicht.

von johnny.m (Gast)


Lesenswert?

Klar, wenn Du in Deiner Interrupt-Routine den Riesenbrocken printf
aufrufst, dann ist das System erst mal für ne Weile beschäftigt. Ist
nachvollziehbar, dass da was verloren geht! Immer dran denken:
Interrupt Handler so kurz wie möglich, keine Funktionsaufrufe (v.a.
keine riesenhaften Bibliotheksfunktionen wie printf oder irgendwelche
Fließkommaarithmetik...)! In der ISR tust Du nichts anderes als nur
das SPDR einzulesen und in einer Puffer-Variable (Array) zu speichern
(dran denken: Puffer global und volatile deklarieren!). Den ganzen Rest
(eben z.B. die Ausgabe) im Hauptprogramm!

von johnny.m (Gast)


Lesenswert?

Vielleicht noch mal kurz zur Erklärung (Du scheinst noch nicht
sonderlich viel Erfahrung in Sachen µC zu haben):
Tritt ein Interrupt auf, dann löscht die Hardware das I-Bit im
Statusregister, wodurch die Bearbeitung neuer Interrupts während der
Ausführung der Interrupt-Routine verhindert wird. Wenn jetzt in der ISR
ein programmtechnischer Brocken wie printf, der eine
Schnittstellenausgabe macht (was für µC-Verhältnisse ne halbe Ewigkeit
dauert), aufgerufen wird, kann der µC keine weiteren über SPI
reinkommenden Daten verarbeiten.

In Deinem Fall bedeutet das: Es kommt ein Byte rein, die ISR wird
aufgerufen. Während das empfangene Byte ausgegeben wird (was eine
Weile dauert), kommen schon die beiden nächsten Bytes an. Dann passiert
wieder genau das, was am Anfang schon das Problem war: Das zuletzt
empfangene Byte (also das dritte) überschreibt das zweite, was dadurch
verloren geht.

Generell gilt bei der Datenkommunikation, dass man ankommende Daten in
der entsprechenden ISR in einem Puffer speichert. Dieser Puffer (i.a.
ein Array von ausreichender Größe) kann nun mit (in kurzen Abständen
eintreffenden) Daten gefüllt werden. In einer Sendepause hat man dann
genug Zeit, die Daten weiterzuverarbeiten.

In Deinem Fall müsste eine Variable 'volatile unsigned char
buffer[3]' her, in dem Du die drei Werte zwischenspeichern kannst.
Wenn der Master dann seine drei Bytes gesendet hat, kannst Du im
Hauptprogramm in aller Ruhe mit printf den ganzen Mist ausgeben. Dabei
geht nix verloren, weil ein printf im Hauptprogramm durch einen
Interrupt unterbrochen werden kann, was in der ISR nicht geht.

von Jürgen (Gast)


Lesenswert?

Danke für die Erklärungen, die nimmt ein Anfänger wie ich gerne auf. Ich
habe es auch genauso gemacht, jetzt gibt er aber für die ersten beiden
Werte 0 aus und nur der dritte stimmt.

volatile unsigned char dataarray[3];
// SPI interrupt service routine
interrupt [SPI_STC] void spi_isr(void)
{
unsigned char data;
int i;
data=SPDR;
// Place your code here
for (i=0; i<3; i++)
  dataarray[i]=data;

}

Ausgabe:

...
int j;
for (j = 0; j<3; j++)
{
printf("%d",dataarray[j]);
}

von johnny.m (Gast)


Lesenswert?

Da ist ein logischer Fehler drin: Was soll die for-Schleife in der ISR?
Du schreibst Dein dataarray mit einem einzigen Wert voll. Das kann so
nicht klappen. Im Prinzip müsstest Du Dir den Index, bei dem Du das
letzte Element gespeichert hast, global merken und in der ISR jeweils
den nächsten Wert schreiben. Der jeweils nächste Wert kann ja erst
gespeichert werden, wenn er auch eingetroffen ist.

Also, Reihenfolge (Beispiel):
1. Wert trifft ein
2. ISR wird aufgerufen
3. In der ISR wird der eingetroffene Wert gesichert (Index 0)
4. Die ISR wird verlassen.
5. Der nächste Wert trifft ein
6. ISR wird erneut aufgerufen
7. zweiter Wert wird gespeichert (Index 1)
8. Raus aus der ISR.
9.-12. Das ganze noch mal
13. Die drei Werte können ausgegeben werden

Wenn Du das mit dem Speichermanagement hinbekommst, kannst Du
selbstverständlich auch schon mit der Ausgabe beginnen, sobald der
erste Wert vorliegt. Da die Ausgabe im Hauptprogramm stattfindet, kann
sie ja durch einen Interrupt unterbrochen werden, so dass keine Daten
verloren gehen. Aber für den Anfang solltest Du es vielleicht mit der
Variante von oben probieren, also erst ausgeben, wenn alle drei Werte
da sind.

von Jürgen (Gast)


Lesenswert?

Danke!
Ich habe die For Schleife rausgeworfen und eine globale Variable
hochzählen lassen.

volatile unsigned char dataarray[3];
volatile int i=0;
// SPI interrupt service routine

interrupt [SPI_STC] void spi_isr(void)
{
  unsigned char data;

  data=SPDR;
  // Place your code here
  dataarray[i]=data;
   i++;
}


Um die richtige Ausgabe zu erhalten, habe ich noch ein delay
eingebaut, da mir der erste Wert sonst nicht angezeigt wird. So
funktioniert es jetzt endlich, aber kann ich das auch noch eleganter
als mit einem delay lösen?

delay_ms(100);
for (j = 0; j<3; j++)
{
printf("%d",dataarray[j]);
}

von johnny.m (Gast)


Lesenswert?

Ein delay ist eigentlich immer die schlechteste Lösung. Du willst ja,
wenn drei Werte da sind, ausgeben. Du hast eine globale Indexvariable,
die Du abfragen kannst. Mach z.B. ne while-Schleife, in der Du wartest,
bis i den Wert 2 erreicht hat, was ja bedeutet, dass alle drei Werte
drin sind. Der Umweg über dei lokale Variable data in der ISR ist
übrigens überflüssig. Du kannst auch direkt 'dataarray[i] = SPDR;'
schreiben...

von johnny.m (Gast)


Lesenswert?

Ach ja, Du musst natürlich abfragen, ob i drei ist und nicht zwei.
Wird ja bei Dir nach jedem empfangenen Zeichen inkrementiert...

von Jürgen (Gast)


Lesenswert?

Leider gibt er mir bei der while Schleife gar keine Werte mehr aus. Die
Zählvariable i zählt anscheinend nicht bis 3.

while (i==3)
      {
      for (j = 0; j<3; j++)
    {
    printf("%d",dataarray[j]);
    }
      };

von johnny.m (Gast)


Lesenswert?

while(i == 3) macht keinen Sinn! Eine Warteschleife sieht so aus:
while(i < 3);
Das ist eine leere Schleife, die so lange ausgeführt wird, wie i
kleiner als drei ist. Danach erst soll ausgegeben werden. Anschließend
sollte i wieder '0' gesetzt werden, damit die nächsten drei Zeichen
empfangen werden können. Also z.B.:

void main(void)
{
    unsigned char i, j;
//...irgendwelcher Code...
    while(1)
    {
        while(i < 3);
        for(j = 0; j < 3; j++)
            printf("%d",dataarray[j]);
        i = 0;
    }
}

von Karl heinz B. (kbucheg)


Lesenswert?

Du sollst ja auch warten, bis i den Wert 3 erreicht hat!


while( i != 3 )
  ;    // mach nichts

bzw. normalerweise bindet man das ganze in die
grosse Hauptschleife ein:

int main()
{

   ...
   i = 0;

   interruptes einschalten

   while( 1 ) {


     if( i == 3 ) {    // 3 Werte sind angekommen
       for (j = 0; j<3; j++)
       {
         printf("%d",dataarray[j]);
       }
       i = 0;   // bereit zur Aufnahme der nächsten 3 Werte
     }

     ..
   }
}

von Jürgen (Gast)


Lesenswert?

Oh je, das war ja wirklich ein C Anfängerfehler. Ich werde zukünftig
aufmerksamer programmieren, um dann keine  peinliche Fragen mehr zu
posten.
Es funktioniert jetzt. Danke!

von Jürgen (Gast)


Lesenswert?

Kann ein Slave auch von sich aus Daten an den Master schicken?

von johnny.m (Gast)


Lesenswert?

Nein, er muss vom Master dazu aufgefordert werden. Außerdem muss i.a.
gleichzeitig der Master Daten der entsprechenden Länge an den Slave
schicken, da der Master Clock nur beim Ausgeben von Daten läuft. D.h.
der Slave kann nur dann z.B. 4 Bytes Daten an den Master schicken, wenn
er gleichzeitig 4 Bytes vom Master empfängt. Der Master kann natürlich
einen Dummy schicken, aber es ist eigentlich immer eine bidirektionale
Kommunikation. Der Master hat immer die volle Kontrolle über das
System.

von Jürgen (Gast)


Lesenswert?

Schade, habe ich mir schon gedacht.

von Karl heinz B. (kbucheg)


Lesenswert?

Wieso 'schade'.
Ist alles  nur eine Frage des Protokolls.

Der Master kann zb reihum alle Slaves befragen
(indem er ein bestimmtes Byte schickt) ob und wieviele
Daten ein Slave zum Master schicken will.
Danach fordert der Master einen sendewilligen Slave auf
seine Daten zu senden. Der Master weiss ja jetzt wieviele
Bytes der Slave schicken will und kann daher entsprechend
viele Dummy-Bytes zum Slave schicken.

Wenn das System nicht so wäre, dann würde man sich eine
Menge Probleme mit Bus-Arbritierung einhandeln: Was ist
wenn 2 Slaves gleichzeitig Daten schicken wollen? Dein
Slave müsste ständig den Bus überwachen um nicht eine Sendung
anzufangen während ein anderer Slave gerade Daten sendet. Usw.

Dadurch dass die Initiative immer vom Master ausgeht wird
vieles einfacher.

von johnny.m (Gast)


Lesenswert?

Genau. Wenn es jedem Busteilnehmer ermöglicht werden soll, jederzeit
Daten zu senden, dann muss man den Buszugriff über wesentlich
kompliziertere Protokolle regulieren. Das gibt dann viel Overhead und
führt zu Arbitrierungsverfahren wie CSMA-CD/CR, die in Feldbussystemen
Verwendung finden. Kannst ja mal nach CSMA o.ä. oder Profibus und
Artverwandtem googeln und Dir mal anschauen, wie das da gelöst wird.
Das ist schon ein bisschen komplizierter als die Protokolle, das man
für SPI verwenden kann.

von Jürgen (Gast)


Angehängte Dateien:

Lesenswert?

Danke für den Code zum Senden von 4 Bytes(an Karl Heinz Buchegger).
Verwende ihn mit einem Interrupt. Klappt gut. Wenn der Slave nun auch 4
Bytes Versenden soll klappt das leider noch nicht.

von Karl heinz B. (kbucheg)


Lesenswert?

> unsigned char Master_Read(unsigned char swdata)
> {
>    swdata=SPDR;
>    return swdata;
> }

Du hast da eine Inkonsistenz.
Wie gibt Master_Read das gelesene Zeichen an den Aufrufer
der Funktion?

Entweder per Return Wert oder aber in dem der Aufrufer eine
Variable angibt in die Master_Read das Zeichen hineinschreibt.

Nun: Im obigen klappt die Methode mit dem Return Wert, die andere,
Übergabe einer Variablen klappt nicht, da ist ein Programm-Fehler.

Also: Return Wert würde klappen, blöderweise

>    Master_write( *pData++ );
>    Master_Read(swdata1);

benutzt du das nicht.

Du willst also die Übergabe per Commandline machen. (Auch hier
wieder: Das sind eigentlich C-Grundlagen, daher muss ich wieder
mal den Hinweis auf Literatur anbringen: Kauf dir Bücher!)

Nachdem der Aufgerufene beim Aufrufer eine Variable ändern
können soll, musst du einen Pointer auf die Variable übergeben
(Warum? Steht in jedem schlechterem C-Buch)

Also:

   void Master_Read( unsigned char* swdata )
   {
     *swdata = SPDR;
   }

und der Aufruf würde so aussehen

    Master_write( *pData++ );
    Master_Read( &swdata1 );

oder aber Variante 2: Rückgabe als Return Wert

   unsigned char Master_Read()
   {
     return SPDR;
   }

und der Aufruf würde so aussehen

    Master_write( *pData++ );
    swdata1 = Master_Read();

Das Allerschlechteste ist allerdings ein Mischmasch aus dem
Einen und dem Anderen. Wenn dann noch (wie hier) ein Programmier-
fehler dazukommt, dann kompiliert das Ganze wunderbar. Nur
funktioniert es halt nicht.

von Karl heinz B. (kbucheg)


Lesenswert?

> Du willst also die Übergabe per Commandline machen.

Sorry: Tippfehler:

                                  ***********
                                  Argumentübergabe

von Jürgen (Gast)


Lesenswert?

Meine C-Grundlagen sind leiderschon etwas länger her und selbst
beigebracht und deshalb leider lückenhaft.
Ich habe es geändert:
void SendLong( long DerWert )
  {
    unsigned char *pData;
    pData=&DerWert;

    Master_write( *pData++ );
    swdata1 = Master_Read();
  printf("%d",swdata1);

    Master_write( *pData++ );
    swdata2 = Master_Read();
  printf("%d",swdata2);

    Master_write( *pData++ );
    swdata3 = Master_Read();
  printf("%d",swdata3);

    Master_write( *pData++ );
    swdata4 = Master_Read();
  printf("%d",swdata4);
  }


unsigned char Master_Read()
{
  return SPDR;

}

Ich bekomme nun Werte ausgegeben, aber leider nicht in der vom Slave
vorgegebenen Reihenfolge, sondern manche gar nicht und manche doppelt.

von Hannes (Gast)


Lesenswert?

Ich habe die Beiträge hier im Forum über das SPI mit Interesse verfolgt.

Auch ich habe ein Problem. Mein System aus Bewegungssensoren
kommuniziert über SPI, was auch einwandfrei funktioniert. Jeder Slave
hat einen eigenen Mikrocontroller und eine externes Quarz. Wie kann ich
alle Quarze synchronisieren? Da ich die Slaves nur nacheinander abfragen
kann, alle Daten aber zum exakt gleichen Zeitpunkt aufgenommen werden
sollen, benötige ich eine Synchronisation der Quarze. Der Vorschlag nur
 ein Quarz zu nehmen geht nicht, da ich die Hardware leider schon
aufgebaut habe und die Synchronisation gerne per Software hinbekommen
würde. Als Busleitungen sind Clock, MOSI, MISO, SS und sonst noch
Versorgungsspannung, GND und RESET vorhanden.

von Hannes (Gast)


Lesenswert?

Hat denn niemand einen Lösungsvorschlag oder eine Idee?
Muß ich tatsächlich das Layout nochmal verändern?

von Wolfgang Horn (Gast)


Lesenswert?

Hi, Hannes,

kein Lösungsvorschlag wegen Rätselei: Denn der SPI-Master steuert mit
SCK ja diejenigen Slaves, mit denen er Daten austauschen will.

Ich hoffe, das, was Du gerade "Clock" nennst, ist dieser SCK nach
Datenblatt der Atmegas, andernfalls kämst Du um eine asynchrone
Kommunikation nach Art der UART und RS-232 nicht herum.

Ciao
Wolfgang Horn

von Hannes (Gast)


Lesenswert?

Ja, mit Clock meinte ich SCK.
Aber ich kann ja über den SPI die Slaves nur einzeln ansprechen und
somit keine gemeinsame, zeitgleiche Synchronisation der einzelnen
Slaves erreichen. Um zu verhindern, dass die Quarze der einzelnen Slave
zu weit "auseinanderlaufen", würde ich sie von Zeit zu Zeit
synchronisieren.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Du kannst ja die Slaves auf Software-SPI umschalten (z. B. mit
einem vorgelagerten Kommando), damit sie für den nächsten SPI-
Transfer ihren MISO-Treiber außer Betrieb nehmen.  Über diese
Software-SPI überträgst du dann (mit so weit reduzierter Datenrate,
dass die Slaves folgen können) eine Art "Broadcast-SPI-Kommando"
zum Synchronisieren der Zeit.  Danach reaktivieren die Slaves
ihr Hardware-SPI, damit sie nach der Messung vom Master schnell
der Reihe nach gepollt werden können.

von Hannes (Gast)


Lesenswert?

Das klingt ja sehr einfach, aber leider weiß ich nicht wie man auf
Software SPI umschaltet und mit einem vorgelagerten Kommando den
MISO-Treiber außer Betrieb nehmen kann. Ich habe leider auch nichts
dazu gefunden.

von masterof (Gast)


Lesenswert?

da ich jetzt anfange mich mit SPI zu beschäftigen ist der beitrag
gerade richtig.

@Hannes

Oder ziehe die Quartze auf eine gleiche Frequenz mit hilfe
Trimmerkondensator.

von Hannes (Gast)


Lesenswert?

@masterof:
Ich möchte die Synchronisation per Software lösen.

@Jörg Wunsch:
Wie kann ich auf Software SPI umschalten und den MISO Treiber außer
Betrieb nehmen?

von Hannes (Gast)


Lesenswert?

Kann mir denn keiner helfen, dabei wie man auf Software SPI umschalten
und den MISO Treiber außer Betrieb nehmen kann?

von Simon K. (simon) Benutzerseite


Lesenswert?

@Hannes: Ich versteh nicht was du willst. Ein Software SPI ist eine
selbstprogrammierte Schnittstelle. Hast du schon eine selbst
programmiert? Was für einen "Miso Treiber" meinst du? Der Pin hat
seine ursprüngliche Funktion, indem man das Hardware SPI deaktiviert.

von Hannes (Gast)


Lesenswert?

Ja und genau hier ist leider mein Problem. Ich habe keine Ahnung, wie
ich diese Schnittstelle selber programmieren kann. Das Hardware SPI
kann ich deaktivieren indem ich das SPI Control Register null setze.

von Wolfram (Gast)


Lesenswert?

>Ich habe keine Ahnung, wie ich diese Schnittstelle selber programmieren
>kann.
Das steht im Datenblatt

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.