Sign in Join
Wiki copytemporary

AVR Embedded Tutorial - SPI-Slave/de: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: AVR Embedded Tutorial - SPI-Slave/de

OldNewLine
1+# SPI als Slave
2+
3+## Vorwort
4+
5+SPI kann man auch als Slave verwenden.
6+
7+Das SPI auf eine Eingabe reagieren kann, löst man dies am besten Interruptgesteuert.
8+
9+Die folgenden Funktionen, sind in folgenden Tutorials beschrieben:
10+
11+- [[AVR Embedded Tutorial - Simple GPIO on and off output/de|GPIO - Aus / Ein-gabe]] - Wie mache ich einen GPIO-Zugriff am AVR.
12+- [[AVR Embedded Tutorial - UART/de|UART]] - Serielle Ein und Ausgabe über UART (COM-Port).
13+- [[AVR Embedded Tutorial - SPI/de|SPI]] - Nutzung der Hardware-SPI-Schnittstelle.
14+
15+## Beispiel Atmega328 / Arduino Uno/Nano
16+
17+In diesem Beispiel wird ein Interrupt ausgelöst, sobald ein Zeichen am Eingang anliegt und anschliessend wird dieses in den Ringpuffer geschrieben.
18+
19+In der Hauptschleife wird geprüft, ob sich etwas im Ringbuffer befindet, wen ja, wird dies über UART ausgegeben.
20+
21+Was man hier aufpassen muss, das nicht zu viel über SPI reinkommt, da diese Schnittstelle um einige sschneller ist als UART.
22+
23+Als Master habe ich eine ATtiny2313 verwendet, welcher auf Tastendruck eine String über SPI ausgibt.
24+
25+Am Ende ist noch der Code für den ATTiny angehängt, welcher die Strings sendet.
26+
27+### Units
28+
29+Wird für SEI benötig.
30+
31+``` pascal
32+uses
33+ intrinsics;
34+```
35+
36+### Konstanten und Variablen
37+
38+Variablen für Ringpuffer.
39+
40+``` pascal
41+const
42+ // Buffergrösse
43+ SPI_Buf_Len = 255;
44+
45+var
46+ // Pufferezeiger unf Puffer
47+ SPI_Buf_FirstOut: byte = 0;
48+ SPI_Buf_LastIn: byte = 0;
49+ SPI_Buf_Data: array[0..SPI_Buf_Len - 1] of byte;
50+```
51+
52+Pins welche an PORTB für SPI benötigt werden.
53+
54+Wird aber nur gebraucht, wen man etwas sendet.
55+
56+``` pascal
57+type
58+ TSPI_GPIO = bitpacked record
59+ p0, p1, SlaveSelect, MOSI, MISO, Clock, p6, p7: boolean;
60+ end;
61+
62+var
63+ SPI_Port: TSPI_GPIO absolute PORTB;
64+ SPI_DDR: TSPI_GPIO absolute DDRB;
65+```
66+
67+### Zeichen von SPI empfangen
68+
69+Sobald der Master am SS anklopft, wird der Interrupt ausgelöst und das kommende Zeichen in den Ringpuffer geschrieben.
70+
71+``` pascal
72+ procedure SPI_Int_Send; public Name 'SPI__STC_ISR'; interrupt;
73+ var
74+ tchr: byte;
75+ begin
76+ tchr := SPDR;
77+ if tchr <> 0 then begin
78+ SPI_Buf_Data[SPI_Buf_LastIn] := tchr;
79+ Inc(SPI_Buf_LastIn);
80+ if SPI_Buf_LastIn >= SPI_Buf_Len then begin
81+ SPI_Buf_LastIn := 0;
82+ end;
83+ end;
84+ end;
85+```
86+
87+### Hauptprogramm
88+
89+Im Hauptprogramm wird einfach geprüft, ob etwas im Ringpuffer ist und sobald etwas dort ist, wird es über UART ausgegeben.
90+
91+``` pascal
92+var
93+ ch: byte;
94+
95+begin
96+ // UART auf inizialisieren.
97+ UARTInit;
98+
99+ // SPI als Slave, Interrupt gesteuert.
100+ SPCR := (1 shl SPE) or (1 shl SPIE);
101+
102+ // Interrupt aktivieren.
103+ avr_sei;
104+
105+ // SendePin
106+ SPI_DDR.MISO := True; // Nur nötig, wen der Slave auch sendet.
107+
108+ repeat
109+ while SPI_Buf_LastIn <> SPI_Buf_FirstOut do begin // Ist etwas im Puffer ?
110+ ch := SPI_Buf_Data[SPI_Buf_FirstOut];
111+ Inc(SPI_Buf_FirstOut);
112+ if SPI_Buf_FirstOut >= SPI_Buf_Len then begin
113+ SPI_Buf_FirstOut := 0;
114+ end;
115+ UARTSendChar(char(ch));
116+ end;
117+ until 1 = 2;
118+end.
119+```
120+
121+## Sendecode des ATtiny2313
122+
123+Dieser Code sendet einen String, sobald eine Taste gedrückt wird.
124+
125+Da der ATTiny2313 keinen echten SPI besitzt, wird die Ausgabe über die Universal-Schnittelle (USI) gemacht.
126+
127+Es sind 3 Taster vorhanden.
128+
129+``` pascal
130+program Project1;
131+
132+{$O-}
133+type
134+ TSPI_GPIO = bitpacked record
135+ p0, p1, p2, p3, SlaveSelect, DataInt, DataOut, Clock: boolean;
136+ end;
137+
138+ TButton_GPIO = bitpacked array[0..2] of boolean;
139+
140+var
141+ SPI_PORT: TSPI_GPIO absolute PORTB;
142+ SPI_DDR: TSPI_GPIO absolute DDRB;
143+
144+ Button_PIN: TButton_GPIO absolute PIND;
145+
146+ procedure delay;
147+ var
148+ i: UInt32;
149+ begin
150+ for i := 0 to 65000 do;
151+ end;
152+
153+ procedure SPIWriteData(p: PByte; len: byte);
154+ var
155+ i: byte;
156+ begin
157+ SPI_PORT.SlaveSelect := False;
158+ for i := 0 to len - 1 do begin
159+ USIDR := p[i];
160+ USISR := 1 shl USIOIF;
161+
162+ repeat
163+ USICR := (%01 shl USIWM) or (%10 shl USICS) or (1 shl USICLK) or (1 shl USITC);
164+ until (USISR and (1 shl USIOIF)) <> 0;
165+
166+ end;
167+ SPI_PORT.SlaveSelect := True;
168+ end;
169+
170+const
171+ Text0 = 'Lazarus ist Toll !' + #13#10;
172+ Text1 = 'Hello World !, Hello AVR' + #13#10;
173+ Text2 = 'SPI als Slave' + #13#10;
174+
175+begin
176+ SPI_DDR.DataOut := True;
177+ SPI_DDR.Clock := True;
178+ SPI_DDR.SlaveSelect := True;
179+
180+ repeat
181+ if not Button_PIN[0] then begin
182+ SPIWriteData(@Text0[1], Length(Text0));
183+ delay;
184+ end;
185+ if not Button_PIN[1] then begin
186+ SPIWriteData(@Text1[1], Length(Text1));
187+ delay;
188+ end;
189+ if not Button_PIN[2] then begin
190+ SPIWriteData(@Text2[1], Length(Text2));
191+ delay;
192+ end;
193+ until 1 = 2;
194+end.
195+```
196+
197+# Siehe auch
198+
199+- Übersichtseite [[AVR Embedded Tutorial/de|AVR Embedded Tutorial]]
200+- [[AVR Embedded Tutorial - Shiftregister/de|Schieberegister]] - Wie steuere ich Schieberegister an.
201+- [[AVR Embedded Tutorial - SPI/de|SPI]] - Nutzung der Hardware-SPI-Schnittstelle bei einem ATmega328 / Arduino.
202+
203+Autor: Mathias
204+
205+---
206+*From the Free Pascal wiki, page "AVR Embedded Tutorial - SPI-Slave/de", as it stood on 2020-03-06 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history