Sign in Join
Wiki copytemporary

AVR Embedded Tutorial - SPI Shiftregister/de: what changed

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

Title: AVR Embedded Tutorial - SPI Shiftregister/de

OldNewLine
1+# Schieberegister 74HC595 über SPI
2+
3+## Vorwort
4+
5+Es können auch andere Schieberegister angesteuert werden.\
6+Die SPI Version hat einen grossen Vorteil gegenüber einem normalen [[AVR Embedded Tutorial - Shiftregister/de|Schieberegister]], das sie etwa den Faktor 10 schneller ist (ATmega328). Dies macht sich bei einem grösseren Multiplex bemerkbar.
7+
8+Die folgenden Funktionen, sind in folgenden Tutorials beschrieben:
9+
10+- [[AVR Embedded Tutorial - Simple GPIO on and off output/de|GPIO - Aus / Ein-gabe]] - Wie mache ich einen GPIO-Zugriff am AVR.
11+- [[AVR Embedded Tutorial - SPI/de|SPI]] - Nutzung der Hardware-SPI-Schnittstelle.
12+
13+## Beispiel Atmega328 / Arduino Uno/Nano
14+
15+### Konstanten
16+
17+Pins welche an PORTB für SPI benötigt werden.
18+
19+``` pascal
20+const
21+ SPI_SlaveSelect = 2;
22+ SPI_MOSI = 3;
23+ SPI_Clock = 5;
24+```
25+
26+### Schreiben eines Pins
27+
28+Beschreiben eines Pins von PORTB, wird für SlaveSelect und für die Softwareversion gebraucht.
29+
30+``` pascal
31+ procedure WritePortB(Pin: byte; Value: boolean);
32+ begin
33+ if Value then begin
34+ PORTB := PORTB or (1 shl Pin);
35+ end else begin
36+ PORTB := PORTB and not (1 shl Pin);
37+ end;
38+ end;
39+```
40+
41+Ein Funktion welche eine Zeichenkette an den SPI-Port sendet.
42+
43+### Schreiben der Zeichenkette
44+
45+``` pascal
46+ procedure WriteDataHardSPI(p: PByte; len: byte);
47+ var
48+ i: byte;
49+ begin
50+ WritePortB(SPI_SlaveSelect, False);
51+ for i := len - 1 downto 0 do begin
52+ SPDR := p[i];
53+ while (SPSR and (1 shl SPIF)) = 0 do begin
54+ end;
55+ end;
56+ WritePortB(SPI_SlaveSelect, True);
57+ end;
58+```
59+
60+### Hauptprogramm
61+
62+Die Register von SPI wird auf die höchst mögliche Geschwindigkeit gestellt.
63+
64+``` pascal
65+var
66+ z: uint16;
67+begin
68+ // Alle Pins auf Output.
69+ DDRB := (1 shl SPI_MOSI) or (1 shl SPI_Clock) or (1 shl SPI_SlaveSelect);
70+
71+ // SPI-Register einstellen.
72+ SPCR := (1 shl SPE) or (1 shl MSTR) or (%00 shl SPR);
73+ SPSR := (1 shl SPI2X);
74+
75+ repeat
76+ // Zähler hochzählen, bei Überlauf wieder auf 0.
77+ Inc(z);
78+
79+ // SPI-Port beschrieben.
80+ WriteDataHardSPI(@z, 2); // 2 Byte schreiben.
81+ until 1 = 2;
82+end.
83+```
84+
85+## Beispiel ATTiny2313
86+
87+Der **ATTiny2313** besitzt keine direkte SPI-Schnittstelle, dafür gibt es die universelle **USI**-Schnittstelle, welche hier für **SPI** verwendet wird. Dies ist beim Beschreiben ein wenig komplizierter als bei der direkte SPI-Schnittstelle des Atmega.
88+
89+**Hinweis:** Der **ATTiny2313** hat auch **MOSI** und **MISO**-Anschlüsse, diese habe aber nur für den Programmer Verwendung. Dafür sind **DO** und **DI** vorhanden, welche aber genau in der umgekehrten Reihenfolge arbeiten.
90+
91+### Deklarationen
92+
93+Pins welche an PORTB für SPI benötigt werden.
94+
95+Dafür wir ein **bitpacked record** verwendet, somit kann man **direkt** auf die Pins zugreifen.
96+
97+``` pascal
98+type
99+ TSPIGPIO = bitpacked record
100+ p0, p1, p2, p3, SlaveSelect, DataInt, DataOut, Clock: boolean;
101+ end;
102+
103+var
104+ SPI_PORT: TSPIGPIO absolute PORTB;
105+ SPI_DDR: TSPIGPIO absolute DDRB;
106+```
107+
108+Ein Funktion welche eine Zeichenkette an den SPI-Port sendet.
109+
110+### Schreiben der Zeichenkette
111+
112+``` pascal
113+ procedure SPIWriteData(p: PByte; len: byte);
114+ var
115+ i: byte;
116+ begin
117+ SPI_PORT.SlaveSelect := False;
118+ for i := len - 1 downto 0 do begin
119+ USIDR := p[i];
120+ USISR := 1 shl USIOIF;
121+
122+ repeat
123+ USICR := (%01 shl USIWM) or (%10 shl USICS) or (1 shl USICLK) or (1 shl USITC);
124+ until (USISR and (1 shl USIOIF)) <> 0;
125+
126+ end;
127+ SPI_PORT.SlaveSelect := True;
128+ end;
129+```
130+
131+### Hauptprogramm
132+
133+Diese Beispiel zeigt da Beschreiben von 2 kaskadierten Schieberegister.
134+
135+Es wird einfach einen Integer Wert ausgegeben.
136+
137+Man sieht auch das keine Konfiguration von **USI** am Anfang notwendig ist, ausser das man die Ports auf Ausgabe stellen muss.
138+
139+``` pascal
140+var
141+ z: uint16 = 0;
142+begin
143+ SPI_DDR.DataOut := True;
144+ SPI_DDR.Clock := True;
145+ SPI_DDR.SlaveSelect := True;
146+
147+ repeat
148+ Inc(z);
149+ SPIWriteData(@z, 2); // Integer ausgeben.
150+ until 1 = 2;
151+end.
152+```
153+
154+## Software Version
155+
156+Das man SPI sehr gut auch Softwareemuliert machen kann, zeige ich es hier auch.
157+
158+Dies ist aber um etwa den Faktor 10 langsamer als die Hardwareversion des Atmega328, dafür kann man beliebige Ports nehmen.
159+
160+Die Software-Version hat den Vorteil, sie läuft auf jedem AVR und kann auch benutzt werden, wen man mehrere SPI-Schnittstellen braucht.
161+
162+``` pascal
163+ procedure WriteDataSoftSPI(p: PByte; len: byte);
164+ var
165+ i, j: byte;
166+ begin
167+ WritePortB(SPI_SlaveSelect, False);
168+ for j := 0 to len - 1 do begin
169+
170+ for i := 7 downto 0 do begin
171+ if (p[j] and (1 shl i)) <> 0 then begin
172+ WritePortB(SPI_MOSI, True);
173+ end else begin
174+ WritePortB(SPI_MOSI, False);
175+ end;
176+ WritePortB(SPI_Clock, True);
177+ WritePortB(SPI_Clock, False);
178+ end;
179+ WritePortB(SPI_SlaveSelect, True);
180+
181+ end;
182+ end;
183+```
184+
185+# Siehe auch
186+
187+- Übersichtseite [[AVR Embedded Tutorial/de|AVR Embedded Tutorial]]
188+- [[AVR Embedded Tutorial - Shiftregister/de|Schieberegister]] - Wie steuere ich Schieberegister an.
189+- [[AVR Embedded Tutorial - SPI/de|SPI]] - Nutzung der Hardware-SPI-Schnittstelle bei einem ATmega328 / Arduino.
190+
191+Autor: Mathias
192+
193+---
194+*From the Free Pascal wiki, page "AVR Embedded Tutorial - SPI Shiftregister/de", as it stood on 2020-02-27 after a change by Mathias, 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).*
195+Category: AVR/de
196+Category: Arduino/de
197+Category: Deutsch
198+Category: Embedded/de
199+Category: Tutorials/de

Back to history