heim - Antivirenprogramme
Serielle Schnittstelle SPI (3-Draht). Grundlagen des SPI-Protokolls Spi-Programmierung

SPI In Arduino ist es eines der Hauptprotokolle für den Datenaustausch zwischen dem Arduino-Board und angeschlossenen Geräten. Zusammen mit I2C und UART wird dieses Protokoll häufig für viele Arten von Peripheriegeräten verwendet, sodass Kenntnisse über die Prinzipien des SPI-Betriebs für jeden Arduino-Ingenieur erforderlich sind. In diesem Artikel werfen wir einen kurzen Blick auf die Grundprinzipien, das Interaktionsschema und die Methode zum Anschluss von SPI-Sensoren und -Bildschirmen an Arduino.

SPI ist ein weit verbreitetes Datenübertragungsprotokoll zwischen einem Mikrocontroller (Master) und Peripheriegeräten (Slave). In unseren Projekten wird am häufigsten ein Arduino-Board als Master verwendet. Die SPI-Schnittstelle wurde von Motorola erfunden und verwendet, entwickelte sich jedoch im Laufe der Zeit zum Industriestandard. Der Hauptvorteil der Arbeit mit dieser Schnittstelle ist ihre hohe Geschwindigkeit und die Möglichkeit, mehrere Geräte an einen Datenbus anzuschließen.

SPI-Pins und Pins

Die Kommunikation über die SPI-Arduino-Schnittstelle erfolgt zwischen mehreren Geräten, die sich nahe beieinander befinden. Arduino-Boards sind mit separaten Pins für SPI ausgestattet. Die Kopplung erfolgt über vier Kontakte:

  • MOSI – Informationen werden über diese Leitung vom Master an den Slave übertragen.
  • MISO – wird verwendet, um Informationen vom Slave zum Master zu übertragen.
  • SCLK – Erzeugung von Taktimpulsen zur synchronen Datenübertragung.
  • SS – Auswahl des Slave-Geräts.

Interaktion von SPI-Geräten

Die Geräteinteraktion beginnt, wenn der SS-Ausgang auf Low geht.

Bevor Sie mit der Arbeit beginnen, müssen Sie Folgendes festlegen:

  • Bei welchem ​​Bit soll die Verschiebung beginnen – hoch oder niedrig? Die Reihenfolge wird mit der Funktion PI.setBitOrder() angepasst.
  • Bestimmen Sie den Pegel, auf dem sich die SCK-Leitung befinden sollte, wenn kein Taktimpuls vorhanden ist. Einstellbar durch die Funktion SPI.setDataMode().
  • Wählen Sie die Datenübertragungsrate. Wird durch die Funktion SPI.setClockDivider() bestimmt.

Der nächste Schritt besteht darin, zu bestimmen, in welchem ​​Modus die Informationen übertragen werden. Die Wahl des Modus wird durch Indikatoren wie Polarität und Phase des Taktimpulses bestimmt. Wenn der Pegel niedrig ist, wird 0 aufgezeichnet, hoch - 1. Insgesamt gibt es 4 Modi:

  • Modus 0 – SPI_MODE0: Polarität (CPOL) 0, Phase (CPHA) 0.
  • Modus 1: Polarität 0, Phase 1.
  • Modus 2: Polarität 1, Phase 0.
  • Modus 3: Polarität 1, Phase 1.

Ursprünglich war Arduino darauf ausgelegt, Daten mit dem höchstwertigen Bit zuerst zu übertragen, aber bevor Sie beginnen, müssen Sie dies in der Dokumentation klären. Sie können die Modi im Bild demonstrieren.

In der SPI-Schnittstelle sind zwei Arten von Verbindungen möglich: unabhängig und kaskadiert. Im ersten Fall spricht der Master beim Verbinden jeden Slave einzeln an, im zweiten Fall erfolgt die Verbindung einzeln, d.h. Kaskade.

SPI mit Arduino verbinden

Jedes Arduino-Modell verfügt über eigene SPI-Pins. Diese Schlussfolgerungen:

  • Uno: MOSI entspricht Pin 11 oder ICSP-4, MISO – 12 oder ICSP-1, SCK – 13 oder ICSP-3, SS (Slave) – 10.
  • Mega1280 oder Mega2560: MOSI – 51 oder ICSP-4, MISO – 50 oder ICSP-1, SCK – 52 oder ICSP-3, SS (Slave) – 53.
  • Leonardo: MOSI – ICSP-4, MISO – ICSP-1, SCK – ICSP-3.
  • Fällig: MOSI – ICSP-4, MISO –ICSP-1, SCK –ICSP-3, SS (Master) – 4, 10, 52.

Der neueste Arduino Due-Controller erweitert die Benutzerfunktionen und ermöglicht die Implementierung von mehr Aufgaben als andere Mikrocontroller. Beispielsweise ist es möglich, das Slave-Gerät automatisch zu steuern und verschiedene Konfigurationen (Taktrate, Modus usw.) automatisch auszuwählen.

Arduino SPI-Bibliothek

Für die Arbeit mit Arduino wurde eine separate Bibliothek erstellt, die SPI implementiert. Bevor Sie mit dem Code beginnen, müssen Sie #include hinzufügen um die Bibliothek zu aktivieren.

Hauptfunktionen:

  • begin() und end() – Arbeit ein- und ausschalten. Während der Initialisierung werden die Leitungen SCLK, MOSI und SS am Ausgang konfiguriert und senden einen niedrigen Pegel an SCLK, MOSI und einen hohen Pegel an SS. Die Funktion end() ändert die Leitungsebenen nicht; sie wird benötigt, um den mit der Schnittstelle auf dem Arduino-Board verknüpften Block auszuschalten.
  • setBitOrder(order) – Festlegung der Reihenfolge der gesendeten Informationsbits (MSBFIRST – Priorität des höchstwertigen Bits, LSBFIRST – Priorität des niedrigstwertigen Bits).
  • setClockDivider(divider) – Einstellen der Hauptfrequenz-Taktteiler. Sie können Teiler von 2, 4, 8, 16, 32, 64 und 128 festlegen. Es wird wie folgt geschrieben: SPI_CLOCK_DIVn, wobei n der ausgewählte Teiler ist.
  • setDataMode(mode) – Wählen Sie einen von vier Betriebsmodi.
  • transfer(value) – überträgt ein Byte vom Master-Gerät und gibt das vom Slave-Gerät empfangene Byte zurück.
  • ShiftIn(miso_pin, sclk_pin, bit_order) und ShiftOut(mosi_pin, sclk_pin, order, value) – Empfangen und Senden von Daten, können mit beliebigen digitalen Pins verbunden werden, aber vorher müssen Sie sie selbst konfigurieren.

