mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik SPI per Software


Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

leider hat die Suche im Forum nichts erbracht.
Folgendes Problem: Ich möchte auf einem AT89C52 ein SPI Interface
realisieren. Entsprechende und für meine Anwendung funktionierende
Assembler-Routinen habe ich schon geschrieben. Allerdings muss ich mich
mit C beschäftigen, und davon hab ich leider nicht viel Ahnung.

1. Wie kann ich das Einlesen und Ausgeben realisieren?
2. Gibt es irgendwo eine Sammlung solcher Code-Schnipsel, damit sich
Anfänger nicht so schwer tun?

Danke

Gruß Ralf

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
avrfreaks.net
--> Anmeldung erforderlich, aber viel Beispielsource zu verschiedenen
Themen
--> Englischkenntnisse erforderlich

Gruß, Alex

Autor: Auf Merk Sam (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
AT89C52 !

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

hat noch niemand sowas gemacht?

Gruß Ralf

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In C ist es egal, ob 8051, MSP, ARM oder AVR.

Allerdings hat der 8051 spezielle Erweiterungen, um auf Portpins
zugreifen zu können. Damit kann man den Code noch etwas optimieren.
Funktionieren tuts aber auch ohne.

Wenn Du kein C kannst, solltest Du es zuerst lernen, z.B. mit
Borland-C.

Ein Bespiel zu schreiben und dann kapierst Du es nicht, dazu hat keiner
Lust.

Für SPI mußt Du for, if, &, |, <<, >> kennen.


Peter

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
doch, sicher.
Aber geh doch andersherum ran: wenn du verstanden hast, wie das
physikalisch funktioniert, klappt das auch mit der Programmierei. Wenn
du dich mit C beschäftigen willst, nutzt es dir doch nichts,
vorgekauten Kram zu bekommen. Nichts ist dafür besser als eigene
Erfolgserlebnisse.

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter:

Mach mir ein Beispiel, und ich sag dir, ob ich es verstanden habe ;-)
Nein, im Ernst, ich verstehe dich. FOR, IF, &, |(oder), sowie << und >>
(shiften bzw. rolieren), ist alles klar. Mein Problem war eher, dass ich
den Lösungsansatz suche, inzwischen habe ich eine der Routinen zum
laufen bekommen, aber auf diese Lösungsart bin ich nicht gekommen, weil
ich sie so nicht ERWARTET habe. Da hilft denke ich nur Input von denen,
die es können.

@Crazy Horse:

Wie ich Peter bereits sagte, auf den Lösungsansatz muss man gefasst
sein. Aber das mit den Erfolgserlebnissen, da hast du freilich recht.

Gruß Ralf

Autor: crazy horse (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
hier mal ein Beispiel für das SPI-Schreiben, die Grundroutine write_spi
und ein Funktion, die diese benutzt.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welche Lösung hast Du denn gefunden ?
Es gibt ja so viele.
Hier z.B. eine, die die Bits nicht nur in auf- oder absteigender
Reihenfolge, sondern x-beliebig senden kann:

http://www.mikrocontroller.net/forum/read-4-22246.html

Das Beispiel von crazy horse ist auch eine, wenn auch nicht sehr
effektiv. Ehe man eine extra Maskenbyte schiebt, ist es schneller und
kürzer, wenn man das Datenbyte selbst schiebt. In der Regel braucht man
nämlich das Datenbyte danach nicht mehr bzw. kann damit gleichzeitig die
empfangenen Bits reinschieben.


Peter

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Crazy Horse,

also... Ist die Routine zum SPI-Schreiben nicht ein bisschen dick?
Meine sieht so aus:

SPI_OUT(unsigned char output) {
  unsigned char i;

  for (i = 8; i; i--) {
  SCK = 0;
  MOSI = output & 0x01;
  output = output >> 1;
  SCK = 1;
  }
}

Oder übersehe ich irgendwo etwas in deiner Routine? Ich nehme an, du
machst weiche Ware für einen AVR oder so, vielleicht macht die Routine
da so mehr Sinn.

Gruß Ralf

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Das Beispiel von crazy horse ist auch eine, wenn auch nicht sehr
effektiv" - ich wusste, dass das von dir kommt :-)

weiss ich selbst, aber man versteht es eigentlich recht gut, wie es
funktioniert. Man braucht auch keinen extra loop-Zähler.

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Ralf: nicht immer ist ein einfacher aussehendes C-Programm auch die
optimale Lösung im Endergebnis, kommt natürlich auch auf den Compiler
an.
Konkret, (rein Interese halber habe mal beides compiliert) und siehe
da:
dein C-Code erzeugt 4 words mehr Maschinencode (absolut 19 zu 23) und
benötigt 271 Takte statt 193 bei meinem.

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@crazy horse:

Ich wollte dir auch nicht auf die Hufe... äh... Füsse treten. Du hast
den Code jetzt für einen AVR generiert, oder? Ich werd bei Gelegenheit
mal deinen für den 8051 generieren, mal sehen, ob meiner da auch so
groß ist im Gegensatz zu deinem. In dem Fall würde ich deinen nehmen,
wenn da kein Copyright drauf ist :-)

