- Co to jest protokół komunikacyjny I2C?
- Jak działa komunikacja I2C?
- Gdzie używać komunikacji I2C?
- I2C na Nuvoton N76E003 - wymagania sprzętowe
- Połączenie AT24LC64 z Nuvoton N76E003 - schemat obwodu
- Piny I2C w Nuvoton N76E003
- Komunikacja I2C w N76E003
- Programowanie N76E003 do komunikacji I2C
- Flashowanie kodu i wyjścia
W rozległym systemie aplikacji wbudowanych żaden mikrokontroler nie jest w stanie samodzielnie wykonać wszystkich czynności. Na pewnym etapie musi komunikować się z innymi urządzeniami, aby udostępniać informacje, istnieje wiele różnych typów protokołów komunikacyjnych do udostępniania tych informacji, ale najczęściej używane są USART, IIC, SPI i CAN. Każdy protokół komunikacyjny ma swoje zalety i wady. Na razie skupmy się na części IIC, ponieważ tego nauczymy się w tym samouczku. Jeśli jesteś tu nowy, zapoznaj się z samouczkami Nuvoton, w których omówiliśmy każde urządzenie peryferyjne mikrokontrolera N76E003 z bardzo podstawowego samouczka wprowadzającego. Jeśli chcesz dowiedzieć się, jak używać I2C z innymi mikrokontrolerami, możesz sprawdzić poniższe linki.
- Jak korzystać z I2C w Arduino: Komunikacja między dwoma płytami Arduino
- Komunikacja I2C z mikrokontrolerem PIC PIC16F877
- Połączenie wyświetlacza LCD 16X2 z ESP32 za pomocą I2C
- Komunikacja I2C z MSP430 Launchpad
- Łączenie LCD z NodeMCU bez użycia I2C
- Jak obsługiwać wiele komunikacji (I2C SPI UART) w jednym programie Arduino
I2C to ważny protokół komunikacyjny opracowany przez firmę Philips (obecnie NXP). Korzystając z tego protokołu I2C, MCU można połączyć z wieloma urządzeniami i rozpocząć komunikację. I2C działa tylko z dwoma przewodami, a mianowicie SDA i SCL. Gdzie SDA to Serial data, a SCL to Serial Clock. Jednak te dwa piny wymagają rezystorów podciągających do poziomu napięcia VCC, a przy odpowiednim rezystorze podwyższającym magistrala może obsługiwać 127 urządzeń o unikalnym adresie.
Co to jest protokół komunikacyjny I2C?
Termin IIC oznacza „ Inter Integrated Circuits ”. Zwykle jest oznaczany jako I2C lub I do kwadratu C lub nawet jako protokół interfejsu 2-przewodowego (TWI) w niektórych miejscach, ale wszystko oznacza to samo. I2C to synchroniczny protokół komunikacyjny, co oznacza, że oba urządzenia, które udostępniają informacje, muszą dzielić wspólny sygnał zegarowy. Ma tylko dwa przewody do udostępniania informacji, z których jeden służy do sygnału zegara, a drugi do wysyłania i odbierania danych.
Jak działa komunikacja I2C?
Komunikację I2C po raz pierwszy wprowadził Phillips. Jak wspomniano wcześniej, ma dwa przewody, te dwa przewody zostaną połączone między dwoma urządzeniami. W tym przypadku jedno urządzenie nosi nazwę master, a drugie urządzenie slave. Komunikacja powinna i zawsze będzie zachodzić między dwoma, Master i Slave. Zaletą komunikacji I2C jest to, że więcej niż jeden slave może być podłączony do Master.
Cała komunikacja odbywa się za pośrednictwem tych dwóch przewodów, mianowicie zegara szeregowego (SCL) i danych szeregowych (SDA).
Zegar szeregowy (SCL): dzieli sygnał zegara generowany przez urządzenie nadrzędne z urządzeniem podrzędnym
Serial Data (SDA): Wysyła dane do i pomiędzy Master a Slave.
W dowolnym momencie tylko kapitan będzie mógł zainicjować komunikację. Ponieważ w magistrali jest więcej niż jeden slave, master musi odnosić się do każdego slave'a za pomocą innego adresu. Po zaadresowaniu tylko maść z tym konkretnym adresem odpowie z informacją, podczas gdy inni milczą. W ten sposób możemy używać tej samej magistrali do komunikacji z wieloma urządzeniami.
Gdzie używać komunikacji I2C?
Komunikacja I2C jest używana tylko do komunikacji na krótkie odległości. Z pewnością jest do pewnego stopnia niezawodny, ponieważ ma zsynchronizowany impuls zegara, aby uczynić go inteligentnym. Protokół ten jest używany głównie do komunikacji z czujnikiem lub innymi urządzeniami, które muszą przesyłać informacje do mastera. Jest to bardzo przydatne, gdy mikrokontroler musi komunikować się z wieloma innymi modułami slave przy użyciu minimum samych przewodów. Jeśli szukasz komunikacji dalekiego zasięgu, powinieneś wypróbować RS232, a jeśli szukasz bardziej niezawodnej komunikacji, powinieneś wypróbować protokół SPI.
I2C na Nuvoton N76E003 - wymagania sprzętowe
Ponieważ wymaganiem tego projektu jest nauczenie się komunikacji I2C za pomocą N76E003, użyjemy pamięci EEPROM, która będzie połączona linią danych I2C. Będziemy przechowywać niektóre dane w pamięci EEPROM, a także je odczytać i wyświetlić na ekranie UART.
Ponieważ przechowywana wartość zostanie wydrukowana w UART, wymagany jest dowolny rodzaj konwertera USB na UART. Możesz również zapoznać się z samouczkiem dotyczącym UART z Nuvoton, jeśli jesteś nowy w komunikacji UART na N76E003. W naszej aplikacji wykorzystamy konwerter CP2102 UART na USB. Oprócz powyższego wymagamy również następujących komponentów:
- EEPROM 24C02
- 2 sztuki rezystorów 4.7k
Nie wspominając o tym, że oprócz powyższych komponentów potrzebujemy płyty rozwojowej opartej na mikrokontrolerze N76E003, a także programatora Nu-Link. Dodatkowo do podłączenia wszystkich komponentów wymagane są również przewody do styków prototypowych i przyłącza.
Połączenie AT24LC64 z Nuvoton N76E003 - schemat obwodu
Jak widać na poniższym schemacie, EEPROM jest podłączony w linii I2C wraz z dwoma rezystorami podciągającymi. Po lewej stronie pokazane jest połączenie interfejsu programowania.
Użyłem płytki prototypowej dla układu scalonego AT24LC64 i podłączyłem go do płytki programatora nuvoton za pomocą przewodów połączeniowych. Moja konfiguracja sprzętu wraz z programatorem nu-ink jest pokazana poniżej.
Piny I2C w Nuvoton N76E003
Schemat pinów N76E003 można zobaczyć na poniższym obrazku-
Jak widać, każdy pin ma inne specyfikacje, a każdy pin może być używany do wielu celów. Jednak pin 1.4 jest używany jako pin I2C SDA, utraci PWM i inne funkcje. Nie stanowi to jednak problemu, ponieważ w tym projekcie nie jest wymagana inna funkcjonalność. To samo stanie się z P1.3 to pin SCL I2C.
Ponieważ piny I2C działają jako GPIO, należy je skonfigurować. Wszystkie piny GPIO można skonfigurować w niżej opisanym trybie.
Zgodnie z arkuszem danych, PxM1.n i PxM2. n to dwa rejestry, które są używane do określenia operacji sterowania portem I / O. W arkuszu danych podano, że aby korzystać z funkcji I2C, tryby I / O muszą być używane jako Open-Drain dla komunikacji związanej z I2C.
Komunikacja I2C w N76E003
Urządzenie peryferyjne I2C jest ważną rzeczą dla każdego mikrokontrolera obsługującego funkcje I2C. Wiele typów różnych mikrokontrolerów ma wbudowane urządzenie peryferyjne I2C. Jednak w niektórych przypadkach I2C można skonfigurować ręcznie za pomocą sterowania programowego, gdy obsługa sprzętu związana z I2C nie jest dostępna (na przykład wiele mikrokontrolerów 8051). Jednak nuvoton N76E003 jest wyposażony w obsługę urządzeń peryferyjnych I2C.
M76E003 obsługuje cztery typy operacji w trybach I2C - nadajnik główny, odbiornik główny, nadajnik podrzędny i odbiornik podrzędny. Obsługuje również standardowe (100 kb / s) i szybkie (do 400 kb / s) prędkości dla linii I2C. I2C działa z kilkoma ogólnymi regułami w liniach sygnałowych SCL i SDA.
Warunki rozpoczęcia i zatrzymania:
To ważna rzecz w komunikacji I2C. Gdy dane są przesyłane do linii I2C, zaczyna się od warunku początkowego i kończy się warunkiem zatrzymania.
Warunkiem początkowym jest przejście z wysokiego na niski w SDA, gdy linia SCL jest wysoka, a warunek zatrzymania to przejście z niskiego na wysoki na SDA, gdy linia SCL jest wysoka. Te dwa warunki są generowane przez jednostkę główną (MCU lub cokolwiek, co steruje innymi urządzeniami podrzędnymi). Linia autobusowa pozostaje zajęta w tym stanie, kiedy inicjowany jest warunek startu i pozostaje ponownie wolna, gdy zostanie zainicjowany warunek zatrzymania.
Warunek Start i Stop jest doskonale przedstawiony w perspektywie sygnału w arkuszu danych N76E003-
Adres 7-bitowy z formatem danych:
N76E003 obsługuje 7-bitowy adres i format danych. Po zainicjowaniu warunku startowego, urządzenie główne musi wysłać dane do linii I2C. Pierwsze dane są ważne. Jeśli dane te nie zostaną prawidłowo utworzone lub przesłane, podłączone urządzenie nie zostanie zidentyfikowane i nie będzie można nawiązać dalszej komunikacji.
Dane składają się z 7-bitowego adresu slave, oznaczonego jako SLA. Ten 7-bitowy adres musi być unikalny dla każdego urządzenia, jeśli do magistrali podłączonych jest wiele urządzeń. Po 7-bitowym adresie ósmy bit jest bitem kierunku danych. Oznacza to, że w zależności od ósmego bitu, master wysyła informację do urządzenia slave o tym, czy dane będą zapisywane w urządzeniu slave, czy też będą odczytywane z urządzenia slave. Ósmy bit to bit R / W określany jako powiadamiający o odczycie lub zapisie. Jak wszyscy wiemy, 8-bitowe informacje mogą mieć 128 typów, obsługując w ten sposób 128 urządzeń, ale I2C obsługuje 127 typów urządzeń na tej samej magistrali, ale nie 128. Ponieważ adres 0x00 jest zarezerwowanym adresem, który jest nazywany ogólnym adresem wywołania. Jeśli master chce wysłać informacje do wszystkich urządzeń,będzie adresować 0x00 i każde urządzenie będzie odtwarzać w ten sam sposób, jak w przypadku indywidualnych konfiguracji oprogramowania.
Zatem transmisja danych wygląda jak poniżej-
Uznać:
Na powyższym obrazie adresu danych, dziewiąty bit, po którym następuje bit R / W, nazywany jest bitem potwierdzenia. Jest to ważne, ponieważ używając tego bitu, master lub slave odpowiada na nadajnik danych, ciągnąc linię SDA w dół. Aby otrzymać bit potwierdzenia, nadajnik musi zwolnić linię SDA.
Programowanie N76E003 do komunikacji I2C
Kompletny program użyty w tym samouczku można znaleźć na dole tej strony. Wyjaśnienie ważnych segmentów w kodzie jest następujące:
Ustaw Piny jako Otwarty Dren i skonfiguruj je dla I2C:
Zacznijmy od sekcji pinów I2C. Jak opisano wcześniej, porty I2C SCL i SDA należy skonfigurować i ustawić jako konfigurację otwartego drenu. Aby to zrobić, jesteśmy za pomocą pliku nagłówka I2C.h wraz z plikiem źródłowym I2C.c . Fragment kodu wygląda następująco:
zrobić {P13_OpenDrain_Mode; P14_OpenDrain_Mode; clr_I2CPX;} podczas (0)
Powyższy kod ustawia P13 i P14 jako styk Open-Drain, a clr_I2CPX służy do wyboru P13 i P14 jako pin SCL na P1.3 i styk SDA na P1.4.
Ten I2CPX jest zerowym bitem rejestru sterującego I2C I2CON. Jeśli to I2C_PX jest ustawione na 1, piny są zmieniane na P0.2 jako SCL i P1.6 jako SDA. Jednak użyjemy P13 i P14. Alternatywne piny nie są tutaj używane.
Rejestr sterowania I2C I2CON:
Rejestr sterujący I2C I2CON jest używany do sterowania operacjami I2C. Pierwszy bit to bit wyboru pinów I2C. Ustawienie 0 konfiguruje pin I2C jako P13 i P14.
Bit AA jest flagą potwierdzenia potwierdzenia, jeśli flaga AA jest ustawiona, ACK zostanie zwrócony podczas impulsu zegara potwierdzenia linii SCL. Jeśli jest wyczyszczone, NACK (wysoki poziom na SDA) zostanie zwrócony podczas potwierdzonego impulsu zegarowego linii SCL.
Następny bit to SI, który jest przerwaniem stanu I2C. Jeśli włączone jest przerwanie stanu I2C, użytkownik powinien sprawdzić rejestr I2STAT, aby określić, który krok został wykonany i powinien wykonać akcję.
STO to flaga STOP ustawiana w trybie master. STO jest automatycznie kasowane sprzętowo po wykryciu stanu STOP .
Następny bit to bit STA. Jeśli ta flaga jest ustawiona, I2C generuje warunek START, jeśli magistrala jest wolna. Jeśli magistrala jest zajęta, I2C czeka na stan STOP i generuje następujący po nim stan START. Jeżeli STA jest ustawiona, gdy I2C jest już w trybie master i jeden lub więcej bajtów zostało przesłanych lub odebranych, I2C generuje powtarzający się warunek START. STA musi zostać wyczyszczone ręcznie przez oprogramowanie.
Ostatni, I2CEN jest bitem włączania lub wyłączania magistrali I2C.
EEPROM 24C02:
A teraz dochodzimy do 24C02. Pakiet obsługi płyty N76E003 ma kod I2C dla 24LC64 i może być łatwo modyfikowany. Jednak użyjemy prostej metody, aby zrozumieć funkcję I2C.
Jeśli ktoś chce korzystać ze szczegółowego połączenia z EEPROM 24C02, może użyć programu EEPROM w BSP.
Podłączymy 24C02 tylko w I2C, gdzie N76E003 będzie nadrzędnym, a EEPROM będzie podrzędnym. W ten sposób zapiszemy wszelkie dane na adres EEPROM i odczytamy to samo.
Pinout 24C02 EEPROM pokazano poniżej:
A0, A1 i A2 to trzy kołki wyboru adresu. Kołki WP są kołkami chroniącymi przed zapisem i muszą być połączone z VSS, aby umożliwić zapis w EEPROM.
Funkcjonalność zapisu bajtów jest pokazana na poniższym obrazku-
Pełny cykl zapisu odbywa się z bitem startowym. Następnie należy przesłać bajt sterujący. W bajcie kontrolnym wymagane są następujące rzeczy:
Po bicie startowym zawiera adres slave. 1010 to statyczny, a A0, A1 i A2 to adresy oparte na połączeniu sprzętowym. Jeśli trzy piny są połączone z zasilaniem GND lub VSS, zostanie odczytane jako 0. W przeciwnym razie, jeśli połączone z VCC, zostanie odczytane jako 1. W naszym przypadku wszystkie A0, A1 i A2 są połączone z VSS. Zatem wszystko to będzie równe 0.
Wydatki na warunek odczytu lub zapisu. Wartość adresu z bitem odczytu lub zapisu będzie wynosić - 0xA0 dla zapisu i 0xA1 dla odczytu. Następny jest bit potwierdzenia, a następnie 8-bitowy adres zostanie przesłany, gdzie dane muszą zostać zapisane, a na końcu dane, które będą przechowywane w odpowiedniej lokalizacji. Te czynności są wykonywane krok po kroku w funkcji głównej.
Główna funkcja i pętla While:
void main (void) {char c = 0x00; InitialUART0_Timer3 (115200); TI = 1; // Ważne, użyj funkcji prinft, musisz ustawić TI = 1; I2C_init (); while (1) {EEPROM_write (1,0x55); c = EEPROM_read (1); printf ("\ n Odczytana wartość to% x", c & 0xff); }; }
Główna funkcja jest prosta, polega na ciągłym zapisywaniu wartości do pamięci EEPROM pod adresem 1 i odczytywaniu danych. Dane są następnie drukowane za pomocą funkcji printf. Printf wypisuje wartość w postaci szesnastkowej.
Funkcja zapisu EEPROM składa się z następujących rzeczy, które zostały opisane w sekcji EEPROM:
void EEPROM_write (adres bez znaku, wartość bez znaku) {I2C_start (); I2C_write (0xA0); I2C_write (adres); I2C_write (wartość); I2C_stop (); }
Funkcja startu I2C składa się z następujących elementów:
void I2C_start (void) {podpisany int czas = limit czasu; set_STA; clr_SI; while ((SI == 0) && (czas> 0)) {czas--; }; }
W tej funkcji sprawdzany jest stan SI wraz z predefiniowanym limitem czasu (zdefiniowanym w I2C.h, gdzie wstępnie zdefiniowany czas jest ustawiony na 1000). Funkcja startu zaczyna się od ustawienia STA i wyczyszczenia SI.
void I2C_stop (void) {podpisany int czas = limit czasu; clr_SI; set_STO; while ((STO == 1) && (czas> 0)) {czas--; }; }
Używana jest taka sama jak funkcja Start, stop. Funkcja stop jest inicjowana przez ustawienie STO, po którym następuje wyczyszczenie SI. Poniżej funkcja znajduje się funkcja odczytu I2C-
unsigned char I2C_read (unsigned char ac_mode) {podpisany int czas = limit czasu; wartość znaku bez znaku = 0x00; set_AA; clr_SI; while ((SI == 0) && (t> 0)) {czas--; }; wartość = I2DAT; if (ACK_mode == I2C_NACK) {t = timeout_count; clr_AA; clr_SI; while ((SI == 0) && (t> 0)) {czas--; }; } zwracana wartość; }
Ack_mode i I2C_NACK , jak zdefiniowano w pliku nagłówka I2C jako 0 i 1, odpowiednio.
Podobnie tworzona jest funkcja zapisu -
void I2C_write (wartość bez znaku) {czas int ze znakiem = limit czasu; I2DAT = wartość; clr_STA; clr_SI; while ((SI == 0) && (czas> 0)) {czas--; }; }
Flashowanie kodu i wyjścia
Kod zwrócił 0 ostrzeżeń i 0 błędów i został sflashowany przy użyciu domyślnej metody flashowania przez Keil. Jeśli jesteś nowy, zapoznaj się z samouczkiem rozpoczynającym pracę z nuvoton, aby zrozumieć, jak załadować kod. Informacje dotyczące kompilacji kodu można znaleźć poniżej.
Buduj cel „I2C_EEPROM” kompilując I2C_EEPROM.c… kompilując I2C.c… łącząc… Rozmiar programu: data = 59.2 xdata = 0 kod = 2409 tworzenie pliku szesnastkowego z ". \ Output \ I2C_EEPROM"… ". \ Output \ I2C_EEPROM "- 0 błędów, 0 ostrzeżeń. Czas kompilacji, który upłynął: 00:00:04 Podsumowanie kompilacji zbiorczej: 1 powiodło się, 0 nie powiodło się, 0 pominięto - Czas, który upłynął: 00:00:04
Sprzęt jest konfigurowany na płytce prototypowej i działa zgodnie z oczekiwaniami. Jak widać na poniższym obrazku, byliśmy w stanie zapisać wartość do EEPROM i odczytać ją z pamięci i wyświetlić na monitorze szeregowym.
Obejrzyj poniższy film, aby uzyskać pełną demonstrację działania płyty dla tego kodu. Mam nadzieję, że spodobał Ci się samouczek i nauczyłeś się czegoś przydatnego, jeśli masz jakieś pytania, zostaw je w sekcji komentarzy poniżej. Możesz również skorzystać z naszych forów, aby zadać inne pytania techniczne.