Vor- und Nachteile von SPI

Vorteile der SPI-Schnittstelle:

  • Möglichkeit zur Übertragung großer Datenmengen, nicht auf 8 Bit beschränkt.
  • Einfach zu implementierende Software.
  • Einfache Hardware-Implementierung.
  • Es werden weniger Pins benötigt als bei parallelen Schnittstellen.
  • Lediglich die Geschwindigkeit der Geräte begrenzt die maximale Taktfrequenz.

Mängel:

  • Große Anzahl an Pins im Vergleich zu I2C.
  • Slave kann den Informationsfluss nicht kontrollieren.
  • Fehlen eines Standardprotokolls zur Fehlererkennung.
  • Eine große Anzahl von Möglichkeiten, die Schnittstelle zu implementieren.
  • Fehlende Bestätigung des Erhalts der Informationen.

Ein Beispiel für die Verwendung von Arduino SPI in einem Projekt mit einem Drucksensor

Zur Umsetzung des Projekts benötigen wir einen Arduino, einen Drucksensor, ein Steckbrett und Drähte. Ein Beispiel für den Sensoranschluss ist in der Abbildung dargestellt.

Mithilfe des SCP1000-Sensors ist es möglich, Parameter wie Druck und Temperatur zu erkennen und diese Werte per SPI zu übertragen.

Grundelemente einer Programmskizze

Zunächst werden die Sensorregister mittels setup() im Code registriert. Vom Gerät werden mehrere Werte zurückgegeben – einer in 19 Bit für den empfangenen Druck, ein weiterer in 16 Bit für die Temperatur. Danach werden zwei Temperaturbytes und der Druck in zwei Stufen gelesen. Zuerst nimmt das Programm die drei höchstwertigen Bits, dann die nächsten 16 Bits, danach werden diese beiden Werte durch eine Bitverschiebung zu einem zusammengefasst. Der tatsächliche Druck ist der 19-stellige Wert geteilt durch 4.

const int DRUCK = 0x1F; // erste Stufe der Druckbestimmung (drei höchstwertige Bits werden erkannt)

const int PRESSURE_LSB = 0x20; // zweite Stufe, die 16 Bits für Druck definiert

const int TEMPERATUR = 0x21; //16 Bit für Temperatur

Um die Temperaturdaten auszulesen und in Celsius umzurechnen, wird das folgende Codeelement verwendet:

int tempData = readRegister(0x21, 2);

float realTemp = (float)tempData / 20.0; // Um ​​den tatsächlichen Temperaturwert in Celsius zu ermitteln, müssen Sie die resultierende Zahl durch 20 teilen

Serial.print(“Temp

Serial.print(realTemp);

Druckbits lesen und kombinieren:

Byte Pressure_data_high = readRegister(0x1F, 1);

Pressure_data_high &= 0b00000111;

unsigned int Pressure_data_low = readRegister(0x20, 2);

langer Druck = ((Druck_Daten_Hoch<< 16) | pressure_data_low) / 4; //определение давления в Паскалях.

Kurze Schlussfolgerungen zu SPI

SPI-Shields und -Sensoren sind häufig in Arduino-Projekten zu finden, daher müssen Sie wissen, wie dieses Protokoll funktioniert. Grundsätzlich ist der Anschluss von SPI-Geräten nicht kompliziert. Die Hauptsache ist, die Drähte richtig anzuschließen und die Methoden der Standardbibliothek in der richtigen Reihenfolge zu verwenden. Für manche Geräte, beispielsweise SD-Karten oder OLED-Bildschirme, gibt es grundsätzlich keine Alternativen.

SPI – Serial Peripheral Interface oder „Serial Peripheral Interface“ ist ein synchrones Datenübertragungsprotokoll für das Pairing Master-Gerät Mit Peripheriegeräte (Slave). Das Master-Gerät ist häufig ein Mikrocontroller. Die Kommunikation zwischen Geräten erfolgt über vier Drähte, weshalb SPI manchmal als „Vierdrahtschnittstelle“ bezeichnet wird. Das sind die Reifen:

Es gibt vier Datenübertragungsmodi ( SPI_MODE0, SPI_MODE1, SPI_MODE2, SPI_MODE3), verursacht durch die Kombination der Polarität der Taktimpulse (wir arbeiten auf HIGH- oder LOW-Pegel), Taktpolarität, CPOL, und die Phase der Taktimpulse (Synchronisation auf der steigenden oder fallenden Flanke des Taktimpulses), Taktphase, CPHA. Die letzte Spalte der Tabelle enthält erläuternde Abbildungen. Auf sie Probe Es werden die Zeitpunkte angezeigt, zu denen Daten auf der Leitung bereit sein und von Geräten gelesen werden müssen. Brief Z Es wird darauf hingewiesen, dass der Status der Daten auf der Leitung unbekannt oder unwichtig ist.

Die SPI-Schnittstelle bietet mehrere Möglichkeiten zum Anschluss von Slave-Geräten: unabhängig Und Kaskade. Bei unabhängiger Verbindung mit dem SPI-Bus greift das Master-Gerät individuell auf jedes Slave-Gerät zu. Bei einer Kaskadenschaltung arbeiten die Slave-Geräte nacheinander, wie in einer Kaskade.


Arten der Geräteanbindung für den Betrieb über die SPI-Schnittstelle: unabhängig und kaskadiert

2 Implementierung der SPI-Schnittstelle auf Arduino-Familienplatinen

In Arduino befinden sich SPI-Schnittstellenbusse an bestimmten Ports. Jede Platine hat ihre eigene Pinbelegung. Der Einfachheit halber werden die Schlussfolgerungen dupliziert und auch separat aufgeführt ICSP-Anschluss(Bei der seriellen Schaltungsprogrammierung die Programmierung eines in einer Schaltung enthaltenen Geräts mithilfe eines seriellen Protokolls.) Bitte beachten Sie, dass der ICSP-Anschluss keinen Slave-Auswahlpin hat – SS, weil Es wird davon ausgegangen, dass der Arduino als Master-Gerät im Netzwerk verwendet wird. Bei Bedarf können Sie jedoch einen beliebigen digitalen Pin von Arduino als SS zuweisen.

Die Abbildung zeigt die Standardentsprechung von Pins zu SPI-Bussen für Arduino UNO und Nano.


3 Standardbibliothek für den Betrieb über SPI-Schnittstelle

Für Arduino wurde eine spezielle Bibliothek geschrieben, die das SPI-Protokoll implementiert. Es wird zusammen mit der Entwicklungsumgebung installiert Arduino-IDE. Es verbindet sich so: Am Anfang des Programms fügen wir hinzu #include SPI.h.

Um mit der Verwendung des SPI-Protokolls zu beginnen, müssen Sie die Einstellungen festlegen und dann das Protokoll mithilfe des Verfahrens initialisieren SPI.beginTransaction(). Sie können dies mit einer Anweisung tun: SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0))

