REKLAMA

mcp23016.pdf

Arduino VGA Shield - wersja druga, SMD - z expanderem portów i pamięcią EEPROM

https://obrazki.elektroda.pl/5502422400_1590145798_thumb.jpg Witajcie moi drodzy Chciałbym zaprezentować tutaj drugą wersję mojego Arduino VGA Shield (nakładki na Arduino UNO generującej jednokolorowy obraz VGA i czarno-biały PAL/NTSC) - tym razem wykonaną za pomocą elementów SMD, i z dodatkowymi układami na pokładzie (expander portów MCP23016 oraz dwie kości EEPROM AT24CM02). Opis pierwszej wersji tego shielda znajdziecie tutaj: https://www.elektroda.pl/rtvforum/viewtopic.php?p=18496229#18496229 Co to za Arduino Shield? W dużym skrócie mój shield jest nakładką na Arduino UNO która pozwala bardzo łatwo generować jednokolorowy obraz na monitor VGA oraz obsługiwać klawiaturę PS/2. Opcjonalnie też dostępne jest wyjście sygnału PAL/NTSC dla telewizorów. Shield korzysta z biblioteki 'ASCII Video Terminal' dla PIC32MX250F128B autorstwa geoffg. Arduino UNO komunikuje się z tym shieldem poprzez UART na wybranych przez nas za pomocą lutowanej zworki pinach. Dodatkowo na pokładzie (nowość w tej wersji!) znajduje się: - expander portów MCP23016, dzięki czemu zyskujemy aż 16 dodatkowych IO! - dwie kości EEPROM AT24CM02, dzięki którym zyskujemy aż 512KB pamięci nieulotnej do własnych projektów! Obie nowości znajdują się na magistrali I2C od Arduino. Poniżej szczegółowo opiszę cały projekt, umieszczę proste przykłady użycia nowości na płytce a na koniec dam bardziej zaawansowane demka korzystające z poszczególnych funkcjonalności shielda. Projekt Arduino VGA Shield SMD Niniejszy projekt jest zasadniczo aktualizacją jego poprzedniej wersji która była wykonana w THT (montaż przewlekany): https://obrazki.elektroda.pl/2294289300_1588796118_thumb.jpg W obecnej wersji większość elementów jest w obudowach SMD, dodatkowo dzięki zaoszczędzonemu miejscu udało mi się na płytkę dodać: - złącze USB od PIC32 (do aktualizacji softu poprzez bootloader; może to dać też w przyszłości możliwość łatwego użycia tego shielda bez Arduino, ale na razie brakuje na PCB w tym celu regulatora 3.3V) - dwie kości pamięci EEPROM AT24CM02 na magistralę I2C od Arduino (standardowo piny 4 i 5) - 16-bitowy expander portów MCP23016 na magistralę I2C od Arduino (jak wyżej; piny 4 i 5) - rezystory pull-up na piny 4 i 5 (jak wyżej; magistrala I2C Arduino) W ten sposób obecna wersja wyszła tak: https://obrazki.elektroda.pl/8546300900_1588796382_thumb.jpg Całość open hardware i do pobrania poniżej. Schemat płytki w PDF: 1030456 Schemat płytki w PNG: 1030457 Pełny projekt płytki w Eagle (.sch + .brd): 1030455 Pliki Gerber które wyeksportowałem z Eagle (te same, których użyłem przy zleceniu wykonania gołego PCB płytkarni): 1030453 Tym razem obyło się bez żadnych błędów na płytce. Płytki standardowo zamówiłem w Chinach (10 sztuk - ktoś chętny na kilka?) a jak przybyły to wziąłem się do lutowania. Lutowanie Arduino VGA Shield w wersji SMD Opiszę tutaj szczegółowo jak zlutowałem tę płytkę w warunkach domowych. Na początek przygotowałem wszystkie elementy: https://obrazki.elektroda.pl/8220448100_1588804224_thumb.jpg https://obrazki.elektroda.pl/6139364300_1588804228_thumb.jpg I tym razem nawet nie używałem złącza VGA (DSUB25) z starej płyty głównej od komputera, tylko miałem zakupione przez internet. Do lutowania użyłem mojej wiernej najtańszej lutownicy kolbowej i na tę okazję zmieniłem jej grot na grot ścięty (choć pewnie lepszy byłby grot ścięty typu minifala, ten z wyżłobionym 'zbiorniczkiem' na cynę): https://obrazki.elektroda.pl/4748971600_1588804324_thumb.jpg Zacząłem lutowanie od najmniejszych elementów: https://obrazki.elektroda.pl/3753769700_1588804437_thumb.jpg Dałem też wtedy cynową zworkę na sygnał "B" (Blue) koło złącza VGA, czyli wybrałem niebieski kolor czcionki. Szybko przyszła pora na złącza: https://obrazki.elektroda.pl/8356330500_1588804501_thumb.jpg https://obrazki.elektroda.pl/6638436500_1588804722_thumb.jpg Złącze DSUB25 czyli VGA oraz MDC6 (aka 'mini din') czyli PS/2: https://obrazki.elektroda.pl/6815685300_1588804785_thumb.jpg Na zdjęciu można zobaczyć, że wciąż nie przylutowałem EEPROMów - to dlatego, że dopiero czekałem na paczkę z nimi. Jak przyszły to uzupełniłem ubytek: https://obrazki.elektroda.pl/3204394600_1588804882_thumb.jpg https://obrazki.elektroda.pl/1382751400_1588804914_thumb.jpg Potem jeszcze uzupełniłem ubytek złącza RCA (od sygnału PALNTSC); nie miałem takiego na składzie więc wylutowałem z jakiegoś fragmentu urządzenia elektronicznego, to chyba był odtwarzacz kaset VHS: https://obrazki.elektroda.pl/7021071000_1588805047_thumb.jpg https://obrazki.elektroda.pl/9088830900_1588805043_thumb.jpg https://obrazki.elektroda.pl/5706716800_1588805051_thumb.jpg Złącze RCA: https://obrazki.elektroda.pl/4076050200_1588805209_thumb.jpg I oto końcowy efekt (już po wyczyszczeniu z nadmiaru topnika): https://obrazki.elektroda.pl/1416338600_1588846009_thumb.jpg https://obrazki.elektroda.pl/6408921300_1588846191_thumb.jpg Warto jeszcze pamiętać, że przed użyciem należy zrobić ze spoiwa lutowniczego następujące zworki: - zworka pinu RX shielda z Arduino - zworka pinu TX shielda z Arduino - zworka pinu RESET z Shielda (łączy RESET od PIC32 z RESET od Arduino) - zworka wyboru koloru VGA z Shielda - dwie zworki na magistrali I2C dla EEPROMów Przed użyciem shielda trzeba oczywiście też wgrać mu firmware na PIC32MX250F128B za pomocą PICKIT3 (lub innego programatora) poprzez złącze ICSP dostępne na płytce. Test generowanego sygnału VGA z różnymi monitorami i telewizorem W temacie dotyczącym poprzedniej wersji mojego shielda (tutaj: https://www.elektroda.pl/rtvforum/viewtopic.php?p=18496229#18496229 ) pojawiła się uwaga, że nie działa on z częścią monitorów. Postanowiłem to zweryfikować. Użyłem do tego: - telewizora LG42LE4500 - monitora DELL 1703FP - monitora ASUS VH196S - monitora HP L1706 - monitora SyncMaster 740N Zapraszam do obejrzenia zdjęć z testów. Test 1 - monitor DELL 1703FP: https://obrazki.elektroda.pl/9890789800_1588852185_thumb.jpg https://obrazki.elektroda.pl/5803001300_1588852224_thumb.jpg Tabliczka znamionowa użytego monitora: https://obrazki.elektroda.pl/2073302500_1588783980_thumb.jpg Test 2 - telewizor LG42LE4500: https://obrazki.elektroda.pl/5747425500_1588852640_thumb.jpg https://obrazki.elektroda.pl/7081934500_1588852638_thumb.jpg Tabliczka znamionowa użytego telewizora: https://obrazki.elektroda.pl/7031910900_1588783997_thumb.jpg Test 3 - monitor ASUS VH196S: https://obrazki.elektroda.pl/2275459400_1588854942_thumb.jpg https://obrazki.elektroda.pl/3360872300_1588854987_thumb.jpg Tabliczka znamionowa użytego monitora: https://obrazki.elektroda.pl/5879373100_1588854839_thumb.jpg Test 4 - HP L1706. https://obrazki.elektroda.pl/7060437300_1588855274_thumb.jpg https://obrazki.elektroda.pl/2953685300_1588855274_thumb.jpg Tabliczka znamionowa użytego monitora: https://obrazki.elektroda.pl/6106436200_1588855202_thumb.jpg Test 5 - SyncMaster 740N. Ten monitor naprawiałem tutaj: https://www.elektroda.pl/rtvforum/topic3688191.html , wymieniłem w nim kondensatory elektrolityczne. Dzięki temu może dalej działać i brać udział w testach mojego shielda: https://obrazki.elektroda.pl/4246636900_1588855412_thumb.jpg https://obrazki.elektroda.pl/2066575900_1588855446_thumb.jpg Tabliczka znamionowa użytego monitora: https://obrazki.elektroda.pl/1258439900_1588855496_thumb.jpg Podsumowując, shield VGA przetestowałem z czterema monitorami i jednym telewizorem i w każdym przypadku obraz był poprawnie wyświetlany. Sygnał widziany jest przez wszystkie urządzenia jako 640x480, mimo iż w dokumentacje użytej biblioteki jest podana nieco inna rozdzielczość. Po prostu shield w sprytny sposób sobie z tym radzi zostawiając puste marginesy wokół obrazu (co zresztą widać na większości zdjęć z jego działania). Nie znalazłem ani jednego urządzenia przez którego sygnał VGA z mojego shielda nie był wspierany, a jego timingi (31.5kHz i 60Hz) są zgodne z tym, co jest w kodzie: https://obrazki.elektroda.pl/8567581200_1590314726_thumb.jpg Test generowanego sygnału PAL Generowanie czarno-białego obrazu PAL (oraz NTSC - też jest wspierany) może się przydać gdy chcemy obsłużyć jakiś starszy telewizor, pewnie jeszcze CRT, który nie posiada złącza VGA. Może to być podyktowane chociażby sentymentem - niektórzy lubią korzystać ze starszego sprzętu nawet dla samej satysfakcji korzystania z niego. Z tego powodu przetestowałem też jak shield radzi sobie z generowaniem sygnału PAL. Sygnał PAL ze shielda podłącza się za pomocą przewodu RCA: https://obrazki.elektroda.pl/9451123200_1590143186_thumb.jpg Wystarczy pojedynczy sygnał video, audio nie jest oferowane przez ten shield. Test PAL 1 - telewizor LG42LE4500: Podłączenie: https://obrazki.elektroda.pl/2258585600_1590146184_thumb.jpg https://obrazki.elektroda.pl/9368920000_1590146199_thumb.jpg https://obrazki.elektroda.pl/3942760900_1590146205_thumb.jpg Obraz na ekranie: https://obrazki.elektroda.pl/9427440500_1590146322_thumb.jpg Obraz generowany przez shield jest tutaj rzecz jasna czarno-biały; zworka od koloru (wybór R/G/B) jest tylko dla VGA. Test PAL 2 - stary telewizor CRT TX-21AT1P: Ten pierwszy test PAL z nowym, płaskim telewizorem LG42LE4500 poniekąd mija się z celem, bo użyty tam telewizor ma złącze VGA (i to nie jedno!) więc nic nie stoi na przeszkodzie, by go podłączyć normalnie. Z tego powodu też przetestowałem tryb PAL z telewizorem który jest o wiele bardziej z tym trybem związanym - ze starym, ciężkim telewizorem kineskopowym, dokładniej 'Panasonic Colour TV' model TX-21AT1P: https://obrazki.elektroda.pl/8911258000_1590161461_thumb.jpg Tabliczka znamionowa tego telewizora: https://obrazki.elektroda.pl/8935412200_1590161531_thumb.jpg https://obrazki.elektroda.pl/7483420000_1590161541_thumb.jpg Sygnał PAL podłączyłem z przodu telewizora do złącz RCA: https://obrazki.elektroda.pl/9148315700_1590161702_thumb.jpg Warto tu wspomnieć, że nawet jeśli telewizor nie ma złącz RCA to sygnał PAL można też podać poprzez SCART - w przewodzie SCART jest jeden pin odpowiedzialny za wejście 'composite video'. Sygnał PAL oczywiście tutaj nie jest modulowany i odbieramy go w trybie AV: https://obrazki.elektroda.pl/6474478000_1590161796_thumb.jpg (Aczkolwiek jakby się postarać i użyć np. modulatora ze starego odtwarzacza VHS to można by prosto odbierać sygnał ze shielda poprzez złącze antenowe; choć wtedy jest ryzyko, że będziemy 'siać' sygnał po okolicy; do tej pory pamiętam jak kilkanaście lub więcej lat temu odbierałem przez przypadek na telewizorze obraz z konsoli do gier sąsiada). Na telewizorze uruchomiłem demko, które opisane jest nieco niżej w tekście. Rezultat: https://obrazki.elektroda.pl/3756502800_1590162046_thumb.jpg Uwaga - co jeśli monitor pokazuje 'nieobsługiwany format VGA'? Chciałbym tu tylko jeszcze przypomnieć, że shield w celu obsługi zarówno standardu PAL jak i VGA musi w sprytny sposób między nimi przełączać. Nie generuje dwóch sygnałów naraz. Shield przy starcie (po sygnale RESET lub podaniu zasilania) sam określa, czy monitor VGA jest podłączony i jeśli nie, to przechodzi w tryb PAL. Określa to poprzez badanie stanu na pinie RA4. Więc jeśli podłączymy monitor VGA w trakcie do shielda to powinniśmy wcisnąć przycisk RESET na Arduino lub wyłączyć i włączyć zasilanie - w przeciwnym razie shield będzie już 'nastawiony na PAL' i monitor VGA nic nie wyświetli. RESET z Arduino jest połączony z RESET (aka MCLR) z PIC32 z płytki shielda, ale należy pamiętać by na płytce shielda dać tam zworkę by oba układy resetowały się razem. (O tym, że mam wspomnieć o tym problemie przypomniał mi Bartek, który odkupił ode mnie jedno PCB poprzedniej wersji shielda - za przetestowanie układu i zwrócenie uwagi tu dziękuję) Test magistrali I2C - skan dostępnych urządzeń Na samym początku na mojej płytce uruchomiłem prosty program całkowicie niezwiązany z VGA - skaner I2C. Program ten pochodzi z oficjalnej strony Arduino: https://playground.arduino.cc/Main/I2cScanner/ i po prostu wykrywa wszystkie urządzenia podłączone na magistralę I2C, czyli w przypadku użytego przeze mnie Arduino UNO na jego piny 4 i 5. Program drukuje adresy I2C znalezionych urządzeń na port szeregowy/terminal Arduino. #include <Wire.h> //include Wire.h library void setup() { Wire.begin(); // Wire communication begin Serial.begin(9600); // The baudrate of Serial monitor is set in 9600 while (!Serial); // Waiting for Serial Monitor Serial.println("\nI2C Scanner"); } void loop() { byte error, address; //variable for error and I2C address int nDevices; Serial.println("Scanning..."); nDevices = 0; for (address = 1; address < 127; address++ ) { // The i2c_scanner uses the return value of // the Write.endTransmisstion to see if // a device did acknowledge to the address. Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address < 16) Serial.print("0"); Serial.print(address, HEX); Serial.println(" !"); nDevices++; } else if (error == 4) { Serial.print("Unknown error at address 0x"); if (address < 16) Serial.print("0"); Serial.println(address, HEX); } } if (nDevices == 0) Serial.println("No I2C devices found\n"); else Serial.println("done\n"); delay(5000); // wait 5 seconds for the next I2C scan } Program skompilowałem i wgrałem na Arduino z założonym moim shieldem. Rezultat sketchu: https://obrazki.elektroda.pl/8259841700_1588789861_thumb.jpg Widzimy, że skan I2C znalazł aż 9 urządzeń! Ale czy na pewno? Na powyższym zrzucie ekranu: - adres 0x20 to port expander MCP23016 - adresy 0x50, 0x51, 0x52, 0x53 to pierwszy AT24CM02 (przypominam: w adresie urządzenia AT24CM02 dwa bity odpowiadają za jego 'wewnętrzny adres' pamięci; dwa bity dają nam 4 możliwe adresy) - adresy 0x54, 0x55, 0x56, 0x57 to drugi AT24CM02 Czyli wszystko jest okej - dwie pamięci EEPROM i jeden expander portów. Poniżej zaprezentuję już jak można ich użyć. Lutowanie przejściówki do expandera portów (dla płytki stykowej) Na płytce znajduje się 16-pinowe złącze 2.54mm (2 rzędy po 8 pinów) od MCP23016: https://obrazki.elektroda.pl/3189098400_1588846402_thumb.jpg Oferuje ono dodatkowe 16 pinów IO którymi możemy sterować przez I2C. Polecam używać go w połączeniu z takim przewodem (najlepiej też zakupić odpowiednie gniazdo pod ten przewód by nie dało się go wsadzić odwrotnie, ale ja takiego pod ręką nie miałem): https://obrazki.elektroda.pl/1013751400_1588799286_thumb.jpg https://obrazki.elektroda.pl/6126385500_1588799285_thumb.jpg Do tego sugeruję zlutować sobie przejściówkę z tego przewodu do płytki stykowej/prototypowej. Płytka stykowa ma rozstaw pól 2.54mm pasujący do goldpinów, za wyjątkiem środkowego przedziałka płytki który ma akurat 5.08mm, czyli tyle ile wąski rozstaw pinów z obudowy DIP. Aż prosi się to wykorzystać. Opiszę tutaj jak - na początek trzeba przygotować goldpiny 1x8 (dwie sztuki) i 2x8 (jedna sztuka) oraz płytkę wierconą: https://obrazki.elektroda.pl/8689529400_1588799587_thumb.jpg https://obrazki.elektroda.pl/3694746900_1588799587_thumb.jpg Następnie warto dodać topnik na płytkę, by się lepiej lutowało: https://obrazki.elektroda.pl/4560970200_1588799647_thumb.jpg Dalej umieścić na naszej płytce pierwszy rząd goldpinów (on będzie wchodzić w płytkę stykową), ale odwrotnie niż zazwyczaj: https://obrazki.elektroda.pl/3611174500_1588799703_thumb.jpg Teraz trzeba ją przylutować - najwygodniej bardzo cienką końcówką. Przy lutowaniu pilnować, by goldpiny były prostopadle do płytki: https://obrazki.elektroda.pl/8970239000_1588799870_thumb.jpg Pierwszy lut gotowy: https://obrazki.elektroda.pl/5596099700_1588799906_thumb.jpg Następnie trzeba dokończyć wszystkie luty i można od drugiej strony płytki dać złącze 2x8 2.54mm goldpin i zacząć łączyć odpowiednie piny: https://obrazki.elektroda.pl/1829572700_1588799984_thumb.jpg Dalej polecam delikatnie przylutować drugi pojedynczy rząd goldpinów który wejdzie w płytkę stykową: https://obrazki.elektroda.pl/6292228500_1588800085_thumb.jpg https://obrazki.elektroda.pl/3709848100_1588800087_thumb.jpg Następnie wystarczy zmostkować odpowiednie piny za pomocą lutownicy. Jeszcze tylko trzeba odciąć zbędny fragment PCB: https://obrazki.elektroda.pl/8851617300_1588800172_thumb.jpg Przejściówka gotowa: https://obrazki.elektroda.pl/5095248300_1588800212_thumb.jpg Idealnie pasuje do wybranego przeze mnie przewodu (choć ponownie tu Wam polecam użyć nie zwykłych goldpinów 2x8, lecz złącza pod ten konkretny kabelek; wtedy unikniecie ryzyka podłączenia go odwrotnie): https://obrazki.elektroda.pl/1732464200_1588800500_thumb.jpg Przejściówka expandera portów gotowa. Tak wygląda razem z Shieldem i Arduino: https://obrazki.elektroda.pl/3922228300_1588800544_thumb.jpg Następne cztery akapity przedstawią testy MCP23016 w oparciu o te połączenie. Test expandera portu - MCP23016 - użyta biblioteka Na początku do obsługi expandera portów MCP23016 sterowanego poprzez I2C próbowałem użyć tej biblioteki od Adafruit (mimo iż jest ona dla MCP23017 - liczyłem na podobieństwo układów): https://obrazki.elektroda.pl/9380545400_1588790023_thumb.jpg Ale nie zadziałała, więc ostatecznie użyłem biblioteki CyMCP23016 autorstwa Chris Brunner aka cyrusbuilt, stąd: https://github.com/cyrusbuilt/CyMCP23016 Kopia zapasowa repozytorium (na czas pisania tematu): 1030477 Bibliotekę dodałem do Arduino poprzez Sketch->Include Library->Add .ZIP Library. Test expandera portu - MCP23016 - układ testowy Do przygotowania układu testowego MCP23016 użyłem płytki stykowej i wcześniej opisanej przejściówki i kabelka, do tego kilka rezystorów: https://obrazki.elektroda.pl/7024523100_1588802931_thumb.jpg https://obrazki.elektroda.pl/2680579400_1588802952_thumb.jpg Do tego oczywiście trzeba osobno podpiąć masę (i zasilanie, jeśli go potrzebujemy) https://obrazki.elektroda.pl/4391025300_1588803055_thumb.jpg Test expandera portu - MCP23016 - blink LED Pierwszym przykładem użycia MCP23016 jaki przygotowałem jest proste miganie jedną diodą poprzez ten expander portów, poprzez I2C. Wybrałem pin GP0.0, w tej bibliotece oznaczany MCP23016_PIN_GPIO0_0. Kod prawie w całości pochodzi z przykładu biblioteki z Githuba: /** * Basic input/output test for MCP23016 expander. */ #include <Arduino.h> #include "CyMCP23016.h" CyMCP23016 mcp; void setup() { Serial.begin(9600); Serial.println(("start")); // Init MCP23016 at the default address. This assumes we are running on // an ATmel AVR-based arduino, like the Arduino Uno. mcp.begin(); Serial.println(("begin")); // Set Pin 0 on Port 0 as an output. mcp.pinMode(MCP23016_PIN_GPIO0_0, OUTPUT); Serial.println(("pm")); } void loop() { delay(1000); // Set the pin HIGH and read back the state. mcp.digitalWrite(MCP23016_PIN_GPIO0_0, HIGH); uint8_t val = mcp.digitalRead(MCP23016_PIN_GPIO0_0); Serial.print(F("Pin 0.0 is ")); Serial.println(val == HIGH ? "HIGH" : "LOW"); delay(1000); // Set the pin LOW and read back the state. mcp.digitalWrite(MCP23016_PIN_GPIO0_0, LOW); val = mcp.digitalRead(MCP23016_PIN_GPIO0_0); Serial.print(F("Pin 0.0 is ")); Serial.println(val == HIGH ? "HIGH" : "LOW"); } Kod tylko przełącza stan na pierwszym pinie expandera i dodatkowo wysyła jego stan na UART. Rezultat w Serial Monitor: https://obrazki.elektroda.pl/7086169000_1588791010_thumb.jpg Rezultat na filmie: https://filmy.elektroda.pl/92_1588794181.mp4 W taki sam sposób możemy sterować wszystkimi 16 pinami od MCP23016. Test expandera portu - MCP23016 - prosty licznik binarny Drugim, bardziej zaawansowanym przykładem użycia MCP23016 jaki tu zaprezentuję jest prosty licznik binarny zrealizowany na 8 diodach LED (czyli 8-bitowy). Do tego użyłem całego portu GP0: https://obrazki.elektroda.pl/6748085500_1588798418_thumb.jpg Odpowiednio zmodyfikowałem też kod przykładu. Do ustawienia odpowiednich diod LED użyłem pętli for oraz operatorów bitowych, całość sketchu jest do wglądu poniżej: /** * Basic input/output test for MCP23016 expander. */ #include <Arduino.h> #include "CyMCP23016.h" CyMCP23016 mcp; int counter = 0; void setup() { Serial.begin(9600); Serial.println(("start")); mcp.begin(); Serial.println(("begin")); // Set Pin 0 on Port 0 as an output. for(int i = 0; i < 8; i++) { mcp.pinMode(i, OUTPUT); mcp.digitalWrite(i, LOW); } delay(1000); Serial.println(("pm")); } void loop() { delay(250); for(int i = 0; i < 8; i++) { mcp.digitalWrite(i, counter & (1<<(i))); } counter++; } Powyższy kod powinien być zrozumiały nawet dla początkujących z Arduino, jedyną z pozoru trudną rzeczą w nim jest 'wyłuskanie' bitu za pomocą counter & (1<<(i)). Ta linijka po prostu sprawdza, czy i-ty bit zmiennej counter jest zapalony. Rezultat na filmie: https://filmy.elektroda.pl/15_1588793680.mp4 Wszystko działa poprawnie. Można by jeszcze sprawdzić czy wszystko jest okej z drugim portem od MCP23016, ale uznałem, że to już jest zbędne. Test pamięci EEPROM - AT24CM02 - użyta biblioteka Do obsługi pamięci EEPROM a dokładniej dwóch kości AT24CM02 użyłem biblioteki autorstwa Rushikesh Patel aka luffykesh z Githuba, tej: https://github.com/luffykesh/AT24Cx Kopia zapasowa/snapshot repo na czas pisania artykułu: 1030460 Bibliotekę dodałem do Arduino poprzez Sketch->Include Library->Add .ZIP Library. Test pamięci EEPROM - AT24CM02 - test zapisu i odczytu Na początek sprawdziłem czy w ogóle komunikacja z AT24CM02 działa poprawnie. W tym celu użyłem przykładowego kodu z wybranej biblioteki, jedynie tylko zmodyfikowałem go by korzystał z konkretnie AT24CM02 (z pierwszego na PCB, o adresie 0x50): /* * * Read and write demo of the AT24CX library * Written by Christian Paul, 2014-11-24 * * */ // include libraries #include <Wire.h> #include <AT24CX.h> // EEPROM object AT24CM02 mem; // setup void setup() { // serial init Serial.begin(9600); Serial.println("AT24CX read/write demo"); Serial.println("----------------------"); } // main loop void loop() { // read and write byte Serial.println("Write 42 to address 12"); mem.write(12, 42); Serial.println("Read byte from address 12 ..."); byte b = mem.read(12); Serial.print("... read: "); Serial.println(b, DEC); Serial.println(); // read and write integer Serial.println("Write 65000 to address 15"); mem.writeInt(15, 65000); Serial.println("Read integer from address 15 ..."); unsigned int i = mem.readInt(15); Serial.print("... read: "); Serial.println(i, DEC); Serial.println(); // read and write long Serial.println("Write 3293732729 to address 20"); mem.writeLong(20, 3293732729UL); Serial.println("Read long from address 20 ..."); unsigned long l = mem.readLong(20); Serial.print("... read: "); Serial.println(l, DEC); Serial.println(); // read and write long Serial.println("Write 1111111111 to address 31"); mem.writeLong(31, 1111111111); Serial.println("Read long from address 31 ..."); unsigned long l2 = mem.readLong(31); Serial.print("... read: "); Serial.println(l2, DEC); Serial.println(); // read and write float Serial.println("Write 3.14 to address 40"); mem.writeFloat(40, 3.14); Serial.println("Read float from address 40 ..."); float f = mem.readFloat(40); Serial.print("... read: "); Serial.println(f, DEC); Serial.println(); // read and write double Serial.println("Write 3.14159265359 to address 50"); mem.writeDouble(50, 3.14159265359); Serial.println("Read double from address 50 ..."); double d = mem.readDouble(50); Serial.print("... read: "); Serial.println(d, DEC); Serial.println(); // read and write char Serial.print("Write chars: '"); char msg = "This is a message"; Serial.print(msg); Serial.println("' to address 200"); mem.writeChars(200, msg, sizeof(msg)); Serial.println("Read chars from address 200 ..."); char msg2; mem.readChars(200, msg2, sizeof(msg2)); Serial.print("... read: '"); Serial.print(msg2); Serial.println("'"); Serial.println(); // write array of bytes Serial.println("Write array of 80 bytes at address 1000"); byte xy = {0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9, // 10 x 3 = 30 10,11,12,13,14,15,16,17,18,19, // 10 120,121,122,123,124,125,126,127,128,129, // 10 130,131,132,133,134,135,136,137,138,139, // 10 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219}; // 20 mem.write(1000, (byte*)xy, sizeof(xy)); // read bytes with multiple steps Serial.println("Read 80 single bytes starting at address 1000"); for (int i=0; i<sizeof(xy); i++) { byte sb = mem.read(1000+i); Serial.print(" = "); Serial.println(sb); } Serial.println(); // read bytes with one step Serial.println("Read 80 bytes with one operation at address 1000"); byte z; memset(&z, 32, sizeof(z)); mem.read(1000, z, sizeof(z)); for (int i=0; i<sizeof(z); i++) { Serial.print(" = "); Serial.println(z); } // stop while (1==1) {delay(1000);} } https://obrazki.elektroda.pl/7951808100_1588847183_thumb.jpg Następnie zmodyfikowałem ten kod tak, by przetestować użycie dwóch EEPROM jednocześnie. W celu weryfikacji czy na pewno kod korzysta z dwóch różnych kości postanowiłem zapisać na ten sam adres różne wartości (dla pierwszej kości: 42, dla drugiej: 15) i potem je odczytać i sprawdzić czy są zachowywane. /* * * Read and write demo of the AT24CX library * Written by Christian Paul, 2014-11-24 * * */ // include libraries #include <Wire.h> #include <AT24CX.h> // EEPROM object AT24CM02 mem0(0); AT24CM02 mem1(1); // setup void setup() { // serial init Serial.begin(9600); Serial.println("AT24CX read/write demo"); Serial.println("----------------------"); } // main loop void loop() { // read and write byte Serial.println(" Write 42 to address 12"); mem0.write(12, 42); Serial.println(" Write 15 to address 12"); mem1.write(12, 15); Serial.println(" Read byte from address 12 ..."); byte b0 = mem0.read(12); Serial.print(" ... read: "); Serial.println(b0, DEC); Serial.println(" Read byte from address 12 ..."); byte b1 = mem1.read(12); Serial.print(" ... read: "); Serial.println(b1, DEC); // stop while (1==1) {delay(1000);} } Rezultat sketchu: https://obrazki.elektroda.pl/9200007400_1588847521_thumb.jpg Jak widać obie pamięci EEPROM działają poprawnie. W ten sposób zyskujemy całe dodatkowe 512KB (dwie kości po 256KB) pamięci! Małe demko - drukowanie kodów klawiszy na ekranie Teraz przedstawię proste demko już bezpośrednio związane z głównymi atutami mojej nakładki, czyli generowaniem obrazu VGA i obsługą klawiatury PS/2. Poniższe demko odbiera klawisze wciśnięte na klawiaturze i wyświetla ich kody na ekranie - za wyjątkiem strzałek, które są kodowane jako kilka kolejnych wartości i trzeba je w specjalny sposób wykrywać. Każda wciśnięcie jednej ze strzałek daje na UART następujące kody: * Up Arrow - 27 91 65 * Down Arrow - 27 91 66 * Right Arrow 27 91 67 * Left Arrow 27 91 68 Strzałki w poniższym demku są wykrywane poprawne i informacje o ich wciśnięciu są wyświetlane jako tekst. UWAGA: Poniższe demko poprawnie obsługuje Caps Lock i wpisywanie znaków z Shift, ale tego nie ma w kodzie na Arduino, gdyż dzieje się to w samym shieldzie i na klawiaturze. Pełny kod demka: /* * Up Arrow - 27 91 65 * Down Arrow - 27 91 66 * Right Arrow 27 91 67 * Left Arrow 27 91 68 * */ #if 0 #define USE_ARDUINO_RXTX #endif #ifdef USE_ARDUINO_RXTX #define vgaSerial Serial #else #include <SoftwareSerial.h> SoftwareSerial mySerial(2, 3); // RX, TX #define vgaSerial mySerial #endif void SCR_Reset() { vgaSerial.print((char)27); vgaSerial.print("c"); } void SCR_PrintLn(const char *s) { vgaSerial.println(s); } void SCR_Print(const char *s) { vgaSerial.print(s); } void SCR_ClearScreen() { vgaSerial.print((char)27); vgaSerial.print("[2J"); } void SCR_SetPos(int x, int y) { vgaSerial.print((char)27); vgaSerial.print("["); vgaSerial.print(x); vgaSerial.print(";"); vgaSerial.print(y); vgaSerial.print("H"); } void setup() { // Open serial communications and wait for port to open: Serial.begin(57600); while (!Serial) { ; // wait for serial port to connect. Needed for Native USB only } Serial.println("started vga"); #ifndef USE_ARDUINO_RXTX //mySerial.begin(1200); // mySerial.begin(57600); // mySerial.begin(38400); mySerial.begin(19200); //mySerial.begin(115200); mySerial.listen(); #endif delay(10); SCR_Reset(); SCR_ClearScreen(); // put your setup code here, to run once: SCR_PrintLn("Arduino VGA Shield Key Code Tester"); //SCR_SetPos(5,5); //SCR_Print("A"); } char buffer ; //whatever void OnPress_ArrowDown() { sprintf (buffer, "Pressed DOWN ARROW"); SCR_PrintLn(buffer); } void OnPress_ArrowRight() { sprintf (buffer, "Pressed RIGHT ARROW"); SCR_PrintLn(buffer); } void OnPress_ArrowLeft() { sprintf (buffer, "Pressed LEFT ARROW"); SCR_PrintLn(buffer); } void OnPress_ArrowUp() { sprintf (buffer, "Pressed UP ARROW"); SCR_PrintLn(buffer); } void OnPress_Key(char inByte) { sprintf (buffer, "Pressed code %i (visual %c)", (int)inByte, inByte); SCR_PrintLn(buffer); } void loop() { // put your main code here, to run repeatedly: while (vgaSerial.available() > 0) { char inByte = vgaSerial.read(); if(inByte == 27) { while (vgaSerial.available() == 0) { } vgaSerial.read(); while (vgaSerial.available() == 0) { } char inByte2 = vgaSerial.read(); if(inByte2 == 65) { OnPress_ArrowUp(); } if(inByte2 == 66) { OnPress_ArrowDown(); } if(inByte2 == 68) { OnPress_ArrowLeft(); } if(inByte2 == 67) { OnPress_ArrowRight(); } } else { OnPress_Key(inByte); } } } Rezultat działania: https://obrazki.elektroda.pl/9093480600_1589293381_thumb.jpg Shift i Caps-Lock są poprawnie obsługiwane, a same klawisze są bezbłędnie odbierane (za wyjątkiem pewnej sytuacji - ale o tym w następnym akapicie). Dlaczego lepiej korzystać z baud 19200 a nie np. z 1200? Tutaj chciałbym zwrócić uwagę na to jak duże znaczenie ma świadomy wybór odpowiedniego baud komunikacji UART ze shieldem. Nie można wybrać zbyt dużego baud, bo ogranicza nas zdolność SoftwareSerial z Arduino. Przy około 38400 mogą się zacząć problemy. To raczej wiadomo, podobne informacje powtarzają się na forum Arduino: https://forum.arduino.cc/index.php?topic=528912.0 Ale nie można też wybrać zbyt małego baud, bo wtedy będziemy gubić znaki lub co gorsza otrzymywać błędne dane. Łatwo to pokazać uruchamiając demo 'test klawiszy' i wciskając (trzymając cały czas) klawisz strzałki, który wysyłany jest przez UART jako trzy znaki. Zdjęcie demka 'odbiór klawiszy' przy baud 1200: https://obrazki.elektroda.pl/9787153500_1589293837_thumb.jpg Zdjęcie demka 'odbiór klawiszy' przy baud 19200: https://obrazki.elektroda.pl/2876768200_1589293876_thumb.jpg Widzicie różnicę? Wniosek: nieodpowiednio dobrany baud może naprawdę namieszać, również gdy wybierzemy jego zbyt małą wartość. Na zdjęciu widać, że raz nawet wysłała się wartość '109' która odpowiada klawiszowi 'm', co z pewnością mogłoby mieć niepożądany skutek jeśli byśmy w naszym programie korzystali zarówno ze strzałek jak i z tego klawisza. Zaawansowane edytor tekstu Teraz zaprezentuję nieco bardziej zaawansowane demko oparte o mojego shielda, a mianowicie prosty edytor tekstu. Edytor tekstu będzie oferować: - obsługa klawisza Shift - obsługa klawisza Caps Lock - obsługa klawisza Delete (usuwanie znaku po kursorze) - obsługa klawisza Backspace (usuwanie znaku przed kursorem) - obsługa klawisza Enter (dodawanie nowej linii) Część tej funkcjonalności jest po stronie Arduino, a część na shieldzie. Rzeczy takie jak poruszanie kursorem, obsługa bufora tekstu, dodawanie znaków, usuwanie ich itp. są po stronie Arduino. Zdjęcia z działania dema-edytora tekstu na monitorze VGA i klawiaturze PS2: https://obrazki.elektroda.pl/5248090800_1589747497_thumb.jpg https://obrazki.elektroda.pl/5745421400_1589747497_thumb.jpg https://obrazki.elektroda.pl/5153392700_1589747496_thumb.jpg https://obrazki.elektroda.pl/5951234900_1589747502_thumb.jpg https://obrazki.elektroda.pl/5538928900_1589747504_thumb.jpg Edytor tekstu można by znacznie ulepszyć, ograniczyć bardziej zbędne odświeżanie pełnego ekranu lub po prostu przenieść w większej części na PICa. Skecz Arduino do pobrania: 1030452 Test edytora tekstu na starym telewizorze CRT TX-21AT1P W ramach uzupełnienia poprzedniego akapitu przedstawiam tu filmik z działania edytora tekstu w trybie PAL na telewizorze kineskopowym: https://filmy.elektroda.pl/13_1590143145.mp4 Zbędne 'pełne odświeżenie' ekranu w trakcie dodawania nowej linii do tekstu można by usunąć w kodzie programu, ale nie to było celem tego demka. Zaawansowane demko - system plików na EEPROM Przedstawione tutaj demko opracowałem w celu dokładniejszego przetestowania obu pamięci EEPROM znajdujących się na płytce (te pamięci pozwalają nam zapisać dane które nie utracą się nawet po całkowitym odłączeniu zasilania od Arduino). Demko to stanowi podstawową wersję systemu plików, który wspiera podstawowe operacje na plikach i katalogach (tworzenie ich, usuwanie, dodawanie danych, przeglądanie, czyszczenie), pozwala też zagnieżdżać katalogi/pliki w innych katalogach tworząc strukturę drzewa. System oczywiście też jest na różne sposoby ograniczony - brakuje dynamicznej alokacji pamięci dla danych pliku, choć jest ona dostępna dla samych katalogów i plików (używane są ponownie zwolnione sloty). Demko obsługuje się poprzez Serial Monitor od Arduino który pełni dla niego funkcję linii komend i wspiera następujące polecenia: - dirls - wyświetla zawartość bieżącego katalogu - mkdir - tworzy katalog o danej nazwie - rmdir - usuwa katalog z zawartością - resetfs - resetuje EEPROMy do pustego systemu plików - resetfile - resetuje plik do stanu pustego (tj. ustawia jego długość na zero) - rmfile - usuwa plik - cd - przechodzi do danego folderu - mkfile - tworzy pusty plik o danej nazwie - append - dodaje do danego pliku dany ciąg znaków - show - pokazuje dany plik w konsoli Poniżej umieszczam zrzuty ekranu z testów powyższego systemu plików; myślę, że ich zawartość nie wymaga komentarza. Testy komend mkdir, ls, mkfile, append, ls: https://obrazki.elektroda.pl/9208051700_1589744617_thumb.jpg Testy komend: cd, mkdir, mkfile: https://obrazki.elektroda.pl/5551405800_1589744899_thumb.jpg Testy komend: rmdir, rmfile, resetfs: https://obrazki.elektroda.pl/7737634500_1589744985_thumb.jpg Testy komend: show, mkfile, append: https://obrazki.elektroda.pl/9026338300_1589745050_thumb.jpg Demko do pobrania: 1030449 Kompilacja wsadu z kodu źródłowego Jeśli tylko chcecie złożyć i używać tego shielda z Arduino to nie musicie samodzielnie kompilować kodu na PICa, potrzebny dla niego .hex załączam tutaj: 1030451 Ale jeśli ktoś chce zmodyfikować samo działanie shielda, to kod można łatwo skompilować w środowisku MPLAB X IDE v5.20: https://obrazki.elektroda.pl/1438991700_1590314916_thumb.jpg Przy użyciu kompilatora XC32 (v2.20): https://obrazki.elektroda.pl/6079210300_1590315087_thumb.jpg Dodatkowo do kompilacji wymagana jest biblioteka PIC32 Peripheral Library (słynne plib.h wraz z innymi nagłówkami), którą ściąga się osobno ze strony Microchipa: https://www.microchip.com/SWLibraryWeb/product.aspx?product=PIC32%20Peripheral%20Library Gdy już ją zainstalujemy, to wszystko poprawnie się kompiluje: https://obrazki.elektroda.pl/2965134100_1590410028_thumb.jpg Kompilować wsad można w dwóch trybach: - tryb dla bootloadera (do wgrania wsadu przez USB za pomocą PIC32UBL.exe) - wtedy w projekcie załączamy 32MX250F128B.ld - tryb bez bootloadera (do wgrania wsadu przez ICSP) - wtedy w projekcie wykluczamy plik 32MX250F128B.ld Więcej informacji na ten temat znajdziecie w oryginalnej paczce z kodem źródłowym: 1030459 Dalszy rozwój projektu - dalsza minimalizacja? Obecna wersja pozostawia jeszcze pole do popisu i możliwość ulepszenia, m.in. dlatego że np. użyty PIC32 jest w wersji PIC32MX250F128B-50I/SO, czyli obudowa SOIC: https://obrazki.elektroda.pl/7523413500_1588796498_thumb.jpg A ten sam mikrokontroler jest jeszcze dostępny w obudowach SSOP (PIC32MX250F128B-50I/SS): https://obrazki.elektroda.pl/9127079900_1588796563_thumb.jpg ... oraz w QFN (PIC32MX250F128B-50I/ML): https://obrazki.elektroda.pl/2453157800_1588796599_thumb.jpg Wszystkie obudowy naszego PICa (kolejno: QFN, SSOP, SOIC i SPDIP) umieściłem na obrazku poniżej: https://obrazki.elektroda.pl/2428852500_1588857711_thumb.jpg Dalszy rozwój projektu - co można by lepiej zrobić? Projekt (i też jego wykonanie - luty) nie jest idealny i dużo można by jeszcze ulepszyć. - można by dać slot na kartę microSD na płytce (podłączony do SPI od Arduino) - można by (jak wspomniałem wyżej) użyć mniejszych obudów elementów i zyskać w ten sposób miejsce na coś więcej na płytce - można by zastąpić MCP23016 (wymagający zewnętrznego rezystora i kondensatora na pinie CLK) poprzez nieco lepszy MCP23017 (który nie wymaga tych dwóch elementów) - można by też dać tam mocniejszego PICa i/lub iść w stronę kolorowego VGA - umieszczone tu przykłady możny by ulepszyć i zoptymalizować, lecz nie to było ich celem (to tylko demonstracja możliwości shielda, nie miała być wydajna) Możliwe zatem, że za jakiś czas zrobię trzecią wersję shielda. Tabela załączników Dla wygody czytelników umieszczam tutaj raz jeszcze odnośniki do załączników które pojawiły się w temacie: NazwaOpisZałącznik Źródła Eagle projektuPliki .sch i .brd które można edytować w Eagle. Użyjcie tego, jeśli chcecie zrobić własną, zmodyfikowaną wersję tego shielda. 1030455 Pliki Gerber projektuTe pliki wysyłamy płytkarni jeśli chcemy by nam wyprodukowali PCB pod ten projekt. Nie polecam ich edytować. 1030453 Arduino skecz - demo edytora tekstuPełny kod edytora tekstu zrealizowanego na tym shieldzie dla Arduino w formacie .ino. Wymaga podłączonej klawiatury i monitora/telewizora do działania. 1030452 Arduino skecz - demo klawiszyPełny kod testera klawiszy PS/2 z obsługą strzałek zrealizowanego na tym shieldzie dla Arduino w formacie .ino. Wymaga podłączonej klawiatury i monitora/telewizora do działania. 1030450 Arduino skecz - demo system plików na EEPROMPełny kod prostego systemu plików na dwóch kościach EEPROM na magistrali I2C Arduino wraz z linią komend na UART. Ten projekt nie korzysta wcale z VGA i nie korzysta z klawiatury PS/2. Kod w formacie .ino 1030449 Skompilowane firmware dla PICa z ShieldaNiezbędny wsad do jednorazowego wgrania na PIC32MX250F128B znajdującego się na pokładzie shielda. Można go wgrać np. za pomocą PICKIT3. 1030451 Kod źródłowy shieldaKod C firmware shielda na PIC32MX250F128B dla MPLAB. Projekt autorstwa geoffg. 1030459 Datasheet AT24CM02Dla dociekliwych - nota katalogowa użytej kości pamięci 1030458 Datasheet MCP23016Dla dociekliwych - nota katalogowa użytego expandera portów 1030454 Biblioteka AT24CXBiblioteka AT24CX z Githuba - kopia zapasowa, wersja ta którą przetestowałem i wykorzystałem do tego projektu. Tę paczkę .ZIP można łatwo dodać do Arduino poprzez 'Add .ZIP Library...'. 1030460 Biblioteka CyMCP23016Biblioteka CyMCP23016 z Githuba - kopia zapasowa, wersja ta którą przetestowałem i wykorzystałem do tego projektu. Tę paczkę .ZIP można łatwo dodać do Arduino poprzez 'Add .ZIP Library...'. 1030477 Podsumowanie Jestem bardzo zadowolony z drugiej wersji mojego shielda. Przejście z montażu przewlekanego na powierzchniowy pozwoliło mi zmieścić na nim nieco więcej niż w pierwszej wersji. Dzięki oparciu o Arduino UNO całość jest wygodna i prosta w użyciu nawet dla początkujących. Umieszczone dodatkowo na płytce układy (MCP23016 i AT24CM02) też posiadają gotowe biblioteki dla Arduino dostępne w sieci, co sprawia, że obsługa mojego shielda sprowadza się do składania programów niemalże jak z klocków, a użycie klawiatury PS/2 oraz możliwość wyświetlania jednokolorowego obrazu VGA oraz czarno-białego obrazu PAL/NTSC nadaje całości nieco 'oldschoolowy' klimat.


