AVR Embedded Tutorial - SPI-Slave/de
SPI als Slave
Vorwort
SPI kann man auch als Slave verwenden.
Das SPI auf eine Eingabe reagieren kann, löst man dies am besten Interruptgesteuert.
Die folgenden Funktionen, sind in folgenden Tutorials beschrieben:
- GPIO - Aus / Ein-gabe - Wie mache ich einen GPIO-Zugriff am AVR.
- UART - Serielle Ein und Ausgabe über UART (COM-Port).
- SPI - Nutzung der Hardware-SPI-Schnittstelle.
Beispiel Atmega328 / Arduino Uno/Nano
In diesem Beispiel wird ein Interrupt ausgelöst, sobald ein Zeichen am Eingang anliegt und anschliessend wird dieses in den Ringpuffer geschrieben.
Als Master habe ich eine ATtiny2313 verwendet, welcher auf Tastendruck eine String über SPI ausgibt.
Units
Wird für SEI benötig.
uses
intrinsics;
Konstanten und Variablen
Variablen für Ringpuffer.
const
// Buffergrösse
SPI_Buf_Len = 255;
var
// Pufferezeiger unf Puffer
SPI_Buf_FirstOut: byte = 0;
SPI_Buf_LastIn: byte = 0;
SPI_Buf_Data: array[0..SPI_Buf_Len - 1] of byte;
Pins welche an PORTB für SPI benötigt werden.
Wird aber nur gebraucht, wen man etwas sendet.
type
TSPI_GPIO = bitpacked record
p0, p1, SlaveSelect, MOSI, MISO, Clock, p6, p7: boolean;
end;
var
SPI_Port: TSPI_GPIO absolute PORTB;
SPI_DDR: TSPI_GPIO absolute DDRB;
Zeichen von SPI empfangen
Sobald der Master am SS anklopft, wird der Interrupt ausgelöst und das kommende Zeichen in den Ringpuffer geschrieben.
procedure SPI_Int_Send; public Name 'SPI__STC_ISR'; interrupt;
var
tchr: byte;
begin
tchr := SPDR;
if tchr <> 0 then begin
SPI_Buf_Data[SPI_Buf_LastIn] := tchr;
Inc(SPI_Buf_LastIn);
if SPI_Buf_LastIn >= SPI_Buf_Len then begin
SPI_Buf_LastIn := 0;
end;
end;
end;
Hauptprogramm
Im Hauptprogramm wird einfach geprüft, ob etwas im Ringpuffer ist und sobald etwas dort ist, wird es über UART ausgegeben.
var
ch: byte;
begin
// UART auf inizialisieren.
UARTInit;
// SPI als Slave, Interrupt gesteuert.
SPCR := (1 shl SPE) or (1 shl SPIE);
// Interrupt aktivieren.
avr_sei;
// SendePin
SPI_DDR.MISO := True; // Nur nötig, wen der Slave auch sendet.
repeat
while SPI_Buf_LastIn <> SPI_Buf_FirstOut do begin // Ist etwas im Puffer ?
ch := SPI_Buf_Data[SPI_Buf_FirstOut];
Inc(SPI_Buf_FirstOut);
if SPI_Buf_FirstOut >= SPI_Buf_Len then begin
SPI_Buf_FirstOut := 0;
end;
UARTSendChar(char(ch));
end;
until 1 = 2;
end.
Siehe auch
- Übersichtseite AVR Embedded Tutorial
- Schieberegister - Wie steuere ich Schieberegister an.
- SPI - Nutzung der Hardware-SPI-Schnittstelle bei einem ATmega328 / Arduino.
Autor: Mathias