Das bedeutet, dass wir das SPI-Protokoll mit einer Frequenz von 14 MHz initialisieren, die Datenübertragung erfolgt beginnend mit MSB (höchstwertiges Bit) im Modus SPI_MODE0.

Wählen Sie nach der Initialisierung das Slave-Gerät aus, indem Sie den entsprechenden SS-Pin in den Status verschieben NIEDRIG. Anschließend übertragen wir mit dem Befehl die Daten an das Slave-Gerät SPI.transfer(). Nach der Übergabe geben wir SS an den Staat zurück HOCH.


Die Arbeit mit dem Protokoll wird mit dem Befehl abgeschlossen SPI.endTransaction().

Es empfiehlt sich, die Übertragungszeit zwischen den Anweisungen SPI.beginTransaction() und SPI.endTransaction() zu minimieren, um Probleme zu vermeiden, wenn ein anderes Gerät versucht, eine Datenübertragung mit anderen Einstellungen zu initiieren.

Wenn Sie in Ihrer Skizze Standard-Arduino-Pins verwenden möchten, müssen Sie diese nicht zu Beginn des Programms beschreiben, denn Sie sind bereits in der Bibliothek selbst definiert und haben die folgenden Namen:

#PIN_SPI_SS definieren (10) #PIN_SPI_MOSI definieren (11) #PIN_SPI_MISO definieren (12) #PIN_SPI_SCK definieren (13)

Diese Pins sind in der Datei definiert pins_arduino.h, das auf dem Weg liegt %programfiles%\arduino-(version)\hardware\arduino\avr\variants\(wenn Sie das Programm an einem Standardspeicherort installiert haben). Das heißt, um beispielsweise den Slave-Auswahlpin auf den Zustand „0“ zu senken, können Sie schreiben:

DigitalWrite(PIN_SPI_SS, LOW);

4 Anschluss eines Schieberegisters zu Arduino

Betrachten wir die praktische Anwendung der SPI-Schnittstelle. Wir werden die LEDs zum Leuchten bringen, indem wir ein 8-Bit-Schieberegister über den SPI-Bus steuern. Verbinden wir uns mit Arduino Schieberegister 74HC595. An jeden der 8 Registerausgänge schließen wir über einen Begrenzungswiderstand eine LED mit einem Nennwert von 220 Ohm an. Das Diagramm ist in der Abbildung dargestellt.


5 Skizze zur Ansteuerung eines Schieberegistersüber SPI-Schnittstelle

Schreiben wir eine Skizze, die eine „Wanderwelle“ implementiert, indem die LEDs, die mit den Ausgängen des Schieberegisters verbunden sind, nacheinander aufleuchten.

#enthalten const int pinSelect = 8; // Select-Pin registrieren void setup() ( SPI.begin(); // Initialisierung der SPI-Schnittstelle pinMode(pinSelect, OUTPUT); // digitalWrite(pinSelect, LOW); // Slave-Geräte auswählen (Register) SPI.transfer(0); // den Inhalt des Registers löschen digitalWrite(pinSelect, HIGH); // Ende der Übertragung Serial.begin(9600); } void loop() ( for (int i=0; i )

Verbinden wir zunächst die SPI-Bibliothek und initialisieren wir die SPI-Schnittstelle. Definieren wir Pin 8 als SS-Slave-Auswahlpin. Löschen wir das Schieberegister, indem wir ihm den Wert „0“ senden. Initialisieren Sie die serielle Schnittstelle.

Um eine bestimmte LED mithilfe eines Schieberegisters zum Leuchten zu bringen, müssen Sie eine 8-Bit-Zahl an deren Eingang anlegen. Damit beispielsweise die erste LED aufleuchtet, geben wir die Binärzahl 00000001 an, für die zweite - 00000010, für die dritte - 00000100 usw. Diese Binärzahlen bilden bei der Umrechnung in das dezimale Zahlensystem die folgende Folge: 1, 2, 4, 8, 16, 32, 64, 128 und sind Zweierpotenzen von 0 bis 7.

Dementsprechend im Zyklus Schleife() Basierend auf der Anzahl der LEDs berechnen wir von 0 auf 7. Funktion pow(Basis, Grad) Erhöht den Schleifenzähler um 2. Mikrocontroller arbeiten mit Zahlen vom Typ „double“ nicht sehr genau, daher verwenden wir die Rundungsfunktion, um das Ergebnis in eine ganze Zahl umzuwandeln runden(). Und wir übertragen die resultierende Zahl in das Schieberegister. Der Übersichtlichkeit halber zeigt der Monitor der seriellen Schnittstelle die während dieses Vorgangs erhaltenen Werte an: Das Gerät „läuft“ durch die Entladungen – die LEDs leuchten wellenförmig auf.

6 „Laufende Welle“ aus LEDs

Die LEDs leuchten nacheinander auf und wir beobachten eine laufende „Welle“ von Lichtern. Die Ansteuerung der LEDs erfolgt über ein Schieberegister, das wir über die SPI-Schnittstelle angeschlossen haben. Dadurch werden nur 3 Arduino-Pins zur Ansteuerung von 8 LEDs verwendet. Wenn wir die LEDs direkt an die digitalen Ports des Arduino anschließen würden, müssten wir für jede LED einen separaten Port verwenden.