Pobierz plik - link do postu

MCP23016
16-Bit I2C™ I/O Expander
Features

Package Types

• 16-bit remote bidirectional I/O port
- 16 I/O pins default to 16 inputs
• Fast I2C™ bus clock frequency (0 - 400 kbits/s)
• Three hardware address pins allow use of up to
eight devices
• High-current drive capability per I/O: ±25 mA
• Open-drain interrupt output on input change
• Interrupt port capture register
• Internal Power-On Reset (POR)
• Polarity inversion register to configure the polarity
of the input port data
• Compatible with most microcontrollers
• Available temperature range:
- Industrial (I): -40°C to +85°C

PDIP, SOIC, SSOP

QFN

GP1.2
GP1.3
INT
GP1.4
VSS
CLK
TP

CMOS Technology
• Operating Supply Voltage: 2.0V to 5.5V
• Low standby current

GP0.7
GP0.6
GP0.5
GP0.4
GP0.3
GP0.2
GP0.1
GP0.0
VDD
VSS
A2
A1
A0
SDA

28
27
26
25
24
23
22
21
20
19
18
17
16
15

GP1.1
GP1.0
Vss
GP0.7
GP0.6
GP0.5
GP0.4

•1
2
3
4
5
6
7
8
9
10
11
12
13
14

