- Що таке протокол зв'язку I2C?
- Як працює I2C Communication?
- Де використовувати зв'язок I2C?
- I2C з PIC16F877a за допомогою компілятора XC8
- Програмування за допомогою заголовкових файлів I2C:
- Моделювання протея:
Мікроконтролери PIC - це потужна платформа, що надається мікрочіпом для вбудованих проектів, завдяки своїй універсальності вона знаходить шляхи для багатьох застосувань, і фаза все ще триває. Якщо ви дотримувались наших навчальних посібників з PIC, тоді б ви помітили, що ми вже охопили широкий спектр підручників з мікроконтролера PIC, починаючи з самих основ. Відтепер ми розглянули основи, за якими ми можемо потрапити в такі цікаві речі, як комунікаційний портал.
У великій системі вбудованих програм жоден мікроконтролер не може виконувати всі дії самостійно. На певному етапі часу йому доводиться спілкуватися з іншими пристроями для обміну інформацією, існує багато різних типів протоколів зв'язку для обміну цією інформацією, але найбільш використовуваними є USART, IIC, SPI та CAN. Кожен протокол зв'язку має свої переваги та недоліки. Поки зосередимося на частині IIC, оскільки саме про це ми будемо вчитися в цьому посібнику.
Що таке протокол зв'язку I2C?
Термін IIC розшифровується як “ Інтегральні мікросхеми ”. Зазвичай це позначається як I2C, або я в квадраті C, або навіть як 2-провідний інтерфейсний протокол (TWI) в деяких місцях, але все це означає одне і те ж. I2C - це протокол синхронного зв'язку, що означає, що обидва пристрої, які обмінюються інформацією, повинні мати спільний тактовий сигнал. Він має лише два дроти для обміну інформацією, з яких один використовується для сигналу крана, а інший - для передачі та прийому даних.
Як працює I2C Communication?
Вперше зв'язок I2C був представлений Філіпсом. Як вже було сказано раніше, він має два дроти, ці два дроти будуть з'єднані між собою двома пристроями. Тут один пристрій називається ведучим, а інший пристрій - веденим. Спілкування повинно і завжди відбуватиметься між двома Володарем і Рабом. Перевага зв'язку I2C полягає в тому, що до ведучого може бути підключено більше одного веденого пристрою.
Повна комунікація відбувається за допомогою цих двох проводів, а саме: послідовного годинника (SCL) та послідовних даних (SDA).
Серійний годинник (SCL): Поділяє тактовий сигнал, сформований ведучим, із веденим пристроєм
Серійні дані (SDA): Надсилає дані до головного та веденого пристроїв та назад.
У будь-який момент часу тільки майстер зможе ініціювати спілкування. Оскільки в шині більше одного веденого, ведучий повинен посилатися на кожного веденого, використовуючи іншу адресу. У разі звернення лише особа із зазначеною адресою відповідає з інформацією, тоді як інші продовжують виходити. Таким чином ми можемо використовувати одну і ту ж шину для зв'язку з кількома пристроями.
Де використовувати зв'язок I2C?
Зв'язок I2C використовується лише для зв'язку на короткі відстані. Це, безумовно, надійно до певної міри, оскільки він має синхронізований тактовий імпульс, щоб зробити його розумним. Цей протокол в основному використовується для зв'язку з датчиком або іншими пристроями, які повинні надсилати інформацію майстру. Дуже зручно, коли мікроконтролер повинен взаємодіяти з багатьма іншими підлеглими модулями, використовуючи мінімум лише дроти. Якщо ви шукаєте зв'язку на великі відстані, вам слід спробувати RS232, а якщо ви шукаєте більш надійний зв'язок, спробуйте протокол SPI.
I2C з PIC16F877a за допомогою компілятора XC8
Досить вступу, давайте зайдемо в нього і дізнаємося, як ми можемо використовувати мікроконтролер для здійснення зв'язку I2C. Перш ніж ми почнемо чітко заявляти, що в цьому підручнику йдеться лише про I2C у PIC16F877a із використанням компілятора XC8, процес буде однаковим для інших мікроконтролерів, але можуть знадобитися незначні зміни. Також пам’ятайте, що для таких просунутих мікроконтролерів, як серія PIC18F, сам компілятор може мати вбудовану бібліотеку для використання функцій I2C, але для PIC16F877A нічого подібного не існує, тому давайте створимо його самостійно. Пояснена тут бібліотека буде надана у вигляді заголовка для завантаження внизу, який може бути використаний для PIC16F877A для зв'язку з іншими пристроями I2C.
Як завжди найкращим місцем для початку чого-небудь є наш технічний паспорт. Шукайте детальну інформацію про I2C у таблиці та перевірте, які регістри потрібно налаштувати. Я не збираюся детально пояснювати, оскільки в таблиці даних це вже зроблено за вас. Далі нижче я розповім про різні функції, присутні у файлі заголовка, та їх відповідальність у програмі.
void I2C_Initialize ()
Функція ініціалізації використовується, щоб повідомити мікроконтролеру, що ми будемо використовувати протокол I2C. Це можна зробити, встановивши необхідні біти для реєстру SSPCON та SSPCON2. Першим кроком було б оголосити виводи IIC як вхідні висновки, тут виводи RC3 та RC4 слід використовувати для зв'язку I2C, тому ми оголошуємо їх як вхідні висновки. Далі слід встановити SSPCON та SSPCON2, які є регістрами управління MSSP. Ми працюємо з PIC в основному режимі IIC з тактовою частотою FOSC / (4 * (SSPADD + 1)). Зверніться до номерів сторінок таблиці, згаданих у рядках коментарів нижче, щоб зрозуміти, чому саме цей регістр встановлений таким чином.
Отже, далі ми повинні встановити тактову частоту, тактова частота для різних додатків може змінюватися, отже, ми отримуємо вибір від користувача через змінну feq_k і використовуємо її у наших формулах для встановлення реєстру SSPADD.
void I2C_Initialize (const unsigned long feq_K) // Почати IIC як master { TRISC3 = 1; TRISC4 = 1; // Встановити шпильки SDA та SCL як вхідні штифти SSPCON = 0b00101000; // pg84 / 234 SSPCON2 = 0b00000000; // pg85 / 234 SSPADD = (_XTAL_FREQ / (4 * feq_K * 100)) - 1; // Встановлення тактової частоти pg99 / 234 SSPSTAT = 0b00000000; // pg83 / 234 }
Порожнеча I2C_Hold ()
Наступною важливою функцією є функція I2C_hold, яка використовується для утримання виконання пристрою до завершення поточної операції I2C. Перш ніж розпочати будь-яку нову операцію, нам доведеться перевірити, чи слід проводити операції I2C. Це можна зробити, перевіривши реєстр SSPSTAT та SSPCON2. SSPSTAT містить інформацію про стан шини I2C.
Програма може здатися дещо складною, оскільки вона включає оператори "і" та "або". Коли ти розбиваєш його як
SSPSTAT & 0b00000100 SSPCON2 & 0b00011111
U
Це означає, що ми переконуємось, що 2- й біт на SSPSTAT дорівнює нулю, і аналогічним чином біти від 0 до 4 дорівнюють нулю на SSPCON2. Потім ми об'єднуємо все це, щоб перевірити, що результат дорівнює нулю. Якщо результат дорівнює нулю, то програма буде тривати, якщо не буде тримати там до тих пір, поки він отримує нуль, так як він використовується в той час як цикл.
void I2C_Hold () { while ((SSPCON2 & 0b00011111) - (SSPSTAT & 0b00000100)); // перевірити це на регістри, щоб переконатися, що IIC не виконується }
Порожнеча I2C_Begin () та порожнеча I2C_End ()
Кожного разу, коли ми пишемо або читаємо будь-які дані за допомогою шини I2C, ми повинні починати та закінчувати з'єднання I2C. Щоб розпочати зв’язок I2C, ми повинні встановити біт SEN, а щоб закінчити спілкування - біт стану PEN. Перш ніж перемикати будь-який з цих бітів, ми також повинні перевірити, чи зайнята шина I2C, використовуючи функцію I2C_Hold, як обговорювалося вище.
void I2C_Begin () { I2C_Hold (); // Утримуємо програму I2C зайнято SEN = 1; // Початок IIC pg85 / 234 } void I2C_End () { I2C_Hold (); // Утримуємо програму I2C зайнято PEN = 1; // Кінець IIC pg85 / 234 }
Порожнеча I2C_Write ()
Функція запису використовується для передачі будь-яких даних з головного модуля в модуль salve. Ця функція, як правило, використовується після функції початку I2C, а потім - функції закінчення I2C. Дані, які потрібно записати на шину IIC, передаються через дані змінної. Потім ці дані завантажуються в буферний регістр SSPBUF, щоб відправити їх через шину I2C.
Зазвичай перед написанням даних буде записана адреса, тому вам доведеться використовувати функцію запису двічі, один раз для встановлення адреси, а інший раз для надсилання фактичних даних.
void I2C_Write (дані без підпису) { I2C_Hold (); // Утримуємо програму I2C зайнято SSPBUF = дані; // pg82 / 234 }
непідписаний короткий I2C_Read ()
Кінцевою функцією, про яку ми повинні знати, є функція I2C_Read . Ця функція використовується для зчитування даних, які зараз знаходяться на шині I2C. Він використовується після запиту веденого, щоб записати якесь значення на шину. Отримане значення буде в SSPBUF, ми можемо передати це значення в будь-яку змінну для нашої операції.
Під час зв'язку I2C ведений після надсилання даних, запитаних Master, надішле інший біт, який є бітом підтвердження, цей біт також повинен бути перевірений майстром, щоб переконатися, що зв'язок був успішним. Після перевірки біта ACKDT на підтвердження його слід увімкнути, встановивши біт ACKEN.
непідписаний короткий I2C_Read (непідписаний короткий ack) { неподписаний короткий вхідний; I2C_Hold (); RCEN = 1; I2C_Hold (); вхідні = SSPBUF; // отримуємо дані, збережені в SSPBUF I2C_Hold (); ACKDT = (ack)? 0: 1; // перевіряємо, чи отримав біт ack ACKEN = 1; // стор. 85/234 повернути вхідне; }
Це все, цих функцій має бути достатньо для налаштування зв'язку I2C та запису або читання даних з пристрою. Також зауважте, що існує безліч інших функціональних можливостей, які може виконувати зв’язок I2C, але для простоти ми їх тут не обговорюємо. Ви завжди можете звернутися до таблиці, щоб дізнатись про повну роботу
Повний код із заголовком для зв'язку PIC16F877A I2C можна завантажити за посиланням.
Програмування за допомогою заголовкових файлів I2C:
Тепер, коли ми дізналися, як працює зв'язок I2C і як ми можемо використовувати заголовочний файл, створений для нього, давайте створимо просту програму, в якій ми будемо використовувати заголовочний файл і записувати деякі значення в рядки I2C. Потім ми змоделюємо цю програму та перевіримо, чи ці значення записуються на шині.
Як завжди програма починається з налаштування бітів конфігурації та встановлення тактової частоти до 20 МГц, як показано нижче
#pragma config FOSC = HS // Біти вибору осцилятора (HS oscillator) #pragma config WDTE = OFF // Біт включення сторожового таймера (WDT вимкнено) #pragma config PWRTE = ON // Біт активації таймера включення (PWRT увімкнено) # pragma config BOREN = ON // Біт увімкнення скидання коригування (BOR увімкнено) #pragma config LVP = OFF // Біт ввімкнення послідовного програмування в ланцюзі низької напруги (одне живлення) (RB3 - цифровий ввід / вивід, HV увімкнено Для програмування потрібно використовувати MCLR) #pragma config CPD = OFF // Біт захисту коду пам'яті EEPROM (захист коду EEPROM даних вимкнений) #pragma config WRT = OFF // Flash Program Memory Ввімкнути біти (Захист від запису; вся пам'ять програми може бути надіслано до управління EECON) #pragma config CP = OFF // Біт захисту коду пам'яті Flash-програми (захист коду вимкнено) #define _XTAL_FREQ 20000000
Наступним кроком буде додавання файлу заголовка, про який ми щойно обговорювали. Файл заголовка називається PIC16F877a_I2C.h і його можна завантажити за посиланням, про яке ми говорили вище. Переконайтеся, що файл заголовка додано у файл заголовка вашого списку проектів, структура файлу вашого проекту повинна виглядати так
Переконавшись, що файл заголовка додано до файлу проекту, включіть файл заголовка в основний файл C.
#включати
Усередині в той час циклу ми почнемо з I2C зв'язку записи кілька випадкових значень до шини I2C, а потім Завершення I2C зв'язку. Вибрані випадкові значення - D0, 88 та FF. Ви можете ввести будь-які значення, які хочете. Але пам’ятайте ці значення, оскільки ми будемо перевіряти їх у нашому моделюванні.
while (1) { I2C_Begin (); I2C_Write (0xD0); I2C_Write (0x88); I2C_Write (0xFF); I2C_End (); __delay_ms (1000); }
Повна програма може бути знайдена в нижній частині сторінки, ви можете використовувати його або завантажити повна поштова файл програми тут. Отримавши програму, скомпілюйте її і підготуйтеся до моделювання.
Моделювання протея:
У Proteus є приємний інструмент, який називається налагоджувачем I2C, який можна використовувати для зчитування даних на шині I2C, тому давайте побудуємо схему, використовуючи його, і перевіримо, чи дані успішно записуються. Повна електрична схема показана нижче
Завантажте шістнадцятковий файл, створений нашою програмою, подвійним клацанням на мікроконтролері. Потім змоделюйте програму. Ви помітите спливаюче вікно, яке відображатиме всю інформацію про шину I2C. Вікно нашої програми показано нижче.
Якщо ви уважно подивитесь на дані, що записуються, ви помітите, що вони такі самі, як ми писали в нашій програмі. Значення D0, 88 і FF. Значення записуються кожні 1 секунду, тому час також оновлюється, як показано нижче. Синя стрілка вказує на те, що вона написана від ведучого до веденого, інакше вона буде спрямована в протилежний бік. Нижче наведено детальний огляд даних, що надсилаються.
Це лише проблиск того, що I2C може зробити, він також може читати та записувати дані на кілька пристроїв. Детальніше про I2C ми розглянемо у наступних навчальних посібниках, пов’язуючи різні модулі, що працюють з протоколом I2C.
Сподіваюся, ви зрозуміли проект і навчились з нього щось корисне. Якщо у вас є сумніви, опублікуйте їх у розділі коментарів нижче або скористайтесь форумами для отримання технічної допомоги.
Повний код наведено нижче; Ви можете завантажити файли заголовків з усім кодом звідси.