Wir haben das einfachste Beispiel für die Arbeit von Arduino mit dem SPI-Bus untersucht. Die Funktionsweise mehrerer Schieberegister mit unabhängigen und kaskadierten Verbindungen werden wir in einem separaten Artikel genauer betrachten.

Die synchrone serielle Schnittstelle SPI ist für die Eingabe/Ausgabe von Daten in Punkt-zu-Punkt-Schnittstellen mit einem Master-Gerät (SPI-Master) und einem Slave-Gerät (SPI-Slave) konzipiert (Abb. 1.24). Die SPI-Master-Steuerschaltung erzeugt Taktimpulse SCK, die gleichzeitig Signale am MOSI-Ausgang senden und Signale am MISO-Eingang empfangen. Dieselben SCK-Taktimpulse, die in den SPI-Slave gelangen, steuern den Empfang von Signalen an seinem MOSI-Eingang und die Erzeugung von Signalen an seinem MISO-Ausgang. Separate MOSI- und MISO-Signalkreise ermöglichen die einfache Implementierung einer Vollduplex-Kommunikation.

Datenformate, Signalparameter, Timing-Eigenschaften usw. werden in der Schnittstelle nicht geregelt, die Datenaustauschrate wird beispielsweise nur durch die Frequenz der vom SPI-Master generierten SCK-Taktimpulse bestimmt. Die maximale Entfernung hängt vom Grad der Signalverzerrung in den Kommunikationsleitungen ab; es wird davon ausgegangen, dass ein zuverlässiger Datenaustausch bei Entfernungen von bis zu mehreren Metern möglich ist.

Im Wesentlichen handelt es sich nicht einmal um eine vollwertige Schnittstelle für die physische Ebene. Tatsächlich implementiert SPI ein Standardverfahren für die Eingabe/Ausgabe von Daten in Schieberegistern; es sind keine Betriebssteuerungsalgorithmen oder eine Steuerung der übertragenen Daten vorgesehen. Alle notwendigen Kontrollvorgänge müssen vom SPI-Master durchgeführt werden. Dies erfordert einerseits den Einsatz zusätzlicher Steuerungstools und vereinfacht andererseits die Implementierung der SPI-Schnittstelle selbst weitestgehend. Der SPI-Slave ist ein Standard-Schieberegister mit der erforderlichen Anzahl an Datenbits.

Beispielsweise unterstützen Mikrocontroller der AVR-Familie von ATMEL die Dateneingabe/-ausgabe sowohl im SPI-Master- als auch im SPI-Slave-Modus. Der Standardaustauschzyklus beinhaltet die gleichzeitige Übertragung eines Datenbytes in beide Richtungen (Abb. 1.24). Bei der Übertragung von Multibyte-Nachrichten muss der SPI-Slave ein Schieberegister mit der entsprechenden Breite enthalten und der SPI-Master muss den Austausch der erforderlichen Datenbyte-Sequenz steuern, jedes Byte nach dem nächsten Standardschnittstellen-Betriebszyklus verarbeiten und sicherstellen Beginn des nächsten Standard-Austauschzyklus.

Es wird nicht nur für den Datenaustausch zwischen Mikrocontrollern verwendet, sondern auch für die Verbindung von Mikrocontrollern mit externen ADCs (ADC) und DACs (DAC), Speicherchips – SRAM, FRAM, SEERAM und vielen anderen Geräten. Dank des seriellen Datenformats und der einfachen logischen Organisation der SPI-Schnittstelle werden diese Chips in kompakten 8-16-Pin-Gehäusen hergestellt. In der Tabelle In Abb. 1.6 zeigt Beispiele für Mikroschaltungen verschiedener Funktionszwecke und verschiedener Hersteller mit einer SPI-Schnittstelle. Diese Beispiele zeigen, dass das serielle Schnittstellenformat die erforderliche Anzahl an I/O-Leitungen deutlich reduzieren kann.

Tabelle 1.6

Chip-Typ

Haupteinstellungen

Art der Schale

Hersteller

24-Bit, Delta-Sigma, 15 Hz

24-Bit, Delta-Sigma, 41 kHz

16-Bit, SAR, 100 kHz

16-Bit, PulsAR, 500 kHz

12-Bit, U-out, 2,5 µs

16-Bit, U-out, 10 µs

14-Bit, I-out, 0,04 µs

12-Bit, I-out, 0,6 µs

16-Bit, U-out, 1 µs

www.maxim-ic.com

Chip-Typ

Haupteinstellungen

Art der Schale

Hersteller

16 kBit, 1 Billion

4 kBit, unbegrenzt

64 kBit, unbegrenzt

256K, 32768×8, 0,1 Millionen Zyklen

8K, 1024×8, 0,1 Millionen Zyklen

16K, 8192×8, 0,1 Millionen Zyklen

128K, 16384×8, 0,1 Millionen Zyklen

256K, 32768×8, 0,1 Millionen Zyklen

Thermosensor

13-Bit, -40 bis +150 °C (±0,5 °C)

Eines der Probleme, die bei Automatisierungstools häufig gelöst werden müssen, hängt mit der begrenzten Anzahl von I/O-Leitungen auf Mikrocontrollern zusammen. Typischerweise übersteigt die Anzahl der übertragenen Signale die Fähigkeiten paralleler Ports erheblich, aber die Verarbeitungsalgorithmen für die meisten übertragenen Signale lassen zusätzliche Zeitverzögerungen zu, die mit ihrer Übertragung im seriellen Format verbunden sind. In diesen Fällen ist die Verwendung von Standard-Seriell-Parallel-Registern effektiv.

Beispielsweise kann die SPI-Schnittstelle nützlich sein, um den Status einer großen Anzahl von Ein-Aus-Sensoren auszulesen oder Multibit-Daten in einem parallelen Format einzugeben. Für diese Zwecke ist es zweckmäßig, separate Register mit parallelem Schreiben und seriellem Lesen (8-Bit Parallel-In/Serial-Out-Schieberegister) zu verwenden, zum Beispiel CD74HCT166 (Abb. 1.25).