MCP23016

Vss
GP1.0
GP1.1
GP1.2
GP1.3
INT
GP1.4
VSS
CLK
TP
GP1.5
GP1.6
GP1.7
SCL

28 27 26 2524 23 22
21
20
19
MCP23016 18
17
16
15
8 9 10 11 121314

GP0.3
GP0.2
GP0.1
GP0.0
VDD
VSS
A2

GP1.5
GP1.6
GP1.7
SCL
SDA
A0
A1

Packages

1
2
3
4
5
6
7

• 28-pin PDIP, 300 mil; 28-pin SOIC, 300 mil
• 28-pin SSOP, 209 mil; 28-pin QFN, 6x6 mm

Block Diagram
Low Pass
Filter

Interrupt
Logic

INT

SDA

CLKIN
TP
VDD

I2C™ Bus
Interface/
Protocol
Handler

Address
Decoder
I2C™ Bus
Control

IARES
16 Bits

Clock
Gen

VSS

© 2007 Microchip Technology Inc.

GP1.0 to GP1.7

Write pulse

Power-on
Reset
8-Bit

GP0.0 to GP0.7
I/O
Port

Control

SCL

Serializer/
Deserializer

A0
A1
A2

Read pulse
Configuration
Registers

Control

DS20090C-page 1

MCP23016
NOTES:

