Sign in Join
Wiki copytemporary

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

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

OldNewLine
1+## Contents
2+
3+ * 1 SPI als Slave
4+ * 1.1 Vorwort
5+ * 1.2 Beispiel Atmega328 / Arduino Uno/Nano
6+ * 1.2.1 Units
7+ * 1.2.2 Konstanten und Variablen
8+ * 1.2.3 Zeichen von SPI empfangen
9+ * 1.2.4 Hauptprogramm
10+ * 1.3 Sendecode des ATtiny2313
11+ * 2 Siehe auch
12+
113# SPI als Slave
214
315## Vorwort
416
5-SPI kann man auch als Slave verwenden.
17+SPI kann man auch als Slave verwenden.
618
7-Das SPI auf eine Eingabe reagieren kann, löst man dies am besten Interruptgesteuert.
19+Das SPI auf eine Eingabe reagieren kann, löst man dies am besten Interruptgesteuert.
820
9-Die folgenden Funktionen, sind in folgenden Tutorials beschrieben:
21+Die folgenden Funktionen, sind in folgenden Tutorials beschrieben:
1022
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.
23+ * [[AVR Embedded Tutorial - Simple GPIO on and off output/de|GPIO - Aus / Ein-gabe]] \- Wie mache ich einen GPIO-Zugriff am AVR.
24+ * [[AVR Embedded Tutorial - UART/de|UART]] \- Serielle Ein und Ausgabe über UART (COM-Port).
25+ * [[AVR Embedded Tutorial - SPI/de|SPI]] \- Nutzung der Hardware-SPI-Schnittstelle.
1426
1527## Beispiel Atmega328 / Arduino Uno/Nano
1628
17-In diesem Beispiel wird ein Interrupt ausgelöst, sobald ein Zeichen am Eingang anliegt und anschliessend wird dieses in den Ringpuffer geschrieben.
29+In diesem Beispiel wird ein Interrupt ausgelöst, sobald ein Zeichen am Eingang anliegt und anschliessend wird dieses in den Ringpuffer geschrieben.
1830
19-In der Hauptschleife wird geprüft, ob sich etwas im Ringbuffer befindet, wen ja, wird dies über UART ausgegeben.
31+In der Hauptschleife wird geprüft, ob sich etwas im Ringbuffer befindet, wen ja, wird dies über UART ausgegeben.
2032
21-Was man hier aufpassen muss, das nicht zu viel über SPI reinkommt, da diese Schnittstelle um einige sschneller ist als UART.
33+Was man hier aufpassen muss, das nicht zu viel über SPI reinkommt, da diese Schnittstelle um einige sschneller ist als UART.
2234
23-Als Master habe ich eine ATtiny2313 verwendet, welcher auf Tastendruck eine String über SPI ausgibt.
35+Als Master habe ich eine ATtiny2313 verwendet, welcher auf Tastendruck eine String über SPI ausgibt.
2436
25-Am Ende ist noch der Code für den ATTiny angehängt, welcher die Strings sendet.
37+Am Ende ist noch der Code für den ATTiny angehängt, welcher die Strings sendet.
2638
2739### Units
2840
29-Wird für SEI benötig.
30-
31-``` pascal
41+Wird für SEI benötig.
42+```
3243uses
33- intrinsics;
44+ intrinsics;
3445```
3546
3647### Konstanten und Variablen
3748
38-Variablen für Ringpuffer.
39-
40-``` pascal
49+Variablen für Ringpuffer.
50+```
4151const
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;
52+ // Buffergrösse
53+ SPI_Buf_Len = 255;
54+
55+ var
56+ // Pufferezeiger unf Puffer
57+ SPI_Buf_FirstOut: byte = 0;
58+ SPI_Buf_LastIn: byte = 0;
59+ SPI_Buf_Data: array[0..SPI_Buf_Len - 1] of byte;
5060```
5161
52-Pins welche an PORTB für SPI benötigt werden.
53-
54-Wird aber nur gebraucht, wen man etwas sendet.
62+Pins welche an PORTB für SPI benötigt werden.
5563
56-``` pascal
64+Wird aber nur gebraucht, wen man etwas sendet.
65+```
5766type
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;
67+ TSPI_GPIO = bitpacked record
68+ p0, p1, SlaveSelect, MOSI, MISO, Clock, p6, p7: boolean;
69+ end;
70+
71+ var
72+ SPI_Port: TSPI_GPIO absolute PORTB;
73+ SPI_DDR: TSPI_GPIO absolute DDRB;
6574```
6675
6776### Zeichen von SPI empfangen
6877
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;
78+Sobald der Master am SS anklopft, wird der Interrupt ausgelöst und das kommende Zeichen in den Ringpuffer geschrieben.
79+```
80+procedure SPI_Int_Send; public Name 'SPI__STC_ISR'; interrupt;
81+ var
82+ tchr: byte;
83+ begin
84+ tchr := SPDR;
85+ if tchr <> 0 then begin
86+ SPI_Buf_Data[SPI_Buf_LastIn] := tchr;
87+ Inc(SPI_Buf_LastIn);
88+ if SPI_Buf_LastIn >= SPI_Buf_Len then begin
89+ SPI_Buf_LastIn := 0;
90+ end;
91+ end;
8292 end;
83- end;
84- end;
8593```
8694
8795### Hauptprogramm
8896
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
97+Im Hauptprogramm wird einfach geprüft, ob etwas im Ringpuffer ist und sobald etwas dort ist, wird es über UART ausgegeben.
98+```
9299var
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.
100+ ch: byte;
101+
102+ begin
103+ // UART auf inizialisieren.
104+ UARTInit;
105+
106+ // SPI als Slave, Interrupt gesteuert.
107+ SPCR := (1 shl SPE) or (1 shl SPIE);
108+
109+ // Interrupt aktivieren.
110+ avr_sei;
111+
112+ // SendePin
113+ SPI_DDR.MISO := True; // Nur nötig, wen der Slave auch sendet.
114+
115+ repeat
116+ while SPI_Buf_LastIn <> SPI_Buf_FirstOut do begin // Ist etwas im Puffer ?
117+ ch := SPI_Buf_Data[SPI_Buf_FirstOut];
118+ Inc(SPI_Buf_FirstOut);
119+ if SPI_Buf_FirstOut >= SPI_Buf_Len then begin
120+ SPI_Buf_FirstOut := 0;
121+ end;
122+ UARTSendChar(char(ch));
123+ end;
124+ until 1 = 2;
125+ end.
119126```
120127
121128## Sendecode des ATtiny2313
122129
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.
130+Dieser Code sendet einen String, sobald eine Taste gedrückt wird.
126131
127-Es sind 3 Taster vorhanden.
132+Da der ATTiny2313 keinen echten SPI besitzt, wird die Ausgabe über die Universal-Schnittelle (USI) gemacht.
128133
129-``` pascal
134+Es sind 3 Taster vorhanden.
135+```
130136program 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-
137+
138+ {$O-}
139+ type
140+ TSPI_GPIO = bitpacked record
141+ p0, p1, p2, p3, SlaveSelect, DataInt, DataOut, Clock: boolean;
142+ end;
143+
144+ TButton_GPIO = bitpacked array[0..2] of boolean;
145+
146+ var
147+ SPI_PORT: TSPI_GPIO absolute PORTB;
148+ SPI_DDR: TSPI_GPIO absolute DDRB;
149+
150+ Button_PIN: TButton_GPIO absolute PIND;
151+
152+ procedure delay;
153+ var
154+ i: UInt32;
155+ begin
156+ for i := 0 to 65000 do;
157+ end;
158+
159+ procedure SPIWriteData(p: PByte; len: byte);
160+ var
161+ i: byte;
162+ begin
163+ SPI_PORT.SlaveSelect := False;
164+ for i := 0 to len - 1 do begin
165+ USIDR := p[i];
166+ USISR := 1 shl USIOIF;
167+
168+ repeat
169+ USICR := (%01 shl USIWM) or (%10 shl USICS) or (1 shl USICLK) or (1 shl USITC);
170+ until (USISR and (1 shl USIOIF)) <> 0;
171+
172+ end;
173+ SPI_PORT.SlaveSelect := True;
174+ end;
175+
176+ const
177+ Text0 = 'Lazarus ist Toll !' + #13#10;
178+ Text1 = 'Hello World !, Hello AVR' + #13#10;
179+ Text2 = 'SPI als Slave' + #13#10;
180+
181+ begin
182+ SPI_DDR.DataOut := True;
183+ SPI_DDR.Clock := True;
184+ SPI_DDR.SlaveSelect := True;
185+
162186 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.
187+ if not Button_PIN[0] then begin
188+ SPIWriteData(@Text0[1], Length(Text0));
189+ delay;
190+ end;
191+ if not Button_PIN[1] then begin
192+ SPIWriteData(@Text1[1], Length(Text1));
193+ delay;
194+ end;
195+ if not Button_PIN[2] then begin
196+ SPIWriteData(@Text2[1], Length(Text2));
197+ delay;
198+ end;
199+ until 1 = 2;
200+ end.
195201```
196202
197203# Siehe auch
198204
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.
205+ * Übersichtseite [[AVR Embedded Tutorial/de|AVR Embedded Tutorial]]
206+ * [[AVR Embedded Tutorial - Shiftregister/de|Schieberegister]] \- Wie steuere ich Schieberegister an.
207+ * [[AVR Embedded Tutorial - SPI/de|SPI]] \- Nutzung der Hardware-SPI-Schnittstelle bei einem ATmega328 / Arduino.
202208
203-Autor: Mathias
209+Autor: [Mathias](</User:Mathias> "User:Mathias")
204210
205211---
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).*
212+*From the Free Pascal wiki, page "AVR Embedded Tutorial - SPI-Slave/de", as the Internet Archive kept it on 2023-03-27. 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