Der Anschlussplan für sechzehn Zweipositionssensoren (S1 – S16) über die SPI-Schnittstelle des Mikrocontrollers ist in Abb. dargestellt. 1.26. Es ist zu beachten, dass vor Beginn des Betriebs der SPI-Schnittstelle ein Signal zum Schreiben von Informationen in Register von den parallelen Eingängen D0-D7 generiert werden muss. Dazu können Sie einen der Ausgänge des Mikrocontrollers nutzen, in diesem Beispiel PC0.

Reis. 1,25. Funktionsdiagramm des CD74HCT166-Registers

Reis. 1.26. Anschluss von Zweipositionssensoren an die SPI-Schnittstelle

Reis. 1.27. Anschließen eines sechsstelligen Indikators an die SPI-Schnittstelle

Mithilfe von Registern mit sequentieller Aufzeichnung und paralleler Ausgabe von Informationen (8-Bit Serial-In, Parallel-Out Shift Register) - SN74HC595 kann die SPI-Schnittstelle auch für die parallele Mehrbyte-Ausgabe von Informationen verwendet werden. Als Beispiel in Abb. Abbildung 1.27 zeigt ein Diagramm zum Anschluss einer sechsstelligen Sieben-Segment-Anzeige an einen Mikrocontroller. Im Gegensatz zur vorherigen Schaltung muss das parallele Ausgangssignal (PB1) erzeugt werden, nachdem die SPI-Schnittstelle die Datenübertragung über Mittel außerhalb der Schnittstelle abgeschlossen hat. Beispielsweise muss der Algorithmus zur Interaktion mit der Schnittstelle eine Überwachung der Anzahl der übertragenen Datenbytes vorsehen und nach Abschluss der Übertragung des letzten Bytes zusätzlich ein paralleles Ausgangssignal übertragen.

Eine weitere Schnittstelle, über die sich ein Gerät problemlos mit einem elektronischen Projekt verbinden lässt, ist die SPI-Schnittstelle.

SPI(Serial Peripheral Interface – serielle Peripherieschnittstelle) ist wie UART eine ziemlich alte, einfache und beliebte Schnittstelle. An dieser Schnittstelle arbeiten viele Geräte (Mikrocontroller, EEPROM, ADC, DAC...). Wir werden es auch für unsere Geräte nutzen.
Die SPI-Schnittstelle nutzt drei Leitungen zur Datenübertragung: MOSI- Übertragung; MISO– Empfang; SCK– Taktung. Es wird eine zusätzliche Zeile verwendet SS(Slave Select?) – Wählen Sie ein Gerät aus (falls mehrere vorhanden sind). SPI ist eine synchrone Vollduplex-Schnittstelle – Senden und Empfangen erfolgen parallel. Das Master-Gerät initiiert und taktet den Austausch – Meister(kann nur einer sein). Sklave - Sklave- Ein Gerät (es können mehrere sein) empfängt/sendet ein Byte unter dem Einfluss eines Taktsignals.

In AVR-Mikrocontrollern wird die SPI-Schnittstelle doppelt genutzt, als Kommunikationsschnittstelle und als Schnittstelle für serielle In-Circuit-Programmierung. Die überwiegende Mehrheit der Controller verfügt über eine SPI-Schnittstelle (es gibt Ausnahmen bei Tiny-Modellen), aber selbst wenn diese nicht vorhanden ist, wird es nicht schwierig sein, sie in Software zu implementieren.

Wie funktioniert also die SPI-Schnittstelle?
Und sein Design ist unglaublich einfach (es ist schwer, es überhaupt als Schnittstelle zu bezeichnen) – zwei Schieberegister (Master und Slave) plus ein Generator auf der Master-Seite – das ist alles! Die Schieberegister sind ringförmig entlang der MOSI- und MISO-Leitungen geschlossen, das Taktsignal vom Generator wird beiden Schieberegistern (über die SCK-Leitung dem Slave) zugeführt.

Bevor der Austausch beginnt, werden die Daten in Schieberegister gelegt, der Master startet den Generator, der Generator „schaltet“ 8 Taktzyklen aus, während dieser 8 Taktzyklen „ändern“ die Schieberegister ihren Inhalt (der Master empfängt das Byte des Slaves, und der Sklave erhält die des Meisters) - das war's!
Bei mehreren Slave-Geräten erfolgt der Austausch nur mit einem, dessen Signal an SS Low ist.

SPI ist die schnellste serielle Schnittstelle. Mit einer Mikrocontroller-Master-Oszillatorfrequenz von 20 MHz kann er mit einer Geschwindigkeit von 10.000.000 Baud austauschen
(1,2 Megabyte pro Sekunde)!

Der Nachteil der Schnittstelle besteht darin, dass der Initiator des Austauschs immer der Master ist. Das heißt, wenn an der Peripherie etwas passiert ist, erfährt der Master erst dann davon, wenn er selbst „beschließt“, eine Kommunikationssitzung durchzuführen (Effizienz geht verloren). AVR-Hersteller haben einen Weg gefunden, diesen Nachteil zu umgehen. Wenn der SPI des Mikrocontrollers als Master konfiguriert ist, kann der SS-Pin sowohl als Eingang als auch als Ausgang konfiguriert werden. Wenn der Pin als Ausgang konfiguriert ist, wird er zur Auswahl des Slave-Geräts verwendet. Wenn der SS-Pin jedoch als Eingang konfiguriert ist, schaltet der Mikrocontroller den SPI automatisch in den Slave-Modus und kann Daten von einem anderen Master empfangen, wenn an diesem Pin ein niedriger Pegel auftritt. Nach der Austauschsitzung bleibt SPI im Slave-Modus. Um es in den Master-Modus zu übertragen, müssen Sie SPI neu konfigurieren.

Ich denke, dass dieser Master-Slave-Umschaltalgorithmus für Blog-Geräte selten benötigt wird, daher werden wir SPI nur als Master oder nur als Slave verwenden.
Wenn das Blog-Gerät ein Ausgabegerät ist (z. B. eine Tastatur), ist der SPI der Master und in Ihrem Projekt der SPI der Slave.
Wenn es sich bei dem Blog-Gerät um ein Eingabegerät handelt (z. B. eine digitale Anzeige), ist der SPI der Slave und in Ihrem Projekt der SPI der Master.

