Sign in Join
Wiki copytemporary

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

Revision 2 to 3. 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-
131# SPI als Slave
142
153## Vorwort
164
17-SPI kann man auch als Slave verwenden.
5+SPI kann man auch als Slave verwenden.
186
19-Das SPI auf eine Eingabe reagieren kann, löst man dies am besten Interruptgesteuert.
7+Das SPI auf eine Eingabe reagieren kann, löst man dies am besten Interruptgesteuert.
208
21-Die folgenden Funktionen, sind in folgenden Tutorials beschrieben:
9+Die folgenden Funktionen, sind in folgenden Tutorials beschrieben:
2210
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.
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.
2614
2715## Beispiel Atmega328 / Arduino Uno/Nano
2816
29-In diesem Beispiel wird ein Interrupt ausgelöst, sobald ein Zeichen am Eingang anliegt und anschliessend wird dieses in den Ringpuffer geschrieben.
17+In diesem Beispiel wird ein Interrupt ausgelöst, sobald ein Zeichen am Eingang anliegt und anschliessend wird dieses in den Ringpuffer geschrieben.
3018
31-In der Hauptschleife wird geprüft, ob sich etwas im Ringbuffer befindet, wen ja, wird dies über UART ausgegeben.
19+In der Hauptschleife wird geprüft, ob sich etwas im Ringbuffer befindet, wen ja, wird dies über UART ausgegeben.
3220
33-Was man hier aufpassen muss, das nicht zu viel über SPI reinkommt, da diese Schnittstelle um einige sschneller ist als UART.
21+Was man hier aufpassen muss, das nicht zu viel über SPI reinkommt, da diese Schnittstelle um einige sschneller ist als UART.
3422
35-Als Master habe ich eine ATtiny2313 verwendet, welcher auf Tastendruck eine String über SPI ausgibt.
23+Als Master habe ich eine ATtiny2313 verwendet, welcher auf Tastendruck eine String über SPI ausgibt.
3624
37-Am Ende ist noch der Code für den ATTiny angehängt, welcher die Strings sendet.
25+Am Ende ist noch der Code für den ATTiny angehängt, welcher die Strings sendet.
3826
3927### Units
4028
41-Wird für SEI benötig.
42-```
29+Wird für SEI benötig.
30+
31+``` pascal
4332uses
44- intrinsics;
33+ intrinsics;
4534```
4635
4736### Konstanten und Variablen
4837
49-Variablen für Ringpuffer.
50-```
38+Variablen für Ringpuffer.
39+
40+``` pascal
5141const
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;
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;
6050```
6151
62-Pins welche an PORTB für SPI benötigt werden.
52+Pins welche an PORTB für SPI benötigt werden.
6353
64-Wird aber nur gebraucht, wen man etwas sendet.
65-```
54+Wird aber nur gebraucht, wen man etwas sendet.
55+
56+``` pascal
6657type
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;
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;
7465```
7566
7667### Zeichen von SPI empfangen
7768
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;
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;
9282 end;
83+ end;
84+ end;
9385```
9486
9587### Hauptprogramm
9688
97-Im Hauptprogramm wird einfach geprüft, ob etwas im Ringpuffer ist und sobald etwas dort ist, wird es über UART ausgegeben.
98-```
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
9992var
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.
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.
126119```
127120
128121## Sendecode des ATtiny2313
129122
130-Dieser Code sendet einen String, sobald eine Taste gedrückt wird.
123+Dieser Code sendet einen String, sobald eine Taste gedrückt wird.
131124
132-Da der ATTiny2313 keinen echten SPI besitzt, wird die Ausgabe über die Universal-Schnittelle (USI) gemacht.
125+Da der ATTiny2313 keinen echten SPI besitzt, wird die Ausgabe über die Universal-Schnittelle (USI) gemacht.
133126
134-Es sind 3 Taster vorhanden.
135-```
127+Es sind 3 Taster vorhanden.
128+
129+``` pascal
136130program Project1;
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-
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+
186162 repeat
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.
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.
201195```
202196
203197# Siehe auch
204198
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.
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.
208202
209-Autor: [Mathias](</User:Mathias> "User:Mathias")
203+Autor: Mathias
210204
211205---
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).*
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