Gruß Ralf

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach was :-)
Ja, war für nen AVR (2313) mit CodeVision.

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch ein Test, ohne extra loop-counter

void write_spi (unsigned char data_out){       //msb first
unsigned char mask;
for (mask=0x80; mask; mask=mask>>1)
    {sclk=0;
    if (data_out & mask) mosi=1;
    else mosi=0;
    sclk=1;
    }
}
schlägt mit 16 words und 159 Takten (mit Aufruf und return) zu Buche.

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch knuffig. Ich muss jetzt mal anfangen, die Sache real (sprich nicht
Simulator) auszutesten, und mal sehen was dabei rauskommt.
Hoffentlich tuts auch...

Gruß Ralf

Autor: Peter Dannegger (peda)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Anbei mal der Code mit dem WINAVR (20 Byte) und mit dem Keil (17 Byte).


Der WINAVR gestattet leider keine Portpindefinitionen, daher die etwas
umständlichere Schreibweise mit Maskierung.
Ist aber alles nur ne Gewöhnungsfrage.


Peter

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kannst du mal das Listing anhängen?
Deine Lösung erzeugt bei mir das schlechteste Ergebnis (29 words, 439
Takte). Da besteht offensichtlich deutlicher Optimierungsbedarf am
Compiler.

Autor: Peter Dannegger (peda)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Anbei das Listing für den WINAVR.

Er erkennt, wenn nur ein Portpin gesetzt oder gelöscht werden soll und
nimmt dann SBI/CBI.


Der Keil vertraut darauf, daß man Pins, die man einzeln benutzen will
auch als einzelne Bits definiert.
Warscheinlich der CodeVision auch.



Peter

Autor: Paul K. (fluctuation)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>1. Wie kann ich das Einlesen und Ausgeben realisieren?
Das Ausgeben habt Ihr hier super beschrieben, doch wie sieht es mit 
Einlesen aus?
Brauche ich für meinen ATTiny13 Project, der ja kein SPI kann (nur ISP 
über SPI seltsamerweise...steht auch im Datenblatt nix dazu...)

Ein Mega8 wird bei mir Soft- oder Hardware SPI benutzen (werde sehen, 
was besser ist), um dem Tiny13 Befehle zur Steuerung einer RGB-LED zu 
geben.
Der Tiny13 muss diese Befehle auslesen und interpretieren.

Danke in Voraus

Grüße, paul

Autor: spi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist schon etwas älter aber hatte ähnliches problem und fand diese seite 
bei google.

meine lösung für CPHA=1 und CPOL=1 
(http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus)

void SOFT_SPI_init(void){
  // MOSI und CLK auf Ausgang setzen
  SOFT_SPI_MOSI_DDR |=(1<<SOFT_SPI_MOSI_BIT);
  SOFT_SPI_CLK_DDR  |=(1<<SOFT_SPI_CLK_BIT);

  // MOSI und CLK auf HIGH setzen
  SOFT_SPI_MOSI_PORT|=(1<<SOFT_SPI_MOSI_BIT);
  SOFT_SPI_CLK_PORT |=(1<<SOFT_SPI_CLK_BIT);

  // MISO auf Eingang setzen
  SOFT_SPI_MISO_DDR &=~(1<<SOFT_SPI_MISO_BIT);
}

unsigned char SOFT_SPI_WriteRead(unsigned char dataout)
{
  uint8_t datain=0;
  //das Byte wird Bitweise nacheinander Gesendet MSB zuerst
  for (uint8_t a=8; a>0; a--){                
      datain<<=1;                      //Schieben um das Richtige Bit zusetzen
      SOFT_SPI_CLK_PORT &=~(1<<SOFT_SPI_CLK_BIT);     // Clock auf LOW
                                
      if (dataout & 0x80){                //Ist Bit a in Byte gesetzt
        SOFT_SPI_MOSI_PORT |=(1<<SOFT_SPI_MOSI_BIT);   //Set Output High
      }
      else{
        SOFT_SPI_MOSI_PORT &=~(1<<SOFT_SPI_MOSI_BIT);   //Set Output Low
      }
      _delay_us(1);
      if (SOFT_SPI_MISO_PIN & (1<<SOFT_SPI_MISO_BIT))   //Lesen des Pegels 
        {
        datain |= 1;
        }

      _delay_us(1);
      SOFT_SPI_CLK_PORT |=(1<<SOFT_SPI_CLK_BIT);       // Clock auf High
      _delay_us(2);
      dataout<<=1;                     //Schiebe um nächstes Bit zusenden
    }

  return datain;
}

mit den Delay zeiten kann man noch etwas spielen.

Autor: S. G. (goeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe für einen ATTiny2313 auch eine Software SPI Lösung gesucht und hier 
gefunden. Danke vor allem an meinen Vorposter, der Code funktioniert 
eiwandfrei. Habe ihn etwas angepasst, da ich CPHA=1 und CPOL=1 nicht 
nutze.
Benötigte den Code für die Kommunikation mit einem SCA3000. Werde die 
Bibliothek(en) in einem neuen Thread posten.

Grüße
Göck

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.