Um das Gerät über die SPI-Schnittstelle mit Ihrem Projekt zu verbinden, benötigen Sie:
1 Verbinden Sie das Blog-Gerät mit den entsprechenden Pins des Mikrocontrollers.
2 Konfigurieren Sie den SPI Ihres Controllers (als Master oder Slave). Schreiben Sie dazu bestimmte Werte auf die entsprechenden I/O-Ports.
3 Haben (Schreib-)Prozeduren zum Empfangen/Übertragen von Nachrichten über SPI in Ihrem Programm.
Schauen wir uns nun jeden Punkt im Detail an:


1 ANSCHLUSS VON GERÄTEN ÜBER SPI.
Wir verbinden einfach die gleichnamigen Pins MOSI-MOSI, MISO-MISO, SCK-SCK, SS-SS. Wenn die Verbindung nur zwischen zwei Geräten besteht, ist SS-SS im Prinzip nicht erforderlich, Sie müssen jedoch sicherstellen, dass der SS-Pin des Slave-Geräts niedrig ist (auf Masse gezogen), andernfalls nimmt das Gerät nicht teil der Austausch.


2 SPI-EINSTELLUNG.

SPI verfügt über vier Betriebsarten (0, 1, 2, 3). Die Betriebsart hängt davon ab, an welcher Flanke des Taktsignals der Austausch durchgeführt wird. Darüber hinaus können Sie konfigurieren, welches Bit (höchstwertiges oder niedrigstwertiges) zuerst übertragen wird. Für den Austausch spielt dies keine Rolle – das Ergebnis wird das gleiche sein (Betriebsmodi sind erforderlich, um SPI an Geräte verschiedener Hersteller anzupassen). Master und Slave müssen im gleichen Modus arbeiten.
Für Blog-Geräte verwenden wir die folgenden SPI-Einstellungen:
Modus - 0
Es wird das höchstwertige Bit übertragen Erste
Taktfrequenz - je nach den Umständen(Für SPI ist die Frequenz nicht so wichtig, da der Takt aus einer einzigen Quelle stammt).
Nehmen wir zum Beispiel den ATmega8-Mikrocontroller mit einem internen 8-MHz-Masteroszillator. Wir werden die Steuereingangs-/-ausgangsports des Controllers in verschiedenen Programmierumgebungen konfigurieren.

Algorithmus-Builder.
Erstellen Sie ein Projekt ( Datei/Neu). Wählen Sie den Mikrocontroller und die Frequenz des Master-Oszillators aus Optionen/Projektoptionen…(ATmega8, interner Master-Oszillator bei 8 MHz). Klicken Sie in der Symbolleiste auf die Schaltfläche „S“ – Control Register Customizer“ und wählen Sie SPI aus.
Einstellungen für Meister(zur Kommunikation mit einem Ausgabegerät):

Einstellungen für Sklave(zur Kommunikation mit Eingabegerät):


OK klicken". Bereit – SPI ist initialisiert und einsatzbereit.

Monteur. Sie können tiefer in das Datenblatt für den Controller eintauchen, Sie können ein Stück Asma aus einem kompilierten Projekt in C übernehmen, Sie können die mnemonischen Befehle des Algorithm Builder übersetzen – wählen Sie, was Ihnen gefällt.
Einstellungen für Master (zur Kommunikation mit Ausgabegerät):

init-SPI-slave: sbi 0x17,0x04 ldi r16,0x00 out 0x0E,r16 ldi r16,0xC0 out 0x0D,r16

CodeVisionAVR. Um SPI-Einstellungen zu generieren, klicken Sie auf das Zahnradsymbol ( CodeWisardAVR) in der Symbolleiste. Wählen Sie im sich öffnenden Fenster zunächst die Registerkarte „Chip“ aus, wählen Sie darin den Mikrocontroller aus und stellen Sie die Frequenz ein, mit der der Master-Oszillator arbeiten soll. Als nächstes wählen Sie die Registerkarte SPI aus und füllen sie entsprechend den erforderlichen Merkmalen aus.

Einstellungen für Master (zur Kommunikation mit Ausgabegerät):

// Initialisierung von Port B // Func7=In Func6=In Func5=Out Func4=In Func3=Out Func2=Out Func1=In Func0=In // State7=T State6=T State5=0 State4=T State3=0 State2=0 State1=T State0=T PORTB= 0x00 ; DDRB= 0x2C ; // SPI-Initialisierung // SPI-Typ: Master // SPI-Taktpolarität: Niedrig // SPI-Datenreihenfolge: MSB First SPCR= 0xD0 ; SPSR= 0x00 ;

// Initialisierung von Port B // Func7=In Func6=In Func5=Out Func4=In Func3=Out Func2=Out Func1=In Func0=In // State7=T State6=T State5=0 State4=T State3=0 State2= 0 State1=T State0=T PORTB=0x00; DDRB=0x2C; // SPI-Initialisierung // SPI-Typ: Master // SPI-Taktrate: 2000.000 kHz // SPI-Taktphase: Zyklushälfte // SPI-Taktpolarität: Niedrig // SPI-Datenreihenfolge: MSB First SPCR=0xD0; SPSR=0x00;

Einstellungen für Slave (zur Kommunikation mit Eingabegerät):

// Initialisierung von Port B // Func7=In Func6=In Func5=In Func4=Out Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=0 State3=T State2=T State1=T State0=T PORTB= 0x00 ; DDRB= 0x10 ; // SPI-Initialisierung // SPI-Typ: Slave // SPI-Taktrate: 2000.000 kHz // SPI-Taktphase: Zyklushälfte// SPI-Taktpolarität: Niedrig // SPI-Datenreihenfolge: MSB First SPCR= 0xC0 ; SPSR= 0x00 ;

// Initialisierung von Port B // Func7=In Func6=In Func5=In Func4=Out Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=0 State3=T State2= T State1=T State0=T PORTB=0x00; DDRB=0x10; // SPI-Initialisierung // SPI-Typ: Slave // ​​​​SPI-Taktrate: 2000.000 kHz // SPI-Taktphase: Zyklushälfte // SPI-Taktpolarität: Niedrig // SPI-Datenreihenfolge: MSB First SPCR=0xC0; SPSR=0x00;

Speichern Sie das generierte Projekt ( Datei\Generieren, Speichern und Beenden). Es wurde ein Projekt mit allen notwendigen Einstellungen für SPI erstellt. Auch andere (oft unnötige) Peripheriegeräte werden im Projekt initialisiert. Nachdem Sie ein Projekt erstellt haben, können Sie es korrigieren – entfernen Sie alles, was nicht erforderlich ist.


