Sign in Join
Wiki copytemporary

AVR Embedded Tutorial - Simple GPIO on and off output: what changed

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

Title: AVR Embedded Tutorial - Simple GPIO on and off output

OldNewLine
1+# Easy GPIO input and output
2+
3+## Direct port manipulation
4+
5+Before you can switch a GPIO pin x to HIGH, you have to configure it as an output. This is done using **DDR**x.
6+
7+- Configure pin as an output:
8+
9+``` pascal
10+ DDRx := DDRx or (1 shl Pinx);
11+```
12+
13+- Set pin to be HIGH:
14+
15+``` pascal
16+ PORTx := PORTx or (1 shl Pinx);
17+```
18+
19+- Set pin to be LOW:
20+
21+``` pascal
22+ PORTx := PORTx and not (1 shl Pinx);
23+```
24+
25+- Switch pin (high to low or low to high):
26+
27+``` pascal
28+ PORTx := PORTx xor (1 shl Pinx);
29+```
30+
31+If you leave **DDR**x LOW, a pull-up resistor is enabled using **PORT**x. This is needed to connect a push button to GND. So you can do without an external pull-up resistor.
32+
33+The status of the GPIO pin x can be queried using **PIN**x.
34+
35+``` pascal
36+ if PINx and (1 shl Pinx) > 0 then
37+ Pin_is_HIGH;
38+```
39+
40+## Blink example
41+
42+This example shows how to address a GPIO with an ATtiy2313. For this, two LEDs are connected to pins 0 and 1 of Port D.
43+
44+### Alternating indicator ATtiny2313
45+
46+``` pascal
47+ program Project1;
48+ const
49+ DP0 = 0; // Pin 0 PortD
50+ DP1 = 1; // Pin 1 PortD
51+ sl = 150000; // Delay
52+
53+ procedure mysleep(t: int32); // A simple delay
54+ var
55+ i: Int32;
56+ begin
57+ for i := 0 to t do
58+ asm
59+ nop
60+ end;
61+ end;
62+
63+ begin
64+ // Configure pin 0 and 1 of Port D as output
65+ DDRD := DDRD or (1 shl DP0) or (1 shl DP1);
66+
67+ repeat
68+ // change LED
69+ PORTD := PORTD or (1 shl DP0); // Pin 0 on (high)
70+ PORTD := PORTD and not (1 shl DP1); // Pin 1 off (low)
71+ mysleep(sl); // Delay
72+
73+ // change LED
74+ PORTD := PORTD or (1 shl DP1); // Pin 1 on (high)
75+ PORTD := PORTD and not (1 shl DP0); // Pin 0 off (low)
76+ mysleep(sl); // Delay
77+ until 1 = 2;
78+ end.
79+```
80+
81+### Toggle pin ATtiny2313
82+
83+If you want to switch the pin, no matter what its original state, you can use an **xor** operator. This also works for an alternating high/low signal. **DP0** is first set to HIGH.
84+
85+``` pascal
86+ begin
87+ // Configure Pin 0 and 1 of Port D as output
88+ DDRD := DDRD or (1 shl DP0) or (1 shl DP1);
89+ PORTD := PORTD or (1 shl DP0); // Pin 0 on (high)
90+
91+ repeat
92+ // Blink LED
93+ PORTD := PORTD xor (1 shl DP0); // Switch pin 0
94+ PORTD := PORTD xor (1 shl DP1); // Switch pin 1
95+ mysleep(sl); // Delay
96+ until 1 = 2;
97+ end.
98+```
99+
100+## Simplify port access
101+
102+If you access ports and do not always want to write the *and*, or *'and xor* operators, you can also use the following procedures/functions. The examples below show this for PORT D. You can easily adjust these for other ports.
103+
104+### pinMode
105+
106+This corresponds roughly to **pinMode(...** from the Arduino.
107+
108+``` pascal
109+procedure ModePortD(Pin: byte; Value: Boolean);
110+ begin
111+ if Value then
112+ begin
113+ DDRD := DDRD or (1 shl pin);
114+ end
115+ else
116+ begin
117+ DDRD := DDRD and not (1 shl pin);
118+ end;
119+ end;
120+```
121+
122+### Digital write
123+
124+This corresponds approximately to **digitalWrite(...** from the Arduino.
125+
126+``` pascal
127+procedure WritePortD(Pin: byte; Value: Boolean);
128+ begin
129+ if Value then
130+ begin
131+ PORTD := PORTD or (1 shl pin);
132+ end
133+ else
134+ begin
135+ PORTD := PORTD and not (1 shl pin);
136+ end;
137+ end;
138+```
139+
140+### Digital switch
141+
142+Switches the pin, there is no equal function from the Arduino.
143+
144+``` pascal
145+procedure WritePortD(Pin: byte);
146+ begin
147+ PORTD := PORTD xor (1 shl pin);
148+ end;
149+```
150+
151+### Digital read
152+
153+This corresponds approximately to **digitalRead(...** from the Arduino.
154+
155+``` pascal
156+ function ReadPortD(bit: byte): Boolean;
157+ begin
158+ Result := PIND and (1 shl bit) <> 0;
159+ end;
160+```
161+
162+## Address pin directly
163+
164+If you connect an absolute bit-packed array, record or set to the port, you can access each pin directly, without annoying **or'' and**and not''' operators.
165+
166+The compiled code is exactly the same size as the conventional method with **or** and **and not**. It could hardly be more elegant.
167+
168+The following three examples address the first 4 pins from PORT D which control 4 LEDs.
169+
170+### Bitpacked array
171+
172+``` pascal
173+ var
174+ LEDPort: bitpacked array[0..7] of boolean absolute PORTD;
175+
176+ begin
177+ LEDPort [0] := True;
178+ LEDPort [1] := True;
179+ LEDPort [2] := False;
180+ LEDPort [3] := False;
181+```
182+
183+### Bitpacked record
184+
185+``` pascal
186+ var
187+ LEDPort: bitpacked record
188+ red, green, yellow, blue: boolean;
189+ end absolute PORTD;
190+
191+ begin
192+ LEDPort.red := True;
193+ LEDPort.green := True;
194+ LEDPort.yellow := False;
195+ LEDPort.blue := False;
196+```
197+
198+### Set
199+
200+``` pascal
201+ var
202+ LEDPortS: set of (green, yellow, red, blue) absolute PORTD;
203+
204+ begin
205+ LEDPortS := [yellow, red]; // yellow, red on
206+ LEDPortS := LEDPortS + [green, blue] - [red]; // green, blue on; red off
207+ LEDPortS := LEDPortS - [green, blue] + [red]; // green, blue off; red on
208+```
209+
210+### DDR and PORT
211+
212+**DDR**x can be solved in a similar way to **PORT**x. It is best to declare the LEDs as a type:
213+
214+``` pascal
215+ Type
216+ TLed = bitpacked record
217+ green, yellow, red, blue: boolean;
218+ end;
219+
220+ var
221+ LedPORT: TLed absolute PORTD;
222+ LedDDR: TLed absolute DDRD;
223+
224+ begin
225+ LedDDR.green := True;
226+ LedDDR.red := True;
227+
228+ repeat
229+ LedPORT.green := True;
230+ LedPORT.red := False;
231+ ...
232+```
233+
234+**PIN**x can be solved in a similar way.
235+
236+## Arduino pins PD0 and PD1
237+
238+This description refers to the Arduino Uno/Nano, other AVRs may also be affected.
239+
240+The PORTD **PD0** and **PD1** pins are also used for the UART interface by default and are therefore not usable. If you still want to use these pins, you have to disable their UART functions.
241+
242+``` pascal
243+ UCSR0B := 0; // Disable UART functions
244+```
245+
246+Note: The LEDs **RX** and **TX** will light in the opposite way because the anode of these LEDs is directly connected to Vcc.
247+
248+For more information about the UART, see [[AVR Embedded Tutorial - UART|UART]] - serial input and output via UART (COM port).
249+
250+## See also
251+
252+- [[AVR Embedded Tutorial|AVR Embedded Tutorials]] - Overview
253+
254+---
255+*From the Free Pascal wiki, page "AVR Embedded Tutorial - Simple GPIO on and off output", as it stood on 2020-01-26 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).*
256+Category: AVR
257+Category: Arduino
258+Category: Embedded
259+Category: Tutorials

Back to history