<!DOCTYPE html PUBLIC
    "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"
    "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">
<html 
   xmlns="http://www.w3.org/1999/xhtml"
   xmlns:svg="http://www.w3.org/2000/svg" 
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns:mathml="http://www.w3.org/1998/Math/MathML"
   >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>MCP 23018 address select resistor values</title>
<style type="text/css">
  body { font-family: serif; }
.tab { border-collapse: collapse; }
.tab > * > tr > * { border: solid black 1px; padding: 0.5ex; }
 .pinout { float: left; }
 .pd { float: right; }
h1 { font-family: sans; text-align: center; font-size: 150%; }
h2 { font-family: sans; text-align: left; font-size: 110%; }
.subtitle { font-weight: bold; font-family: sans; text-align: center; }
@media print {
  .screenonly { display: none; } 
  .tab > * > tr > * { font-size: 75%; }
}
</style>
</head>
<body onload="bodyloaded()">

  <h1>MCP23018</h1>
<p class="subtitle">16-Bit I/O Expander with Open-Drain Outputs</p>

<div class="pinout">
<svg xmlns="http://www.w3.org/2000/svg" 
     width="3in" height="4in" 
     viewBox="0 0 550 1500" version="1.1" xml:space="preserve">
  <style type="text/css">
    .normal {fill:none; stroke: black; stroke-width: 5px;}
    .sub { font-size: smaller }
    .r { color: black; font-size: 40px; font-family: serif; text-anchor: end; alignment-baseline: middle; }
    .l { color: black; font-size: 40px; font-family: serif; text-anchor: start; alignment-baseline: middle; }
    .o { text-decoration: overline; }
  </style>
  <defs>
    <g id="pin">
      <rect x="-20" y="10" width="20" height="50" class="normal"/>
      <rect x="285" y="10" width="20" height="50" class="normal"/>
   </g>
 </defs>

   <rect x="50" y="50" width="285" height="1365" class="normal" />
   <path d="M167.5,50 A25,25 0 1,0 217.5,50" class="normal"/>
   <use x="50" y="50" xlink:href="#pin" />
   <use x="50" y="150" xlink:href="#pin" />
   <use x="50" y="250" xlink:href="#pin" />
   <use x="50" y="350" xlink:href="#pin" />
   <use x="50" y="450" xlink:href="#pin" />
   <use x="50" y="550" xlink:href="#pin" />
   <use x="50" y="650" xlink:href="#pin" />
   <use x="50" y="750" xlink:href="#pin" />
   <use x="50" y="850" xlink:href="#pin" />
   <use x="50" y="950" xlink:href="#pin" />
   <use x="50" y="1050" xlink:href="#pin" />
   <use x="50" y="1150" xlink:href="#pin" />
   <use x="50" y="1250" xlink:href="#pin" />
   <use x="50" y="1350" xlink:href="#pin" />

  <text x="20" y="100" class="r">V<tspan class="sub" dy="10">SS</tspan></text>
  <text x="20" y="200" class="r">NC</text>
  <text x="20" y="300" class="r">GPB0</text>
  <text x="20" y="400" class="r">GPB1</text>
  <text x="20" y="500" class="r">GPB2</text>
  <text x="20" y="600" class="r">GPB3</text>
  <text x="20" y="700" class="r">GPB4</text>
  <text x="20" y="800" class="r">GPB5</text>
  <text x="20" y="900" class="r">GPB6</text>
  <text x="20" y="1000" class="r">GPB7</text>
  <text x="20" y="1100" class="r">V<tspan class="sub" dy="10">DD</tspan></text>
  <text x="20" y="1200" class="r">SCL</text>
  <text x="20" y="1300" class="r">SDA</text>
  <text x="20" y="1400" class="r">NC</text>

  <text x="365" y="100" class="l">NC</text>
  <text x="365" y="200" class="l">GPA7</text>
  <text x="365" y="300" class="l">GPA6</text>
  <text x="365" y="400" class="l">GPA5</text>
  <text x="365" y="500" class="l">GPA4</text>
  <text x="365" y="600" class="l">GPA3</text>
  <text x="365" y="700" class="l">GPA2</text>
  <text x="365" y="800" class="l">GPA1</text>
  <text x="365" y="900" class="l">GPA0</text>
  <text x="365" y="1000" class="l">INTA</text>
  <text x="365" y="1100" class="l">INTB</text>
  <text x="365" y="1200" class="l">NC</text>
  <text x="365" y="1300" class="l o">RESET</text>
  <text x="365" y="1400" class="l">ADDR</text>