3 ERSTELLUNG VON SPI-VERARBEITUNGSVERFAHREN.

Die Arbeit mit SPI im Mikrocontroller ist sehr einfach organisiert. Um den Datenaustausch im Master-Controller zu starten, schreiben Sie einfach das übertragene Byte in das SPDR-Register – der Austausch beginnt automatisch. Nach Abschluss des Austauschs wird die Interrupt-Handling-Prozedur aufgerufen, bei der wir das empfangene Byte aus dem SPDR lesen. Mit einem Slave-Controller ist es noch einfacher: Nach Abschluss des Austauschs wird die Interrupt-Handling-Prozedur aufgerufen, bei der wir das empfangene Byte aus dem SPDR lesen.

Algorithmus-Builder.
Übertragen. Sowohl beim Master als auch beim Slave muss das übertragene Byte in das SPDR-Register geschrieben werden. Für den Master leitet das Schreiben eines Bytes in SPDR den Austausch ein.
Rezeption. Sowohl beim Master als auch beim Slave wird nach dem Empfang des Bytes ein Interrupt aufgerufen, in dem das Senden verarbeitet wird.

Wenn während einer Byteübertragung versucht wird, in das SPDR-Register zu schreiben, kommt es zu einem Schreibkonflikt. Daher muss das Programm sicherstellen, dass das nächste Byte übertragen wird, nachdem das vorherige empfangen wurde. Die beste Lösung für dieses Problem wäre der folgende Algorithmus: Das erste Byte, der Anfang des Bytepakets, wird vom Hauptteil des Programms übertragen, und der Rest wird vom Interrupt am Ende der Übertragung über SPI übertragen. Somit wird das Hauptprogramm von der Arbeit der Übertragung eines Bytestrings „befreit“ und gleichzeitig kann es nicht zu einem Schreibkonflikt kommen, da der Interrupt aufgerufen wird, wenn der Austausch abgeschlossen ist.

Da wir planen, einzelne Bytes über SPI zu übertragen, werden wir den oben genannten Algorithmus nicht verwenden.

Monteur.
Der Code ist äußerst einfach. Zur Übertragung schreiben wir in SPDR, das empfangene Byte wird von SPDR im Interrupt-Body gelesen.

CodeVisionAVR. Zusätzlich zur Initialisierung erstellt CodeWisardAVR auch eine Interrupt-Behandlungsprozedur. Es ist nichts Zusätzliches erforderlich.

// Empfangen/Übertragen von Daten über SPI im Interrupt-Körper Interrupt void spi_isr(void) ( unsigned char data; data=SPDR; ) // Vorbereiten/Übertragen von Daten über SPI im Hauptteil des Programms unsigned char data; SPDR=Daten;

Das scheint alles zu sein, was ich über SPI sagen wollte.
Die Benutzeroberfläche ist recht einfach und sollte bei der Verwendung keine Probleme bereiten.

(5.231 Mal besucht, 1 Besuch heute)

Nachdem Sie nun ein allgemeines Verständnis der seriellen Peripherieschnittstelle haben, können Sie mit dem SPI-Modul fortfahren.
Das SPI-Modul des AVR atmega16-Mikrocontrollers verwendet für seinen Betrieb 4 Pins – MOSI, MISO, SCK und SS. Wenn das Modul nicht verwendet wird, dienen diese Pins als Allzweck-I/O-Portleitungen. Bei Aktivierung des Moduls werden die Betriebsarten dieser Pins gemäß der folgenden Tabelle neu definiert.

Wenn mehr als ein Peripheriegerät an den Mikrocontroller angeschlossen ist, können alle Universalpins als zusätzliche Auswahlpins (SS) verwendet werden. In diesem Fall muss der Standard-SS-Pin immer korrekt konfiguriert sein, auch wenn er nicht verwendet wird.

SPI-Modulregister

Der atmega16-Mikrocontroller verwendet drei Register, um mit dem SPI-Modul zu arbeiten:

SPCR-Steuerregister,
- SPSR-Statusregister,
- SPDR-Datenregister.

Alle drei Register sind Acht-Bit-Register.

Die SPI-Modulkonfiguration wird mithilfe des SPCR (SPI Control Register) festgelegt.

SPIE– Aktiviert/deaktiviert Interrupts vom SPI-Modul. Wenn dieses Bit auf 1 gesetzt ist, sind SPI-Interrupts aktiviert.

SPE– schaltet das SPI-Modul ein/aus. Wenn das Bit auf 1 gesetzt ist, ist das SPI-Modul aktiviert.

DORD– bestimmt die Reihenfolge der Datenübertragung. Wenn das Bit auf 1 gesetzt ist, wird der Inhalt des Datenregisters zuerst als niedrigstwertiges Bit übertragen. Wenn ein Bit gelöscht wird, steht das höchstwertige Bit an erster Stelle.

MSTR– bestimmt die Betriebsart des Mikrocontrollers. Wenn das Bit auf 1 gesetzt ist, arbeitet der Mikrocontroller im Master-Modus. Wenn das Bit zurückgesetzt ist, befindet es sich im Slave-Modus. Typischerweise arbeitet der Mikrocontroller im Master-Modus.

CPOL Und CPHA– Bestimmen Sie, in welchem ​​Modus das SPI-Modul arbeitet. Der erforderliche Betriebsmodus hängt vom verwendeten Peripheriegerät ab.


SPR1
Und SPR0– Bestimmen Sie die Frequenz des SPI-Modultaktsignals, also den Wechselkurs. Die maximal mögliche Übertragungsgeschwindigkeit ist immer in der Spezifikation des Peripheriegeräts angegeben.


Das SPSR-Statusregister (SPI-Statusregister) dient zur Überwachung des Status des SPI-Moduls
Darüber hinaus enthält es ein zusätzliches Baudraten-Steuerbit.


SPIF
– SPI-Interrupt-Flag. Nach Abschluss einer Datenbyteübertragung wird es auf 1 gesetzt. Wenn Modul-Interrupts aktiviert sind, wird gleichzeitig mit dem Setzen dieses Flags ein SPI-Interrupt generiert. Dieses Flag wird auch auf 1 gesetzt, wenn der Mikrocontroller über den SS-Pin vom Master-Modus in den Slave-Modus wechselt.
Das Flag wird von der Hardware zurückgesetzt, wenn eine Interrupt-Routine aufgerufen wird oder nachdem das SPSR-Register gelesen und dann auf das SPDR-Datenregister zugegriffen wurde.