DS20090C-page 2

© 2007 Microchip Technology Inc.

MCP23016
1.0

DEVICE OVERVIEW

The MCP23016 device provides 16-bit, general
purpose, parallel I/O expansion for I2C bus
applications.
This device includes high-current drive capability, low
supply current and individual I/O configuration. I/O
expanders provide a simple solution when additional
I/Os are needed for ACPI, power switches, sensors,
push buttons, LEDs and so on.
The MCP23016 consists of multiple 8-bit configuration
registers for input, output and polarity selection. The
system master can enable the I/Os as either inputs or
outputs by writing the I/O configuration bits. The data
for each input or output is kept in the corresponding

1.1

input or output register. The polarity of the read register
can be inverted with the polarity inversion register (see
Section 1.7.3, “Input Polarity Registers”). All
registers can be read by the system master.
The open-drain interrupt output is activated when any
input state differs from its corresponding input port
register state. This is used to indicate to the system
master that an input state has changed. The interrupt
capture register captures port value at this time. The
Power-on Reset sets the registers to their default values and initializes the device state machine.
Three device inputs (A0 - A2) determine the I2C
address and allow up to eight I/O expander devices to
share the same I2C bus.

Pin Descriptions

TABLE 1-1:
Pin Name

PINOUT DESCRIPTION
PDIP,
SOIC,
SSOP
Pin No.

QFN
Pin No.

I/O/P
Type

Buffer
Type

Description

CLK

9

6

I

ST

Clock source input

TP

10

7

O



Test Pin (This pin must be left floating)

GP1.0

2

27

I/O

TTL

D0 digital input/output for GP1

GP1.1

3

28

I/O

TTL

D1 digital input/output for GP1

GP1.2

4

1

I/O

TTL

D2 digital input/output for GP1

GP1.3

5

2

I/O

TTL

D3 digital input/output for GP1

GP1.4

7

4

I/O

TTL

D4 digital input/output for GP1

GP1.5

11

8

I/O

ST

D5 digital input/output for GP1

GP1.6

12

9

I/O

ST

D6 digital input/output for GP1

GP1.7

13

10

I/O

ST

D7 digital input/output for GP1

GP0.0

21

18

I/O

TTL

D0 digital input/output for GP0

GP0.1

22

19

I/O

TTL

D1 digital input/output for GP0

GP0.2

23

20

I/O

TTL

D2 digital input/output for GP0

GP0.3

24

21

I/O

TTL

D3 digital input/output for GP0

GP0.4

25

22

I/O

TTL

D4 digital input/output for GP0

GP0.5

26

23

I/O

TTL

D5 digital input/output for GP0

GP0.6

27

24

I/O

TTL

D6 digital input/output for GP0

GP0.7

28

25

I/O

TTL

D7 digital input/output for GP0

SCL

14

11

I

ST

Serial clock input

SDA

15

12

I/O

ST

Serial data I/O

INT

6

3

O

OD

Interrupt output

A0

16

13

I

ST

Address input 1

A1

17

14

I

ST

Address input 2

A2

18

15

I

ST

Address input 3

VSS

1, 8, 19

5, 16, 26

P



Ground reference for logic and I/O pins

VDD

20

17

P



Positive supply for logic and I/O pins

© 2007 Microchip Technology Inc.

DS20090C-page 3

MCP23016
1.2

Power-on Reset (POR)

The on-chip POR circuit holds the chip in RESET until
VDD has reached a high enough level to deactivate the
POR circuit (i.e., release RESET). A maximum rise
time for VDD is specified in the electrical specifications.
When the device starts normal operation (exits the
RESET condition), device operating parameters
(voltage, frequency, temperature) must be met to
ensure proper operation.

