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
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.
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
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
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
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.
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
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
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
Hallo, da es eine Schleife ist, werden sofort wieder alle Pins auf 1 gesetzt. Eine _delay_ms(500); am 2ten Ende fehlt noch.
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 | }
|
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.
Das mit dem zweiten _delay war der Fehler. Die leichtesten Sachen sieht man nicht. Danke für eure Hilfe. Henry
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?
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.