Explore 1.5M+ audiobooks & ebooks free for days

From $11.99/month after trial. Cancel anytime.

The Book of I²C: A Guide for Adventurers
The Book of I²C: A Guide for Adventurers
The Book of I²C: A Guide for Adventurers
Ebook868 pages6 hours

The Book of I²C: A Guide for Adventurers

Rating: 0 out of 5 stars

()

Read preview

About this ebook

An extensive practical guide to connecting real-world devices to microcontrollers with the popular I2C bus.

If you work with embedded systems, you’re bound to encounter the ubiquitous Inter-Integrated Circuit bus (IIC or I2C) – a serial protocol for connecting integrated circuits in a computer system. In The Book of I2C, the first comprehensive guide to this bus, bestselling author Randall Hyde draws on 40 years of industry experience to get you started designing and programming I2C systems. 

Aided by over 100 detailed figures and annotated source-code listings, you’ll learn the I2C implementations of systems like Arduino, Teensy, and Raspberry Pi, as well as variants of the I2C and common I2C peripheral ICs complete with programming examples. For hardware hackers, electronics hobbyists, and software engineers of every skill level, the extensive coverage in this book will make it a go-to reference when it comes to connecting real-world devices to I2C microcontrollers.
LanguageEnglish
PublisherNo Starch Press
Release dateOct 11, 2022
ISBN9781718502475
The Book of I²C: A Guide for Adventurers

Read more from Randall Hyde

Related to The Book of I²C

Related ebooks

Computers For You

View More

Reviews for The Book of I²C

Rating: 0 out of 5 stars
0 ratings

0 ratings0 reviews

What did you think?

Tap to rate

