Forum: Mikrocontroller und Digitale Elektronik MCP23017 Funktion der Register


von Henry (Gast)


Lesenswert?

Hallo Gemeinde
ich möchte mit dem MCP23017 mehrere Taster auslesen und LED ansteuern. 
Im Netz habe ich viele Beispile dazu gefunden. Leider waren die meisten 
für den Arduino oder in Python geschrieben.
Da ich mit C arbeite passt das nicht so gut zusammen. Leider habe ich 
auch keine gute Erklärung zu den Registern gefunden oder in Englisch 
(sorry)
Kann mir da jemand helfen und den IC zu verstehen.
Gibt es ein paar Beispiele dazu mit C und dem Atmega 128?

LG Henry

von Einer K. (Gast)


Lesenswert?

Henry schrieb:
> in Englisch

Ja, Datenblätter, in Englisch zu verfassen, ist eine weltweite Marotte.
Ein deutsches, für den MCP23017, ist mir noch nicht unter gekommen.

von Henry (Gast)


Lesenswert?

Das mit dem englisch ist das kleinste Problem. Du würdest mir weitaus 
helfen wenn du was zu den Registern hättest oder Beispiel zum lesen oder 
schreiben des MCP.

Henry

von Michael U. (amiga)


Lesenswert?

Hallo,

was findest Du denn nicht im Datenblatt?
http://ww1.microchip.com/downloads/en/DeviceDoc/20001952C.pdf

Die Tabellen der Registeradressen und die Funktionen sind doch recht 
übersichtlich.
Ansonsten ist es ein normaler I2C-Chip und dazu steht auch einiges im 
Datenblatt.

Gruß aus Berlin
Michael

von Henry (Gast)


Lesenswert?

Hallo Michael
habe bisher immer mit dem PCF gearbeitet und wollte jetzt mit dem MCP 
weiter machen. Da der MCP 11 Register hat kann man einiges einstellen. 
Da auch die GPIO in A und B getrennt sind. Da liegt mein Problem. Habe 
bisher nicht verstanden was die Register mit welcher Einstellung die 
GPIO A/B zu Ein- oder Ausgang machen. Bei der übertragung wird zuerst 
das Register beschrieben und danach der Wert. Als Beispiel habe ich die 
Angabe 0xFF für alle einschalten gefunden. Leider ist englisch nicht 
meine Stärke, aber dazu gibt es dann ja google. Die müssen nur noch 
begreiffen das ein Port kein Hafen ist.

LG Henry

von Bernd K. (prof7bit)


Lesenswert?

Henry schrieb:
> Leider ist englisch nicht
> meine Stärke

Das lässt sich doch ändern.

Wenn Du Dich wirklich mit diesem Thema beschäftigen willst wirst Du an 
jeder Ecke auf englischsprachige Dokumentation treffen, ich stell mir 
das auf Dauer sehr frustierend vor die Sprache nicht lesen zu können in 
der alle notwendigen Handbücher und andere Texte verfasst sind und alle 
5 Minuten über eine Sprachbarriere zu stolpern.

Englisch ist doch für deutschsprachige relativ einfach zu erlernen, die 
Sprachen sind sich sehr ähnlich, es ist leichter als Du denkst. Das würd 
ich über kurz oder lang ernsthaft in Angriff nehmen. Kann auch beruflich 
nur von Vorteil sein.

von Philipp K. (philipp_k59)


Lesenswert?

Du brauchst ja nur 5 Register oder so.. aussserdem gibt es viele 
Deutsche Tutorials die Register beschreiben.

Dazu hast Du nichts zu Deiner Vorgehensweise/Equipment/System 
geschrieben, sonst hätte man auch Tips geben können. So weiß man jetzt 
nicht, ob Du Raspi-Tutorials in Deutsch nicht gefunden hast oder mit nem 
USBToI2C Stick am Tower oder wie auch immer programmieren willst.

Für Buttons wären ja auch mindestens 1 Eingang am Rechner nicht 
verkehrt, sonst müsste man ja durchgehend abfragen..

GPIO Eingänge lesen
(Wenn man es beschreibt wird mit den Daten OLATA beschrieben)

OLAT Ausgänge setzen
(Gibt gelesen nur den aktuellen Wert und nicht den Pinstatus)

IODIR Richtung 1=INPUT 0=OUTPUT

IPOL  Invertierung 1=Invertiern 0=Normal

GPPU  Internes Pullup Register

Wenn Du auch Buttons benutzen willst kann man noch einen Interrupt 
aktivieren damit Du nicht immer Abrufen musst.

Interrupts sind auch nicht viel schwerer.

: Bearbeitet durch User
von Henry (Gast)


Lesenswert?

Habe mal mit diesem Code gearbeitet:
1
#include <stdbool.h>
2
#include <avr/pgmspace.h>
3
#include "main.h"
4
#include "i2cmaster.h"
5
#include "avr/io.h"
6
#include "util/delay.h"
7
#include "avr/interrupt.h"
8
#include "stdlib.h"
9
10
#define CP2317  0x40 //Habe A0 bis A2 auf GND gelegt 0x40
11
12
int main(void)
13
{
14
  cli();    
15
  i2c_init();                 // initialize I2C library
16
  
17
  //Setzte GPB als Ausgänge      ret = i2c_start(adr1_w);  
18
  i2c_start(CP2317);     //set device address +write mode
19
  i2c_write(0x00);                      //spreche IODIR von GPB an  0x01
20
  i2c_write(0x00);                      //setzte GPB auf Ausgänge  0x00
21
  i2c_stop();
22
23
  while(1)
24
  {
25
    i2c_start(CP2317);
26
    i2c_write(0x1a);                        // write adresse = OLATB  15
27
    i2c_write(0xFF);                        // schalte alle Ausgänge ein
28
    i2c_stop();
29
    _delay_ms(500);
30
    i2c_start(CP2317);
31
    i2c_write(0x1a);                        // write address = OLATB  15
32
    i2c_write(0x00);                        // schalte alle Ausgänge aus
33
    i2c_stop();
34
  }
35
}
damit sollte eigentlich der Port A blinken.
Hardware:
Port A alles über LED und Vorwiderstand nach GND
Port B alles mit Taster nach GND und Wideständen nach 5V
Leider geht es nicht. Wahrscheinlich liegt der Fehler in den Registern.