A 1 MHz (typ.) internal clock is needed for the device to
function properly. The internal clock can be measured
on the TP pin. Recommended REXT and CEXT values
are shown in Table 1-2.
Note:

Set IARES = 1 to measure the clock
output on TP.

TABLE 1-2:

RECOMMENDED VALUES

Power-up Timer (PWRT)

The Power-up Timer provides a 72 ms nominal timeout on power-up, keeping the device in RESET and
allowing VDD to rise to an acceptable level.
The power-up time delay will vary from chip-to-chip due
to VDD, temperature and process variation. See
Table 2-4 for details (TPWRT, parameter 3).

1.5

CEXT

3.9 kΩ

1.3

REXT

33 pF

I2C Bus Interface/ Protocol
Handler

This block manages the functionality of the I2C bus
interface and protocol handling. The MCP23016
supports the following commands:

TABLE 1-3:

1.4

Clock Generator

The MCP23016 uses an external RC circuit to
determine the internal clock speed. The user must
connect R and C to the MCP23016, as shown in
Figure 1-1.

COMMAND BYTE TO
REGISTER RELATIONSHIP

Command Byte

Result

1h

Access to INTCAP1 (Read-Only)
Access to IOCON0

Bh

1.6

Access to INTCAP0 (Read-Only)

Ah

MCP23016

Access to IODIR1

9h

VSS

Access to IODIR0

8h

CEXT

Access to IPOL1

7h

CLK

Access to IPOL0

6h
Internal Clock

Access to OLAT1

5h

REXT

Access to OLAT0

4h
VDD

Access to GP1

3h

CLOCK CONFIGURATION

Access to GP0

2h

FIGURE 1-1:

0h

Access to IOCON1

Address Decoder

The last three LSb of the 7-bit address are user-defined
(see Table 1-4). Three hardware pins ( &amp; lt; A2:A0 &amp; gt; ) define
these bits.

TABLE 1-4:
0

DS20090C-page 4

1

DEVICE ADDRESS
0

0

A2

A1

A0

© 2007 Microchip Technology Inc.

MCP23016
1.7

Register Block

The register block contains the Configuration and Port registers, as shown in Table 1-5.

TABLE 1-5:
Name

REGISTER SUMMARY
Bit 7

Bit 6

Bit 5

Bit 4

Bit 3

Bit 2

Bit 1

Bit 0

Value on
POR

Port Registers
GP0

GP0.7

GP0.6

GP0.5

GP0.4

GP0.3

GP0.2

GP0.1

GP0.0

0000 0000

GP1

GP1.7

GP1.6

GP1.5

GP1.4

GP1.3

GP1.2

GP1.1

GP0.0

0000 0000

OLAT0

OL0.7

OL0.6

OL0.5

OL0.4

OL0.3

OL0.2

OL0.1

OL0.0

0000 0000

OLAT1

OL1.7

OL1.6

OL1.5

OL1.4

OL1.3

OL1.2

OL1.1

OL1.0

0000 0000

IGP0.2

IGP0.1

IGP0.0

0000 0000

Configuration Registers
IPOL0

IGP0.7

IGP0.6

IGP0.5

IGP0.4

IGP0.3

IPOL1

IGP1.7

IGP1.6

IGP1.5

IGP1.4

IGP1.3

IGP1.2

IGP1.1

IGP1.0

0000 0000

IODIR0

IOD0.7

IOD0.6

IOD0.5

IOD0.4

IOD0.3

IOD0.2

IOD0.1

IOD0.0

1111 1111

IODIR1

IOD1.7

IOD1.6

IOD1.5

IOD1.4

IOD1.3

IOD1.2

IOD1.1

IOD1.0

1111 1111

INTCAP0

ICP0.7

ICP0.6

ICP0.5

ICP0.4

ICP0.3

ICP0.2

ICP0.1

ICP0.0

xxxx xxxx

INTCAP1

ICP1.7

ICP1.6

ICP1.5

ICP1.4

ICP1.3

ICP1.2

ICP1.1

ICP1.0

xxxx xxxx

IOCON0















IARES

---- ---0

IOCON1















IARES

---- ---0

Legend: ‘1’ bit is set, ‘0’ bit is cleared, x = unknown, — = unimplemented.

© 2007 Microchip Technology Inc.

DS20090C-page 5

MCP23016
1.7.1

DATA PORT REGISTERS

Two registers provide access to the two GPIO ports:
• GP0 (provides access to data port GP0)
• GP1 (provides access to data port GP1)
A read from this register provides status on pins of
these ports. A write to these registers will modify the
output latch registers (OLAT0, OLAT1) and data output.

REGISTER 1-1:

GP0 - GENERAL PURPOSE I/O PORT REGISTER 0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

GP0.7

GP0.6

GP0.5

GP0.4

GP0.3

GP0.2

GP0.1

GP0.0

bit 7
bit 7-0

bit 0

GP0.0:GP0.7: Reflects the logic level on the pins.
1 = Logic ‘1’
0 = Logic ‘0’
Legend:
R = Readable bit

W = Writable bit

U = Unimplemented bit, read as ‘0’

- n = Value at POR

‘1’ = Bit is set

‘0’ = Bit is cleared

REGISTER 1-2:

x = Bit is unknown

GP1 - GENERAL PURPOSE I/O PORT REGISTER 1

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

GP1.7

GP1.6

GP1.5

GP1.4

GP1.3

GP1.2

GP1.1

GP1.0

bit 7
bit 7-0

bit 0

GP1.0:GP1.7: Reflects the logic level on the pins.
1 = Logic ‘1’
0 = Logic ‘0’
Legend:
R = Readable bit

W = Writable bit

U = Unimplemented bit, read as ‘0’

- n = Value at POR

‘1’ = Bit is set

‘0’ = Bit is cleared

DS20090C-page 6

x = Bit is unknown

© 2007 Microchip Technology Inc.

MCP23016
1.7.2

OUTPUT LATCH REGISTERS

Two registers provide access to the two port output
latches:
• OLAT0 (provides access to the output latch for
port GP0)
• OLAT1 (provides access to the output latch for
port GP1)
A read from these registers results in a read of the latch
that controls the output and not the actual port. A write
to these registers updates the output latch that controls
the output.

REGISTER 1-3:

OLAT0 - OUTPUT LATCH REGISTER 0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

OL0.7

OL0.6

OL0.5

OL0.4

OL0.3

OL0.2

OL0.1

OL0.0

bit 7
bit 7-0

bit 0

OL0.0:O0.7: Reflects the logic level on the output latch.
1 = Logic ‘1’
0 = Logic ‘0’
Legend:
R = Readable bit

W = Writable bit

U = Unimplemented bit, read as ‘0’

- n = Value at POR

‘1’ = Bit is set

‘0’ = Bit is cleared

REGISTER 1-4:

x = Bit is unknown

OLAT1 - OUTPUT LATCH REGISTER 1

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

OL1.7

OL1.6

OL1.5

OL1.4

OL1.3

OL1.2

OL1.1

OL1.0

bit 7
bit 7-0

bit 0

OL1.0:O1.7: Reflects the logic level on the output latch.
1 = Logic ‘1’
0 = Logic ‘0’
Legend:
R = Readable bit

W = Writable bit

U = Unimplemented bit, read as ‘0’

- n = Value at POR

‘1’ = Bit is set

‘0’ = Bit is cleared

© 2007 Microchip Technology Inc.

x = Bit is unknown

DS20090C-page 7

MCP23016
1.7.3

INPUT POLARITY REGISTERS

These registers allow the user to configure the polarity
of the input port data (GP0 and GP1). If a bit in this register is set, the corresponding input port (GPn) data bit
polarity will be inverted.
• IPOL0 (controls the polarity of GP0)
• IPOL1 (controls the polarity of GP1)

REGISTER 1-5:

IPOL0 - INPUT POLARITY PORT REGISTER 0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

IGP0.7

IGP0.6

IGP0.5

IGP0.4

IGP0.3

IGP0.2

IGP0.1

IGP0.0

bit 7
bit 7-0

bit 0

IGP0.0:IGP0.7: Controls the polarity inversion for the input pins
1 = Corresponding GP0 bit is inverted
0 = Corresponding GP0 bit is not inverted
Legend:
R = Readable bit

W = Writable bit

U = Unimplemented bit, read as ‘0’

- n = Value at POR

‘1’ = Bit is set

‘0’ = Bit is cleared

REGISTER 1-6:

x = Bit is unknown

IPOL1 - INPUT POLARITY PORT REGISTER 1

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

IGP1.7

IGP1.6

IGP1.6

IGP1.4

IGP1.3

IGP1.2

IGP1.1

IGP1.0

bit 7
bit 7-0

bit 0

IGP1.0:IGP1.7: Controls the polarity inversion for the input pins
1 = Corresponding GP1 bit is inverted
0 = Corresponding GP1 bit is not inverted
Legend:
R = Readable bit

W = Writable bit

U = Unimplemented bit, read as ‘0’

- n = Value at POR

‘1’ = Bit is set

‘0’ = Bit is cleared

DS20090C-page 8

x = Bit is unknown

© 2007 Microchip Technology Inc.

MCP23016
1.7.4

I/O DIRECTION REGISTERS

Two registers control the direction of data I/O:
• IODIR0 (controls GP0)
• IODIR1 (controls GP1)
When a bit in these registers is set, the corresponding
pin becomes an input. Otherwise, it becomes an
output. At Power-on Reset, the device ports are
configured as inputs.

REGISTER 1-7:

IODIR0 - I/O DIRECTION REGISTER 0

R/W-1

R/W-1

R/W-1

R/W-1

R/W-1

R/W-1

R/W-1

R/W-1

IOD0.7

IOD0.6

IOD0.5

IOD0.4

IOD0.3

IOD0.2

IOD0.1

IOD0.0

bit 7
bit 7-0

bit 0

IOD0.0:IO0.7: Controls the direction of data I/O
1 = Input
0 = Output
Legend:
R = Readable bit

W = Writable bit

U = Unimplemented bit, read as ‘0’

- n = Value at POR

‘1’ = Bit is set

‘0’ = Bit is cleared

REGISTER 1-8:

x = Bit is unknown

IODIR1 - I/O DIRECTION REGISTER 1

R/W-1

R/W-1

R/W-1

R/W-1

R/W-1

R/W-1

R/W-1

R/W-1

IOD1.7

IOD1.6

IOD1.5

IOD1.4

IOD1.3

IOD1.2

IOD1.1

IOD1.0

bit 7
bit 7-0

bit 0

IOD1.0:IO1.7: Controls the direction of data I/O
1 = Input
0 = Output
Legend:
R = Readable bit

W = Writable bit

U = Unimplemented bit, read as ‘0’

- n = Value at POR

‘1’ = Bit is set

‘0’ = Bit is cleared

© 2007 Microchip Technology Inc.

x = Bit is unknown

DS20090C-page 9

MCP23016
1.7.5

INTERRUPT CAPTURE REGISTERS

Two registers contain the value of the port that
generated the interrupt:
• INTCAP0 contains the value of GP0 at time of
GP0 change interrupt
• INTCAP1 contains the value of GP1 at time of
GP1 change interrupt
These registers are ‘read-only’ registers (A write to
these registers is ignored).

REGISTER 1-9:

INTCAP0 - INTERRUPT CAPTURED VALUE FOR PORT REGISTER 0

R-x

R-x

R-x

R-x

R-x

R-x

R-x

R-x

ICP0.7

ICP0.6

ICP0.5

ICP0.4

ICP0.3

ICP0.2

ICP0.1

ICP0.0

bit 7
bit 7-0

bit 0

ICP0.0:ICP0.7: Reflects the logic level on the GP0 pins at the time of interrupt due to pin
change
1 = Logic ‘1’
0 = Logic ‘0’
Legend:
R = Readable bit

W = Writable bit

U = Unimplemented bit, read as ‘0’

- n = Value at POR

‘1’ = Bit is set

‘0’ = Bit is cleared

REGISTER 1-10:

x = Bit is unknown

INTCAP1 - INTERRUPT CAPTURED VALUE FOR PORT REGISTER 1

R-x

R-x

R-x

R-x

R-x

R-x

R-x

R-x

ICP1.7

ICP1.6

ICP1.5

ICP1.4

ICP1.3

ICP1.2

ICP1.1

ICP1.0

bit 7
bit 7-0

bit 0

ICP1.0:ICP1.7: Reflects the logic level on the GP1 pins at the time of interrupt due to pin
change
1 = Logic ‘1’
0 = Logic ‘0’
Legend:
R = Readable bit

W = Writable bit

U = Unimplemented bit, read as ‘0’

- n = Value at POR

‘1’ = Bit is set

‘0’ = Bit is cleared

DS20090C-page 10

x = Bit is unknown

© 2007 Microchip Technology Inc.

MCP23016
1.7.6

I/O EXPANDER CONTROL
REGISTER

• IOCON0 controls the functionality of the
MCP23016.
The IARES (Interrupt Activity Resolution) bit controls
the sampling frequency of the GP port pins. The higher
the sampling frequency, the higher the device current
requirements. If this bit is ‘0’ (default), the maximum
time to detect the activity on the port is 32 ms (max.),
which results in lower standby current. If this bit is ‘1’,
the maximum time to detect activity on the port is
200 µsec. (max.) and results in higher standby current.

