www.mikrocontroller.net

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


Autor: dieter (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: dieter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kann mir denn keiner helfen!
dieter

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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.)

Autor: dieter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael Wilhelm (Gast)
Datum:

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

MW

Autor: dieter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn du das SPIF im SPSR meinst, das ist null.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: dieter (Gast)
Datum:

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

Autor: dieter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
war ein verzwickter hardwarefehler. klappt jetzt!
trotzdem danke an alle!
dieter

Autor: dieter (Gast)
Datum:

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

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: dieter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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ß.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: Karl heinz Buchegger (kbucheg)
Datum:

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

     return EmpfangenerWert;

>  }

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...)

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jürgen (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Sorry habe den Anhang vergessen.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Jürgen (Gast)
Datum:

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

Autor: Jürgen (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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]);
}

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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]);
}

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: johnny.m (Gast)
Datum:

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

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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]);
    }
      };

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
    }
}

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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
     }

     ..
   }
}

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann ein Slave auch von sich aus Daten an den Master schicken?

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schade, habe ich mir schon gedacht.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jürgen (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Du willst also die Übergabe per Commandline machen.

Sorry: Tippfehler:

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

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hannes (Gast)
Datum:

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

Autor: Wolfgang Horn (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: masterof (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Hannes (Gast)
Datum:

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

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Wolfram (Gast)
Datum:

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.