Henry

von Henry (Gast)


Lesenswert?

Einen Fehler habe ich gerade gefunden.
Habe hier was geändert.
1
i2c_start(CP2317);
2
    i2c_write(0x0A);   <<<                   // write adresse = OLATB  15
3
    i2c_write(0xFF);                        // schalte alle Ausgänge ein
4
    i2c_stop();
5
    _delay_ms(500);
6
    i2c_start(CP2317);
7
    i2c_write(0x0A);  <<<                      // write address = OLATB  15
8
    i2c_write(0x00);                        // schalte alle Ausgänge aus
9
    i2c_stop();
damit leuchten alle 8 LEDs am Port A.
Und wie bekomme ich sie wieder aus?

Henry

von Karl M. (Gast)


Lesenswert?

Hallo,

da es eine Schleife ist, werden sofort wieder alle Pins auf 1 gesetzt.
Eine _delay_ms(500); am 2ten Ende fehlt noch.

von Philipp K. (philipp_k59)


Lesenswert?

mach mal unter dem zweiten stop-Kommando auch noch nen Delay :)

von Karl M. (Gast)


Lesenswert?

Hallo,

ich würde immer noch Fehler abfangen: i2c_start(CP2317) {} else { } und 
auch noch Code Modular über Funktionen erzeugen.
So wäre das eine Möglichkeit
1
void MCP23017_set_port( uint8_t value )
2
{
3
  if (i2c_start(CP2317)) {
4
    i2c_write(0x0A);
5
    i2c_write(value);
6
    i2c_stop();
7
  } else { // i2c error
8
  }
9
}

von Philipp K. (philipp_k59)


Angehängte Dateien:

Lesenswert?

Ich mach mir zum Beispiel auch Listen, wie im Anhang zu sehen für einen 
Parallelport..

Ist einfach besser wenn man es schwarz auf Weiß vor sich hat..

Dazu wenigstens die Registertabelle, und Hextabelle aus dem Datasheet 
cutten und ausdrucken.

Dann ist das in 5 Minuten erledigt.

von Henry (Gast)


Lesenswert?

Das mit dem zweiten _delay war der Fehler.
Die leichtesten Sachen sieht man nicht.
Danke für eure Hilfe.

Henry

von Henry (Gast)


Lesenswert?

Noch ein paar Fragen zu meinem Verständnis.
Ein paar Sachen aus meinem Code:
1
i2c_start(CP2317);
2
    i2c_write(0x0A);                        // write adresse = OLATB  15
3
    i2c_write(0x55);                        // schalte alle Ausgänge ein
4
    i2c_stop();
mit i2c_write(0x0A) gebe ich die Registeradresse, Port A oder Port B an.
Für Port B müsste es dann 0x1A sein.
Das ist dann bei Bank 1 so. Wozu wird dann Bank 0 verwendet?
1
i2c_start(CP2317);     //set device address +write mode
2
  i2c_write(0x00);                      //spreche IODIR von GPB an  0x01
3
  i2c_write(0x00);                      //setzte GPB auf Ausgänge  0x00
4
  i2c_stop();
Was mache ich mit diesem Teil des codes?

von Philipp K. (philipp_k59)


Angehängte Dateien:

Lesenswert?

Schau mal imAnhang in die zweite Spalte. Das sind die Controlbytes.

Wie in einer Zweispaltigen Tabelle, das erste ist welche Zeile als 
Controlbyte  und das zweite welcher wert der Zeile daneben.

Wenn du nach dem Controlbyte ein i2cTransferRead startest liest man das 
Byte.

Dahinter sind die 8 Bits, such mal nach "Binary to hex converter"

Direction hatte ich ja schon geschrieben.

: Bearbeitet durch User
von Michael U. (amiga)


Lesenswert?

Hallo,

Henry schrieb:
> Das ist dann bei Bank 1 so. Wozu wird dann Bank 0 verwendet?

die Bänke beschreiben die Registerzuordnung zu den Adressen.
Wenn IOCON.BANK = 1 ist sind die die Adressen von PortA und danach die 
von PortB nacheinander sortiert.
Bei IOCON.BANK = 0 sind die funktionsgleichen Adressen der Register 
fortlaufend.

Wenn man Daten mit automatischem Increment setzt kann man so z.B. die 
Initialisierung mit weniger Bytes erledigen oder eben die Daten bei 
Zugriff auf beide Ports schneller übertragen.

Gruß aus Berlin
Michael

von Wolfgang R. (wolfgang_r)


Lesenswert?

Hier auch mal ein paar Konfigurationshinweise zum MCP32017 wie ich sie 
vor ein paar Wochen geschrieben habe:
Beitrag "Re: Eingänge/Ausgänge 24V"

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.