REGISTER 1-11:

IOCON0 - I/0 EXPANDER CONTROL REGISTER

U-0

U-0

U-0

U-0

U-0

U-0

U-0

R/W-0















IARES

bit 7

bit 0

bit 1-7

Unimplemented bit: Read as ‘0’

bit 0

IARES: Interrupt Activity Resolution
1 = Fast sample rate
0 = Normal sample rate
Legend:
R = Readable bit

W = Writable bit

U = Unimplemented bit, read as ‘0’

- n = Value at POR

‘1’ = Bit is set

‘0’ = Bit is cleared

x = Bit is unknown

IOCON1 is a shadow register for IOCON0. Access to IOCON1 results in access to IOCON0.

© 2007 Microchip Technology Inc.

DS20090C-page 11

MCP23016
1.8

The Serializer/Deserializer block converts
transfers data between the I2C bus and GPIO.

1.9

1.9.1

Serializer/Deserializer
and

Interrupt Logic

The MCP23016 asserts the open-drain interrupt output
(INT) low when one of the port pins changes state. Only
those pins that are configured as an input can cause an
interrupt. Pins defined as an output have no effect on
INT. The interrupt will remain active until a read from
either the port (GPn) on which the interrupt occurred or
the INTCAPn register is performed. If the input returns
to its previous state before a read operation, it will reset
the interrupt and the INT pin output will tri-state. Each
8-bit port is read separately, so reading GP0 or
INTCAP0 will not clear the interrupt generated by GP1
or INTCAP1, and vice versa.
Input change activity on each port will generate an
interrupt and the value of the particular port will be
captured and copied into INTCAP0/INTCAP1. The
INTCAPn registers are only updated when an interrupt
occurs on INT. These values will stay unchanged until
the user clears the interrupt by reading the port or the
INTCAPn register.

INTERRUPT EVENT DETECTION

The IARES bit controls the resolution for detecting an
interrupt-on-change event. If this bit is ‘0’ (default), the
maximum time for detecting a change of event is high,
which results in lower standby current. If this bit is ‘1’, it
takes less time for scanning the activity on the port and
results in higher standby current.

FIGURE 1-2:

GPx

READING PORTX AFTER
INTERRUPT EVENT

PORT X

PORT X

INT

Port value
is captured
and written to
INTCAPn

Read GPx
or INTCAPn

Port value
is captured
and written to
INTCAPn

If the input port value changes back to normal before a
user-read, the INT output will be reset. However, the
INTCAP0/INTCAP1 will still contain the value of the
port at the interrupt change. If the port value changes
again, it will re-activate the interrupt and the new value
will be captured.
The first interrupt on change event following an
interrupt RESET will result in a capture event. Any further change event that occurs before the interrupt is
reset will not result in a capture event.

DS20090C-page 12

© 2007 Microchip Technology Inc.

MCP23016
FIGURE 1-3:

WRITE TO CONFIGURATION
REGISTERS (CASE 1)

2

9
8
7
6
5
4
3
2
1
9
8
7
6
5
4

SCL held low until
data is processed

3
2
1
9
8
7
6
5
4
3
2
1

D7 D6 D5 D4 D3 D2 D1 D0
ACK

5

6

7

8

ACK
A2 A1 A0
0

2
1
S

1
0

0

R/W=0
Address

9

D7 D6 D5 D4 D3 D2 D1 D0 ACK

Data 2

ACK

The bus must remain free until after the
ninth clock pulse for a minimum of 12 µs
(see Table 2-5 and Figure 2-4).

Command Byte

Note:

D7 D6 D5 D4 D3 D2 D1 D0

There is no limitation on the number of data bytes in
one write transmission. Figure 1-4 shows the case of
multiple byte writes in one write operation. In this case,
the multiple writes are made to the same data pair.

Data 1

The MCP23016 has twelve 8-bit registers. They are
configured to operate as six 16-bit register pairs,
supporting the device’s 16-bit port. These pairs are
formed based on their functions (e.g., GP0 and GP1
are grouped together). The I2C commands apply to one
register pair to provide faster access. The first data byte
following a command byte is written into the register
pointed to by the command byte, while the second data
is written into another register in the same pair. For
example, if the first byte is sent to OLAT1 (command
byte 03h), the next data byte will be written into the second register of that pair, OLAT0. If the first byte is written to OLAT0 (command byte 02h), the second byte
will be written to OLAT1.

P

To write to a MCP23016 register, the Master I C device
needs to follow the requirements, as illustrated in
Figure 1-3. First, the device is selected by sending the
slave address and setting the R/W bit to logic ‘0’. The
command byte is sent after the address and
determines which register will be written. Table 1-3
shows the relationship of the command byte and
register.

4

WRITING THE REGISTERS

3

1.9.2

© 2007 Microchip Technology Inc.

DS20090C-page 13

0

DS20090C-page 14

Data on GP1

2

1

4

3

0

4

0

Address

3

0

6

5

6

7

8

8

R/W=0

7

A2 A1 A0

5

A2 A1 A0

1

2

4

5

Command Byte

3

6

7

9

1

2

3

4

5

6

7

1

2

ACK

9

7

8

9

1

2

Data 2

3

4

5

6

7

3

Data 1

4

5

6

7

8

9

1

2

3

4

5

6

7

9

t GPV0

8

D7 D6 D5 D4 D3 D2 D1 D0 ACK

2

4

5

6

Data 2

SCL held low until
data is processed

3

7

1

2

3

4

5

7

8

9

9

ACK

8

t GPV1

DATA VALID

6

D7 D6 D5 D4 D3 D2 D1 D0

2

8

P

1

6

1

5

VALID
DATA

P

9

D7 D6 D5 D4 D3 D2 D1 D0 ACK

D7 D6 D5 D4 D3 D2 D1 D0 ACK

4

ACK

Data 2

D7 D6 D5 D4 D3 D2 D1 D0 ACK

Data 1

3

D7 D6 D5 D4 D3 D2 D1 D0

SCL held low until
data is processed

8

9

ACK

SCL held low until
data is processed

8

D7 D6 D5 D4 D3 D2 D1 D0

ACK D7 D6 D5 D4 D3 D2 D1 D0

9

ACK

Data 1

FIGURE 1-5:

Data on GP0

1

2

0

Command Byte

WRITE TO CONFIGURATION
REGISTERS (CASE 2)

SCL S

1

1

R/W=0

FIGURE 1-4:

SDA

S

0

Address

MCP23016
WRITE TO OUTPUT PORTS

© 2007 Microchip Technology Inc.

MCP23016
FIGURE 1-6:

READ FROM
CONFIGURATION
REGISTER

© 2007 Microchip Technology Inc.

9
8
7
6
5
4
3
2
1
SCL held low until
data is processed

9
8
7
6
5
4
3
2
1

ACK

7
6
5
4
3
2
1

A1
A2
0
1
0

0

2
1
SCL S

S

A0

8

9

Data from LSB or
MSB of register

SCL held low until
data is processed

D7 D6 D5 D4 D3 D2 D1 D0

9
8
7
6
5
4
3
2
1
9
8
7
6
5
4

A0
1
0
SDA

0

0

A2

A1

R/W=0
Address

3

The bus must remain free until after the
ninth clock pulse for a minimum of 12 µs
(see Table 2-5 and Figure 2-4).

ACK

Note:

Command Byte

There is no limitation on the number of data bytes in
one read transmission. Figure 1-8 shows the case of
multiple byte read in one read operation. In this case,
the multiple writes are made to the same data pair.

D7 D6 D5 D4 D3 D2 D1 D0

ACK

The MCP23016 holds the clock low after the falling
edge of the ninth clock pulse. The configuration
registers (or port control registers) are read and the
value is stored. Finally, the clock is released to enable
the next transmission.

ACK

The falling edge of the ninth clock initiates the register
read action. The SCL clock will be held low while the
data is read from the register and is transferred to the
I2C bus control block by the Serializer/Deserializer
block.

D7 D6 D5 D4 D3 D2 D1 D0 ACK

Data from MSB or
LSB of register

P

To read a MCP23016 register, the Master needs to
follow the requirements shown in Figure 1-6. First, the
device is selected by sending the slave address and
setting the R/W bit to logic ‘0’. The command byte is
sent after the address and determines which register
will be read. A restart condition is generated and the
device address is sent again with the R/W bit set to
logic ‘1’. The data register defined by the command
byte will be sent first, followed by the other register in
the register pair. The logic for register selection is the
same as explained in Write mode (Section 1.9.2,
“Writing the Registers”).

R/W=0

READING THE REGISTERS

Address

1.9.3

DS20090C-page 15

0

SCL S

DS20090C-page 16
3

0

4

0

Data in GP0

2

1

5

Note:

tIsd

7

8

9

ACK

Data from LSB or
MSB of register

2

tIcd0

tRDd0

1

3

4

5

6

7

8

D7 D6 D5 D4 D3 D2 D1 D0

It is assumed that command byte is already set to ‘00’.

INT

Read signal (Internal) for GP1

Data in GP1

6

A2 A1 A0

R/W=0

1

tIcd1

tRDd1

2

3

4

5

6

7

8

9

D7 D6 D5 D4 D3 D2 D1 D0 ACK

SCL held low until
data is processed

9

ACK

Data from MSB or
LSB of register

P

FIGURE 1-7:

Read signal (Internal) for GP0

1

SDA

Address

MCP23016
READ FROM INPUT PORTS (CASE 1)

© 2007 Microchip Technology Inc.

0

© 2007 Microchip Technology Inc.

2

3

0

4

0

5

A2

6

7

A0

8

1

2

3

4

5

4

5

6

7

8

9

3

1

2

D7 D6 D5 D4 D3 D2 D1 D0

6

8

1

2

3

4

5

1

2

3

4

5

6

7

8

9

6

P

7

8

D7 D6 D5 D4 D3 D2 D1 D0

Data from GP1

9

ACK

Data from GP1

D7 D6 D5 D4 D3 D2 D1 D0 ACK

7

D7 D6 D5 D4 D3 D2 D1 D0

Data from GP0

9

ACK

Data from GP0

ACK

A1

It is assumed that command byte is already set to 00.

SCL S

1

R/W=0

9

ACK

FIGURE 1-8:

Note:

1

SDA

Address

MCP23016

READ FROM INPUT PORTS
(CASE 2)

DS20090C-page 17

MCP23016
NOTES:

DS20090C-page 18

© 2007 Microchip Technology Inc.

MCP23016
2.0

ELECTRICAL CHARACTERISTICS

Absolute Maximum Ratings †
Ambient temperature under bias................................................................................................................ -55 to +125°C
Storage temperature .............................................................................................................................. -65°C to +150°C
Voltage on any pin with respect to VSS ......................................................................................... -0.3V to (VDD + 0.3V)
Voltage on VDD with respect to VSS ......................................................................................................... -0.3V to +6.5V
Total power dissipation (Note 1) ............................................................................................................................ 1.0 W
Maximum current out of VSS pin .......................................................................................................................... 300 mA
Maximum current into VDD pin ............................................................................................................................. 250 mA
Input clamp current, IIK (VI &amp; lt; 0, or VI &amp; gt; VDD) ....................................................................................................... ± 20 mA
Output clamp current, IOK (VO &amp; lt; 0, or VO &amp; gt; VDD) ................................................................................................ ± 20 mA
Maximum output current sunk by any I/O pin......................................................................................................... 25 mA
Maximum output current sourced by any I/O pin ................................................................................................... 25 mA
Maximum current sunk by combined PORTS ...................................................................................................... 200 mA
Maximum current sourced by combined PORTS ................................................................................................ 200 mA
Note 1: Power dissipation is calculated as follows:
Pdis = VDD x {IDD - ∑ IOH} + ∑ {(VDD-VOH) x IOH} + ∑(VOl x IOL)
† NOTICE: Stresses above those listed under “Absolute Maximum Ratings” may cause permanent damage to the
device. This is a stress rating only and functional operation of the device at those or any other conditions above those
indicated in the operation listings of this specification is not implied. Exposure to maximum rating conditions for
extended periods may affect device reliability.

© 2007 Microchip Technology Inc.

DS20090C-page 19

MCP23016
2.1

DC Characteristics

TABLE 2-1:

DC CHARACTERISTICS
Standard Operating Conditions (unless otherwise stated)
Operating temperature: -40°C ≤ TA ≤ +85°C for industrial

DC CHARACTERISTICS
Param
No.

Sym

Min

Typ†

Max

Units

Supply Voltage

VDD

2.0



5.5

V

D002

Standby Current

IDD



0.4

mA

IARES = 1

D003

Standby Current

IPD



25

µA

IARES = 0

Vss



0.15 VDD

V

For entire VDD range

Vss



0.8V

Vss



0.2 VDD

V

D001

Characteristic

Conditions

Input Low Voltage
I/O ports
D004

VIL

TTL buffer

D004A
D005

Schmitt Trigger buffer

4.5V ≤ VDD ≤ 5.5V

Input High Voltage
I/O ports



VIH



VDD

V

4.5V ≤ VDD ≤ 5.5V

VDD

0.25
+ 0.8V

D006



VDD

V

For entire VDD range

0.8 VDD



VDD

V

For entire VDD range





±1.0

µA

Vss ≤ VPIN ≤ VDD,
Pin at hi-impedance