</svg>
</div>

<p>The MCP23018 is very easy to interface with the Raspberry Pi through the
  I<sup>2</sup>C bus. It has 5.5V tolerant inputs, making it possible to read
  TTL inputs without doing any level conversion. If you want TTL level outputs,
  you only need to level change the two I<sup>2</sup> lines and run the device at 5V.</p>

<p>The MCP23018 does, however, have an unusual way to set its address.</p>

<p class="screenonly"><a href="#res">TL;DR</a></p>

<h2>I<sup>2</sup>C bus addressing</h2>

<p>On an I<sup>2</sup>C bus, each device has a unique address, typically
  programmable by hardware address lines. When a message is received on
  the I<sup>2</sup>C bus with a matching the slave addres, the device will respond
  to commands on the bus.</p>

<p>The slave address doesn't change as the device is operating, so using
  address pins uses a lot of space for very little functionality. To reduce the
  number of pins used, the MCP23018 has a single <em>analogue</em> input to set
  the address.</p>

<p>The voltage presented on the ADDR pin is read at power-on and at
  reset, and is decoded by comparing it against several threshold voltages in a 3 bit
  flash-ADC. This address is then remembered until the next reset.</p>

<p>The voltage space is divided up into 8 equal chunks from V<sub>SS</sub> to
  V<sub>DD</sub>, allowing for 8 of these devices on the bus, numbered 0x20 to
  0x27. The ideal voltage
  to present to the ADDR pin is mid-way through the range, ie. 1/16, 3/16,
  5/16, &#x2026; 15/16 of V<sub>DD</sub>.</p>

<h2>Potential Divider</h2>

<div class="pd">
<svg xmlns="http://www.w3.org/2000/svg" 
     width="2in" height="2in" 
     viewBox="-50 0 500 550" version="1.1" xml:space="preserve">
  <style type="text/css">
    .normal {fill:none; stroke: black; stroke-width: 5px;}
    .filled {fill:black; stroke: none; }
    .text { color: black; font-size: 40px; font-family: serif; }
    .ital { color: black; font-size: 40px; font-family: serif; font-style: italic }
    .sub { font-size: smaller }
  </style>
  <defs>
    <g id="resistor">
      <polyline class="normal" points="0,0 0,10, 20,20, -20,40, 20,60, -20,80, 0,90, 0,100" />
    </g>
  </defs>

  <line x1="0" y1="50" x2="150" y2="50" class="normal" />
  <line x1="50" y1="50" x2="50" y2="100" class="normal" />
  <use x="50" y="100" xlink:href="#resistor" />
  <line x1="50" y1="250" x2="150" y2="250" class="normal" />
  <line x1="50" y1="200" x2="50" y2="300" class="normal" />
  <use x="50" y="300" xlink:href="#resistor" />
  <line x1="50" y1="400" x2="50" y2="500" class="normal" />
  <line x1="0" y1="500" x2="150" y2="500" class="normal" />
  <polyline class="normal" points="35,440 50,460 65,440" style="fill: black" />
  <circle cx="50" cy="50" r="10" class="filled" />
  <circle cx="50" cy="250" r="10" class="filled" />
  <circle cx="50" cy="500" r="10" class="filled" />

  <text x="200" y="060" class="ital">V<tspan class="sub" dy="10">DD</tspan></text>
  <text x="100" y="160" class="ital">R<tspan class="sub" dy="10">2</tspan></text>
  <text x="200" y="260" class="ital">V<tspan class="sub" dy="10">ADDR</tspan></text>
  <text x="100" y="360" class="ital">R<tspan class="sub" dy="10">1</tspan></text>
  <text x="200" y="510" class="text">0V</text>
  <text x="100" y="460" class="ital">I<tspan class="sub" dy="10">PD</tspan></text>
</svg>
</div>

<p>A simple potential divider can do the job well, provided that the tolerance
  of the resistors doesn't permit the voltage to stray outside of the permitted
  region. The permitted region for each address is where the ADC will
  definitely decode the presented voltage to the correct address, even if there
  is noise, drift in the reference voltages etc.</p>

<p>The permitted region is relatively small, less than half of the space
  available. The exact formula is &#xb1;20% of 1/8 of the supply voltage.</p>