WCOL- Konfliktflag schreiben. Das Flag wird auf 1 gesetzt, wenn während der Datenübertragung versucht wird, in das SPDR-Datenregister zu schreiben. Das Flag wird von der Hardware gelöscht, nachdem das SPSR-Register gelesen und dann auf das SPDR-Datenregister zugegriffen wurde.

SPI2X- Bit zur Baudratenverdopplung. Wenn Sie dieses Bit auf 1 setzen, verdoppelt sich die Frequenz des SCK-Taktsignals. Der Mikrocontroller muss im Master-Modus arbeiten.

Die Beziehung zwischen den SPR0-, SPR1- und SPI2X-Bits und der SCK-Taktfrequenz ist in der Tabelle dargestellt.

Wobei Fosc die Taktfrequenz des AVR-Mikrocontrollers ist.


Das SPDR-Register (SPI Data Register) dient zum Senden und Empfangen von Daten.
. Das Schreiben von Daten in dieses Register veranlasst das SPI-Modul, Daten zu übertragen. Beim Lesen dieses Registers wird der Inhalt des Schieberegisterpuffers des SPI-Moduls gelesen.

Programmcode

Der minimale Programmcode für die Arbeit mit dem SPI-Modul besteht aus zwei Funktionen:

Initialisierungsfunktionen.
- Funktionen zum Senden/Empfangen von Datenbytes

Initialisierung des SPI-Moduls

Die Initialisierung umfasst die Konfiguration der SPI-Pins des Moduls und des SPCR-Steuerregisters.


#define SPI_PORTX PORTB
#define SPI_DDRX DDRB

#define SPI_MISO 6
#define SPI_MOSI 5
#define SPI_SCK 7
#define SPI_SS 4

/*SPI-Modul im Mastermodus initialisieren*/
void SPI_Init(void)
{

/*E/A-Ports konfigurieren
alle Pins außer MISO-Ausgänge*/
SPI_DDRX |= (1<SPI_PORTX |= (1<

/*SPI-Auflösung, höchstwertiges Bit vorwärts, Master, Modus 0*/
SPCR = (1<SPSR = (0<}

Datenübertragung/-empfang

Der Prozess des Sendens/Empfangens von Daten mithilfe eines SPI-Moduls im Master-Modus besteht aus der folgenden Abfolge von Aktionen:

1. Setzen eines niedrigen Logikpegels auf der SS-Leitung
2. Laden von Daten in das SPDR-Register
3. Warten auf das Ende der Übertragung (Prüfung des SPIF-Flags)
4. Bei Bedarf empfangene Daten speichern (SPDR lesen).
5. Kehren Sie zum 2. Schritt zurück, wenn nicht alle Daten übertragen wurden
6. Setzen Sie den logischen Pegel auf der SS-Leitung auf High

Nachfolgend finden Sie mehrere Optionen für die Datenübertragungs-/Empfangsfunktion.

Übertragen eines Datenbytes über SPI


void SPI_WriteByte(uint8_t data)
{
SPI_PORTX &= ~(1<SPDR = Daten;
while(!(SPSR & (1<SPI_PORTX |= (1<}

Senden und Empfangen eines Datenbytes über SPI

uint8_t SPI_ReadByte(uint8_t data)
{
uint8_t-Bericht;
SPI_PORTX &= ~(1<SPDR = Daten;
while(!(SPSR & (1<Bericht = SPDR;
SPI_PORTX |= (1<Rückgabebericht;
}

Übertragen mehrerer Datenbytes über SPI
*data ist ein Zeiger auf das Array der übertragenen Daten und num ist die Dimension des Arrays


void SPI_WriteArray(uint8_t num, uint8_t *data)
{
SPI_PORTX &= ~(1<while(num--)(
SPDR = *data++;
while(!(SPSR & (1< }
SPI_PORTX |= (1<}

//Anwendungsbeispiel:
uint8_t buf = (12, 43, 98);


SPI_WriteArray(3, buf);

Senden und Empfangen mehrerer Datenbytes über SPI
*data ist ein Zeiger auf das Array der übertragenen Daten und num ist die Dimension des Arrays.
Die empfangenen Daten werden im selben Array gespeichert.


void SPI_ReadArray(uint8_t num, uint8_t *data)
{
SPI_PORTX &= ~(1<while(num--)(
SPDR = *data;
while(!(SPSR & (1<*data++ = SPDR;
}
SPI_PORTX |= (1<}

Dateien

Ein einfacher SPI-Treiber, der alle oben beschriebenen Funktionen vereint -



 


Lesen:



So richten Sie Hotkeys für jedes Programm ein. So richten Sie Tastaturtasten ein

So richten Sie Hotkeys für jedes Programm ein. So richten Sie Tastaturtasten ein

Die Maus ist das bequemste Handsteuerungsgerät, ihre Verwendung zur Dateneingabe ist jedoch sehr umständlich. Das bequemste und effektivste Gerät...

FQ: Registrieren und Sicherheitsfragen festlegen Hier finden Sie eine kurze Liste der Anforderungen für E-Mail-Marketing in China

FQ: Registrieren und Sicherheitsfragen festlegen Hier finden Sie eine kurze Liste der Anforderungen für E-Mail-Marketing in China

In diesem Artikel erkläre ich Ihnen, wie Sie ohne tiefe Sprachkenntnisse eine chinesische E-Mail beim beliebten TOM.com-Dienst registrieren können. A...

So platzieren Sie VKontakte-Kommentare in WordPress

So platzieren Sie VKontakte-Kommentare in WordPress

Hallo! Gäste kamen in unsere gemietete thailändische Wohnung; es ist so toll, Landsleute zu sehen, wenn man nicht zu Hause ist. Heute will ich dich...

VKontakte-Webcam: neue Funktionen

VKontakte-Webcam: neue Funktionen

In letzter Zeit hat die Verwaltung des sozialen Netzwerks nicht aufgehört, Benutzer mit verschiedenen nützlichen und weniger nützlichen Innovationen zu begeistern. Auf jeden Fall,...

Feed-Bild RSS