±5.0

µA

Vss ≤ VPIN ≤ VDD

VOL





0.6

V

IOL = 8.5 mA, VDD = 4.5V
IOH = 3.0 mA, VDD = 4.5V

TTL buffer

2.0

D006A
D007

Schmitt Trigger buffer
Input Leakage Current

D008

I/O ports

D009

IIL

CLK
Output Low Voltage

D010

I/O Ports
Output High Voltage

D010

I/O Ports

VOH

VDD-0.7





V

D011

VDD start voltage to ensure
internal POR signal

VPOR



Vss



V

D012

VDD rise rate to ensure
internal POR signal

SVDD

0.05

-



DC Trip Point

VTPOR

1.5

1.7

1.9

VDD rise rate to ensure
internal POR signal with
PWRT enabled

SVDD

0.05





DC Current Draw

IPOR



5.0



D012

Note 1:
2:
3:
4:

5:

V/ms Note 1
V

DC Slow Ramp

V/ms Note 1

µA

At 5.0V (1 µ/Volt typical)

These parameters are characterized but not tested.
Data in &quot; Typ &quot; column is at 5V, 25°C unless otherwise stated. These parameters are for design guidance
only and are not tested.
Standby current is measured with all I/O in hi-impedance state and tied to VDD and VSS.
For RC CLK, current through REXT is not included. The current through the resistor can be estimated by
the formula
Ir = VDD/2 REXT (mA) with REXT in kohm.
Negative current is defined as coming out of the pin.

DS20090C-page 20

© 2007 Microchip Technology Inc.

MCP23016
FIGURE 2-1:

RESPONSE TIME

VDD
1

TABLE 2-2:
Parameter
No.

RESPONSE TIME
Symbol

1

Characteristic
Response Time

FIGURE 2-2:

Min

Typ†

Max

Units

100





ns

Conditions
Minimum time where a VDD
transition from 5.0V to 0.0V to
5.0V will cause a RESET. All
times less than 100 ns will be
filtered.

TEST POINT CLOCK TIMING
2

TTP

TABLE 2-3:
Parameter
No.

TEST POINT CLOCK TIMING
Symbol

Characteristic

Min

Typ†

Max

Units

Conditions

FTP



1.0



MHz

Measured at TP pin,
IARES = ‘1’.

TTP

2

TP pin Frequency
TP pin CLK Period



1.0



µs

Measured at TP pin,
IARES = ‘1’.

† Data in &quot; Typ &quot; column is at 5V, +25°C unless otherwise stated. These parameters are for design guidance
only and are not tested.

TABLE 2-4:

POWER-UP TIMER REQUIREMENTS

Parameter
No.

Symbol

3

TPWRT

Characteristic
Power-up Timer Period

Min

Typ†

Max

Units



72



ms

Conditions

† Data in &quot; Typ &quot; column is at 5V, +25°C unless otherwise stated. These parameters are for design guidance
only and are not tested.

© 2007 Microchip Technology Inc.

DS20090C-page 21

MCP23016
I2C BUS START/STOP BITS TIMING

FIGURE 2-3:

SCL

91

93

90

92

SDA

STOP
Condition

START
Condition

I2C BUS START/STOP BITS REQUIREMENTS

TABLE 2-5:
Param
No.

Symbol

90

TSU:STA

START condition
Setup time

400 kHz mode

600





91

THD:STA

START condition

100 kHz mode

4000





Hold time

400 kHz mode

600





100 kHz mode

4700





Min

Ty
Max Units
p

4700



Characteristic
100 kHz mode



92

TSU:STO

STOP condition
Setup time

400 kHz mode

600



THD:STO

STOP condition

100 kHz mode

4000





Hold time

400 kHz mode

600



ns

Only relevant for Repeated
START condition (Note 1)

ns

After this period, the first
clock pulse is generated
(Note 1)



93

Conditions



Note 1:

ns
ns

These parameters are characterized but not tested.

DS20090C-page 22

© 2007 Microchip Technology Inc.

MCP23016
FIGURE 2-4:

I2C BUS DATA TIMING
103

102

100
101

SCL

90

106
111

91

107
92

SDA
In
110
109

109

SDA
Out

© 2007 Microchip Technology Inc.

DS20090C-page 23

MCP23016
I2C BUS DATA REQUIREMENTS

TABLE 2-5:
Param
No.

Symbol

100

THIGH

Clock High Time

101

TLOW

Clock Low Time

102

TR

Characteristic

Min

Max

Units

100 kHz mode

4.0



µs

400 kHz mode

0.6



µs

100 kHz mode

4.7



µs

Conditions
(Note 1)
(Note 1)

400 kHz mode

TF

TSU:STA

90
91

THD:STA

106
107

THD:DAT
TSU:DAT
TSU:STO

92
109
110

TAA
TBUF

CB
111

Note 1:
2:
3:

TWAIT



µs



1000

ns

(Note 1)

20 + 0.1 CB

300

ns

CB is specified to be from
10 - 400 pF

SDA and SCL Fall
Time

100 kHz mode



300

ns

(Note 1)

400 kHz mode

20 + 0.1 CB

300

ns

CB is specified to be from
10 - 400 pF

START Condition
Setup Time

100 kHz mode

4.7



µs

400 kHz mode

0.6



µs

Only relevant for repeated
START condition (Note 1)

START Condition
Hold Time

100 kHz mode

4.0



µs

400 kHz mode

0.6



µs

After this period, the first
clock pulse is generated
(Note 1)

Data Input Hold
Time

100 kHz mode

0



ns

(Note 1)

400 kHz mode

0

0.9

µs

Data Input Setup
Time

100 kHz mode

250



ns

400 kHz mode

100



ns

STOP Condition
Setup Time

100 kHz mode

4.7



µs

400 kHz mode

0.6



µs

Output Valid from
Clock

100 kHz mode



3500

ns

400 kHz mode





ns

100 kHz mode

4.7



µs

400 kHz mode

103

1.3

SDA and SCL Rise 100 kHz mode
Time
400 kHz mode

1.3



µs

Bus Free Time

Bus Capacitive Loading
Clock wait time
after ninth pulse



400

12 µs



µs

400 kHz mode

12 µs



µs

(Note 1)
(Note 1) (Note 2)
Time the bus must be free
before a new transmission can start (Note 1)

pF

100 kHz mode

(Note 1) (Note 3)

Time the bus must remain
free after the ninth clock
pulse before a new
transmission can start.

These parameters are characterized but not tested.
As a transmitter, the device must provide this internal minimum delay time to bridge the undefined region
(min. 300 ns) of the falling edge of SCL to avoid unintended generation of START or STOP conditions.
A Fast mode (400 kHz) I2C bus device can be used in a Standard mode (100 kHz) I2C bus system, but the
requirement TSU:DAT ≥ 250 ns must then be met. This will automatically be the case if the device does not
stretch the LOW period of the SCL signal. If such a device does stretch the LOW period of the SCL signal,
it must output the next data bit to the SDA line TR max.+TSU:DAT = 1000 + 250 = 1250 ns (according to the
Standard mode I2C bus specification), before the SCL line is released.

DS20090C-page 24

© 2007 Microchip Technology Inc.

MCP23016
TABLE 2-7:
Param
No.

GP0 AND GP1 TIMING REQUIREMENTS

Symbol

Characteristic

Min

Typ.

Max

Units

Conditions

tGPV0

GP0 output data
valid time



40



µs

tGPV1

GP1 output data
valid time



50



µs

tRDd0

GP0 data read
delay time



40



µs

tRDd1

GP1 data read
delay time



50



µs

tISD0

GP0 Interrupt set
delay time





200

µs

IARES = 1, TP = 1 MHz





32

ms

IARES = 0, TP = 1 MHz

GP1 Interrupt set
delay time





200

µs

IARES = 1, TP = 1 MHz





32

ms

IARES = 0, TP = 1 MHz

tLCD0

GP0 Interrupt clear
delay time (for
read)



100



µs

TP = 1 MHz

tLCD1

GP1 Interrupt clear
delay time (for
read)



100



µs

tISD1

Note 1:

TP = 1 MHz

These parameters are characterized but not tested.

© 2007 Microchip Technology Inc.

DS20090C-page 25

DS20090C-page 26

SCL S

SDA

3

0

4

0

Data in GP0

2

1

5

Note:

tIsd

7

A0

8

9

ACK

2

tIcd0

tRDd0

1

3

4

5

6

7

8

9

D7 D6 D5 D4 D3 D2 D1 D0 ACK

Data from LSB or
MSB of register

It is assumed that command byte is already set to ‘00’.

INT

Read signal(Internal) for GP1

Data in GP1

6

A2 A1

R/W=0

2

3

tIcd1

tRDd1

SCL held low until
data is processed

1

4

5

6

7

8

9

D7 D6 D5 D4 D3 D2 D1 D0 ACK

Data from MSB or
LSB of register

P

FIGURE 2-5:

Read signal(Internal) for GP0

1

0

Address

MCP23016
GP0 AND GP1 PORT TIMINGS

© 2007 Microchip Technology Inc.

MCP23016
3.0

PACKAGE INFORMATION

3.1

Package Marking Information
28-Lead PDIP (Skinny DIP)

Example:
MCP23016-I/SP e3

XXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXX
YYWWNNN

28-Lead SOIC

Example:

XXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXX
YYWWNNN

28-Lead SSOP

MCP23016-I/SO e3
0710017

Example:

XXXXXXXXXXXX
XXXXXXXXXXXX
YYWWNNN

28-Lead QFN

MCP23016
-I/SS e3
0720017

Example:

XXXXXXXX
XXXXXXXX
YYWWNNN

MCP23016
-I/ML e3
0710017

Legend: XX...X
Y
YY
WW
NNN
*

e3

Note:

0717017

Customer-specific information
Year code (last digit of calendar year)
Year code (last 2 digits of calendar year)
Week code (week of January 1 is week ‘01’)
Alphanumeric traceability code
Pb-free JEDEC designator for Matte Tin (Sn)
This package is Pb-free. The Pb-free JEDEC designator (
can be found on the outer packaging for this package.

)

e3

In the event the full Microchip part number cannot be marked on one line, it will
be carried over to the next line, thus limiting the number of available
characters for customer-specific information.

© 2007 Microchip Technology Inc.

DS20090C-page 27

MCP23016
28-Lead Skinny Plastic Dual In-Line (SP) – 300 mil Body [SPDIP]
Note:

For the most current package drawings, please see the Microchip Packaging Specification located at
http://www.microchip.com/packaging

N
NOTE 1
E1

1 2 3
D
E
A2

A

L

c

b1

A1

b

e

eB

Units
Dimension Limits
Number of Pins

INCHES
MIN

N

Pitch

A

MAX

28

e

Top to Seating Plane

NOM
.100 BSC





.200

Molded Package Thickness

A2

.120

.135

.150

Base to Seating Plane

A1

.015





Shoulder to Shoulder Width

E

.290

.310

.335

Molded Package Width

E1

.240

.285

.295

Overall Length

D

1.345

1.365

1.400

Tip to Seating Plane

L

.110

.130

.150

Lead Thickness

c

.008

.010

.015

Upper Lead Width

b1

.040

.050

.070

Lower Lead Width

b

.014

.018

.022

Overall Row Spacing §
eB


.430
Notes:
1. Pin 1 visual index feature may vary, but must be located within the hatched area.
2. § Significant Characteristic.
3. Dimensions D and E1 do not include mold flash or protrusions. Mold flash or protrusions shall not exceed .010 &quot; per side.
4. Dimensioning and tolerancing per ASME Y14.5M.

DS20090C-page 28

© 2007 Microchip Technology Inc.

MCP23016
28-Lead Plastic Small Outline (SO) – Wide, 7.50 mm Body [SOIC]
Note:

For the most current package drawings, please see the Microchip Packaging Specification located at
http://www.microchip.com/packaging
D
N

E
E1
NOTE 1
1 2 3
b

e

h

α

A2

A

h
c

φ

L
A1

Units
Dimension Limits
Number of Pins

β

L1

MILLMETERS
MIN

N

NOM

MAX

28

Pitch

e

Overall Height

A



1.27 BSC


Molded Package Thickness

A2

2.05





Standoff §

A1

0.10



0.30

Overall Width

E

Molded Package Width

E1

7.50 BSC

Overall Length

D

2.65

10.30 BSC
17.90 BSC

Chamfer (optional)

h

0.25



0.75

Foot Length

L

0.40



1.27

Footprint

L1

Foot Angle Top

φ







Lead Thickness

c

0.18



0.33

Lead Width

b

0.31



0.51

Mold Draft Angle Top

α





15°

Mold Draft Angle Bottom

β





1.40 REF

15°
Notes:
1. Pin 1 visual index feature may vary, but must be located within the hatched area.
2. § Significant Characteristic.
3. Dimensions D and E1 do not include mold flash or protrusions. Mold flash or protrusions shall not exceed 0.15 mm per side.
4. Dimensioning and tolerancing per ASME Y14.5M.
BSC: Basic Dimension. Theoretically exact value shown without tolerances.
REF: Reference Dimension, usually without tolerance, for information purposes only.
Microchip Technology Drawing C04-052B

© 2007 Microchip Technology Inc.

DS20090C-page 29

MCP23016
28-Lead Plastic Shrink Small Outline (SS) – 5.30 mm Body [SSOP]
Note:

