|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
|
<html>
|
|
|
<head>
|
|
|
<title>Arduino - PortManipulation </title>
|
|
|
<link rel='stylesheet' href='arduino.css' type='text/css' />
|
|
|
<meta name="verify-v1" content="TtxFIEJAB6zdJ509wLxjnapQzKAMNm9u0Wj4ho6wxIY=" />
|
|
|
</head>
|
|
|
<body>
|
|
|
<div id="page">
|
|
|
<!--PageHeaderFmt-->
|
|
|
<div id="pageheader">
|
|
|
<div class="title"><a href="http://www.arduino.cc"/>Arduino</a></div>
|
|
|
<div class="search">
|
|
|
<!-- SiteSearch Google -->
|
|
|
<FORM method=GET action="http://www.google.com/search">
|
|
|
<input type=hidden name=ie value=UTF-8>
|
|
|
<input type=hidden name=oe value=UTF-8>
|
|
|
<INPUT TYPE=text name=q size=25 maxlength=255 value="">
|
|
|
<INPUT type=submit name=btnG VALUE="search">
|
|
|
<input type=hidden name=domains value="http://www.arduino.cc/">
|
|
|
<input type=hidden name=sitesearch value="http://www.arduino.cc/">
|
|
|
</FORM>
|
|
|
<!-- SiteSearch Google -->
|
|
|
</div>
|
|
|
</div>
|
|
|
<!--/PageHeaderFmt-->
|
|
|
<!--PageLeftFmt-->
|
|
|
<div id="pagenav" style="text-align: right">
|
|
|
<div style="float: left;">
|
|
|
<p><a class='wikilink' href='http://arduino.cc/en/Main/Buy'>Buy</a>
|
|
|
|
|
|
|
<a class='wikilink' href='http://arduino.cc/en/Main/Software'>Download</a>
|
|
|
|
|
|
|
<a class='wikilink' href='Guide_index.html'>Getting Started</a>
|
|
|
|
|
|
|
<a class='wikilink' href='http://arduino.cc/en/Tutorial/HomePage'>Learning</a>
|
|
|
|
|
|
|
<a class='wikilink' href='index.html'>Reference</a>
|
|
|
|
|
|
|
<a class='wikilink' href='http://arduino.cc/en/Main/Hardware'>Hardware</a>
|
|
|
|
|
|
|
<a class='wikilink' href='FAQ.html'>FAQ</a>
|
|
|
</p>
|
|
|
<p class='vspace'></p>
|
|
|
|
|
|
</div>
|
|
|
<a class="urllink" href="http://www.arduino.cc/blog/" rel="nofollow">Blog »</a> |
|
|
|
<a class="urllink" href="http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl" rel="nofollow">Forum »</a> |
|
|
|
<a class="urllink" href="http://www.arduino.cc/playground/" rel="nofollow">Playground »</a>
|
|
|
</div>
|
|
|
<!--/PageLeftFmt-->
|
|
|
<div id="pagetext">
|
|
|
<!--PageText-->
|
|
|
<div id='wikitext'>
|
|
|
<p><strong>Reference</strong> <a class='wikilink' href='index.html'>Language</a> (<a class='wikilink' href='Extended.html'>extended</a>) | <a class='wikilink' href='Libraries.html'>Libraries</a> | <a class='wikilink' href='Comparison.html'>Comparison</a> | <a class='wikilink' href='Changes.html'>Changes</a>
|
|
|
</p>
|
|
|
<p class='vspace'></p><h2>Port Registers</h2>
|
|
|
<p>Port registers allow for lower-level and faster manipulation of the i/o pins of the microcontroller on an Arduino board. The chips used on the Arduino board (the <span class='wikiword'>ATmega8</span> and <span class='wikiword'>ATmega168</span>) have three ports:
|
|
|
</p><ul><li>B (digital pin 8 to 13)
|
|
|
</li><li>C (analog input pins)
|
|
|
</li><li>D (digital pins 0 to 7)
|
|
|
</li></ul><p class='vspace'></p><p>Each port is controlled by three registers, which are also defined variables in the arduino language. The DDR register, determines whether the pin is an INPUT or OUTPUT. The PORT register controls whether the pin is HIGH or LOW, and the PIN register reads the state of INPUT pins set to input with pinMode(). The maps of the <a class='urllink' href='http://www.arduino.cc/en/Hacking/PinMapping' rel='nofollow'>ATmega8</a> and <a class='wikilink' href='Atmega168Hardware.html'>ATmega168</a> chips show the ports.
|
|
|
</p>
|
|
|
<p class='vspace'></p><p>DDR and PORT registers may be both written to, and read. PIN registers correspond to the state of inputs and may only be read.
|
|
|
</p>
|
|
|
<p class='vspace'></p><p><strong>PORTD</strong> maps to Arduino digital pins 0 to 7
|
|
|
</p><dl><dd><div class='indent'>DDRD - The Port D Data Direction Register - read/write
|
|
|
</div><div class='indent'>PORTD - The Port D Data Register - read/write
|
|
|
</div><div class='indent'>PIND - The Port D Input Pins Register - read only
|
|
|
</div></dd></dl><p class='vspace'></p><p><strong>PORTB</strong> maps to Arduino digital pins 8 to 13 The two high bits (6 & 7) map to the crystal pins and are not usable
|
|
|
</p>
|
|
|
<p class='vspace'></p><dl><dd><div class='indent'>DDRB - The Port B Data Direction Register - read/write
|
|
|
</div><div class='indent'>PORTB - The Port B Data Register - read/write
|
|
|
</div><div class='indent'>PINB - The Port B Input Pins Register - read only
|
|
|
</div></dd></dl><p class='vspace'></p><p><strong>PORTC</strong> maps to Arduino analog pins 0 to 5. Pins 6 & 7 are only accessible on the Arduino Mini
|
|
|
</p><dl><dd><div class='indent'>DDRC - The Port C Data Direction Register - read/write
|
|
|
</div><div class='indent'>PORTC - The Port C Data Register - read/write
|
|
|
</div><div class='indent'>PINC - The Port C Input Pins Register - read only
|
|
|
</div></dd></dl><p class='vspace'></p><p>Each bit of these registers corresponds to a single pin; e.g. the low bit of DDRB, PORTB, and PINB refers to pin <span class='wikiword'>PB0</span> (digital pin 8). For a complete mapping of Arduino pin numbers to ports and bits, see the diagram for your chip: <a class='wikilink' href='http://arduino.cc/en/Hacking/PinMapping'>ATmega8</a>, <a class='wikilink' href='http://arduino.cc/en/Hacking/PinMapping168'>ATmega168</a>. (Note that some bits of a port may be used for things other than i/o; be careful not to change the values of the register bits corresponding to them.)
|
|
|
</p>
|
|
|
<p class='vspace'></p><h4>Examples</h4>
|
|
|
<p>Referring to the pin map above, the <span class='wikiword'>PortD</span> registers control Arduino digital pins 0 <20> 7.
|
|
|
</p>
|
|
|
<p class='vspace'></p><p>You should note, however, that pins 0 & 1 are used for serial communications for programming and debugging the Arduino, so changing these pins should usually be avoided unless needed for serial input or output functions. Be aware that this can interfere with program download or debugging.
|
|
|
</p>
|
|
|
<p class='vspace'></p><p>DDRD is the direction register for Port D (Arduino digital pins 0-7). The bits in this register control whether the pins in PORTD are configured as inputs or outputs so, for example:
|
|
|
</p>
|
|
|
<p class='vspace'></p><pre>DDRD = B11111110; // sets Arduino pins 1 <20> 7 as outputs, pin 0 as input
|
|
|
DDRD = DDRD | B11111100; // this is safer <20> it sets pins 2 to 7 as outputs
|
|
|
// without changing the value of pins 0 & 1, which are RX & TX
|
|
|
</pre>
|
|
|
<p class='vspace'></p><p><code>//See the bitwise operators reference pages and</code>
|
|
|
<a class='urllink' href='http://www.arduino.cc/playground/Code/BitMath' rel='nofollow'>The Bitmath Tutorial</a> in the Playground
|
|
|
</p>
|
|
|
<p class='vspace'></p><p>PORTB is the register for the state of the outputs. For example;
|
|
|
</p>
|
|
|
<p class='vspace'></p><p><code>PORTD = B10101000; // sets digital pins 7,5,3 HIGH</code>
|
|
|
</p>
|
|
|
<p class='vspace'></p><p>You will only see 5 volts on these pins however if the pins have been set as outputs using the DDRD register or with pinMode().
|
|
|
</p>
|
|
|
<p class='vspace'></p><p>PINB is the input register variable It will read all of the digital input pins at the same time.
|
|
|
</p>
|
|
|
<p class='vspace'></p><h4>Why use port manipulation?</h4>
|
|
|
<p>From <a class='urllink' href='http://www.arduino.cc/playground/Code/BitMath' rel='nofollow'>The Bitmath Tutorial</a>
|
|
|
</p>
|
|
|
<p class='vspace'></p><p>Generally speaking, doing this sort of thing is <strong>not</strong> a good idea. Why not? Here are a few reasons:
|
|
|
</p>
|
|
|
<p class='vspace'></p><ul><li>The code is much more difficult for you to debug and maintain, and is a lot harder for other people to understand. It only takes a few microseconds for the processor to execute code, but it might take hours for you to figure out why it isn't working right and fix it! Your time is valuable, right? But the computer's time is very cheap, measured in the cost of the electricity you feed it. Usually it is much better to write code the most obvious way.
|
|
|
<p class='vspace'></p></li><li>The code is less portable. If you use digitalRead() and digitalWrite(), it is much easier to write code that will run on all of the Atmel microcontrollers, whereas the control and port registers can be different on each kind of microcontroller.
|
|
|
<p class='vspace'></p></li><li>It is a lot easier to cause unintentional malfunctions with direct port access. Notice how the line DDRD = B11111110; above mentions that it must leave pin 0 as an input pin. Pin 0 is the receive line (RX) on the serial port. It would be very easy to accidentally cause your serial port to stop working by changing pin 0 into an output pin! Now that would be very confusing when you suddenly are unable to receive serial data, wouldn't it?
|
|
|
</li></ul><p class='vspace'></p><p>So you might be saying to yourself, great, why would I ever want to use this stuff then? Here are some of the positive aspects of direct port access:
|
|
|
</p>
|
|
|
<p class='vspace'></p><ul><li>You may need to be able to turn pins on and off very quickly, meaning within fractions of a microsecond. If you look at the source code in lib/targets/arduino/wiring.c, you will see that digitalRead() and digitalWrite() are each about a dozen or so lines of code, which get compiled into quite a few machine instructions. Each machine instruction requires one clock cycle at 16MHz, which can add up in time-sensitive applications. Direct port access can do the same job in a lot fewer clock cycles.
|
|
|
<p class='vspace'></p></li><li>Sometimes you might need to set multiple output pins at exactly the same time. Calling digitalWrite(10,HIGH); followed by digitalWrite(11,HIGH); will cause pin 10 to go HIGH several microseconds before pin 11, which may confuse certain time-sensitive external digital circuits you have hooked up. Alternatively, you could set both pins high at exactly the same moment in time using PORTB |= B1100;
|
|
|
<p class='vspace'></p></li><li>If you are running low on program memory, you can use these tricks to make your code smaller. It requires a lot fewer bytes of compiled code to simultaneously write a bunch of hardware pins simultaneously via the port registers than it would using a for loop to set each pin separately. In some cases, this might make the difference between your program fitting in flash memory or not!
|
|
|
</li></ul><p class='vspace'></p><h3>See </h3>
|
|
|
<ul><li><a class='urllink' href='http://arduino.cc/en/Hacking/Atmega168Hardware' rel='nofollow'>Pin Mapping of Atmega 168/328</a>
|
|
|
</li></ul><p class='vspace'></p><p><a class='wikilink' href='index.html'>Reference Home</a>
|
|
|
</p>
|
|
|
<p class='vspace'></p><p><em>Corrections, suggestions, and new documentation should be posted to the <a class='urllink' href='http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?board=swbugs' rel='nofollow'>Forum</a>.</em>
|
|
|
</p>
|
|
|
<p class='vspace'></p><p>The text of the Arduino reference is licensed under a
|
|
|
<a class='urllink' href='http://creativecommons.org/licenses/by-sa/3.0/' rel='nofollow'>Creative Commons Attribution-ShareAlike 3.0 License</a>. Code samples in the reference are released into the public domain.
|
|
|
</p>
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
<!--PageFooterFmt-->
|
|
|
<div id="pagefooter">
|
|
|
<a href='#'>Edit Page</a> | <a href='#'>Page History</a> | <a href='#' target='_blank'>Printable View</a> | <a href='http://arduino.cc/en/Site/AllRecentChanges'>All Recent Site Changes</a>
|
|
|
</div>
|
|
|
<!--/PageFooterFmt-->
|
|
|
</div>
|
|
|
</body>
|
|
|
</html>
|