Review must be at least 10 words

    Book preview

    The Book of I²C - Randall Hyde

    The Book of I²C

    A Guide for Adventurers

    by Randall Hyde

    nsp_logo_black_rk

    THE BOOK OF I²C. Copyright © 2023 by Randall Hyde.

    All rights reserved. No part of this work may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording, or by any information storage or retrieval system, without the prior written permission of the copyright owner and the publisher.

    First printing

    26 25 24 23 22 1 2 3 4 5

    ISBN-13: 978-1-7185-0246-8 (print)

    ISBN-13: 978-1-7185-0247-5 (ebook)

    Publisher: William Pollock

    Managing Editor: Jill Franklin

    Production Manager: Rachel Monaghan

    Production Editor: Miles Bond

    Developmental Editors: Abigail Schott-Rosenfield, Athabasca Witschi, and Jill Franklin

    Cover Illustrator: Gina Redman

    Interior Design: Octopod Studios

    Technical Reviewer: Anthony Tribelli

    Copyeditor: Kim Wimpsett

    Compositor: Happenstance Type-O-Rama

    Proofreader: Sadie Barry

    For information on distribution, bulk sales, corporate sales, or translations, please contact No Starch Press, Inc. directly at [email protected] or:

    No Starch Press, Inc.

    245 8th Street, San Francisco, CA 94103

    phone: 1.415.863.9900

    www.nostarch.com

    Library of Congress Cataloging-in-Publication Data

    Names: Hyde, Randall, author. Title: The book of I²C : a guide for adventurers / Randall Hyde.

    Description: San Francisco : No Starch Press, [2022] | Includes index. |

    Identifiers: LCCN 2022018708 (print) | LCCN 2022018709 (ebook) | ISBN 9781718502468 (print) |

       ISBN 9781718502475 (ebook) Subjects: LCSH: I2C (Computer bus) | Microcomputers--Programming. | Microcontrollers--Programming.

    Classification: LCC TK7895.B87 H94 2022 (print) | LCC TK7895.B87 (ebook)

       | DDC 621.39/16--dc23/eng/20220627

    LC record available at https://lccn.loc.gov/2022018708

    LC ebook record available at https://lccn.loc.gov/2022018709

    No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names mentioned herein may be the trademarks of their respective owners. Rather than use a trademark symbol with every occurrence of a trademarked name, we are using the names only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark.

    The information in this book is distributed on an As Is basis, without warranty. While every precaution has been taken in the preparation of this work, neither the author nor No Starch Press, Inc. shall have any liability to any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by the information contained in it.

    This book is dedicated to Limor Lady Ada Fried of Adafruit and Nathan Seidle of SparkFun. Without these two great companies, I never would have thought about creating a book such as this one.

    About the Author

    Randall Hyde is the author of The Art of 64-Bit Assembly; The Art of Assembly Language; and Write Great Code, Volumes 1, 2, and 3 (all from No Starch Press); as well as Using 6502 Assembly Language and P-Source (Datamost). He is also the coauthor of Microsoft Macro Assembler 6.0 Bible (The Waite Group). Over the past 40 years, Hyde has worked as an embedded software and hardware engineer developing instrumentation for nuclear reactors, traffic control systems, and other consumer electronics devices. He has also taught computer science at California State Polytechnic University, Pomona, and at the University of California, Riverside. His website is https://www.randallhyde.com.

    About the Technical Reviewer

    Anthony Tribelli has more than 35 years of experience in software development. This experience ranges, among other things, from embedded device kernels to molecular modeling and visualization to video games. The latter includes 10 years at Blizzard Entertainment. He is currently a software development consultant and is privately developing applications utilizing computer vision.

    Acknowledgments

    I would like to briefly mention the people at No Starch Press who made this book possible: Abigail Schott-Rosenfield, Athabasca Witschi, Jill Franklin, Bill Pollock, the production team, and anyone else I’ve missed.

    I would also like to thank Anthony Tribelli for the great job he did as the technical reviewer for this book. The amount of effort he put into searching through datasheets, reviewing code, writing sample programs to test the book’s concepts, and otherwise ensuring this book was of the highest technical quality was amazing.

    I would like to thank Adafruit and Limor Lady Ada Fried for allowing me to use the Adafruit I²C Address Compilation. This is an incredible resource for I²C programmers, and its presence in this book is no small asset.

    Finally, I would like to mention No Starch Press’s original The Book of SCSI: The Adventure Begins by David Deming (2nd edition by Field, Ridge, et al.), the inspiration for this book’s title.

    Introduction

    Welcome to The Book of I2C. This book provides the resources you need to design and program systems using the Inter-Integrated Circuit Bus (IIC, I2C, or I²C), a serial protocol for connecting various integrated circuits (ICs) together in computer systems. This book will teach you how to expand your embedded system design by adding I²C peripherals with minimal wiring and software.

    To paraphrase from https://i2c.info, I²C uses only two wires to easily connect devices such as microcontrollers, A/D and D/A converters, digital I/O, memory, and many others, together in an embedded system. Although it was originally developed by Philips (now NXP Semiconductors), most major IC manufacturers now support I²C. I²C is popular because it is ubiquitous—most CPUs destined for embedded systems include support for I²C—and its peripheral ICs are inexpensive. It is present in hobbyist systems like Arduino and Raspberry Pi, as well as in most professional single-board computers (SBCs) intended for use in embedded systems.

    The I²C bus is especially important on hobbyist-level embedded systems employed by makers working on personal projects, which typically use a commercially available off-the-shelf (COTS) SBC like an Arduino Uno, Teensy 4.x, or Raspberry Pi as the brains for the system. Such SBCs generally have limited I/O capability or other limitations, so the addition of peripheral ICs may be necessary to realize a given design. The I²C bus is one of the most popular and common ways to expand such systems, since it’s easy, convenient, and inexpensive to use. Furthermore, there are hundreds of different devices available as individual ICs with a wide range of capabilities that connect directly to the I²C bus. Combined with a huge library of open source code to control these devices (especially for Arduino devices), it’s almost trivial to expand small systems using the I²C bus.

    NOTE

    The SPI bus is another popular option for hobbyist systems, but discussing it will have to wait for a different book.

    Although higher-end custom SBCs intended for professional embedded systems often include many of the peripherals missing in hobbyist-grade SBCs, the I²C bus is still a cost-effective way to design such systems. Often, peripherals that don’t have high-performance requirements connect to the CPU on the SBC using the I²C bus.

    Because of the ubiquity of the I²C, it is difficult to work on embedded systems these days without at least a passing familiarity with the I²C bus. Sadly, most programmers are expected to figure out how to use the I²C bus on their own by searching the internet and piecing together design and programming information. This book rectifies that situation, collecting into one comprehensive book the resources needed to fully understand how to design and program systems using the I²C bus.

    Expectations and Prerequisites

    Working with I²C peripherals requires some hardware and software expertise. In theory, an electrical engineer with no software experience could design some hardware and hand it off to a software engineer with no hardware experience, and the two of them could get something working. However, this book is not intended to be read by such teams. Rather, it’s meant for software engineers who aren’t afraid to get their hands dirty by working directly with the hardware, or for hardware engineers who aren’t afraid to sit down with a text editor and write software.

    The Book of I2C assumes you are capable of reading schematics and wiring a COTS SBC (such as an Arduino, Pi, or other commercially available SBC) to various peripheral devices using breadboarding or point-to-point wiring on prototyping boards. You should be comfortable using tools such as DVMs, oscilloscopes, logic analyzers, and more to examine and debug such circuits.

    This book also assumes you are familiar with the C/C++ programming language and are capable of creating, testing, and debugging decent-sized programs on the aforementioned SBCs. Although I²C code can be written in many different languages (including assembly language, Java, and Python), C/C++ is the universal language for embedded systems. Almost every COTS SBC’s development software supports using C/C++, so the book assumes prior knowledge of this language.

    Most of the examples in this book use the Arduino library due to its widespread use and simplicity. Therefore, it assumes at least a passing familiarity with the Arduino system. The Raspberry Pi examples obviously use the Raspberry Pi OS (Linux) and the Pi OS I²C library code; the book provides links to the documentation for those libraries as appropriate. For other systems (for example, µC/OS running on a NetBurner module or MBED running on an STM32 module), this book assumes no prior knowledge and provides either the necessary information or links to the associated documentation.

    The software tools for embedded system programming generally run on Windows, macOS, or Linux. You should be familiar with the particular system running these tools (for example, the C/C++ compilers) and capable of running those tools on your own system, including learning how to use, install, and configure those tools with their accompanying documentation. As necessary, this book will describe how to find those tools and their documentation; however, its focus is the I²C bus, not running C/C++ compilers and integrated development environments (IDEs), so it leaves you to learn more about tools on your own.

    Source Code in This Book

    This book contains considerable C/C++ source code that comes in one of three forms: code snippets, modules, and full-blown programs.

    Code snippets are fragments of a program, provided to make a point or provide an example of some programming technique. They are not stand-alone, and you cannot compile them using a C/C++ compiler. Here is a typical example of a snippet:

    while( inputPin() == 0 )

    {

      .

      .

      .

    }

    The vertical ellipses in this example denote some arbitrary code that could appear in their place.

    Modules are small C/C++ code sections that are compilable but won’t run on their own. Modules typically contain a function that some other program will call. Here is a typical example:

    // inputPin function

     

    int inputPin( void )

    {

        int p = readPort( 0x48 )

        return p & 1;

    }

    Full-blown programs are called listings in this book, and I refer to them by listing number or filename. For example, the following example listing for an Arduino blink program is taken from the file Listing1-1.ino. The name indicates that it is the first listing in Chapter 1, and I refer to it as Listing 1-1 in the surrounding text, labeling the code itself with the filename in the comments:

    // Listing1-1

    .ino

    //

    // An Arduino ″Blink″ program.

     

    int led = 13;

     

    void setup()

    {

        pinMode( led, OUTPUT );

    }

     

    void loop()

    {

      digitalWrite( led, HIGH );  // Turn on the LED

      delay( 500 );                // Wait for 1/2 second

      digitalWrite( led, LOW );    // Turn off the LED

      delay( 500 );                // Wait for a second

    }

    Note that the Listing1-1.ino filename format applies only to code of my own making. Any other source code retains its original filename. For example, I refer to Chapter 16’s code from the TinyWire library as attiny84_Periph.ino. Certain non-Arduino systems (Pi OS and MBED, for example) use a standard main.cpp filename for their main programs; this book will generally place such programs in a subdirectory with a name such as Listingx-x and refer to that whole directory as the listing. Many listings in this book are sufficiently long that I’ve broken them up into sections with text annotation between the sections. In such instances, I will place a comment such as // Listing10-1.ino (cont.) at the beginning of each section to provide continuity.

    All listings and modules are available in electronic form at my website https://bookofi2c.randallhyde.com, either individually or as a ZIP file containing all the listings and other support information for this book, including errata, electronic chapters, and more.

    Unless otherwise noted, all source code appearing in this book is covered under the Creative Commons 4.0 license. You may freely use that code in your own projects as per the Creative Commons license. See https://creativecommons.org/licenses/by/4.0 for more details.

    Typography and Pedantry

    Computer books have a habit of abusing the English language, and this book is no exception. Whenever source code snippets appear in the middle of an English sentence, there is often a conflict between the grammar rules of the programming language and English. In this section, I describe my choices for differentiating syntactical rules in English versus programming languages, in addition to a few other conventions.

    First, this book uses a monospace font to denote any text that appears as part of a program source file. This includes variable and procedure function names, program output, and user input to a program. Therefore, when you see something like get, you know that the book is describing an identifier in a program, not commanding you to get something.

    There are a few logic operations whose names also have common English meanings. These logic operations are AND, OR, and NOT. When using these terms as logic functions, this book uses all caps to help differentiate otherwise confusing English statements. When using these terms as English, this book uses the standard typeset font. The fourth logic operator, exclusive-OR (XOR), doesn’t normally appear in English statements, but this book still capitalizes it.

    In general, I always try to define any acronym or abbreviation the first time I use it. If I haven’t used the term in a while, I often redefine it when I use it next. I’ve added a glossary where I define most of the acronyms (and other technical terms) appearing in this book.

    Finally, hardcore electrical engineers will often use the term buss when describing a collection of electronic signals, especially when describing buss bars. However, I use the spellings bus and buses simply because they are more prevalent in literature discussing the I²C bus.

    A Note About Terminology

    In 2020, several major electronics firms and other members of the Open Source Hardware Association (OSHWA) proposed changing the names of various SPI bus terms to eliminate terms that some find morally questionable. The electronics industry has long used the terms master and slave to describe the operating hierarchy of various devices in the system. There is no technical justification for these names; they don’t even precisely describe the relationship between devices, so better terms would be desirable even if other issues weren’t a factor.

    Although this is a book about the I²C bus, not the SPI bus, I²C is probably next on the list (as SparkFun notes at https://www.sparkfun.com/spi_signal_names). Though the I²C bus does not have pins using the names master or slave, the terms master, slave, multimaster, and multislave are common in I²C literature. This book substitutes the following more descriptive and less offensive terms, as per the OSHWA guidelines for the SPI bus:

    Master becomes controller

    Multimaster becomes multicontroller

    Slave becomes peripheral

    Multislave becomes multiperipheral

    Of course, controller and peripheral have their own meanings and may not always correspond to an I²C bus controller or peripheral device. However, context within this book will make it clear which meaning I intend. Considerable historical documentation continues to use the terms master and slave, but you can simply mentally convert between master/controller and slave/peripheral. To avoid confusion with such historical documentation, this book uses master and slave only when referring to external documentation that uses those terms.

    Organization

    This book is organized into four parts as follows, in addition to appendixes and online chapters:

    Part I: Low-Level Protocols and Hardware

    This part describes the signals and hardware for the I²C. Though you don’t necessarily need to know this information in order to design systems using the I²C bus or to write code to program peripherals, this knowledge is handy when debugging hardware and software that use the I²C bus. Part I also includes a software implementation of the I²C bus for those software engineers who relate more to code than electrical specifications, as well as a section on analyzing and debugging I²C bus transactions. Finally, the section concludes by discussing various real-world extensions to the I²C bus.

    Part II: Hardware Implementations

    This part describes several real-world implementations of the I²C bus. In particular, it reviews the I²C implementation of the following pieces of hardware:

    Arduino systems (and compatibles)

    The Teensy 3.x and 4.x SBC I²C implementations

    The Raspberry Pi, BeagleBone Black, PINE64 and ROCKPro64, Onion, and other Linux systems

    The STM32/Nucleo-144/Nucleo-64 I²C implementation

    The NetBurner MOD54415 I²C implementation

    Part II also describes the following I²C bus implementations:

    The Adafruit Feather bus

    The SparkFun Qwiic bus

    The Seeed Studio Grove bus

    Part III: Programming the I²C Bus

    This part discusses programming devices on the I²C bus. It covers various generic programming techniques, such as real-time OS I²C programming, as well as providing specific real-world programming examples for Arduino, Raspberry Pi, Teensy, MBED, and NetBurner. Part III also describes how to implement an I²C using bare-metal programming techniques—those that work at the hardware level rather than calling library code.

    Part IV: I²C Peripheral Programming Examples

    This part provides programming examples for some common real-world I²C peripheral ICs, including the MCP23017 GPIO expander, ADS1115 16-bit A/D converter, MCP4725 D/A converter, and TCA9548A I²C multiplexer. Part IV also describes how to use a SparkFun Atto84 module as a custom I²C peripheral.

    Appendixes

    Appendix A is a snapshot of the Adafruit I²C Address Compilation, which lists the addresses of hundreds of commerically available I²C peripheral ICs.

    Appendix B contains an overview of the online content. No matter how many pages I add to this book, it will be woefully incomplete. There are just too many I²C controllers and peripherals available. Furthermore, new peripherals will certainly appear after this book is published. To resolve this conundrum (and reduce the price you have to pay for this book), additional chapters are available online at https://bookofi2c.randallhyde.com.

    The online content will cover (among other things) the following topics:

    The MCP4728 quad DAC

    The Maxim DS3502 digital potentiometer

    The DS3231 precision real-time clock

    The MCP9600 thermocouple amplifier

    I²C displays

    The SX1509 GPIO interface

    The PCA9685 PCM/servo interface

    The INA169 and INA218 current sensors

    The MPR121 capacitive touch interface

    The Raspberry Pi Pico SBC

    Espressif ESP32 (and ESP8266) SBCs

    Glossary

    A list of the terms and acronyms appearing in this book.

    In addition to the online chapters, the website will contain help on constructing the circuitry appearing in this book and other information of interest to someone programming I²C peripherals. It will also contain a parts list for all the electronic projects appearing within this book. My goal is to continuously update this information as new (important) peripherals and controllers appear that utilize the I²C bus.

    Part I

    Low-Level Protocols and Hardware

    1

    I²C Low-Level Hardware

    The I²C bus is a worldwide standard for communication between integrated circuits (ICs) on printed circuit boards (PCBs) and across multiple PCBs within a system. According to NXP Semiconductors, I²C is in use on more than 1,000 different ICs made by more than 50 different manufacturers. Without question, I²C is one of the more popular inter-IC data communication schemes available (Serial Peripheral Interface [SPI] being another).

    The popularity of the I²C bus increased with the introduction of hobbyist-level single-board computers (SBCs) such as the Arduino and Raspberry Pi that include I²C support. Today, tens of thousands of programmers have learned the basics of the I²C bus because they wanted to interface some device to an Arduino- or Pi-class system. Because of the vast amount of open source library code available, it is possible to use and program devices on the I²C bus without really understanding its low-level signal protocols. However, to truly make the most of a design employing I²C peripherals, you need to understand those protocols, both hardware and software. This chapter introduces the low-level hardware aspects of the I²C, which you’ll need to understand before learning about the signal protocols.

    1.1 I²C Overview

    Before buses such as the I²C bus, different components of a computer system communicated with one another using traditional CPU-style buses. These buses typically used 8 to 32 data lines and some number of address signals. Connecting a single 8-bit parallel I/O device to a CPU required a fair amount of PCB space to hold all the signal traces. Of course, adding additional I/O increased signal, space, and noise accordingly. In addition to space, those lines also increased the amount of noise that system engineers had to deal with in their designs.

    The I²C bus was invented to alleviate these problems. With the I²C bus, a single pair of signal lines (PCB traces) can connect a wide variety of different I/O peripherals to a CPU. This reduces cost and eliminates many problems when building complex (embedded) computer systems (see the text box Advantages of the I²C Bus for more information).

    I²C devices are divided into two general categories: controller devices (formerly known as masters) and peripheral devices (formerly slaves). A controller device, as its name suggests, controls the communication between the controller and the peripheral device. The peripheral device does not initiate any communication on its own and relies on the controller to manage the communication process.

    The I²C protocol is a synchronous serial communication using two signal lines: SCL, which stands for serial clock, and SDA, which stands for serial data. The controller drives the clock line. When the peripheral is sending data to the controller, it puts the data bits on the data line; when the peripheral is receiving data, the controller places the serial data bits on the data line. Except for one special case—clock stretching, discussed later in this chapter—the peripheral never controls the clock line.

    A typical system has a single controller and one or more peripheral devices. Each peripheral device has an address unique to a given I²C bus, which the controller uses to differentiate multiple peripherals on the same bus. In theory, a single I²C bus supports up to 127 or even 1,024 different peripheral devices, though practical matters limit the number of peripheral devices to a much smaller number.

    Although a typical system has only a single controller, the I²C bus supports multiple controllers on the same bus. This allows multiple controllers to share a common set of peripheral devices. A given system can also support multiple I²C buses, so peripheral devices with the same address, which cannot be used together on the same I²C bus, can still be deployed in a given system.

    Advantages of the I²C Bus

    The I²C bus offers several advantages over other inter-IC connection schemes, including the following:

    Only two signal lines are required: SDA (the data line) and SCL (the clock line). For this reason, I²C is sometimes known as the two-wire interface (TWI), though technically a ground wire is also required. (Note that TWI may refer either to I²C in general or to a subset of the I²C protocol with limited capabilities.)

    Each peripheral connected to the bus has its own unique address. A controller-peripheral relationship exists at all times.

    The I²C bus supports multicontroller relationships on the same I²C bus, with arbitration to prevent data corruption.

    The I²C bus supports several standard bidirectional data transmission rates, including 100 kbit/sec, 400 kbit/sec, 1 Mbit/sec, and up to 3.4 Mbit/sec, depending on bus capacitance. A special unidirectional transfer mode supports up to 5 Mbit/sec.

    The number of ICs that can be connected to the bus is limited only by bus capacitance. Technically, the number of I²C addresses (128 or 1,024) is another limitation, but a typical system will probably reach the bus capacitance limit before reaching the addressing limit.

    Wiring an I²C peripheral onto the bus is extremely simple and usually consists of connecting only three wires (SDA, SCL, and Gnd).

    Because I²C peripherals have their own unique address, there’s no need for bus address decoding hardware and extra decoding lines.

    The controller-peripheral relationship is fundamental to the I²C protocol. While, in theory, it is possible for a single IC to behave either as a controller or as a peripheral and even switch between these two functions in a given system, such activity is rare; in general, a device functions either as a peripheral or as a controller within a system.

    1.2 Open-Drain (Open-Collector) Logic and Four-Wire Mode

    One of the most fundamental electrical aspects of the I²C bus is that it is based on an open-drain (or open-collector) logic system. That is, a device connected to the I²C bus does not drive the signal lines high or low; instead, it can only pull these lines low using an open-drain (FET) connection. Pullup resistors that connect the signal lines on the I²C bus to a power supply pull the two bus lines, SDA and SCL, high by default. This design allows multiple controllers and peripherals to control the data and clock lines without running into problems associated with connecting multiple output pins to the same signal line.

    To place a logic 1 on one of the lines, a device puts its open-drain (or open-collector, if using bipolar devices) into the high-impedance state. This allows the default logic 1 to appear on the line, placed there by the pullup resistor. To place a logic 0 on one of the lines, the device activates its open-drain device, which shorts the line to ground.

    Most I²C devices provide open-drain signals to connect to the I²C bus, so you don’t need to have any additional hardware to interface such devices to the bus. However, it is also possible to connect arbitrary logic devices to the I²C bus by routing them through a bipolar transistor (open-collector), JFET, MOSFET, or other open-drain device to control the electrical access to the I²C bus. The following subsection provides an example of this.

    The SDA and SCL lines, by definition, are bidirectional on the controller device and are often bidirectional on peripheral devices. Certain single-board computers or CPUs might not support digital I/O pins that can operate in a bidirectional mode—that is, they can be programmed only as an input pin or an output pin. To resolve this, some system designers implement I²C in four-wire mode. In four-wire mode the I²C bus still has two wires, but the controller uses two wires to implement each of the signals: two output pins and two input pins. Figure 1-1 diagrams this four-wire controller connection.

    Figure 1-1: Four-wire controller connection

    To prevent electrical conflicts (connecting two outputs together), the output pins drive the base of a transistor (gate on a FET or MOSFET), and the collector (drain) connects to the appropriate bus line. Then the controller CPU can simultaneously read the data on the bus lines using the input pins while writing data on the output pins with no electrical conflict and without support for bidirectional I/O pins.

    1.3 I²C Signal Levels

    When the I²C was designed in the early 1980s, 5 V logic was the prevalent design technology, so the original I²C assumed the use of 5-V logic signals. However, as the I²C bus is based on open-drain connections, the high voltage level is completely determined by the power supply that the pullup resistors connect to when designing the system. As computer systems started using 3.3 V or even down to 1.8 V, system designers began hooking up those pullup resistors to power supplies other than 5 V.

    From the perspective of the I²C bus, as long as the controllers and peripherals can handle and properly work with the voltage levels appearing on the bus, any voltage should work fine. In reality, however, some voltages may cause problems. For this reason, recent I²C standards state that the voltage on the bus must be at least 2 V (so 1.8-V logic won’t work). They also specify that a logic high is defined as greater than 70 percent of the power supply voltage and a logic low is defined as less than 30 percent of the power supply voltage. Today, generic I²C devices almost always expect 5-V or 3.3-V logic.

    1.3.1 Level Shifting

    What happens if you want to mix 3.3-V and 5-V I²C devices on the same bus? Sending a 3.3-V signal into a 5-V device probably won’t damage it, but the device may not interpret 3.3 V as a logic 1, because the standard calls for a logic 1 are equal to 3.5 V on a 5-V system (70 percent of 5 V is 3.5 V). Sending a 5-V signal into a 3.3-V device is far worse; often, this will destroy the device. Clearly, you should avoid this situation at all costs.

    When mixing 3.3-V and 5-V (or other different voltage range) devices on the same I²C bus, you must use voltage translation, or level shifting, to convert the actual voltage on the bus to something that is compatible with the device(s). NXP Semiconductors provides a technical note describing how to do this using discrete MOSFETs (see For More Information at the end of this chapter). Another solution is to purchase a commercial-off-the-shelf (COTS) part such as the Adafruit, four-channel, I²C-safe, bidirectional logic level converter (BSS138). The Adafruit BSS138 device provides a bridge between two I²C buses operating at 3.3 V and 5 V—or, if you need a larger voltage range, it’s rated down to 1.8 V and up to 10 V. As I’m writing this, these Adafruit devices cost about $4 each (US) and support two independent I²C bus level shifters (the I²C bus requires two level shifters, one for the SDA line and one for the SCL line).

    A third option is to level-shift with the TCA9548A I²C multiplexer device. This IC will split the I²C bus into eight separately controlled I²C buses. Each independent bus can have its own pullup resistor to an independent power supply (for example, 3.3 V or 5 V). Therefore, you can put the 3.3-V devices on one bus and the 5-V devices into another. The incoming bus (from the CPU to the TCA9548A) can be either voltage. See Chapter 12 for more information.

    1.4 Choosing Pullup Resistor Sizes

    Choosing resistor sizes for the SDA and SCL pullup resistors requires a bit of thought. While I won’t go into the heavy math behind this choice, keep in mind that pullup resistors should be somewhere in the range of 1 kΩ to about 20 kΩ based on the supply voltage and bus capacitance. The higher the bus capacitance (in particular, the longer your I²C bus lines are), the lower the resistor should be. The minimum value is generally determined by the power supply voltage. For 3.3-V systems, you can go to slightly below 1 kΩ, if you have to. For 5-V systems, 1.5 kΩ is probably as low as you should go.

    NOTE

    To dive into the math behind choosing resistor sizes, see UM10204: I²C Bus Specification and User Manual in For More Information.

    Generally, most systems start out with 4.7-kΩ pullups and go down from there if necessary. Note that if you are using commonly available COTS parts, such as breakout boards from Adafruit, SparkFun, or Seeed Studio, the boards often have pullup resistors already installed. If you attach two or more of these devices to your system, you have to compute the final resistance using a parallel resistance calculation (1/R = 1/R1 + 1/R2 + . . . + 1/Rn). This means if you install two boards, each with a 4.7-kΩ pullup, you’ve actually got 2.35-kΩ pullups on the two lines. If you add too many of these boards on the same bus, you can wind up with pullup values below the minimum suggested resistances.

    1.5 Bus Capacitance and Pullup Resistor Values

    The speed of the I²C bus, which I’ll discuss further in the next section, is largely determined by the value of the pullup resistors (Rp) and the bus capacitance (Cp). Although the system designer has direct control over the value of the pullup resistors, bus capacitance is mostly a function of two things: input capacitance of the devices connected to the bus, and the length of the bus itself. Capacitance increases with bus length, as does resistance, though only by a small and generally insignificant amount. Why do these two parameters affect bus speed?

    From electronics theory you know that the product of resistance and capacitance is time. In particular, 1 Ω × 1 farad = 1 second. When a device pulls one of the bus lines low or releases a bus line so that the pullup resistor returns the signal high, the bus capacitance and resistance affect the amount of time it takes for the signal to rise or fall. If this time exceeds a certain value, the I²C bus will not be able to operate at its full rated speed.

    The I²C standard limits bus capacitance to 400 pF (picofarads, each of which is one trillionth of a farad). A typical pullup resistor on the I²C bus is between 1 kΩ and 10 kΩ. This produces rise times in the range of 0.4 μsec (microseconds) to 4 μsec. If the I²C bus is operating at 100 kHz (that is, a 10-μsec period), a 10-kΩ pullup (4-μsec rise time) will likely not work out well. The solution is to reduce the capacitance or the resistance.

    The primary way to reduce bus capacitance is to keep the bus as short as possible. Longer bus lines dramatically increase the bus capacitance. You can also reduce bus capacitance by putting fewer I²C devices on the bus. If you must put a fixed number of devices on the bus, you can reduce the number of devices on a given bus by using two separate buses.

    Of course, another solution to reducing the rise time is to reduce the value of the pullup resistor. Using a 4.7-kΩ resistor rather than a 10-kΩ resistor, for example, cuts the rise time by about one half.

    1.5.1 What If the Bus Capacitance Is Too High?

    Reducing bus capacitance can be a difficult process. Shortening the I²C bus length is the primary approach. You can also use better cabling if the I²C signals are transmitted across wires, or you can reduce the number of devices on the bus (for example, move half the devices to a second I²C bus).

    If these solutions are impossible or insufficient, reduce the bus speed. If you’re running at 400 kHz, drop down to 100 kHz; if you’re already at 100 kHz, drop down to 50 kHz, and so on. If this doesn’t solve the problem, a major circuit redesign may be necessary. Another solution to consider at this point is a differential bus driver like the SparkFun QwiicBus Kit: https://www.sparkfun.com/products/17250.

    1.6 I²C Bus Speeds

    As discussed, the I²C bus has two signal lines: serial data and serial clock. Controllers transmit data to and from peripherals on the SDA line. The SCL line controls the speed at which this serial data transfer takes place. The frequency of the signal on the SCL line controls how fast data moves between the controller and peripheral devices. The I²C bus standard defines the following data transfer rates:

    Standard mode: 100-kHz SCL frequency, transferring data between devices at 100 kbit/sec

    Fast mode: 400-kHz SCL frequency, transferring data between the controller and peripherals at 400 kbit/sec

    Fast mode plus: 1-MHz SCL frequency, transferring data between the controller and peripherals at 1 Mbit/sec

    High-speed mode: Up to 3.4-MHz SCL frequency, transferring data between the controller and peripherals at up to 3.4 Mbit/sec

    Ultra-fast mode: 5-MHz SCL frequency, though data transmission is unidirectional only

    In practice, the upper bound on the I²C bus frequency is largely determined by the bus capacitance pullup resistors on the bus. However, there generally isn’t a lower bound on the frequency. Indeed, many peripheral devices will actually freeze data transmission using clock stretching (see section 1.9, Clock Stretching, later in this chapter) to provide the peripheral time to process data coming from the controller, which effectively reduces the clock speed and average data transmission speed. Furthermore, there is no requirement that the controller device place a 100-kHz signal (or whatever frequency) on the SCL line. It could run SCL at 50 kHz or any other frequency less than the usual clock speed, if desired.

    The SCL signal is not a free-running clock. The I²C controller explicitly toggles this line when it shifts a bit onto the SDA line. When the controller is not transmitting or receiving data on the SDA line, the controller leaves the SCL line programmed high. The I²C bus frequency, therefore, is the SCL frequency during data transactions on the I²C bus.

    Probably the main limitation on the I²C bus speed is that you have to run the bus at the speed of the slowest devices on the bus. If there is a 100-kbit/sec peripheral on the bus, you must run the bus at 100 kHz, even when communicating with 400-kbit/sec (or faster) peripherals on the same bus. Because most I²C-compatible ICs are 100- or 400-kbit/sec devices, systems rarely run the I²C bus above 400 kHz except for some very special hardware-specific cases. Typically, if you want to run above 400 kHz, you switch to the SPI bus.

    Note

    This book will mainly stick to standard and fast mode I²C bus operation. In theory, this material also covers fast mode plus operation, as it is nearly the same as fast mode with tighter hardware specifications. High-speed mode and ultra-fast mode require special hardware to implement. See the I²C Bus Specification and User Manual for more information about these two modes, via the link provided in For More Information.

    1.7 Multicontroller I²C Bus Clock Synchronization

    The I²C bus optionally supports multiple controllers on the same bus, which is known as a multicontroller configuration. In such cases the SCL frequencies of the two controllers must match, and they must both support multicontroller operation. However, running at the same frequency is not a sufficient condition for a multicontroller environment; their clocks must also be synchronized. Two controllers operate asynchronously with respect to one other. That is, if the bus is currently not being used by either controller, both controllers could decide to use the bus at the same time. However, it’s unlikely that both controllers will

    Enjoying the preview?
    Page 1 of 1