For the most current package drawings, please see the Microchip Packaging Specification located at
http://www.microchip.com/packaging
D
N

E
E1

1 2
NOTE 1

b
e

c
A2

A

φ

A1

L

L1
Units
Dimension Limits
Number of Pins

MILLIMETERS
MIN

N

Pitch

A

MAX

28

e

Overall Height

NOM
0.65 BSC





2.00
1.85

Molded Package Thickness

A2

1.65

1.75

Standoff

A1

0.05





Overall Width

E

7.40

7.80

8.20

Molded Package Width

E1

5.00

5.30

5.60

Overall Length

D

9.90

10.20

10.50

Foot Length

L

0.55

0.75

0.95

Footprint

L1

1.25 REF

Lead Thickness

c

0.09



Foot Angle

φ





0.25


Lead Width

b

0.22



0.38

Notes:
1. Pin 1 visual index feature may vary, but must be located within the hatched area.
2. Dimensions D and E1 do not include mold flash or protrusions. Mold flash or protrusions shall not exceed 0.20 mm per side.
3. Dimensioning and tolerancing per ASME Y14.5M.
BSC: Basic Dimension. Theoretically exact value shown without tolerances.
REF: Reference Dimension, usually without tolerance, for information purposes only.
Microchip Technology Drawing C04-073B

DS20090C-page 30

© 2007 Microchip Technology Inc.

MCP23016
28-Lead Plastic Quad Flat, No Lead Package (ML) – 6x6 mm Body [QFN]
with 0.55 mm Contact Length
Note:

For the most current package drawings, please see the Microchip Packaging Specification located at
http://www.microchip.com/packaging
D

D2

EXPOSED
PAD

e
E

b

E2
2

2

1

1

N

K
N

NOTE 1

L
BOTTOM VIEW

TOP VIEW

A

A3

A1
Units
Dimension Limits
Number of Pins

MILLIMETERS
MIN

N

NOM

MAX

28

Pitch

e

Overall Height

A

0.80

0.65 BSC
0.90

1.00

Standoff

A1

0.00

0.02

0.05

Contact Thickness

A3

0.20 REF

Overall Width

E

6.00 BSC

Exposed Pad Width

E2

Overall Length

D

Exposed Pad Length

3.65

3.70

4.20

6.00 BSC

D2

3.65

3.70

4.20

Contact Width

b

0.23

0.30

0.35

Contact Length

L

0.50

0.55

0.70

Contact-to-Exposed Pad
K
0.20

Notes:
1. Pin 1 visual index feature may vary, but must be located within the hatched area.
2. Package is saw singulated.
3. Dimensioning and tolerancing per ASME Y14.5M.
BSC: Basic Dimension. Theoretically exact value shown without tolerances.
REF: Reference Dimension, usually without tolerance, for information purposes only.



Microchip Technology Drawing C04-105B

© 2007 Microchip Technology Inc.

DS20090C-page 31

MCP23016
NOTES:

DS20090C-page 32

© 2007 Microchip Technology Inc.

MCP23016
APPENDIX A:

REVISION HISTORY

Revision A (December 2002)
Original data sheet for MCP23016 device.

Revision B (September 2003)
1.
2.

Addition of Output Low Voltage section to
Table 2-1 in Electrical Characteristics.
Addition of Output High Voltage section to
Table 2-1 in Electrical Characteristics.

Revision C (January 2007)
This revision includes updates to the packaging
diagrams.

© 2007 Microchip Technology Inc.

DS20090C-page 33

MCP23016
NOTES:

DS20090C-page 34

© 2007 Microchip Technology Inc.

MCP23016
PRODUCT IDENTIFICATION SYSTEM
To order or obtain information (e.g., on pricing or delivery) refer to the factory or the listed sales office.
PART NO.

X

/XX

Device

Temperature
Range

Package

Examples:

DSTEMP: 16-Bit I2C I/O Expander

Temperature
Range:

I = -40°C to +85°C

Package:

SP
SO
SS
ML

=
=
=
=

DSTEMP-I/P:

a)

DSTEMP-I/SO:

a)

DSTEMP-I/SS:

a)

Device:

a)

DSTEMP-I/ML:

Industrial Temperature,
PDIP package.
Industrial Temperature,
SOIC package.
Industrial Temperature,
SOIC package.
Industrial Temperature,
QFN package.

Plastic DIP (300 mil Body), 28-lead
Plastic SOIC, Wide (300 mil Body), 28-lead
Plastic SOIC, (209 mil, 5.30mm), 28-lead
Plastic Quad, Flat No Leads (QFN), 28-lead

© 2007 Microchip Technology Inc.

DS20090C-page 35

MCP23016
NOTES:

DS20090C-page 36

© 2007 Microchip Technology Inc.

Note the following details of the code protection feature on Microchip devices:


Microchip products meet the specification contained in their particular Microchip Data Sheet.



Microchip believes that its family of products is one of the most secure families of its kind on the market today, when used in the
intended manner and under normal conditions.



There are dishonest and possibly illegal methods used to breach the code protection feature. All of these methods, to our
knowledge, require using the Microchip products in a manner outside the operating specifications contained in Microchip’s Data
Sheets. Most likely, the person doing so is engaged in theft of intellectual property.



Microchip is willing to work with the customer who is concerned about the integrity of their code.



Neither Microchip nor any other semiconductor manufacturer can guarantee the security of their code. Code protection does not
mean that we are guaranteeing the product as “unbreakable.”

Code protection is constantly evolving. We at Microchip are committed to continuously improving the code protection features of our
products. Attempts to break Microchip’s code protection feature may be a violation of the Digital Millennium Copyright Act. If such acts
allow unauthorized access to your software or other copyrighted work, you may have a right to sue for relief under that Act.

Information contained in this publication regarding device
applications and the like is provided only for your convenience
and may be superseded by updates. It is your responsibility to
ensure that your application meets with your specifications.
MICROCHIP MAKES NO REPRESENTATIONS OR
WARRANTIES OF ANY KIND WHETHER EXPRESS OR
IMPLIED, WRITTEN OR ORAL, STATUTORY OR
OTHERWISE, RELATED TO THE INFORMATION,
INCLUDING BUT NOT LIMITED TO ITS CONDITION,
QUALITY, PERFORMANCE, MERCHANTABILITY OR
FITNESS FOR PURPOSE. Microchip disclaims all liability
arising from this information and its use. Use of Microchip
devices in life support and/or safety applications is entirely at
the buyer’s risk, and the buyer agrees to defend, indemnify and
hold harmless Microchip from any and all damages, claims,
suits, or expenses resulting from such use. No licenses are
conveyed, implicitly or otherwise, under any Microchip
intellectual property rights.

Trademarks
The Microchip name and logo, the Microchip logo, Accuron,
dsPIC, KEELOQ, microID, MPLAB, PIC, PICmicro, PICSTART,
PRO MATE, PowerSmart, rfPIC, and SmartShunt are
registered trademarks of Microchip Technology Incorporated
in the U.S.A. and other countries.
AmpLab, FilterLab, Migratable Memory, MXDEV, MXLAB,
SEEVAL, SmartSensor and The Embedded Control Solutions
Company are registered trademarks of Microchip Technology
Incorporated in the U.S.A.
Analog-for-the-Digital Age, Application Maestro, CodeGuard,
dsPICDEM, dsPICDEM.net, dsPICworks, ECAN,
ECONOMONITOR, FanSense, FlexROM, fuzzyLAB,
In-Circuit Serial Programming, ICSP, ICEPIC, Linear Active
Thermistor, Mindi, MiWi, MPASM, MPLIB, MPLINK, PICkit,
PICDEM, PICDEM.net, PICLAB, PICtail, PowerCal,
PowerInfo, PowerMate, PowerTool, REAL ICE, rfLAB,
rfPICDEM, Select Mode, Smart Serial, SmartTel, Total
Endurance, UNI/O, WiperLock and ZENA are trademarks of
Microchip Technology Incorporated in the U.S.A. and other
countries.
SQTP is a service mark of Microchip Technology Incorporated
in the U.S.A.
All other trademarks mentioned herein are property of their
respective companies.
© 2007, Microchip Technology Incorporated, Printed in the
U.S.A., All Rights Reserved.
Printed on recycled paper.

Microchip received ISO/TS-16949:2002 certification for its worldwide
headquarters, design and wafer fabrication facilities in Chandler and
Tempe, Arizona, Gresham, Oregon and Mountain View, California. The
Company’s quality system processes and procedures are for its PIC®
MCUs and dsPIC DSCs, KEELOQ® code hopping devices, Serial
EEPROMs, microperipherals, nonvolatile memory and analog
products. In addition, Microchip’s quality system for the design and
manufacture of development systems is ISO 9001:2000 certified.

© 2007 Microchip Technology Inc.

DS20090C-page 37

WORLDWIDE SALES AND SERVICE
AMERICAS

ASIA/PACIFIC

ASIA/PACIFIC

EUROPE

Corporate Office
2355 West Chandler Blvd.
Chandler, AZ 85224-6199
Tel: 480-792-7200
Fax: 480-792-7277
Technical Support:
http://support.microchip.com
Web Address:
www.microchip.com

Asia Pacific Office
Suites 3707-14, 37th Floor
Tower 6, The Gateway
Habour City, Kowloon
Hong Kong
Tel: 852-2401-1200
Fax: 852-2401-3431

India - Bangalore
Tel: 91-80-4182-8400
Fax: 91-80-4182-8422
India - New Delhi
Tel: 91-11-4160-8631
Fax: 91-11-4160-8632

Austria - Wels
Tel: 43-7242-2244-39
Fax: 43-7242-2244-393
Denmark - Copenhagen
Tel: 45-4450-2828
Fax: 45-4485-2829

India - Pune
Tel: 91-20-2566-1512
Fax: 91-20-2566-1513

France - Paris
Tel: 33-1-69-53-63-20
Fax: 33-1-69-30-90-79

Japan - Yokohama
Tel: 81-45-471- 6166
Fax: 81-45-471-6122

Germany - Munich
Tel: 49-89-627-144-0
Fax: 49-89-627-144-44

Atlanta
Duluth, GA
Tel: 678-957-9614
Fax: 678-957-1455
Boston
Westborough, MA
Tel: 774-760-0087
Fax: 774-760-0088
Chicago
Itasca, IL
Tel: 630-285-0071
Fax: 630-285-0075
Dallas
Addison, TX
Tel: 972-818-7423
Fax: 972-818-2924
Detroit
Farmington Hills, MI
Tel: 248-538-2250
Fax: 248-538-2260
Kokomo
Kokomo, IN
Tel: 765-864-8360
Fax: 765-864-8387
Los Angeles
Mission Viejo, CA
Tel: 949-462-9523
Fax: 949-462-9608
Santa Clara
Santa Clara, CA
Tel: 408-961-6444
Fax: 408-961-6445
Toronto
Mississauga, Ontario,
Canada
Tel: 905-673-0699
Fax: 905-673-6509

Australia - Sydney
Tel: 61-2-9868-6733
Fax: 61-2-9868-6755
China - Beijing
Tel: 86-10-8528-2100
Fax: 86-10-8528-2104
China - Chengdu
Tel: 86-28-8665-5511
Fax: 86-28-8665-7889

Korea - Gumi
Tel: 82-54-473-4301
Fax: 82-54-473-4302

China - Fuzhou
Tel: 86-591-8750-3506
Fax: 86-591-8750-3521

Korea - Seoul
Tel: 82-2-554-7200
Fax: 82-2-558-5932 or
82-2-558-5934

China - Hong Kong SAR
Tel: 852-2401-1200
Fax: 852-2401-3431

Malaysia - Penang
Tel: 60-4-646-8870
Fax: 60-4-646-5086

China - Qingdao
Tel: 86-532-8502-7355
Fax: 86-532-8502-7205

Philippines - Manila
Tel: 63-2-634-9065
Fax: 63-2-634-9069

China - Shanghai
Tel: 86-21-5407-5533
Fax: 86-21-5407-5066

Taiwan - Hsin Chu
Tel: 886-3-572-9526
Fax: 886-3-572-6459

China - Shenzhen
Tel: 86-755-8203-2660
Fax: 86-755-8203-1760

Taiwan - Kaohsiung
Tel: 886-7-536-4818
Fax: 886-7-536-4803

China - Shunde
Tel: 86-757-2839-5507
Fax: 86-757-2839-5571

Taiwan - Taipei
Tel: 886-2-2500-6610
Fax: 886-2-2508-0102

China - Wuhan
Tel: 86-27-5980-5300
Fax: 86-27-5980-5118

Netherlands - Drunen
Tel: 31-416-690399
Fax: 31-416-690340

Singapore
Tel: 65-6334-8870
Fax: 65-6334-8850

China - Shenyang
Tel: 86-24-2334-2829
Fax: 86-24-2334-2393

Italy - Milan
Tel: 39-0331-742611
Fax: 39-0331-466781

Thailand - Bangkok
Tel: 66-2-694-1351
Fax: 66-2-694-1350

Spain - Madrid
Tel: 34-91-708-08-90
Fax: 34-91-708-08-91
UK - Wokingham
Tel: 44-118-921-5869
Fax: 44-118-921-5820

China - Xian
Tel: 86-29-8833-7250
Fax: 86-29-8833-7256

12/08/06

DS20090C-page 38

© 2007 Microchip Technology Inc.