Arduino und I2C - MCP23017 und MCP23008


Gepostet September 2017, Kategorie: I2C & SPI


Arduino und I2C - MCP23017 und MCP23008

Der MCP23008 ist ein 8-Bit I/0-Expander, der über das serielle Protokoll I2C angesteuert wird. Daher ist dies der kleine Bruder des MCP23017. In diesem Artikel wird beschrieben, wie diese beiden ICs an einen I2C-Bus angeschlossen werden können.


Inhaltsverzeichnis


    Diesem Post ist ein anderer Post über den MCP23017 vorausgegangen. Dies ist der große Bruder des MCP23008. Um Verständnis für diesen Post zu bekommen, sollte jener zuvor gelesen werden:
    Arduino und I2C - MCP23017

    Der MCP23017 ist ein 8-Bit I/O-Expander, der über das serielle Protokoll I2C angesteuert wird. Dieser Chip besitzt 8 Pins, die als Aus- oder Eingänge unabhängig voneinander programmiert werden können. Die Betriebsspannung kann sich im Bereich von 1,8 bis 5,5 V befinden. Das bedeutet, dass die Stromversorgung des Arduinos (5 V) verwendet werden kann. Die I2C-Schnittstelle kann ebenfalls auf einem 5 V-Pegel betrieben werden.

    Datenblatt: http://ww1.microchip.com/downloads/en/DeviceDoc/21919e.pdf

    Aufbau

    Foto des Aufbaus Schaltplan

    Der Aufbau des MCP23017 stammt aus dem vorausgegangenen Artikel. Der MCP23008 wird an den selben I2C-Bus angeschlossen und wird aus diesem Grund mit dem SDA- und SCL-Pins des Arduino und des MCP23017 verbunden. Als Adresse wird 0x21 eingestellt. Aus diesem Grund wird der A0-Pin auf H-Pegel gelegt. Am Pin 0 ist eine LED angeschlossen und an Pin 7 ein Schalter.

    Programmierung mit Arduino-Bibliothek

    Erster Test

    Für die Programmierung des MCP23008 wird die Arduino-Bibliothek verwendet, die unter folgenden Link heruntergeladen werden muss: https://github.com/adafruit/Adafruit-MCP23008-library

    Das folgende Beispielprogramm stellt die Verbindung zwischen Arduino und MCP23008 her. Der Pin, an den der Button angeschlossen ist, wird als Eingang eingestellt und zusätzlich der interne Pullup des Pins aktiviert. Der LED-Pin wird als Ausgang eingestellt, damit die LED ein und ausgeschalten werden kann.

    Der Wert des Taster-Eingangspin wird ausgelesen und negiert als Wert des LED-Ausgangspin gesetzt. Aus diesem Grund leuchtet die LED, wenn der Taster gedrückt wird.

    #include <Wire.h>
    #include "Adafruit_MCP23008.h"
     
    const uint8_t LED = 0; // LED an GPIO_A0
    const uint8_t BTN = 7; // Taster an GPIO_B0
    const uint8_t ADDRESS = 1; // Adresse des MCP, Einstellen mit A0, A1, A2
     
    Adafruit_MCP23008 mcp;
     
    void setup() {  
      mcp.begin(ADDRESS);
     
      // Button-Pin als Eingang mit Pullup
      mcp.pinMode(BTN, INPUT);
      mcp.pullUp(BTN, HIGH);
     
      // LED-Pin als Ausgang
      mcp.pinMode(LED, OUTPUT);
    }
     
    void loop() {
      // Button auslesen
      uint8_t state = mcp.digitalRead(BTN);
     
      // LED setzen, Negation des Zustandes
      mcp.digitalWrite(LED, ! state);
    }

    Ansteuern des MCP23017 und MCP23008

    Das folgende Programm zeigt, wie die beiden ICs angesteuert werden können, wenn diese an die selbe Schnittstelle angeschlossen sind.

    #include <Wire.h>
    #include "Adafruit_MCP23017.h"
    #include "Adafruit_MCP23008.h"
     
    Adafruit_MCP23017 mcp1;
    const uint8_t LED1 = 0; // LED an GPIO_A0
    const uint8_t BTN1 = 8; // Taster an GPIO_B0
    const uint8_t ADDRESS1 = 0; // Adresse des MCP, Einstellen mit A0, A1, A2
     
    Adafruit_MCP23008 mcp2;
    const uint8_t LED2 = 0; // LED an GPIO_A0
    const uint8_t BTN2 = 7; // Taster an GPIO_B0
    const uint8_t ADDRESS2 = 1; // Adresse des MCP, Einstellen mit A0, A1, A2
     
     
    void setup() {  
      mcp1.begin(ADDRESS1);
      mcp2.begin(ADDRESS2);
     
      // Button-Pin als Eingang mit Pullup
      mcp1.pinMode(BTN1, INPUT);
      mcp1.pullUp(BTN1, HIGH);
     
      mcp2.pinMode(BTN2, INPUT);
      mcp2.pullUp(BTN2, HIGH);
     
      // LED-Pin als Ausgang
      mcp1.pinMode(LED1, OUTPUT);
      mcp2.pinMode(LED2, OUTPUT);
    }
     
    void loop() {
      uint8_t state = mcp1.digitalRead(BTN1);
      mcp1.digitalWrite(LED1, ! state);
     
      state = mcp2.digitalRead(BTN2);
      mcp2.digitalWrite(LED2, ! state);
    }

    Dieses Programm verbindet die Funktionalität der Testprogramme der beiden ICs. Aus diesem Grund werden zunächst beiden MCP-Bibliotheken importiert. Die Konstantendefinition findet für beiden MCPs statt, beide MCPs werden initialisiert und alle Pins eingestellt.

    In der loop()-Funktion werden die beiden Taster-Pins abgefragt und die LED-Pins entsprechend gesetzt.

    Programmierung ohne Arduino-Bibliothek

    Die Grundlage dieses Abschnittes bilden die Abschnitte Blinkende LED und Auslesen von Eingängen des Artikels Arduino und I2C - MCP23017.

    Registeradressen des MCP23008

    Da der MCP23008 nur 8 GPIO-Pins besitzt, gibt es für diese jeweils nur ein Register. Die Adressen der Register sind im Datenblatt in Tabelle 1-3 auf Seite 9, oder in der folgenden Konstantendefinition abzulesen.

    const uint8_t MCP_IODIR = 0x00;
    const uint8_t MCP_GPPU = 0x06;
    const uint8_t MCP_GPIO = 0x09;

    Ansteuern der GPIO-Pins

    Das folgende Programm besitzt die Funktionalität des ersten Testprogrammes. Erläuterung zu diesem Programm sind dem Abschnitt 6.4 LED durch Taster schalten des Artikels Arduino und I2C - MCP23017 zu entnehmen.

    #include <Wire.h>
     
    const uint8_t MCP_ADDRESS = 0x21;
    const uint8_t MCP_IODIR = 0x00;
    const uint8_t MCP_GPPU = 0x06;
    const uint8_t MCP_GPIO = 0x09;
     
    void setup() {
      Wire.begin();
      writeRegister(MCP_IODIR, 0b11111110);
      writeRegister(MCP_GPPU, 0b10000000);
    }
     
    void loop() {
      uint8_t reg = readRegister(MCP_GPIO);
     
      if (reg & 0b10000000) {
        writeRegister(MCP_GPIO, 0b00000000);
      } else {
        writeRegister(MCP_GPIO, 0b00000001);
      }
    }
     
    void writeRegister(uint8_t address, uint8_t value) {
      Wire.beginTransmission(MCP_ADDRESS);
      Wire.write(address);
      Wire.write(value);
      Wire.endTransmission();
    }
     
    uint8_t readRegister(uint8_t address) {
      Wire.beginTransmission(MCP_ADDRESS);
      Wire.write(address);
      Wire.endTransmission();
     
      Wire.requestFrom(MCP_ADDRESS, (uint8_t) 1);
      return Wire.read();
    }
    Wetterdaten Eilenburg
    Temperatur: 18.7 °C
    Luftdruck: 1020.5 hPa
    Luftfeuchte: 63 %
    [mehr]