<p>It can be quite tricky to find appropriate resistor values to set the
  address. If you only have two devices to attach, I suggest using addresses
  0x20 and 0x27, for which any resistor will work.</p>

<h2>Assumptions</h2>

<p>When generating the tables below, I have assumed 5% tolerance resistors
  throughout. Apart from the top and bottom addresses, you cannot guarantee
  correct operation with 10% tolerance resistors. You can, of course, use
  resistors with better tolerance, but it is not necessary.</p>

<p>I have planned for a current flow of 1mA through the the potential
  divider with V<sub>DD</sub> at 5V. I can't find documentation on the current flow through the the ADDR
  pin, but it is should be several orders of magnitude less so it won't affect the
  resistor calculations.</p>

<h2>About the tables</h2>

<p>Only the relative voltages are important, so apart from the current flow in the final column, all
  the voltage levels are normalised to the range&#160;0&#x2026;1. Multiply them by
  V<sub>DD</sub> if you want to compare them with measurements.</p>

<p>The <em>Actual level</em> column gives the lowest and highest levels that
  will be seen on the ADDR pin should the resistors be at the very limit of their allowed
  tolerance. In all cases, these are within the permitted range.</p>

<h2 id="res">Picking the resistors</h2>

<p>Look up the address, and use the R<sub>1</sub> the R<sub>2</sub> values
  from <em>any</em> of the tables below. Check that the resistor tolerance is at least as good as&#160;5%.</p>

<h2>E24 series</h2>
<table class="tab">
<thead>
<tr>
<th>Address</th><th>Ideal level</th><th>Permitted range</th><th>R<sub>1</sub></th><th>R<sub>2</sub></th><th>Actual level<br/>(worst case with<br/>5% tolerance)</th><th>I<sub>PD</sub><br/>for V<sub>DD</sub>=5V</th>
</tr>
</thead>
<tbody>
<tr><th>0x20</th><td>1/16 = 0.625</td><td>0       &#x2013; 0.0875</td><td>4K7</td><td>Open circuit</td><td>0</td><td/></tr>
<tr><th>0x21</th><td>3/16 = 0.1875</td><td>0.1625 &#x2013; 0.2125</td><td>910R</td><td>3K9</td><td>0.1743 &#x2013; 0.2050</td><td>1mA</td></tr>
<tr><th>0x22</th><td>5/16 = 0.3125</td><td>0.2875 &#x2013; 0.3375</td><td>1K5</td><td>3K3</td><td>0.2914 &#x2013; 0.3344</td><td>1mA</td></tr>
<tr><th>0x23</th><td>7/16 = 0.4375</td><td>0.4125 &#x2013; 0.4625</td><td>2K2</td><td>2K4 in series with 430R</td><td>0.4129 &#x2013; 0.4621</td><td>1mA</td></tr>
<tr><th>0x24</th><td>9/16 = 0.5625</td><td>0.5375 &#x2013; 0.5875</td><td>2K4 in series with 430R</td><td>2K2</td><td>0.5379 &#x2013; 0.5871</td><td>1mA</td></tr>
<tr><th>0x25</th><td>11/16 = 0.6875</td><td>0.6625 &#x2013; 0.7125</td><td>3K3</td><td>1K5</td><td>0.6656 &#x2013; 0.7086</td><td>1mA</td></tr>
<tr><th>0x26</th><td>13/16 = 0.8125</td><td>0.7875 &#x2013; 0.8375</td><td>3K9</td><td>910R</td><td>0.7950 &#x2013; 0.8256</td><td>1mA</td></tr>
<tr><th>0x27</th><td>5/16 = 0.9375</td><td>0.9125 &#x2013; 1</td><td>Open circuit</td><td>4K7</td><td>1</td><td></td></tr>
</tbody>
</table>

