Also... Nachdem ich aktuell etwas Schwierigkeiten mit besagtem Thema hatte
möchte ich für die "Mit-Dummies" und Anfänger in der Richtung Hilfestellung geben.
Dazu habe ich begonnen simple (absichtlich primitive) kurze programme zu erstellen
mit denen man den MCP kennenlernen kann.
Mir ist klar, das man das meiste evtl. mit der hälfte Code hätte lösen können...
aber es soll eben für "Neueinsteiger" lesbar und eingängig sein!
Bitte schaut euch dazu diese Codes durch und gebt fleissig Kritik.
Testprogramm "Simpler_Ausgangstest":MCP23017_Simpler_Ausgangstest.bas
Code:
'**********************************************************************
'** Programmbeschreibung **
'**********************************************************************
'** Funktionstest MCP23017 !!!
'** Alle GPA und GPB werden auf Ausgang eingestellt und getoggelt.
'** So Kann man ganz einfach (z.B. mit LED + passendem Vorwiderstand)
'** an den Pins testen, ob der MCP23017 reagiert.
'** Der MCP erhöht in der Standardeinstellung bei jedem folgenden
'** Schreib/Lesezugriff AUTOMATISCH die Registeradresse!
'**
'** Anschlüsse in diesem Test verwendet:
'** >SDA und SCL direkt mit dem Kontroller verbinden und
'** jeweils einen Widerstand als Pullup gegen + verbinden (Ca 4 bis 5 kOhm).
'** >+ und - direkt anschliessen.
'** >Resetpin mit + verbinden.
'** >A0/A1/A2 (Adresspins) mit - verbinden.
'**********************************************************************
$regfile = "M328pdef.dat"
$crystal = 16000000
$baud = 38400
'**********************************************************************
'** Pins
'**********************************************************************
Config Sda = Portc.4 ' I2C Data.
Config Scl = Portc.5 ' I2C Clock.
Config I2cdelay = 10 ' Geschwindigkeit des I2C-Bus
'**********************************************************************
'** Subroutinen
'**********************************************************************
' Subroutine fürs senden der Daten an den MCP23017.
Declare Sub I2c_mcp23016_write(byval Reg As Byte , Byval Abyte As Byte , Byval Bbyte As Byte)
'**********************************************************************
'** Variablen/Konstanten
'**********************************************************************
' Die Adresse des MCP23017 in Hexform (mit A0/A1/A2 jeweils 0 bzw auf Gnd gelegt)
Const Mcp23016_adress_w = &H40 ' Write Adresse des MCP23017: 0 1 0 0 _0 0 0_ 0
Const Mcp23016_adress_r = &H41 ' Read Adresse des MCP23017: 0 1 0 0 _0 0 0_ 1 (hier nicht verwendet)
Dim Reg As Byte ' enthält das Start-Register, in das geschrieben bzw. aus dem gelesen wird
Dim Abyte As Byte ' Diese Variablen werden zum Schreiben verwendet
Dim Bbyte As Byte
'**********************************************************************
'** Haupt-Programm
'**********************************************************************
'Neustart
Waitms 100 ' Kurze Pause bei Neustart
Mcp_initialisieren:
Reg = &H00 ' erstmal beim Register IODIRA mit Schreiben beginnen
Call I2c_mcp23016_write(reg , &H00 , &H00) ' IODIRA und IODIRB alle auf Ausgänge einstellen
Testfunktion:
Do
Reg = &H14 ' jetzt beim Register OLATA mit Schreiben beginnen
Call I2c_mcp23016_write(reg , &HFF , &HFF) ' OLATA und OLATB ... beide auf 1 stellen
Portb.0 = 1 ' Alle Ausgänge einschalten
Waitms 75
Call I2c_mcp23016_write(reg , &H00 , &H00) ' OLATA und OLATB ... beide auf 0 Stellen
Portb.0 = 0 ' Alle Ausgänge ausschalten
Waitms 75
Loop
End
'**********************************************************************
'** Subroutinen
'**********************************************************************
' Daten auf MCP23017 schreiben/senden
Sub I2c_mcp23016_write(byval Reg As Byte , Byval Abyte As Byte , Byval Bbyte As Byte)
I2cstart 'Start senden
I2cwbyte Mcp23016_adress_w 'Adresse fürs Schreiben senden
I2cwbyte Reg 'Registeradresse die als erstes beschrieben werden soll
I2cwbyte Abyte 'Erstes Daten-Byte Senden
I2cwbyte Bbyte 'Zweites Daten-Byte senden (wird automatisch ins nächste Register geschrieben)
I2cstop 'Stop senden
Waitus 50 'Kurze Wartezeit einhalten um den I2C-Bus wieder "frei zu machen"
End Sub
Testprogramm "Register_Auslesen":MCP23017_Register_auslesen.bas
Code:
'**********************************************************************
'** Programmbeschreibung **
'**********************************************************************
'** Funktionstest MCP23017 !!!
'** Alle Register des MCP23017 werden ausgelesen und noch als Beispiel
'** GPIOA und GPIOB einzeln ausgelesen.
'** Der MCP erhöht in der Standardeinstellungbei jedem folgenden
'** Schreib/Lesezugriff AUTOMATISCH die Registeradresse!
'**
'** Anschlüsse in diesem Test verwendet:
'** >SDA und SCL direkt mit dem Kontroller verbinden und
'** jeweils einen Widerstand als Pullup gegen + verbinden (Ca 4 bis 5 kOhm).
'** >+ und - direkt anschliessen.
'** >Resetpin mit + verbinden.
'** >A0/A1/A2 (Adresspins) mit - verbinden.
'**********************************************************************
$regfile = "M328pdef.dat"
$crystal = 16000000
$baud = 38400
'**********************************************************************
'** Pins
'**********************************************************************
Config Sda = Portc.4 ' I2C Data.
Config Scl = Portc.5 ' I2C Clock.
Config I2cdelay = 10 ' Geschwindigkeit des I2C-Bus
'**********************************************************************
'** Subroutinen
'**********************************************************************
' Subroutine fürs senden der Daten an den MCP23017.
Declare Sub I2c_mcp23016_write_two(byval Reg As Byte , Byval Abyte As Byte , Byval Bbyte As Byte)
Declare Sub I2c_mcp23016_read_all
Declare Sub I2c_mcp23016_read_one(byval Reg As Byte)
'**********************************************************************
'** Variablen/Konstanten
'**********************************************************************
' Die Adresse des MCP23017 in Hexform (mit A0/A1/A2 jeweils 0 bzw auf Gnd gelegt)
Const Mcp23016_adress_w = &H40 ' Write Adresse des MCP23017: 0 1 0 0 _0 0 0_ 0
Const Mcp23016_adress_r = &H41 ' Read Adresse des MCP23017: 0 1 0 0 _0 0 0_ 1
Dim Reg As Byte ' enthält das Start-Register, in das geschrieben bzw. aus dem gelesen wird
Dim Abyte As Byte ' Diese Variablen werden zum Schreiben verwendet
Dim Bbyte As Byte
'Variablen jeweils für die einzelnen Registerinhalte
Dim Aa As Byte
Dim Ab As Byte
Dim Ba As Byte
Dim Bb As Byte
Dim Ca As Byte
Dim Cb As Byte
Dim Da As Byte
Dim Db As Byte
Dim Ea As Byte
Dim Eb As Byte
Dim Fa As Byte
Dim Fb As Byte
Dim Ga As Byte
Dim Gb As Byte
Dim Ha As Byte
Dim Hb As Byte
Dim Ia As Byte
Dim Ib As Byte
Dim Ja As Byte
Dim Jb As Byte
Dim Ka As Byte
Dim Kb As Byte
Dim Xx As Byte
'Die Menge an Variablen ist zwar unangebracht und kann leicht "eleganter" gelöst werden...
'soll hier aber den Code "einfacher" gestalten um die Vorgänge besser zu zeigen
'**********************************************************************
'** Haupt-Programm
'**********************************************************************
'Neustart
Waitms 100 ' Kurze Pause bei Neustart
Do
Alle_register_auslesen:
Reg = &H00 ' Register, bei dem mit dem Auslesen angefangen werden soll
Print ">Alle Register Auslesen..."
Call I2c_mcp23016_read_all ' Auslesen beginnen
Print ">IODIRA : " ; Bin(aa)
Print ">IODIRB : " ; Bin(ab)
Print ">IOPOLA : " ; Bin(ba)
Print ">IOPOLB : " ; Bin(bb)
Print ">GPINTENA: " ; Bin(ca)
Print ">GPINTENB: " ; Bin(cb)
Print ">DEFVALA : " ; Bin(da)
Print ">DEFVALB : " ; Bin(db)
Print ">INTCONA : " ; Bin(ea)
Print ">INTCONB : " ; Bin(eb)
Print ">IOCON : " ; Bin(fa)
Print ">IOCON : " ; Bin(fb)
Print ">GPPUA : " ; Bin(ga)
Print ">GPPUB : " ; Bin(gb)
Print ">INTFA : " ; Bin(ha)
Print ">INTFB : " ; Bin(hb)
Print ">INTCAPA : " ; Bin(ia)
Print ">INTCAPB : " ; Bin(ib)
Print ">GPIOA : " ; Bin(ja)
Print ">GPIOB : " ; Bin(jb)
Print ">OLATA : " ; Bin(ka)
Print ">OLATB : " ; Bin(kb)
Print ">"
Waitms 100
Einzelnes_register_auslesen: ' hier als Beispiel GPIOA und GPIOB
Reg = &H12 ' Register das ausgelesen werden soll
Call I2c_mcp23016_read_one(reg) ' Auslesen beginnen
Print ">Gelesenes Register " ; Hex(reg) ; " (Hex) enthaelt die Werte: " ; Bin(xx)
Print ">"
Waitms 100
Reg = &H13 ' Wie zuvor nur diesmal das Register Hex13 auslesen
Call I2c_mcp23016_read_one(reg)
Print ">Gelesenes Register " ; Hex(reg) ; " (Hex) enthaelt die Werte: " ; Bin(xx)
Print ">"
Waitms 100
Wait 3 ' 3 Sekunden warten bevor von vorne begonnen wird
Loop
End
'**********************************************************************
'** Subroutinen
'**********************************************************************
' Daten auf MCP23017 schreiben/senden (hier nicht verwendet)
Sub I2c_mcp23016_write_two(byval Reg As Byte , Byval Abyte As Byte , Byval Bbyte As Byte)
I2cstart 'Start senden
I2cwbyte Mcp23016_adress_w 'Adresse fürs Schreiben senden
I2cwbyte Reg 'Registeradresse die als erstes beschrieben werden soll
I2cwbyte Abyte 'Erstes Daten-Byte Senden
I2cwbyte Bbyte 'Zweites Daten-Byte senden (wird automatisch ins nächste Register geschrieben)
I2cstop 'Stop senden
Waitus 50 'Kurze Wartezeit einhalten um den I2C-Bus wieder "frei zu machen"
End Sub
' Daten vom MCP23017 abrufen (hier z.b. ALLE Register nacheinander)
Sub I2c_mcp23016_read_all
I2cstart 'Start senden
I2cwbyte Mcp23016_adress_w 'Adresse fürs Schreiben senden
I2cwbyte Reg 'Registeradresse die als erstes gelesen werden soll
I2cstop 'Stop senden
I2crepstart 'RepeatedStart senden
I2cwbyte Mcp23016_adress_r 'Adresse fürs Lesen senden. Der MCP folgt dieser Aufforderung mit der Ausgabe des Registerinhalts
I2crbyte Aa , Ack 'Registerinhalt in Variable übernehmen und mit "Ack" zum weiteren senden auffordern
I2crbyte Ab , Ack 'usw.
I2crbyte Ba , Ack 'usw.
I2crbyte Bb , Ack
I2crbyte Ca , Ack
I2crbyte Cb , Ack
I2crbyte Da , Ack
I2crbyte Db , Ack
I2crbyte Ea , Ack
I2crbyte Eb , Ack
I2crbyte Fa , Ack
I2crbyte Fb , Ack
I2crbyte Ga , Ack
I2crbyte Gb , Ack
I2crbyte Ha , Ack
I2crbyte Hb , Ack
I2crbyte Ia , Ack
I2crbyte Ib , Ack
I2crbyte Ja , Ack
I2crbyte Jb , Ack
I2crbyte Ka , Ack
I2crbyte Kb , Nack 'Registerinhalt in Variable übernehmen und mit "Nack" beenden
I2cstop 'Stop senden
Waitus 50 'Kurze Wartezeit einhalten um den I2C-Bus wieder "frei zu machen"
End Sub
' Daten vom MCP23017 abrufen (hier z.b. nur EIN Register)
Sub I2c_mcp23016_read_one
I2cstart 'Start senden
I2cwbyte Mcp23016_adress_w 'Adresse fürs Schreiben senden
I2cwbyte Reg 'Registeradresse die als erstes gelesen werden soll
I2cstop 'Stop senden
I2crepstart 'RepeatedStart senden
I2cwbyte Mcp23016_adress_r 'Adresse fürs Lesen senden. Der MCP folgt dieser Aufforderung mit der Ausgabe des Registerinhalts
I2crbyte Xx , Nack 'Registerinhalt in Variable übernehmen und mit "Nack" beenden
I2cstop 'Stop senden
Waitus 50 'Kurze Wartezeit einhalten um den I2C-Bus wieder "frei zu machen"
End Sub
Grüsse, Joe
Lesezeichen