<h2>E12 series</h2>
<p>This tables allows you to use more common resistors, but they <em>must</em> still be no more than 5% tolerance.</p>
<table class="tab">
<thead>
<tr>
<th>Address</th><th>Ideal level</th><th>Permitted range</th><th>R<sub>1</sub></th><th>R<sub>2</sub></th><th>Actual level<br/>(worst case with<br/>5% tolerance)</th><th>I<sub>PD</sub><br/>for V<sub>DD</sub>=5V</th>
</tr>
</thead>
<tbody>
<tr><th>0x20</th><td>1/16 = 0.625</td><td>0       &#x2013; 0.0875</td><td>4K7</td><td>Open circuit</td><td>0</td><td/></tr>
<tr><th>0x21</th><td>3/16 = 0.1875</td><td>0.1625 &#x2013; 0.2125</td><td>1K</td><td>4K7 in parallel with 56K</td><td>0.1726 &#x2013; 0.2031</td><td>0.9mA</td></tr>
<tr><th>0x22</th><td>5/16 = 0.3125</td><td>0.2875 &#x2013; 0.3375</td><td>1K5</td><td>3K3</td><td>0.2914 &#x2013; 0.3344</td><td>1mA</td></tr>
<tr><th>0x23</th><td>7/16 = 0.4375</td><td>0.4125 &#x2013; 0.4625</td><td>2K2 in parallel with 47K</td><td>2K7</td><td>0.4132 &#x2013; 0.4625</td><td>1mA</td></tr>
<tr><th>0x24</th><td>9/16 = 0.5625</td><td>0.5375 &#x2013; 0.5875</td><td>2K7</td><td>2K2 in parallel with 47K</td><td>0.5375 &#x2013; 0.5868</td><td>1mA</td></tr>
<tr><th>0x25</th><td>11/16 = 0.6875</td><td>0.6625 &#x2013; 0.7125</td><td>3K3</td><td>1K5</td><td>0.6656 &#x2013; 0.7086</td><td>1mA</td></tr>
<tr><th>0x26</th><td>13/16 = 0.8125</td><td>0.7875 &#x2013; 0.8375</td><td>4K7 in parallel with 56K</td><td>1K</td><td>0.7968 &#x2013; 0.8274</td><td>0.9mA</td></tr>
<tr><th>0x27</th><td>5/16 = 0.9375</td><td>0.9125 &#x2013; 1</td><td>Open circuit</td><td>4K7</td><td>1</td><td></td></tr>
</tbody>
</table>

<h2>E6 series</h2>
<p>This tables allows you to use even more common resistors. Again, they <em>must</em> be no more than 5% tolerance.</p>
<table class="tab">
<thead>
<tr>
<th>Address</th><th>Ideal level</th><th>Permitted range</th><th>R<sub>1</sub></th><th>R<sub>2</sub></th><th>Actual level<br/>(worst case with<br/>5% tolerance)</th><th>I<sub>PD</sub><br/>for V<sub>DD</sub>=5V</th>
</tr>
</thead>
<tbody>
<tr><th>0x20</th><td>1/16 = 0.625</td><td>0       &#x2013; 0.0875</td><td>4K7</td><td>Open circuit</td><td>0</td><td/></tr>
<tr><th>0x21</th><td>3/16 = 0.1875</td><td>0.1625 &#x2013; 0.2125</td><td>1K</td><td>4K7 in parallel with 56K</td><td>0.1726 &#x2013; 0.2031</td><td>0.9mA</td></tr>
<tr><th>0x22</th><td>5/16 = 0.3125</td><td>0.2875 &#x2013; 0.3375</td><td>1K5</td><td>3K3</td><td>0.2914 &#x2013; 0.3344</td><td>1mA</td></tr>
<tr><th>0x23</th><td>7/16 = 0.4375</td><td>0.4125 &#x2013; 0.4625</td><td>2K2, 330R and 33R, all in series</td><td>3K3</td><td>0.4127 &#x2013; 0.4619</td><td>0.9mA</td></tr>
<tr><th>0x24</th><td>9/16 = 0.5625</td><td>0.5375 &#x2013; 0.5875</td><td>3K3</td><td>2K2, 330R and 33R, all in series</td><td>0.5381 &#x2013; 0.5873</td><td>0.9mA</td></tr>
<tr><th>0x25</th><td>11/16 = 0.6875</td><td>0.6625 &#x2013; 0.7125</td><td>3K3</td><td>1K5</td><td>0.6656 &#x2013; 0.7086</td><td>1mA</td></tr>
<tr><th>0x26</th><td>13/16 = 0.8125</td><td>0.7875 &#x2013; 0.8375</td><td>4K7 in parallel with 56K</td><td>1K</td><td>0.7968 &#x2013; 0.8274</td><td>0.9mA</td></tr>
<tr><th>0x27</th><td>5/16 = 0.9375</td><td>0.9125 &#x2013; 1</td><td>Open circuit</td><td>4K7</td><td>1</td><td></td></tr>
</tbody>
</table>

<p>Peter Benie &lt;peterb@chiark.greenend.org.uk&gt;<br/>
<a href="../">Electronics</a></p>

</body>
</html>
