Дослідження та реалізація мультимайстерного режиму для I2C-інтерфейсу

  • Вид работы:
    Дипломная (ВКР)
  • Предмет:
    Информационное обеспечение, программирование
  • Язык:
    Украинский
    ,
    Формат файла:
    MS Word
    186,71 Кб
  • Опубликовано:
    2013-10-10
Вы можете узнать стоимость помощи в написании студенческой работы.
Помощь в написании работы, которую точно примут!

Дослідження та реалізація мультимайстерного режиму для I2C-інтерфейсу

АНОТАЦІЯ

У дипломній роботі проведено дослідження можливостей організації мікроконтролерних мереж на основі I2C-інтерфейсу. Детально проаналізовано особливості роботи I2C-інтерфейсу, фізичного середовища для його реалізації, а також функціональні можливості модуля TWI мікроконтролерів AVR для забезпечення обміну даними за I2C-протоколом.

Найважливіша частина дипломної роботи стосується програмної підтримки мультимайстерного режиму роботи мікроконтролерної мережі за I2C-інтерфейсом з використанням апаратних переривань модуля TWI мікроконтролерів AVR.

Для мультимайстерного режиму реалізовані функції арбітражу. Усі розроблені програмні алгоритми для обміну даними за I2C-протоколом експериментально апробовані на фізичному обладнанні.


In the work our study were divided into several stages. The first stage was a detailed analysis of the characteristics of the I2C-interface, the physical environment for its implementation and the functionality of the module TWI AVR Microcontroller for data exchange for I2C-protocol. The next stage was studied implementation of data exchange for multy-master mode. For multy-master mode implemented features arbitration.examples of communication for I2C-protocol experimentally tested.

ВСТУП

Будь-який мікроконтролер призначений для виконання функцій по керуванню або контролю фізичними параметрами конкретних об'єктів керування. Функції керування або контролю зводяться до оброблення і наступного використання цифрової двійкової інформації, що надходить від об'єктів керування по лініях зв'язку від різних пристроїв сполучення мікроконтролера з об'єктом. У якості таких пристроїв можуть бути датчики різних аналогових фізичних параметрів та пов'язані з ними нормуючі перетворювачі електричних сигналів, аналого-цифрові перетворювачі, датчики цифрової інформації та ін. З боку виведення інформації мікроконтролер взаємодіє з цифровими індикаторами, виконавчими механізмами, дисплеями, цифродрукуючими пристроями та іншими засобами запам'ятовування, зберігання і використання результатів обробки інформації.

З'єднання всього різноманіття зовнішніх пристроїв з шинами мікроконтролера здійснюється за допомогою інтерфейсів, які слід розуміти як уніфікований засіб об'єднання різних пристроїв в єдину систему. Будь-який інтерфейс повинен забезпечити вирішення наступних двох завдань.

По-перше, інтерфейс у своїй апаратній частині повинен забезпечити електричне з'єднання різних зовнішніх пристроїв з різними електричними і конструктивними параметрами з єдиною системою шин конкретного мікроконтролера. При цьому мають бути враховані такі параметри, як кількість ліній зв'язку, рівні і потужності електричних сигналів, довжина і завадозахищеність ліній зв'язку.

По-друге, інтерфейс повинен забезпечити гнучке програмне керування всіма підключеними зовнішніми пристроями. У цій частині інтерфейс повинен забезпечити не тільки працездатність зовнішніх пристроїв, але й узгодження по швидкодії різних зовнішніх пристроїв та центрального мікропроцесора.

Таким чином, під інтерфейсом слід розуміти уніфікований програмно-апаратний пристрій, який призначений для організації обміну інформацією між мікропроцесором та зовнішніми пристроями, об'єднаними в єдину систему.

За своїм призначенням інтерфейси бувають внутрішніми і зовнішніми. Внутрішній інтерфейс об'єднує ВІС мікропроцесора, модулі пам'яті і засоби управління вводом-виводом. Зовнішній інтерфейс забезпечує сполучення інформаційних шин МК з зовнішніми пристроями.

Сучасні мікроконтролери деякі зовнішні інтерфейси обміну даними можуть підтримувати на програмному рівні, а для деякий, набагато складніших за своєю структурою, у них є передбачені окремі периферійні модулі. Серед найбільш популярних інтерфейсів можна відзначити такі: USB, Ethernet, САN, UART, I2S, I2C, SSI/SPI.- один з найпоширеніших на сьогоднішній день стандартів організації локальних мереж. Модуль Ethernet, переважно є апаратно реалізований в мікроконтролерах типу ARM.

Шина USB (Universal Serial Bus) з'явилася порівняно недавно - версія першого затвердженого варіанту стандарту з'явилася 15 січня 1996 року. Розробка стандарту була ініційована авторитетними фірмами - Intel, DEC, IBM, NEC, Northen Telecom і Compaq. На сьогоднішній день USB є одним з найбільш затребуваних інтерфейсів передачі даних. Шина строго орієнтована, має поняття «головний пристрій» (Host) і «периферійні пристрої» (Device).

Існує декілька версій специфікації USB: USB 1.0, USB 1.1, USB 2.0, USB 3.0.

Для пристроїв USB 2.0 регламентовано три режими роботи:

• Low-speed, 10 ... 1500 Кбіт/cек (використовується для інтерактивних пристроїв: клавіатури, миші, джойстики);

• Full-speed, 0,5 ... 12 Мбіт/сек (аудіо-, відеопристрої);

• Hi-speed, 25 ... 480 Мбіт/сек (відеопристрої, пристрої зберігання інформації).

Мережевий протокол CAN (Controller Area Network) був розроблений в 1987 році фірмою Bosch для мультипроцесорних автомобільних систем реального часу. CAN оптимізований для систем, в яких передається порівняно невеликий обсяг інформації зі швидкістю до 1 Мбіт/сек. Основні переваги CAN-протоколу - висока завадостійкість, надійність, можливість отримання повідомлень всіма вузлами (контролерами даних) із синхронізацією за часом, неруйнівний арбітраж доступу до шини, мала ймовірність пропуску помилки. Прийнята в CAN-інтерфейсі схема передачі повідомлень дозволяє її розширювати і модернізувати: нові пристрої прийому даних можна додавати до мережі без зміни існуючих програмних засобів і порушення роботи старої системи. Все це привернуло увагу розробників і користувачів різних розподілених систем керування, що використовуються, окрім транспортних засобів, у промисловості, енергетиці, медичному приладобудуванні.(Universal Asynchronous Receiver / Transmitter) - напевно, найвідоміший інтерфейс. Можливо, зв'язок через асинхронний послідовний порт відходить у минуле, проте складно знайти контролер, який не має в складі периферії UART.являє собою абревіатуру Infrared Data Association - асоціації, яка займається розробкою специфікацій для обміну даними по оптичному інтерфейсу за допомогою інфрачервоного світла. Така технологія також згодом отримала назву IrDA.

Досвід показує, що серед інших бездротових ліній передачі інформації інфрачервоний (ІЧ) відкритий оптичний канал є недорогим і зручним способом передачі даних на невеликі відстані (до декількох десятків метрів). Зокрема, він ефективний для забезпечення бездротового зв'язку між персональним комп'ютером і периферійними пристроями.(Local Interconnect Network) - стандарт промислової мережі розроблений консорціумом європейських автовиробників та інших відомих компаній, включаючи Audi AG, BMW AG, Daimler Chrysler AG, Motorola Inc.

Протокол LIN призначений для створення недорогих локальних мереж обміну даними на коротких відстанях. Він служить для передачі вхідних впливів, станів перемикачів на панелях управління, а також для відповідних дій різних пристроїв, що з'єднані в одну систему через LIN і відбуваються в так званому «людському» часовому діапазоні (порядку сотень мілісекунд).S (Inter-Integrated Circuit Sound) - інтерфейс призначений для передачі цифрових аудіоданих.(Synchronous Serial Interface) - популярний інтерфейс для послідовного обміну даними між мікросхемами. Поряд з I2C він належить до найбільш широко використовуваних інтерфейсів для з'єднання мікросхем. SSI дозволяє підключати до контролера різного роду мікросхеми, в т.ч. запам'ятовуючі пристрої (EEPROM, Flash-пам'ять, SRAM), годинник реального часу (RTC), АЦП / ЦАП, цифрові потенціометри, спеціалізовані контролери та ін.

На відміну від стандартного послідовного порту, SSI є синхронним інтерфейсом, тобто будь-яка передача в ньому синхронізована із загальним тактовим сигналом, що генерується головним пристроєм. Приймаюча периферія синхронізує отримання бітової послідовності з тактовим сигналом. До одного послідовного периферійного інтерфейсу провідного пристрою-мікросхеми може приєднуватися кілька мікросхем. Головний пристрій вибирає підлеглий пристрій для передачі, активуючи сигнал «вибір кристалу» на підлеглій мікросхемі.

Найбільшої популярності для мікроконтролерних систем набув I2C-інтерфейс завдяки своїй простоті реалізації, низької собівартості та відносно непоганої швидкості роботи.

Список можливих застосувань I2C-інтерфейсу:

–       доступ до модулів пам'яті RAM;

–       доступ до модулів пам'яті EEPROM;

–       доступ до низькошвидкісних ЦАП/АЦП;

–       доступ до найрізноманітніших давачів;

–       регулювання контрастності, насиченості і колірного балансу моніторів;

–       регулювання звуку в динаміках;

–       управління світлодіодами, в тому числі в мобільних телефонах;

–       читання інформації з датчиків моніторингу і діагностики устаткування, наприклад, термостат центрального процесора або швидкість обертання вентилятора охолодження;

–       читання інформації з годинника реального часу (кварцових генераторів);

–       управління включенням/виключенням живлення системних компонент;

–       інформаційний обмін між мікроконтролерами.

На сьогоднішній день лише асортимент продукції Philips включає більше 150 КМОП і біполярних I2C-сумісних пристроїв. Усі ці пристрої мають вбудований інтерфейс, який дозволяє їм зв'язуватися один з одним по I2C-шині. Це конструкторське рішення вирішує безліч проблем з’єднання різних пристроїв, які зазвичай виникають при розробці цифрових систем.

Переваги використання I2C-інтерфейсу:

–       необхідно лише один мікроконтролер для керування ряду пристроїв;

–       використовується лише дві лінії вводу/виводу загального призначення;

–       стандарт передбачає «гаряче» підключення і відключення пристроїв у процесі роботи системи;

–       вбудований у мікросхеми фільтр фільтрує сплески, забезпечуючи цілісність даних.

Переваги для конструкторів при використанні I2C-інтерфейсу:

–       оскільки такі мікросхеми підключаються безпосередньо до шини без будь-яких додаткових електричних кіл, з'являється можливість модифікації і модернізації системи прототипу шляхом підключення і відключення пристроїв від шини;

–       блоки на функціональній схемі відповідають мікросхемам, перехід від функціональної схеми до принципової відбувається швидко;

–       немає потреби розробляти шинні інтерфейси, так як шина вже інтегрована в мікросхеми;

–       інтегровані адресація пристроїв і протокол передачі даних дозволяють системі бути повністю програмно обумовленою;

–       одні і ті ж типи мікросхем можуть бути часто використані в різних додатках;

–       час розробки знижується, так як конструктори швидко знайомляться з часто використовуваними функціональними блоками і відповідними мікросхемами;

–       мікросхеми можуть бути додані або зняті зі системи без впливу на інші мікросхеми, що підключені до шини (якщо їхня робота незалежна);

–       проста діагностика збоїв та відлагодження; порушення в роботі легко відслідковуються;

–       час розробки програмного забезпечення може бути зменшене за рахунок повторного використання розробленої бібліотеки для роботи з пристроями на I2C-шині.

Мета та завдання дипломної роботи: дослідити та алгоритмічно забезпечити роботу мультимайстерного режиму мікроконтролерної мережі на основі I2C-інтерфейсу.

Практичне значення отриманих результатів: розроблений програмний код мовою високого рівня Сі може використовуватися як готова бібліотека при роботі з пристроями та мережами, що працюють за I2C-інтерфейсом.

Запропонована алгоритмічна реалізація мультимайстерного режиму роботи I2C-шини апробована шляхом натурного експерименту.

1. АНАЛІЗ ПИТАННЯ

1.1 Огляд літературних джерел

.1.1 Аналіз особливостей роботи I2C-інтерфейсу

Інтерфейс I2C (IIC, Inter-Integrated Circuit) розроблений ще на початку 1980-х компанією Philips (зараз NXP Semiconductors) та представляє собою двонаправлену 2-провідну шину, що використовується для контролю та обміну даними з інтегральними схемами.C складається з двох ліній: SDA (даних) та SCL (тактування), які підтягнуті через резистори до напруги живлення та керуються з боку пристроїв через відкритий колектор чи відкритий стік (рис. 1.1).

Інтерфейс передбачає різний набір швидкостей обміну з 7-ми і 10-ти бітною адресацією пристроїв на I2C-шині (розширення можливостей інтерфейсу здійснювалися у різні роки):

–       Стандартний режим (Standard-mode): двонаправлена передача даних зі швидкістю до 100 кбіт/сек. Адреса - 7 біт, адресація до 112 пристроїв на I2C-шині (1982 р. Оригінал).

–       Швидкісний режим (Fast-mode, Fm): двонаправлена передача даних зі швидкістю до 400 кбіт/сек. Розширення адресного простору до 10 біт, адресація до 1008 пристроїв на I2C-шині (1992 р. V.1.0).

–       Високошвидкісний режим (High-speed mode, Hs): двонаправлена передача даних зі швидкістю до 3,4 Мбіт/сек. (1998 р. V.2.0).

–       Швидкісний режим плюс (Fast-mode plus, Fm+): двонаправлена передача даних зі швидкістю до 1 Мбіт/сек. (2007 р. V.3.0).

–       Ультрависокошвидкісний режим (Ultra Fast-mode, UFm): однонаправлена передача даних зі швидкістю до 5 Мбіт/сек. для нових USDA та USCL ліній, що використовують двотактну логіку без підтягуючих резисторів. Пристрої для однонаправленої UFm-шини не є сумісними з пристроями для двонаправленої I2C-шини. (2012 р. V.4.0).

Максимальна кількість пристроїв, що приєднуються до одної I2C-шини, обмежується максимальною ємкістю шини у 400 пФ та здатністю адресації цих пристроїв.

Рис. 1.1 Під’єднання пристроїв до I2C-шини

У вільному стані (коли ніхто нічого не передає) на шині присутній високий рівень «1», що забезпечують підтягуючі резистори до напруги живлення. Пристрої до I2C-шини під’єднуються за принципом монтажного «І»: коли вихідний транзистор (рис. 1.1) виводу SDA чи SCL пристрою закритий, тоді плив з боку пристрою на лінію відсутній, і на лінії присутній високий рівень «1» через підтягуючий резистор до живлення, якщо ж вихідний транзистор відкритий - він підтягує відповідну лінію до землі, і на ній встановлюється низький рівень «0». Тобто, передача/прийом сигналів здійснюється пристроями шляхом подачі/зняття «землі» на/з відповідної лінії I2C-шини (подали на лінію землю - на лінії «0»; відпустили лінію - «1» за рахунок підтягуючих резисторів до живлення).

На рис. 1.1 трикутники на вході вказують, що входи високоомні і не впливають на рівні сигналів на лініях, і лише зчитують значення цих рівнів. Переважно використовуються рівні 5В та 3,3В напруги живлення VDD. Для більшості пристроїв рівні розпізнаються як: високий рівень «1» - від 0,7·VDD, низький рівень «0» - до 0,3·VDD.

Підтягуючі резистори мають номінали від декількох кОм до декількох десятків кОм. Чим вища швидкість, тим менший номінал резистора необхідно встановити. При більшому номіналі резистора лінія буде довше встановлюватися в «1» (за рахунок перезаряду паразитної ємності між дротами). Оптимально вибирають 4,7 або 10 кОм.

Більшість популярних мікросхем (давачі, годинники, АЦП, мікроконтролери AVR і т.п.) працюють на швидкості 100 чи/та 400 кГц та мають 7-бітну адресацію. Тому розглянемо I2C-протокол саме для цього формату.

Керуючі сигнали та формат посилки. Обмін даними на I2C-шині здійснюється у чітко визначеному порядку. За керування обміном даними на шині відповідає головний пристрій (master), хоча на шині може бути присутні декілька головних пристроїв, але керувати передачею у певний момент може лише один з них. Для цього він має «захопити» шину, виконати обмін даними з необхідними пристроями на шині та «відпустити» шину. Трішки далі ми детально розглянемо одномастерний та мультимастерний режими.

Розберемо основні сигнали, що можуть бути присутні на шині.

Передача даних на лінії SDA відбувається послідовно біт за бітом, згідно поданих імпульсів на лінії SCL. Читання біту на лінії SDA здійснюється у момент, коли на синхролінії SCL присутній високий рівень «1». Тому протокол вимагає, щоб поки присутня «1» на синхролінії, сигнал даних SDA не змінювався. Передача байту даних здійснюється, починаючи зі старшого біту. Синхронізацію на шині забезпечує головний пристрій, той що проявив ініціативу для обміну даних.

Для початку передачі даних та її завершення головний пристрій формує на шині відповідні сигнали START та STOP. Між цими сигналами шина вважається занятою, тобто інші головні пристрої не намагаються нічого передавати та чекають поки шина не звільниться.

Сигнал START (S) розпізнається на шині за спадаючим фронтом сигналу SDA при високому рівні «1» на синхролінії SCL.

Сигнал STOP (P), навпаки, розпізнається за зростаючим фронтом сигналу SDA при високому рівні «1» на синхролінії SCL. Сигнал STOP обов’язково має слідувати після сигналу START.

Ще одним керуючим сигналом є «повторний старт» REPEAT START (Sr). За своєю формою він ідентичний сигналу START. Після сигналу START головний пристрій повинен передати адресний байт (7-бітна адреса + 1 біт напряму обміну) підлеглому пристрою, з яким він хоче виконати обмін даними. Якщо головний пристрій хоче змінити напрям передачі чи звернутися до іншого пристрою, то він має видати на шину сигнал REPEAT START та продовжити передачу. Це дає йому можливість виконувати обмін даними з різними пристроями, не втрачаючи контроль за шиною (інші головні пристрої не будуть його перебивати). Як тільки він видасть сигнал STOP, інший головний пристрій може забрати керування шиною собі. Нюанси, що стосуються одночасного захоплення шини декількома головними пристроями та визначення пріоритету надання контролю за шиною, будуть викладені при розгляді мультимастерного режиму.

Після кожного переданого байту (адреси чи даних) слідує 9-й біт підтвердження ACK (від слова acknowledge). Той, хто прийняв байт, має видати на лінію даних SDA підтвердження ACK (A), тобто подати «0» на лінію. Наприклад, ми видали на лінію адресу пристрою, з яким хочемо здійснювати обмін. Якщо пристрій присутній, і він розпізнав свою адресу, тоді він це підтвердить (A), притиснувши лінію до землі («0»). Якщо пристрій відсутній, тоді на лінії ніхто не відгукнеться, і на ній буде присутній NACK (N), тобто високий рівень «1».

Якщо підлеглий пристрій не встигає обробити отриману від головного пристрою інформацію, тоді він може вносити паузи, виставляючи на синхролінії SCL низький рівень «0».

Будь-яка I2C-посилка складається зі старту, адресного пакету, пакету даних, (рестарту, адресного пакету, пакету даних і т.д.) та стопу. Усі пакети завжди є 9-ти бітними.

Адресний пакет формується головним пристроєм та завжди слідує після сигналу старту (рестарту). Він містить 7-бітний адрес підлеглого пристрою (першим передається старший біт), біт напряму обміну W=0 (передача) чи R=1 (прийом) та біт підтвердження ACK від підлеглого пристрою. Підлеглі пристрої можуть мати довільний 7-бітний адрес, за винятком нульового та адресів із діапазону 1111ххх, які є зарезервованими. Нульовий адрес використовується для виконання загальних викликів, тобто передачі даних для усіх підлеглих пристроїв на шині, для яких є дозволені загальні виклики.

Пакет даних містить 8 біт даних (першим передається старший біт) та біт підтвердження ACK від підлеглого пристрою. Якщо пакет даних завершується NACK, тоді передача даних має бути припинена, і має слідувати або повторний старт, або стоп.

Розглянемо типові I2C-посилки.

Якщо головний пристрій (master) націлений лише на передачу даних, то посилка має складатися зі сигналу START, адресного пакету з бітом напряму W (передача) та довільної кількості пакетів з даними, що передаються для підлеглого пристрою (slave). Посилка обов’язково завершується сигналом STOP. Якщо підлеглий пристрій не підтвердить якийсь з пакетів (NACK), тоді подальший прийом зупиняється, а на шину видається сигнал STOP.

Якщо головний пристрій (master) націлений лише на прийом даних, то посилка має складатися зі сигналу START, адресного пакету з бітом напряму R (прийом) та довільної кількості пакетів з даними, що передаються підлеглим пристроєм. Посилка обов’язково завершується сигналом STOP. Після кожного прийнятого головним пристроєм байту даних він виставляє біт підтвердження ACK. Якщо головний пристрій не хоче далі приймати дані, то він обов’язково виставляє NACK та завершує посилку сигналом STOP.

в) Комбінований формат передбачає, що головний пристрій в межах однієї посилки буде як приймати, так і передавати дані до підлеглого пристрою чи навіть здійснювати обмін даними з декількома підлеглими пристроями. Наприклад, для зчитування поточного часу з мікросхеми годинника PCF8583 мікроконтролер формує на шині сигнал START, передає адресу пристрою + W, далі передає пристрою байт даних, що містить адресу регістра з якого потрібно читати дані. Потім для зміни напряму обміну даними формує на шині REPEAT START, передає адресу пристрою + R, а далі читає з регістрів годинника необхідні байти (секунди, хвилини і т.п.). Мікросхема годинника автоматично збільшує на одиницю адресу регістра, з якого необхідно буде далі зчитувати дані. Якщо МК зчитав необхідні йому байти з даними, то для останнього зчитаного байту він обов’язково має видати NACK та завершити посилку сигналом STOP.

-бітна адресація представляє собою розширення для 7-бітної, і полягає у тому, що спершу передається стандартний адресний пакет, що містить п’ять бітів 11110, які вказують, що це 10-розрядний адрес, два старших біти адреси та біт W/R. У другому байті передаються 8 молодших біти адреси. Передача даних передбачає 2 байти з адресою за якими слідують байти з даними. Прийом ж даних передбачає сигнал повторного старту, оскільки перший адресний байт спершу вказує на передачу (W) другого адресного байту, а потім змушений переключитися на прийом, відіславши при цьому лише перший адресний байт з бітом на прийом (R).

В одній посилці також можуть поєднуватися як передача, так і прийом даних, а також і обмін даними з декількома пристроями.

1.1.2 Аналіз TWI-модуля мікроконтролерів AVR

I2C-інтерфейс для МК AVR має назву TWI (Two-wire Serial Interface, двопровідний послідовний інтерфейс).

Він реалізує базову версію I2C-інтерфейсу та підтримує швидкість обміну до 400 кГц. МК можуть мати лише 7-бітну адресу.

Обмін даними по I2C-протоколу здійснюється через відповідні виводи SDA та SCL, що суміщені з виводами одного з портів вводу/виводу. При використанні цих виводів модулем TWI до них можуть бути підключені внутрішні підтягуючі резистори, що дає можливість у деяких випадках обійтися без зовнішніх резисторів, що вимагаються інтерфейсом. Для цих виводів в модулі встановлені обмежувачі швидкості наростання фронтів сигналів, а також фільтри, що відсікають паразитні імпульси тривалістю менше 50 нсек.

Функціонування модуля TWI забезпечується п’ятьма регістрами:- регістр швидкості передачі. Він задає частоту сигналів на виводі SCL. Значення регістра для вказаної швидкості може бути обчислене за такою формулою

 

де TWPS - значення 2-х молодших розрядів регістра TWSR, що виконують функцію подільника. Значення швидкості має бути, як мінімум, меншим у 16 разів за тактову частоту МК. Також значення TWBR має бути не меншим за 10, бо інакше під час передачі байта можуть генеруватися некоректні сигнали на виводах SDA та SCL.- регістр адреси. Старші 7 біт містять I2C-адресу для МК для його роботи у режимі Slave. Молодший розряд TWGCE вказує, чи для МК дозволені загальні виклики (за адресою 0x00). Контроль адресних пакетів виконується навіть у сплячому режиму МК, що дає можливість переводити МК у робочий режим у випадку його адресації.- регістр даних.

Для передачі по I2C-шині у цей регістр заносяться як адреса+R/W підлеглого пристрою, так і байти даних, що мають бути йому передані.

Також звідси зчитуються і отримані модулем TWI байти з I2C-шини. TWCR - регістр керування модулем TWI. Усі маніпуляції, що необхідно здійснити на I2C-шині виконуються за рахунок виставлення відповідних бітів (табл. 1.1) цього регістра.

Таблиця 1.1 Розряди регістра керування TWCR

№біта

Назва

Призначення

7

TWINT

Прапорець переривання від модуля TWI

6

TWEA

Дозвіл на підтвердження ACK («1» - ACK, «0» - NACK і у режимі slave модуль TWI неактивний)

5

TWSTA

Прапорець стану START

4

TWSTO

Прапорець стану STOP

3

TWWC

Прапорець конфлікту запису (виставляється при записі у регістр TWDR, коли прапорець переривання TWINT скинутий)

2

TWEN

Дозвіл на роботу модуля TWI

1

-

Зарезервовано, читається як «0»

0

TWIE

Дозвіл на переривання від модуля TWI

- регістр статусу. Виставлення прапорця TWINT регістра керування TWCR сигналізує, що модуль TWI виконав поточну задачу і очікує подальших дій програми.

У цей час у регістрі статусу у його старших п’яти розрядах міститься певний код, згідно якого можна визначити стан I2C-шини. Тому програма повинна зчитати у проміжну змінну байт значення регістра TWSR, числовою маскою встановити нулі у трьох молодших розрядах та, порівнюючи отриманий код зі таблицею значень в інструкції виробника на МК, вибрати подальші дії TWI-модуля.

1.2 Постановка задачі

Підсумувавши огляд літературних джерел, можна дійти наступного висновку. Для нашого дослідження необхідно підняти та вирішити такі питання:

)        Аналіз роботи модуля TWI мікроконтролера AVR з послідовною шиною за I2C-інтерфейсом.

)        Аналіз роботи модуля TWI МК AVR з I2C-шиною в мультимайстерному режимі.

)        Розробити структуру даних для забезпечення обміну даними за I2C-протоколом, що передбачає використання апаратних переривань модуля TWI мікроконтролера AVR.

)        Розробити мікроконтролерну мережу на основі I2C-інтерфейсу.

Перше питання передбачає аналіз модуля TWI для обміну даними з підлеглими пристроями та розроблення бібліотечних функцій, що будуть забезпечувати роботу модуля з I2C-шиною у звичайному режимі (наявний лише один головний пристрій).

Друге питання передбачає аналіз модуля TWI для обміну даними як з підлеглими пристроями, так і з іншими мікроконтролерами, тобто функціонування I2C-шини в мультимайстерному режимі. Це питання потребує також дослідження функції арбітражу для мікроконтролерів.

Третє питання передбачає забезпечення функціонування модуля TWI з використанням декількох кільцевих буферів. Для цього необхідно розробити структуру внутрішнього протоколу для формування I2C-посилки та її запису у вихідний буфер. Також слід передбачити ще декілька додаткових буферів для прийому даних, оброблення поточних задач, а також для функціонування модуля TWI в режимі slave.

Четверте питання стосується вже виключно реалізації розроблених програмних бібліотек для роботи за I2C-протоколом з конкретними прикладами мікросхем.

модуль мікроконтролер інтерфейс протокол

2. ДОСЛІДЖЕННЯ РОБОТИ I2C-ІНТЕРФЕЙСУ AVR-МІКРОКОНТРОЛЕРА

 

.1 Реалізація I2C-протоколу модулем TWI


Звичайний режим передбачає, що на I2C-шині присутній лише один головний пристрій (мікроконтролер), який виконує обмін даними з підлеглими пристроями (рис. 2.1).

Рис. 2.1 Одномайстерна I2C-шина

Роботу з модулем TWI мікроконтролера можемо організувати як програмно (постійно перевіряти прапорець TWINT на факт завершення поточної задачі), так і в режимі переривання від модуля TWI. У режимі апаратного переривання ми зможемо використати обчислювальні потужності МК для інших поточних задач і лише час від часу перериватися, щоб керувати роботою модуля TWI на I2C-шині. Тому ми будемо розглядати роботу модуля TWI саме з використанням апаратного переривання.

Керування модулем TWI виконується через регістр TWCR. Тут є одна особливість, яка полягає у тому, що ми мусимо повністю перезаписувати його значення, а не виставляти окремі його біти за допомогою присвоєння з логічним АБО (|=).

Як тільки у регістр TWCR заноситься одна з команд керування (рис. 2.2), то модуль TWI починає одразу її реалізовувати, а по завершенню виконання виставляє прапорець TWINT, і програма переходить на підпрограму переривання модуля TWI. У підпрограмі переривання необхідно зчитати значення статусу (табл. 2.1) у регістрі TWSR для виконаної команди та прийняти подальші дії для обміну даними.

Рис. 2.2 Формати команд для модуля TWІ у режимі master

Таблиця 2.1. Коди статусів для модуля TWI у режимі master

Код

Стан I2C-шини та модуля TWI

0x08

Був сформований START

0x10

Був сформований REPEAT START

0x18

Було передано адреса+Write та отримано ACK

0x20

Було передано адреса+Write та отримано NACK

0x28

Був переданий байт даних та отримано ACK

0x30

Був переданий байт даних та отримано NACK

0x40

Було передано адреса+Read та отримано ACK

0x48

Було передано адреса+Read та отримано NACK

0x50

Був прочитаний байт даних та передано ACK

0x58

Був прочитаний байт даних та передано NACK


2.2 Алгоритмічна реалізація роботи з I2C-шиною через апаратні переривання


Для забезпечення роботи з I2C-шиною через апаратні переривання потрібно задіяти 2 кільцеві буфери: один на передачу, а другий на прийом даних з I2C-шини, та реалізувати для буфера передачі чітку послідовність кодів для запису у нього I2C-посилки. Згідно переривань модуля TWI коди з даними будуть послідовно зчитуватися з буфера та буде виконуватися обмін даними з підлеглими пристроями на I2C-шині.

Введемо такі псевдокоди для форматування I2C-посилки у вихідному буфері для модуля TWI:

x04 - код для команди STOP;

x10 - код для команди REPEAT START;

x20 - код адреси (вказує, що у наступній комірці буфера буде адреса пристрою);

x40 - код передачі байту даних (вказує, що у наступній комірці буфера буде байт даних, який потрібно відправити на I2C-шину);

x80 - код для читання байту даних з I2C-шини з підтвердженням МК про прийнятий байт (ACK);

x81 - код для читання останнього байту даних з I2C-шини без підтвердження (NACK).

Окремі сегменти посилки заносяться у буфер через виклики набору функцій (рис. 2.3), які вже безпосередньо заносять псевдокоди з даними у буфер, а також забезпечують додаткову функціональність. Наприклад, при виклику функції Start() ми маємо передати у неї параметр CONTROL чи NOCONTROL, який вказує чи потрібно по завершенню передачі I2C-посилки звітуватися про виконання. Також функція Start() здійснює заборону на глобальні переривання, яка знімається аж у кінці форматування посилки функцією Stop(). Такий крок необхідний для того, щоб передача посилки не здійснювалася, до поки не буде повністю занесена у буфер.

Перед кожним байтом адреси чи даних завжди слідує відповідний псевдокод, за яким можна розпізнати, що міститься у наступній комірці. Формально, передача як адреси, так і даних є однотипна, але окремі коди дають можливість відслідковувати при відладці, що ми передаємо.

Для читання даних введено псевдокод 0x80 з 0 чи 1 у молодшому розряді (якщо 1, тоді код буде 0x81). Якщо 0, то МК підтверджує про прийнятий байт і очікує прийому наступного. Якщо 1, тоді МК виставляє на шину NACK та завершує прийом даних.

У вихідному буфері може бути одночасно записано декілька I2C-посилок. Запуск першої посилки (сигнал START) виконує функція Stop(), а наступні у буфері за нею посилки виконуються вже згідно підпрограми переривання модуля TWI.

Якщо модуль TWI повинен прозвітуватися про виконану посилку, тоді введена нами змінна I2Ctask буде збільшена на 1 (на початку вона рівна 0). Це означає, що у вхідному буфері є прийняті дані, які програма має зчитати. Після цього програма повинна буде зменшити змінну I2Ctask назад на 1.

Для уніфікації даних, що мають передаватися в основні функції, які відповідають за формування I2C-посилки, необхідно також здійснити наступний ряд макровизначень:

#define                         ACK   0       // підтвердження активне

#define                         NACK         1       // підтвердження відсутнє

#define                         I2C_W         0       // запит на запис

#define                         I2C_R 1       // запит на читання

#define                         CONTROL  1       // зворотній контроль виконання посилки

#define                         NOCONTROL      0       // виконання посилки без підтвердження

//розрахунок швидкості TWI

#define                         TWBRcalc   (F_CPU/I2Cspeed-16)/2

Вхідний та вихідний буфер модуля TWI може бути довільної довжини, тому для кожного з них ми забезпечуємо можливість встановлення свого розміру:

#define                         I2C_BUF_SIZE_OUT    32

#define                         I2C_BUF_MASK_OUT (I2C_BUF_SIZE_OUT-1)

#define                         I2C_BUF_SIZE_IN        32

#define                         I2C_BUF_MASK_IN     (I2C_BUF_SIZE_IN-1)

unsigned char      I2C_BufOUT[I2C_BUF_SIZE_OUT], I2C_StartBufOUT=0,C_EndBufOUT=0, I2C_BufOUTer=0;char                I2C_BufIN[I2C_BUF_SIZE_IN], I2C_StartBufIN=0,C_EndBufIN=0, I2C_BufINer=0;

Для забезпечення певної функціональності програмного коду для роботи з I2C-шиною слід оголосити ряд додаткових змінних:char          I2Cproccess=0; // вказує, чи є зараз передача на I2С-шиніchar          I2Ccontrol; // вказує, чи необх. звітув. про викон.unsigned char I2Ctask=0;     //вказує, скільки опрац.пакетів start-stop

Остання змінна оголошена з директивою volatile, оскільки вона одночасно використовується як в підпрограмі переривання, так і в основній програмі. Функції запису/читання буферів працюють за логікою роботи FIFO-буферів, їхня конкретна реалізація для буферів прийомо-передачі модуля TWI.

Також варто звернути увагу на функцію I2C_SearchStartStop(). У випадку, коли підлеглий пристрій не відгукнувся на свою адресу, чи попросту він відсутній на шині, або під час прийому даних він не хоче їх більше приймати, тоді на шині у момент підтвердження буде присутній NACK.

Головний пристрій (master), отримавши NACK, змушений відмовитися від подальшого обміну з цим пристроєм. І тому ця функція у вихідному буфері модуля TWI шукає найближчу команду REPEAT START чи STOP, пропускаючи команди обміну даними з поточним пристроєм.

Основна робота модуля TWI організована через підпрограму переривання. Логічний перемикач отримує значення з регістра статуса TWSR (маскуючи при цьому три молодших біти) та згідно цього коду виконує одну з трьох типових дій, яка обов’язково завершується функцією I2C_Action():

–    якщо прочитано байт даних, то він з регістра TWDR заноситься у вхідний буфер;

–       якщо передача завершилася не успішно (NACK з боку підлеглого пристрою), тоді шукаємо у вихідному буфері найближчу команду повторного старту чи стопу;

–       для решта типових команд лише викликається функція I2C_Action(), яка виконає наступну команду для I2C-шини, що записана у вихідному буфері модуля TWI.

Функція I2C_Action() призначена для зчитування з вихідного буфера модуля TWI поточної команди чи даних та виводу їх на I2C-шину.

2.3 Практичне застосування розробленої алгоритмічної бібліотеки для обміну даними з периферією за I2C-протоколом

До I2C-шини в нас підключені: мікроконтролер ATmega32A, годинник реального часу (RTC) PCF8583 та пам’ять EEPROM M24C08. Значення, зчитані з мікросхеми годинника, будемо передавати для візуалізації на персональний комп’ютер.

Зв’язок з ПК реалізований на основі мікросхеми FT232RL.

Мікросхема FT232RL - міст між інтерфейсами USB і UART. З боку ПК, за допомогою додаткових комп’ютерних драйверів, мікросхема ідентифікується як COM-порт, а з боку пристрою має інтерфейс UART. Завдяки мікросхемі FT232RL можна дуже просто підключити свій пристрій до ПК через інтерфейс USB, не вникаючи в його особливості. Дана мікросхема дуже надійна, стабільна, підтримується всіма операційними системами.

Характеристики та особливості мікросхеми FT232RL:

–    одночіповий перехідник з USB в асинхронний послідовний інтерфейс передачі даних (UART);

–       протокол USB повністю реалізований у мікросхемі;

–       інтерфейс UART підтримує режими передачі 7 або 8 біт даних, 1 або 2 стопових біта, різні режими контролю парності;

–       швидкості передачі від 300 бод до 3 мегабод для RS422 / RS485 / TTL та від 300 бод до 1 мегабод для RS-232;

–       налаштовувані виводи CBUS;

–       можливість виведення стану прийому/передачі на зовнішні світлодіоди;

–       можливість подачі тактового сигналу на зовнішні мікросхеми, контролери, ПЛІС (частоти 6, 12, 24 і 48 МГц);

–       висока здатність навантаження виходів;

–       вбудована енергонезалежна пам'ять EEPROM об'ємом 1024 байт.

Мікросхеми постачаються із запрограмованою EEPROM, тому не потрібно програмувати EEPROM для початку роботи.

При роботі з годинником реального часу PCF8583 виставлення значень часу здійснюється за допомогою додаткових кнопок, підключених до порту B. Спершу необхідно натиснути кнопку «Редагування», потім за допомогою інших кнопок виставити години та хвилини (кнопка «Секунди» буде лише обнулювати значення), та ще раз натиснути кнопку «Редагування» для передачі зміненого значення часу до мікросхеми годинника.

PCF8583 являє собою оперативну пам’ять, ємністю 256 байт, у якій перші 8 байт використовуються для годинника, календаря і функцій лічильника. Наступні 8 байт можуть бути запрограмовані на використання в якості регістрів сигналізації. Решта 240 байт відносяться до оперативної пам'яті. Вбудований регістр адреси автоматично нарощується після читання або запису кожного байта даних. Усі числа в регістрах годин за замовчуванням зберігаються в BCD форматі.

Адреса пристрою на I2C-шині встановлена виробником як 101000A0. Вивід А0 ми подали на землю, отже цей біт дорівнює 0.

Зчитування поточного часу з мікросхеми PCF8583 виконується у підпрограмі переривання таймера №1, який налаштований на інтервал 0,5 сек. У підпрограмі за допомогою відповідних функцій формується I2C- посилка, при цьому логічна змінна logicEdit повинна дорівнювати нулю. За допомогою цієї змінної блокується зчитування часу з годинника у момент, коли ми редагуємо поточні значення часу.

Отримані значення з годинника заносяться у вхідний буфер та по завершенню посилки (про це сигналізує змінна I2Ctask) в основній програмі зчитуються з буфера у змінні second, minute, hour та передаються для візуалізації через UART до персонального комп’ютера.

У режимі редагування (один раз натиснута перша кнопка) ми відповідними кнопками кожним натисканням збільшуємо на 1 значення цих змінних.

Оскільки значення змінних second, minute, hour зберігаються у BCD форматі, то для цього ми використовуємо відповідну функцію BCDplus1(), та після інкременту значення перевіряємо його на переповнення, відповідно, 0x60 та 0x24, і у разі чого обнулюємо.

Повторне натискання кнопки редагування формує I2C-посилку для занесення змінених значень часу у годинник, та встановлює логічну змінну logicEdit в нуль, що переводить програму у режим відображення поточного часу.

Мікросхема пам’яті EEPROM M24C08 додає певну функціональність у нашу програму. Для збереження поточного часу у випадку пропажі напруги живлення значення часу заноситься щохвилини у мікросхему пам’яті.

Об’єм пам’яті M24C08 становить 8 кбіт (1024 байти). Ця мікросхема підтримує швидкість I2C-шини 400 кбіт/сек, працює при напрузі від 2,5 до 5В, побайтний або сторінковий (до 16 байт) запис даних, автоматичне збільшення адреси при читанні та запису даних, більше 1 мільйона операцій запису, можливість захисту від перезапису, максимальний час запису 5 мсек (як для побайтного, так і сторінкового режиму).C-адреса M24C08 має такий вигляд:

0 1 0 E2 A9 A8

де E2 представляє собою фізичний вивід мікросхеми і за допомогою нього можемо підключити 2 EEPROM до I2C-шини. А9 та А8 визначають старші біти адреси для внутрішньої пам’яті.

Вивід E2 ми підключили до високого рівня для уникнення конфлікту адреси з мікросхемою годинника. Таким чином адреса мікросхеми пам’яті має таке значення 1 0 1 0 1 A9 A8.

При старті мікроконтролера (перед основним робочим циклом) з EEPROM зчитується значення часу, та одразу ж заноситься у годинник.

В основному робочому циклі постійно перевіряється чи поточне значення хвилин не змінилося, у разі чого відбувається запис в EEPROM. Аналогічний код розміщений і для кнопки «редагування».

3. ДОСЛІДЖЕННЯ ТА РЕАЛІЗАЦІЯ МУЛЬТИМАЙСТЕРНОГО РЕЖИМУ РОБОТИ I2C-ШИНИ

3.1 Організація структури даних для мультимайстерного режиму

 

Цей режим передбачає, що на I2C-шині можуть одночасно бути присутніми декілька головних пристроїв (мікроконтролерів), які виконуватимуть обмін даними з підлеглими пристроями (рис. 3.1). Кожен з мікроконтролерів може бути як головним (master), так і підлеглим (slave) пристроєм. Тобто, він може адресувати інші пристрої, а може і сам бути адресованим.


Рис. 3.1 Мультимайстерна I2C-шина

У мультимайстерному режимі вести передачу на I2C-шині в певний момент часу може лише один пристрій, тобто, хто перший займе шину (виставить сигнал старт), той і зможе виконувати обмін даними з підлеглими пристроями аж до кінця своєї посилки (сигналу стоп). Якщо ж сигнали старт виставлять одночасно декілька пристроїв, тоді між ними проводиться арбітраж (набір правил для керування пріоритетом доступу до шини конкуруючими головними пристроями).

Рис. 3.2 Процедура арбітражу між двома головними пристроями

Арбітраж виконується на лінії SDA при високому рівні сигналу на SCL (рис. 3.2). Пристрій, що формує на лінії SDA високий рівень, а в той час інший пристрій формує низький рівень, тоді перший втрачає право бути головним і повинен перейти у режим підлеглого. Тобто, арбітраж виграє той, що виставляє на лінії SDA «0» в той момент, коли інші виставляють «1». Спершу арбітраж проводиться для байту адреси. Якщо ж конкуруючі пристрої адресують цей самий підлеглий пристрій, тоді арбітраж проводиться для наступних за адресою байтів даних, і аж до сигналу стоп чи повторного старту. Може бути ситуація, коли головні пристрої виконують однотипний обмін даними з підлеглим пристроєм. Тоді вони не зможуть виявити конфлікт на шині.

Оскільки МК AVR можуть працювати з I2C-шиною як в режимі master, так і в режимі slave, то може виникнути ситуація, що вони, окрім того, що можуть втратити арбітраж, то ще й можуть бути в цей момент адресованими іншими мікроконтролерами.

Модуль TWI відпрацьовує усі ці ситуації, як функції арбітражу, так і роботу в slave-режимі, та виставляє у регістрі статусу TWSR відповідні коди для цих ситуацій. Таблиця 3.1 є доповненням до таблиці 2.1.

Таблиця 3.1. Коди статусів для модуля TWI у режимі slave

Код

Стан I2C-шини та модуля TWI

0x38

Втрата пріоритету в режимі master

0x60

Прийнято власну адресу+Write та відіслано ACK

0x68

Втрата пріоритету: прийнято власну адресу+Write та відіслано ACK

0x70

Прийнято загальний виклик+Write та відіслано ACK

0x78

Втрата пріоритету: прийнято загальний виклик+Write та відіслано ACK

0x80

Прийнято байт даних та відіслано ACK

0x88

Прийнято байт даних та відіслано NACK

0x90

Прийнято байт даних та відіслано ACK (заг. виклик)

0x98

Прийнято байт даних та відіслано NACK (заг. виклик)

0xA0

Отримано сигнал stop чи repeat start у режимі slave

0xA8

Прийнято власну адресу+Read та відіслано ACK

0xB0

Втрата пріоритету: прийнято власну адресу+Read та відіслано ACK

0xB8

Був переданий байт даних та отримано ACK

0xC0

Був переданий байт даних та отримано NACK


Оскільки мультимайстерний режим передбачає оброблення більшої кількості задач та ситуацій, що можуть виникати при передачі на I2C-шині, то для забезпечення необхідної функціональності додамо ще два буфери: інфобуфер та буфер даних.

Найперше, ми введемо можливість контролю за виконанням I2C-посилок згідно присвоєних їм номерів задач.

Номер задачі буде присвоюватися посилці під час її формування, а саме: при виклику функції I2C_Start(). Оскільки молодший біт значення, що передається цій функції, відповідає за контроль за виконанням посилки, то, відповідно, адреса може займати лише старші 7 бітів.

Для цього найкраще передбачити ряд макровизначень:

#define       I2C_Task_1                           (1<<1)

#define       I2C_Task_2                           (2<<1)

// … і т.д.

#define       I2C_Task_Slave_command   (126<<1)

#define       I2C_Task_Slave_byte            (127<<1)

Тоді виклик функції буде виглядати таким чином:

C_Start(I2C_Task_1|CONTROL);

Останні два макровизначення дають можливість сигналізувати про прийом даних у режимі slave (по одному прийнятому байту на кожну задачу). При цьому розрізняються командні (ті, що отримуються після власної адреси+Write) та звичайні байти даних.

Виконані задачі записуються в інфобуфер. У режимі master формат даних містить 2 байти: номер виконаної задачі та кількість прийнятих байтів (для контролю). У режимі slave записуються лише по 1 байту (виконана задача прийнятого командного чи звичайного байта). Отримані байти вже безпосередньо зчитуються з буфера IN у порядку запису виконаних задач в інфобуфері. Якщо командний байт містить адресу в буфері даних, тоді інформація про такі задачі не заноситься в інфобуфер, а отримані байти даних записуються безпосередньо вже у буфер даних підпрограмою переривання модуля TWI.

Аналіз виконаних задач здійснюється в основній програмі за допомогою розгалуженого умовного блоку.

char Ntask, Nbytes;(I2Ctask) // якщо є необроблені задачі

{Ctask--;= ReadI2C_BUFinf();(Ntask == I2C_Task_1)

{ // оброблення даних + контроль за кількістю прийнятих байтів= ReadI2C_BUFinf();

}(Ntask == I2C_Task_Slave_command)

{ // аналіз прийнятого командного байта

}(Ntask == I2C_Task_Slave_byte)

{ // аналіз прийнятого байта даних

}

}

У процесі арбітражу через втрату пріоритету виконання поточної I2C-посилки може бути перерване. Тому необхідно постійно тримати у тимчасовій змінній розміщення початку в буфері OUT поточної посилки, і при необхідності відновлювати.

Від МК у режимі slave зовнішній пристрій може вимагати здійснити такі три дії:

–    виконати певну задачу (включити світло, запустити процес оцифрування даних модуля АЦП і т.п.);

–       прийняти байт даних;

–       вислати байт даних з визначеною інформацією (наприклад, отримані результати від модуля АЦП).

Для цього, на зразок периферійних пристроїв, для режиму slave виділяємо окремий буфер даних (рис. 3.3), у якому за кожною коміркою буде закріплено певна величина. Наприклад, сюди можуть записуватися оцифровані значення з АЦП і при потребі зчитуватися зовнішнім пристроєм. Можуть міститися конфігураційні комірки для функціонування МК, значення яких будуть змінюватися іншими пристроями тощо.

Читання та запис даних здійснюється згідно вказаної адреси розміщення даних у буфері. Адреса при цьому автоматично інкрементується, щоб можна було виконувати операції з послідовними даними, наприклад, зчитати I2C-посилкою одразу декілька байтів. Тобто, МК у режимі slave функціонує за правилами, що визначені I2C-протоколом. Для розділення доступу до даних підпрограмою переривання TWI та основною програмою ми передбачили дві змінні: I2C_AutoincBUFdata (основна програма) та I2C_AutoincBUFdataLib (підпрограма переривання).

Програмний код бібліотеки для роботи з I2C-шиною в мультимайстерному режимі є фактично розширенням попередньої бібліотеки для одномайстерного режиму. Тому представимо лише ті частини коду, що відсутні для одномайстерного режиму чи є модифіковані.

До програмного коду необхідно додати два макровизначення для змінної I2C_status, а також тимчасову змінну для відновлення початку I2C- посилки у буфері OUT:

#define       I2C_BUFinfEr              3       // буфер inf заповнений

#define       I2C_AddressW    7       // прийнято адресу+W

// зберігає початок I2C-посилки (буфер OUT) на випадок втрати пріоритетуchar         I2C_StartBufOUTtemp;

Код для буфера даних інфобуфера:

// Буфер даних для режиму Slave

#define       I2C_BUFdataSIZE                 16

#define       I2C_BUFdataMASK              (I2C_BUFdataSIZE-1)char I2C_BUFdata[I2C_BUFdataSIZE], I2C_commandtemp;char I2C_AutoincBUFdata=0, I2C_AutoincBUFdataLib=0;

// Організація інформаційного буфера про виконані задачі

// №126-127 slave режим; №1-125 master режим;

// №0 не вказано номер задачі

#define                 I2C_BUFinfSIZE 16

#define                 I2C_BUFinfMASK       (I2C_BUFinfSIZE-1)char I2C_BUFinf[I2C_BUFinfSIZE], I2C_StartBUFinf=0, I2C_EndBUFinf=0;char I2C_infoNtask, I2C_infoNbytes;

Буфер даних має більшу кількість функцій, що працюють з його даними. Як вже згадувалося, це пов’язано з його структурою, яка хоч і є зацикленою, однак для буфера даних є виділені два незалежні вказівники на комірки з даними.

Певної модифікації зазнає функція I2C_Action(), а от основний функціональний програмний код, що забезпечує роботу в режимі slave та відслідковує функцію арбітражу на I2C-шині прописується у підпрограмі переривання модуля TWI.

Функція ініціалізації повинна приймати значення I2C-адреси для модуля TWI у режимі slave, а також вказівку «1» чи «0» для дозволу/заборони загальних викликів (з адресою 0x00).

Повний програмний код бібліотеки для роботи з I2C-шиною в мультимайстерному режимі наведено у додатку А.

3.2 Реалізація арбітражу на I2C-шині

Тестування та відлагодження розробленої бібліотеки при роботі з I2C-шиною у мультимайстерному режимі для функцій арбітражу виконувалося безпосередньо на фізичному макеті, оскільки у пакеті Proteus виявлено їхню некоректну роботу для МК AVR.

А. Код статусу 0x38 (втрата пріоритету в режимі master). Для цього тесту функцій арбітражу ми змушуємо мікроконтролери одночасно виконувати звертання до пам’яті EEPROM.

Одна кнопка під’єднана одразу до двох МК, а її натиск ініціалізує запуск процедури запису в пам’ять EEPROM. Кожен з МК звертається до своєї області пам’яті в EEPROM. Очікування натиску кнопки ми зациклили у конструкції while{}. Як тільки кнопка буде натиснутою, мікроконтролери одночасно почнуть змагатися за доступ до пам’яті EEPROM. Хто перший видасть на лінію «0», той і отримає пріоритет для доступу, а інший буде очікувати звільнення шини.

Зауважимо, що оскільки запис у пам’ять EEPROM триває деякий час (5-10 мсек.), то мікросхема почне відповідати на свою адресу лише після циклу запису, а до цього на лінії буде NACK.

Для аналізу результатів арбітражу дані з мікроконтролерів передаються через UART-порт до персонального комп’ютера у клієнтську програму. Клієнтська програма працює одночасно з двома СОМ-портами, через які вона отримує дані з конкуруючих мікроконтолерів.

Перший мікроконтролер програє арбітраж, оскільки в адресі EEPROM сьомий біт рівний одиниці, а в другого мікроконтролера - нуль. Далі перший мікроконтролер намагається отримати доступ до пам’яті EEPROM, а остання не відповідає (5-10 мсек.), бо здійснюється запис. По закінчення запису в EEPROM перший мікроконтролер успішно записує дані.

Б. Коди статусів 0x68, 0x78, 0xB0 (втрата пріоритету та перехід у режим роботи slave). Ці коди сигналізують, що МК при спробі вийти зі спробою передачі даних на шині був перерваний іншим МК для його адресації та обміну з ним даними.

3.3 Практичне застосування мультимайстерного режиму

Для дослідження функціональності розробленої програмної бібліотеки для роботи з TWI модулем через апаратні переривання ми розробили мікроконтролерну мережу на основі I2C-інтерфейсу.

Мікроконтролерна мережа складається з двох головних пристроїв мікроконтролерів ATMega32A, та двох периферійних пристроїв годинника реального часу PCF8583 та пам’яті EEPROM М24C08. Обидва мікроконтролери паралельно працюють з годинником та пам’яттю EEPROM, а також обмінюються даними між собою. У цьому прикладі ми реалізували 2 ситуації обміну даними мікроконтролерами між собою по I2C-шині:

1.   відправлення першим МК пакету даних з 4-х байтів (власна адреса, секунди, хвилини, години) другому МК для їхнього запису в буфер даних;

2.      читання першим МК тестових значень та значення з перемикача «піаніно» з буфера даних другого МК.

Для забезпечення обміну даними між мікроконтролерами простір буферів даних розмічений таким чином:

- тестове значення 1;

- тестове значення 2;

- тестове значення 3;

- значення для вибору;

- зовнішній майстер;

- секунди;

- хвилин;

- години.

Програмний код основної програми розроблений таким чином, щоб могти бути використаним для обох мікроконтролерів одночасно.

Таким чином для них забезпечуються I2C-адреси 0x78 та 0x79.

У функції Initializer() при виклику функції ініціалізації модуля TWI необхідно передати їй 2 параметри: I2C-адресу та дозвіл/заборону загальних викликів, а також організувати вивід I2C-адреси на LCD.

// Ініціалізація I2CC_Init(adressI2c, 0);

// вивід адреси МК на дисплей_GotoYX(1,15);_WriteStr( utoa(adressI2c ,Sbuf,16) );

Повний код основної програми для дослідження роботи I2C-інтерфейсу в мультимайстерному режимі наведено у додатку Б.

Для одночасного зчитування даних клієнтською програмою з мікроконтролерів я задіяв два конвертора USB-UART на основі мікросхеми FT232RL.

Для візуалізації даних був розроблений клієнтський модуль мовою С++.

Кнопка з надписом «Відіслати штамп часу до A/B» ініціалізує передачу власної I2C-адреси та поточного часу, отриманого з мікросхеми годинника, іншому МК та вказівки для передачі через UART інтерфейс до комп’ютера записаного у буфер даних штампу часу. Кнопка з надписом «Прочитати значення з А/В» ініціалізує зчитування тестових значень та значення перемикача «піаніно», що записані у буфері даних іншого МК, та передача цих значень клієнтській програмі на комп’ютері.

Для даного прикладу була проведена експериментальна апробація роботи I2C-інтерфейсу в мультимайстерному режимі на фізичному обладнанні. Також протестовано функції арбітражу, що відповідають кодам статусу модуля TWI 0x68, 0x78, 0xB0 (втрата пріоритету та перехід у режим роботи slave) при одночасній посилці даних мікроконтолерами один одному. Для цього були об’єднані однакові виводи PB6 та PB7.

Розроблена бібліотека для модуля TWI може бути використана для організації обміну даними по I2C-інтерфейсу між довільною кількістю різних пристроїв.

4. ЕКОНОМІЧНА ЧАСТИНА

Завданням дипломної роботи є дослідження та алгоритмічна реалізація мультимайстерного режиму роботи I2C-інтерфейсу. Від ефективності розробленої програмної бібліотеки залежить швидкість та простота розроблення вбудованих систем, що здійснюють обмін даними по I2C-шині. Тому такі дослідження є доцільними.

4.1 Розрахунок витрат на виконання дослідної роботи


Витрати на виконання роботи щодо дослідження та реалізації мультимайстерного режиму для I2C-інтерфейсу розраховуються шляхом складання калькуляції кошторисної вартості ДР за наступними статтями:

1. витрати на оплату праці;

2. відрахування на соціальні заходи;

3. матеріали;

4. витрати на використання комп’ютерної техніки;

5. витрати на використання спец обладнання для наукових (експериментальних) робіт;

6. накладні витрати;

7. інші витрати.

4.1.1 Розрахунок витрат на оплату праці

До цієї статті належать витрати на основну та додаткову заробітну плату керівнику дипломної роботи, студенту, консультанту з питань економіки, обчислені за посадовими окладами та відрядними розцінками для робітників, включаючи преміальні виплати. Вихідні дані наводяться у таблиці 4.1.

Таблиця 4.1. Вихідні дані для розрахунку витрат на оплату праці

№ п/п

Посада виконавців

Місячний оклад, грн.

Середньоденна ставка, грн/дн

1

Керівник ДР, доцент

2500

119,05

2

Консультант з економіки, доцент

2500

119,05

3

Студент

600

28,57


Витрати на оплату праці розробників роботи визначаються за формулою


де nij - чисельність розробників і-ої спеціальності j-го тарифного розряду, які приймають участь в проектуванні, чол.; tij - час, котрий затрачений на розробку проекту співробітника і-ої спеціальності j-го тарифного розряду, днів; Cij - денна заробітна плата і-ої спеціальності j-го тарифного розряду, грн., яка визначається за формулою:


де Cij - основна місячна заробітна плата розробника і-ої спеціальності j-го тарифного розряду, грн.; h - коефіцієнт, що визначає розмір додаткової заробітної плати (при умові наявності доплат); р - середня кількість робочих днів у місяці (приймаємо 21 р.д.).

4.1.2 Відрахування на соціальні заходи

Величну відрахувань у спеціальні державні фонди визначають у відсотковому співвідношенні від суми основної та додаткової заробітної плати. Згідно діючого нормативного законодавства сума відрахувань у спеціальні державні фонди складає 36,2% від суми заробітної плати

 грн.

Таблиця 4.2. Розрахунок витрат на оплату праці

№ п/п

Посада виконавців

Час розробки, дні

Денна заробітна плата, грн

Витрати на розробку, грн

1

Керівник ДР, доцент

5

119,05

595,25

2

Консультант з економіки, Доцент

0,25

119,05

29,76

3

Студент

60

28,57

1714,29

Разом

2339,21

 

4.1.3 Розрахунок витрат на матеріали

У таблиці 4.3 наведено перелік купованих виробів і розраховані витрати на них.

Таблиця 4.3. Розрахунок витрат на куповані вироби

№ п/п

Найменування купованих виробів

Одиниця виміру

Ціна на одиницю виміру, грн

Кількість купованих виробів

Сума, грн

Транспортні витрати (10% від суми)

Загальна сума, грн

1

Папір (формат А4)

уп

45,0

2

90,00

9,0

99,0

2

Ручка кулькова

шт

2,0

2

4,00

0,4

4,40

3

Олівець простий

шт

1,50

2

3,00

0,3

3,30

4

Диски DWD-R

шт

2,0

2

4,00

0,4

4,40

5

Зошит, 96 арк

шт

3,50

1

3,50

0,35

3,85

6

Тонер для принтера

уп

40

1

40

4,0

44,0

Разом

158,95


4.1.4 Витрати на використання комп’ютерної техніки

Витрати на використання комп’ютерної техніки включають витрати на амортизацію комп’ютерної техніки, витрати на користування програмним забезпеченням, витрати на електроенергію, що споживається комп’ютером. За даними обчислювального центру НУ «Львівська політехніка» для ЕОМ типу ІВМ РС/АТХ вартість години роботи становить 4,5 грн. Середній щоденний час роботи на комп’ютері - 4 години. Розрахунок витрат на використання комп’ютерної техніки приведений в таблиці 4.4.

Таблиця 4.4. Розрахунок витрат на використання комп’ютерної техніки

№ п/п

Назва етапів робіт, при виконанні яких використовується комп’ютер

Час використання комп’ютера

Витрати на використання комп’ютера, грн



днів

годин


1

Проведення досліджень та оформлення їх результатів

30

120

540

2

Оформлення розділу “Економіка”

2

8

36

3

Оформлення ДР

16

64

288

Разом

48

192

864


4.1.5 Накладні витрати

Накладні витрати проектних організацій включають три групи видатків: витрати на управління, загальногосподарські витрати, невиробничі витрати. Вони розраховуються за встановленими відсотками до витрат на оплату праці. Середньостатистичний відсоток накладних витрат в організації складає 150%.

 (грн.)

.1.6 Інші витрати.

Інші витрати є витратами, які не враховані в інших статтях. Вони становлять 10% від заробітної плати:

 (грн.)

На основі отриманих даних складається калькуляція планової собівартості загалом по дослідній роботі і зводиться в таблицю 4.5.

Таблиця 4.5. Кошторис витрат на виконання НДР

№ п/п

Найменування елементів витрат

Сума витрат, грн

1

Витрати на оплату праці

2339,21

2

Відрахування у спеціальні державні фонди

846,79

3

Витрати на куповані вироби

158,95

4

Витрати на використання комп’ютерної техніки

864

5

Накладні витрати

3508,82

6

Інші витрати

233,92

Разом

7951,69


4.2 Розрахунок договірної ціни та прибутку дослідної роботи

Величина договірної ціни повинна встановлюватися з врахуванням ефективності, якості і термінів виконання дослідної роботи на рівні, який відповідає економічним інтересам замовника (споживача) і виконавця. Договірна ціна дослідної роботи встановлюється по домовленості між замовником та виконавцем і попередньо розраховується за формулою:

Ц=С*(1 + р)

де Ц - договірна ціна, С - собівартість проведення роботи, р - рівень рентабельності витрат у виконавця робти.

Тоді очікуваний прибуток від реалізації дослідної роботи розраховують за формулою:

П = Ц - С ( грн)

де П - очікуваний прибуток від виконання роботи.

Для даної дослідної роботи ціна визначена як:

 1,3*С = 10337,2 грн.

Тоді прибуток буде рівним:

П=1,3*С-С = 0,3*С=0,3*7951,69=2385,51 (грн).

4.3 Оцінка результативності дослідної роботи

Результатом дослідної роботи є досягнення технічного, економічного або соціального ефекту. У даному підрозділі оцінено рівень ефектів від проведеної дослідної роботи.

Науково-технічний ефект характеризує можливість використання результатів виконуваних досліджень у інших дослідних роботах і забезпечує отримання інформації, необхідної для створення нової техніки.

Оцінка науково-технічної ефективності для дослідної роботи проводиться за допомогою коефіцієнтів, які обчислюються за формулами:

 

де , коефіцієнт науково-технічної результативності; - коефіцієнт значимості і-го фактору, використовуваного для оцінки; - коефіцієнт досягнутого рівня і-го фактору; m - кількість факторів науково-технічної результативності.

При оцінці науково-технічної результативності використовуються різні фактори, які впливають на її кількісну оцінку. В якості факторів при оцінці науково-технічної результативності можуть застосовуватися: перспективність використання результатів; масштаб можливої реалізації результатів; завершеність отриманих результатів.

По кожному із факторів експертним шляхом встановлюється числове значення коефіцієнта значимості. При цьому, сума цих коефіцієнтів повинна бути рівною 1. Коефіцієнт досягнутого рівня фактору також встановлюється експертним шляхом, а його числове значення визначається з урахуванням якості ознаки фактору і його характеристики. При цьому його значення не перевищує 1.

Максимально можливе значення коефіцієнту науково-технічної ефективності рівне 1. Чим ближчі їх значення до 1-і, тим більша результативність дослідної роботи, яка проводиться.

З таблиці 4.6 слід вибрати фактори та ознаки, які характеризують, науково-технічну результативності дослідної роботи .

Таблиця 4.6 Характеристики факторів та ознак науково-технічної результативності дослідної роботи

Фактор науково-технічної результативності

Коефіцієнт значимості фактору

Якість фактора

Характеристика фактора

Коефіцієнт досягнутого рівня

Перспективність використання результатів

0,5

Важлива

Результати будуть використані в конкретному науковому напрямі при розробці нових технічних рішень, націлених на суттєве підвищення продуктивності праці

0,8

Масштаб можливої реалізації результатів

0,3

Галузевий

Час реалізації: до трьох років

0,8

Завершеність отриманих результатів

0,2

Середня

Технічне завдання на прикладні НДР чи ДКР

0,8


Згідно із наведенеми даними розраховуємо коефіцієнт науково-технічної ефективності:


Висновки

У цьому розділі проведено розрахунки собівартості дослідної роботи, планового прибутку від її реалізації та оцінено науково-технічну результативність дослідної роботи.

Дослідження, які проведені у роботі, спрямовані на вивчення особливостей роботи мережі, до якої пристрої підключаються за I2C-протоколом. Розроблено уніфіковану бібліотеку, що може використовуватися у проектних рішення, побудованих з використанням обміну даними за I2C-протоколом.

Розробивши план проведення дослідної роботи, було підраховано кошторис витрат: витрати на заробітну плату, відрахування у спеціальні державні фонди, витрати на куповані вироби, витрати на використання комп’ютерної техніки, накладні витрати. Загалом кошторис витрат на проведення дослідної склав 7951,69 грн.

Коефіцієнт науково-технічної ефективності 0,8, що є хорошим показником. Економічний ефект від використання проектного рішення полягає у зниженні фінансових, ресурсних та часових витрат при використанні сучасних контролерів та давачів.

ВИСНОВКИ

У дипломній роботі проведено актуальні дослідження, що мали на меті реалізацію мультимайстерного режиму для I2C-інтерфейсу, та отримано такі результати:

1.   Згідно проведеного аналізу роботи I2C-інтерфейсу в мультимайстерному режимі запропоновано структуру даних і механізми для їхнього оброблення, що забезпечують роботу з I2C-шиною з використанням апаратних переривань.

2.      Розроблена структура дає можливість у повній мірі реалізувати усі функції арбітражу для I2C-шини.

.        Розроблені алгоритми для реалізації мультимайстерного режиму з використанням апаратних переривань просимулювані та протестовані в пакеті Proteus.

.        Усі отримані результати експериментально апробовані на фізичному обладнанні.

Розроблені алгоритми можуть бути оформлені у вигляді окремої програмної бібліотеки та використовуватися у проектах, що передбачають підключення до мікроконтролерів пристроїв за I2C-інтерфейсом. Використання готової бібліотеки значно пришвидшить процес розроблення проектного рішення.

СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ

1.     Рюмик, С. М. 1000 и одна микроконтроллерная схема Вып. 1//С. М. Рюмик. - Додэка-21, 2010.-356 с.

2.      Шпак. Ю. А. Программирование на языке С для AVR и PIC микроконтроллеров. Изд. 2-е, переработанное и дополненное.// Сост. Ю. А. Шпак - К.: “МК-Пресс”. СП.: “КОРОНА-ВЕК”, 2011 - 544с.

.        Евстифеев А. В. Микроконтроллеры AVR семейства Tiny и Mega фирми ATMEL, 5-е изд., стер. - М.: Издательский дом “Додэка-21”, 2008. - 560с.

4.     Лапин А.А. Интерфейсы. Выбор и реализация. М.: Техносфера, 2005. - 168 с.

5.     ATmega32A. Datasheets - Atmel Corporation. - 353 pages.

6.      Роман Абраш. Книга по работе с WinAVR и AVR Studio. - Підбірка статей у журналі «Радиолюбитель» за період 01/2010-05/2011. - 88 стр.

7.      AVR Libc Development Pages. - <http://www.nongnu.org/avr-libc>.

.        Anil Kumar Maini. Digital Electronics: Principles, Devices and Applications. John Wiley & Sons, Ltd. - 2007. - 727 pages.

.        AVR311: Using the TWI module as I2C slave. Application Note - Atmel Corporation. - 12 pages.

.        AVR315: Using the TWI module as I2C master. Application Note - Atmel Corporation. - 14 pages.

.        UM10204. I2C-bus specification and user manual. - NXP Semicon¬ductors. 2012. - 64 pages.

.        PCF8583. Clock and calendar with 240 x 8-bit RAM. Datasheets - NXP Semiconductors. - 2010. - 37 pages.

.        Иди Ф. Сетевой и межсетевой обмен данными с микроконтроллерами. - М.: Издательский дом «Додэка XXI», 2007. - 376 с.

.        Парк Д., Маккей С., Райт Э. Передача данных в системах контроля и управления. - М.: ООО «Группа ИДТ», 2007. - 480 с.

ДОДАТКИ

Додаток А

Лістинг бібліотеки для роботи з I2C-шиною в мультимайстерному режимі

#define                 ACK           0       //підтвердження активне

#define                 NACK                 1       //підтвердження відсутнє

#define                 I2C_W                 0       //запит на запис

#define                 I2C_R                  1       //запит на читання

#define                 CONTROL          1       //зворотній контроль виконання пакету

#define                 NOCONTROL    0       //зворотній контроль виконання пакету

#define                 TWBRcalc  (F_CPU/I2Cspeed-16)/2

#define                 I2C_BUF_SIZE_OUT  64

#define                 I2C_BUF_MASK_OUT        (I2C_BUF_SIZE_OUT-1)

#define                 I2C_BUF_SIZE_IN                64

#define                 I2C_BUF_MASK_IN            (I2C_BUF_SIZE_IN-1)

char I2C_BufOUT[I2C_BUF_SIZE_OUT], I2C_StartBufOUT=0, I2C_EndBufOUT=0;char I2C_BufIN[I2C_BUF_SIZE_IN], I2C_StartBufIN=0, I2C_EndBufIN=0;char I2C_StartBufOUTtemp; //зберігає поч. буфера на випадок втрати пріоритетуunsigned char I2Ctask=0;       //вказує, скільки опрацьовано повних пакетів start-stopchar I2C_status=0; //0bit-NACKer, 1bit-BufOUTer, 2bit-BufINer, 3bit-BUFinfEr

//5bit-Proccess, 6bit-Control, 7bit-адреса+W

#define                 I2C_NACKer                         0       // slave не відповів NACK

#define                 I2C_BufOUTer             1       // буфер OUT заповнений

#define                 I2C_BufINer                          2       // буфер IN заповнений

#define                 I2C_BUFinfEr              3       // буфер inf заповнений

#define                     I2C_Proccess   5       // вказує, чи відбувається зараз передача на I2-шині

#define                     I2C_Control    6       // вказує, чи необх. звітуватися про викон.

#define                     I2C_AddressW         7       // прийнято адресу+W

// Організація інформаційного буфера про виконані задачі

// №126-127 slave режим; №1-125 master режим; №0 не вказано номер задачі

#define                 I2C_BUFinfSIZE 16

#define                 I2C_BUFinfMASK       (I2C_BUFinfSIZE-1)char I2C_BUFinf[I2C_BUFinfSIZE], I2C_StartBUFinf=0, I2C_EndBUFinf=0;char I2C_infoNtask, I2C_infoNbytes;WriteI2C_BUFinf(unsigned char value)      // запис в інформаційний буфер

{C_BUFinf[I2C_EndBUFinf++] = value;C_EndBUFinf &= I2C_BUFinfMASK;

//перевіряємо на переповнення буфера

//if(I2C_StartBUFinf==I2C_EndBUFinf)

//       I2C_status |= 1<<I2C_BUFinfEr; // помилка: буфер заповнений

}        // розкоментувати при необхідностіchar ReadI2C_BUFinf()       // читання з інформаційного буфера

{char value = I2C_BUFinf[I2C_StartBUFinf++];C_StartBUFinf &= I2C_BUFinfMASK;value;

}

#define                 I2C_Task_1                  (1<<1)

#define                 I2C_Task_2                  (2<<1)

#define                 I2C_Task_3                  (3<<1)

#define                 I2C_Task_4                  (4<<1)

#define                 I2C_Task_5                  (5<<1)

#define                 I2C_Task_Slave_command   (126<<1)

#define                 I2C_Task_Slave_byte   (127<<1)

// Буфер даних для режиму Slave

#define                 I2C_BUFdataSIZE       16

#define                 I2C_BUFdataMASK    (I2C_BUFdataSIZE-1)char I2C_BUFdata[I2C_BUFdataSIZE], I2C_AutoincBUFdata=0, I2C_AutoincBUFdataLib=0;char I2C_commandtemp;

// запис у буфер данихWriteI2C_BUFdata_adr(unsigned char address,unsigned char value) //address=[0, I2C_BUFdataSIZE-1]

{(address<I2C_BUFdataSIZE)

{C_AutoincBUFdata=address;C_BUFdata[I2C_AutoincBUFdata++] = value;C_AutoincBUFdata &= I2C_BUFdataMASK;

}

}WriteI2C_BUFdata(unsigned char value)

{C_BUFdata[I2C_AutoincBUFdata++] = value;C_AutoincBUFdata &= I2C_BUFdataMASK;

}

// запис у буфер даних (бібліотечне)WriteI2C_BUFdataLib(unsigned char value)

{C_BUFdata[I2C_AutoincBUFdataLib++] = value;C_AutoincBUFdataLib &= I2C_BUFdataMASK;

}

// запис у буфер даних без автоінкрементуWriteI2C_BUFdata_noinc(unsigned char address,unsigned char value)

{(address<I2C_BUFdataSIZE)

{C_BUFdata[address] = value;

}

}

// читання з буфера данихchar ReadI2C_BUFdata_adr(unsigned char address)         //address=[0, I2C_BUFdataSIZE-1]

{(address<I2C_BUFdataSIZE)

{C_AutoincBUFdata=address;char value = I2C_BUFdata[I2C_AutoincBUFdata++];C_AutoincBUFdata &= I2C_BUFdataMASK;value;

}0;

}char ReadI2C_BUFdata()

{char value = I2C_BUFdata[I2C_AutoincBUFdata++];C_AutoincBUFdata &= I2C_BUFdataMASK;value;

}

// читання з буфера даних (бібліотечне)char ReadI2C_BUFdataLib()

{char value = I2C_BUFdata[I2C_AutoincBUFdataLib++];C_AutoincBUFdataLib &= I2C_BUFdataMASK;value;

}void I2C_Init(unsigned char address, unsigned char generalcall)

{= TWBRcalc;     //Bit Rate= 0;                          //подільник TWPS=0CDDR &= ~(1<<SCLpin | 1<<SDApin); //на вхідCPORT |= 1<<SCLpin | 1<<SDApin; //підтягуючі резистори= address<<1|generalcall;                  //адреса у режимі slave= 1<<TWEA|1<<TWEN|1<<TWIE;

}WriteI2C_BufOUT(unsigned char value)         // запис у буфер передачі I2C

{C_BufOUT[I2C_EndBufOUT++] = value;C_EndBufOUT &= I2C_BUF_MASK_OUT;

//перевіряємо на переповнення буфера

//if(I2C_StartBufOUT==I2C_EndBufOUT)

//       I2C_status |= 1<<I2C_BufOUTer; // помилка: буфер заповнений

}        // розкоментувати при необхідностіWriteI2C_BufIN(unsigned char value)    // запис у буфер прийому I2C

{C_BufIN[I2C_EndBufIN++] = value;C_EndBufIN &= I2C_BUF_MASK_IN;

//перевіряємо на переповнення буфера

//if(I2C_StartBufIN==I2C_EndBufIN)

//       I2C_status |= 1<<I2C_BufINer; // помилка: буфер заповнений

}        // розкоментувати при необхідностіchar ReadI2C_BufOUT()     // читання з буфера передачі I2C

{char value = I2C_BufOUT[I2C_StartBufOUT++];C_StartBufOUT &= I2C_BUF_MASK_OUT;value;

}char ReadI2C_BufIN()         // читання з буфера передачі I2C

{char value = I2C_BufIN[I2C_StartBufIN++];C_StartBufIN &= I2C_BUF_MASK_IN;value;

}

void I2C_SearchStartStop()

{char temp=1, I2C_StartBufOUTtemp;

{C_StartBufOUTtemp=I2C_StartBufOUT;(ReadI2C_BufOUT())

{0x20: //якщо команда адреси0x40: //якщо команда відправки байтаC_BufOUT(); break;  //то зчитуємо ще й наст. байт0x80: break;      //якщо команда читатння байта0x04:               //якщо команда Stop0x10:                          //якщо комадна ReStart=0; //пошук завершенийC_StartBufOUT=I2C_StartBufOUTtemp; //відновл. адресу у буфері;

}

}(temp==1) ;

inline void I2C_Start(unsigned char control)

{();                                //заборона глобальних перериваньC_BufOUT(control);         //вказує чи потрібно звітуватися про виконання

}void I2C_ReStart()

{C_BufOUT(0x10);      //вказуємо, що Повторний СТАРТ

}void I2C_Address(unsigned char address, unsigned char direction)

{C_BufOUT(0x20);      //вказує, що далі піде передача адресиC_BufOUT(address<<1 | direction); //адреса + напрям передачі

}void I2C_SendByte(unsigned char byte)

{C_BufOUT(0x40);      //вказує, що далі піде передача байту данихC_BufOUT(byte);         //байт даних

}void I2C_ReadByte(unsigned char ack)

{C_BufOUT(0x80+ack);        //вказує, що далі піде читання байту даних

}                                                       //та вказує стан ACK/NACK у мол. біті

inline void I2C_Stop()

{C_BufOUT(0x04);      //вказуємо, що СТОП( (I2C_status&(1<<I2C_Proccess)) == 0)        // якщо передача на I2C-шині відсутня

{C_status |= 1<<I2C_Proccess;       // TWI зайнятий= 1<<TWEA|1<<TWINT|1<<TWSTA|1<<TWEN|1<<TWIE; // StartC_StartBufOUTtemp=I2C_StartBufOUT;char temp = ReadI2C_BufOUT();(temp & 0x01)      I2C_status |= 1<<I2C_Control;                             I2C_status &= ~(1<<I2C_Control);C_infoNtask = 0xFE & temp;C_infoNbytes = 0;

}();              //дозвіл глобальних переривань

}

void I2C_Action()

{(ReadI2C_BufOUT())

{0x04:  //команда СТОП(I2C_status & (1<<I2C_Control))

{Ctask++;(I2C_infoNtask!=0)         // якщо адреса задачі не 0

{C_BUFinf(I2C_infoNtask);  // запис в інфобуфер №задачіC_BUFinf(I2C_infoNbytes);// запис в інфобуфер к-сть прийнятих байт

}

}

// перевіряємо на спорожнення буфера(I2C_StartBufOUT==I2C_EndBufOUT)

{C_status &= ~(1<<I2C_Proccess);                   // TWI вільний= 1<<TWEA|1<<TWINT|1<<TWSTO|1<<TWEN|1<<TWIE; // Stop

}

{= 1<<TWEA|1<<TWINT|1<<TWSTO|1<<TWEN;  //команда Stop= 1<<TWEA|1<<TWINT|1<<TWSTA|1<<TWEN|1<<TWIE; //StartC_StartBufOUTtemp=I2C_StartBufOUT;char temp = ReadI2C_BufOUT();(temp & 0x01)      I2C_status |= 1<<I2C_Control;                                                I2C_status &= ~(1<<I2C_Control);C_infoNtask = 0xFE & temp;C_infoNbytes = 0;

};0x10: //команда ReStart= 1<<TWEA|1<<TWINT|1<<TWSTA|1<<TWEN|1<<TWIE; break;0x20:    //передача адреси на шину I2C0x40: //запис байту даних на шину I2C= ReadI2C_BufOUT();= 1<<TWEA|1<<TWINT|1<<TWEN|1<<TWIE; break;

//читання байту даних на шині I2C0x80:         TWCR = 1<<TWINT|1<<TWEA|1<<TWEN|1<<TWIE; break;0x81: TWCR = 1<<TWINT|0<<TWEA|1<<TWEN|1<<TWIE; break;

}

}

ISR(TWI_vect)

{(TWSR & 0b11111000)

{

//================== у режимі Master =====================================0x08:    //був сформований СТАРТ0x10:         //був сформований Повторний СТАРТ0x18:  //була передана адреса+Write та отримано ACK0x28:   //була переданий байт даних та отримано ACK0x40:       //була передана адреса+Read та отримано ACKC_Action(); break;0x50:       //був прочитаний байт та передано ACK0x58:         //був прочитаний байт та передано NACKC_BufIN(TWDR); I2C_infoNbytes++; I2C_Action(); break;0x20: //була передана адреса+Write та отримано NACK0x30: //був переданий байт даних та отримано NACK0x48: //була передана адреса+Read та отримано NACKC_status |= 1<<I2C_NACKer; // помилка: NACKC_SearchStartStop(); I2C_Action(); break;0x38:      //втрата пріоритетуC_StartBufOUT=I2C_StartBufOUTtemp; //відновл. поч. у буфері= 1<<TWEA|1<<TWINT|1<<TWSTA|1<<TWEN|1<<TWIE;C_BufOUT();;

//================== у режимі Slave =====================================0x68:    //втрата пріоритету ->прийн. власну адресу+W та відісл. ACK0x78:   //втрата пріоритету ->прийн. заг. виклик+W та відісл. ACKC_StartBufOUT=I2C_StartBufOUTtemp; //відновл. поч. у буфері0x60:         //прийнято власну адресу+W та відіслано ACK0x70:       //прийнято загальний виклик+W та відіслано ACKC_status |= 1<<I2C_Proccess;                  // TWI зайнятийC_status |= 1<<I2C_AddressW;                  // прийнято адресу+W= 1<<TWEA|1<<TWINT|1<<TWEN|1<<TWIE;  //Slave готовий;0x88:   //прийнято байт даних та відіслано NACK0x98:      //прийнято байт даних та відіслано NACK (загальний виклик)

0x80: //прийнято байт даних та відіслано ACK0x90:         //прийнято байт даних та відіслано ACK (загальний виклик)( I2C_status & (1<<I2C_AddressW) )

{        //якщо попередньою була адреса МКC_status &= ~(1<<I2C_AddressW);         //скид бітаC_commandtemp=TWDR;(I2C_commandtemp>=I2C_BUFdataSIZE)

{C_BUFinf(I2C_Task_Slave_command);C_BufIN(TWDR);Ctask++;

}C_AutoincBUFdataLib=I2C_commandtemp;

}        // прийом байту даних

{(I2C_commandtemp>=I2C_BUFdataSIZE)

{C_BUFinf(I2C_Task_Slave_byte);                                                                           WriteI2C_BufIN(TWDR);Ctask++;

}        WriteI2C_BUFdataLib(TWDR);

}= 1<<TWEA|1<<TWINT|1<<TWEN|1<<TWIE;;0xA0: // Stop або ReStart у режимі slave(I2C_StartBufOUT!=I2C_EndBufOUT) //якщо вих. буфер не порожн

{= 1<<TWEA|1<<TWINT|1<<TWSTA|1<<TWEN|1<<TWIE;

}

{= 1<<TWEA|1<<TWINT|1<<TWEN|1<<TWIE;      //Slave готовийC_status &= ~(1<<I2C_Proccess);                       // TWI вільний

};0xB0:      // втрата пріоритету ->прийн власну адресу+R та відісл ACKC_StartBufOUT=I2C_StartBufOUTtemp; //відновл. поч. у буфері

0xA8: // прийнято власну адресу+R та відіслано ACKC_status |= 1<<I2C_Proccess;                            // TWI зайнятий= ReadI2C_BUFdataLib();= 1<<TWEA|1<<TWINT|1<<TWEN|1<<TWIE;;0xB8: // був переданий байт даних та отрим. ACK= ReadI2C_BUFdataLib();= 1<<TWEA|1<<TWINT|1<<TWEN|1<<TWIE;;0xC0: // був переданий байт даних та отрим. NACK(I2C_StartBufOUT!=I2C_EndBufOUT) //якщо вих буфер не порожній

{= 1<<TWEA|1<<TWINT|1<<TWSTA|1<<TWEN|1<<TWIE;

}

{= 1<<TWEA|1<<TWINT|1<<TWEN|1<<TWIE;      //Slave готовийC_status &= ~(1<<I2C_Proccess);                       // TWI вільний

};

}

}

Додаток Б

Лістинг програми МК ATmega32A для дослідження роботи

C-інтерфейсу в мультимайстерному режимі

//=========== LCD Define ======================================

#define  LCDPORT       PORTA      // LCD Data Port 0..3

#define  LCDPIN PINA

#define  LCDDDR         DDRA

//=========== I2C Define ======================================

#define  I2CPORT         PORTC

#define  I2CDDR DDRC

#define  SCLpin   PC0

#define  SDApin  PC1

//#define    F_CPU                  8000000L

//100KHz (8MHz)

#define  I2Cspeed 100000L

//=============================================================

#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

#include <stdlib.h>

#include "LCD_4.h"

#include "I2Cmultimaster.h"Initializer();BCDplus1(unsigned char *bcd);LCDout();TimeStampToLCD();TestValueToLCD();Sbuf[10];char second, minute, hour, logicEdit=0, change=0, temp_minute;char tenchar[10] ={'0','1','2','3','4','5','6','7','8','9'};

#define  Master                                0

#define  adressEEPROM                 (0b1010100|Master)

#define  adressI2c                            (0x78|Master)char test1, test2, test3, switchvalue;

//-------------Вектор переривань таймера 1 ----------------------------------(TIMER1_COMPA_vect)

{(logicEdit==0)

{C_Start(I2C_Task_1|CONTROL);C_Address(0b1010000, I2C_W);C_SendByte(0x02);C_ReStart();C_Address(0b1010000, I2C_R);C_ReadByte(ACK);    //читаємо секундиC_ReadByte(ACK); //читаємо хвилиниC_ReadByte(NACK); //читаємо годинуC_Stop();

}

}main()

{();

// заповнення буфера данихC_BUFdata_adr(0,0x12);    //testvalue1C_BUFdata(0x34);                       //testvalue2C_BUFdata(0x56);                     //testvalue3();

// зчитування поточного часу з EEPROMC_Start(CONTROL);C_Address(adressEEPROM, I2C_W);C_SendByte(0x80);C_ReStart();C_Address(adressEEPROM, I2C_R);C_ReadByte(ACK);   //читаємо секундиC_ReadByte(ACK);     //читаємо хвилиниC_ReadByte(NACK);        //читаємо годинуC_Stop();

// очікуємо кінця сеансу читання з I2C-шини(I2Ctask==0) { }Ctask--;

// читаємо з вхідного буфера значення часу=ReadI2C_BufIN();=ReadI2C_BufIN();=ReadI2C_BufIN();( (second&0xF0) >= 0x60 || (second&0x0F) >= 0x0A )= 0;( (minute&0xF0) >= 0x60 || (minute&0x0F) >= 0x0A )= 0;( (hour&0xE0) == 0 && (hour&0x0F) >= 0x0A || hour == 2 && (hour&0x0F) >= 0x04 || (hour&0xF0) >= 0x30)= 0;_minute = minute;

// запис у годинник значення часу з EEPROMC_Start(NOCONTROL);C_Address(0b1010000, I2C_W);C_SendByte(0x02);C_SendByte(second);C_SendByte(minute);C_SendByte(hour);C_Stop();char freePIN=1, key=1, edit=0;char Ntask, Nbytes;char SlaveCommand;(1) //основний робочий цикл

{C_BUFdata_noinc(3,PIND&0x7F);// занесення в буфер даних значення switch(I2Ctask)

{Ctask--;

// розбирання поточної задачі у вхідному буфері TWI= ReadI2C_BUFinf();(Ntask==I2C_Task_1)

{=ReadI2C_BufIN();=ReadI2C_BufIN();=ReadI2C_BufIN();();= ReadI2C_BUFinf();

}(Ntask==I2C_Task_2)

{=ReadI2C_BufIN();=ReadI2C_BufIN();=ReadI2C_BufIN();=ReadI2C_BufIN();();= ReadI2C_BUFinf();

}( Ntask == I2C_Task_Slave_command )

{=ReadI2C_BufIN();(SlaveCommand==51)

{();

}

//else ...

}( Ntask == I2C_Task_Slave_byte )

{

}

}(edit) {LCDout(); edit=0;}(temp_minute != minute)

{    // запис в EEPROM поточного часу_minute = minute;C_Start(NOCONTROL);C_Address(adressEEPROM, I2C_W);C_SendByte(0x80);C_SendByte(second);C_SendByte(minute);C_SendByte(hour);C_Stop();

}(freePIN == 1)    //перевірка чи була натиснута кнопка

{                   //якщо =1, тоді ще не натисалася(PINB != 0xFF)

{= 0;|= 1<<7;   //включаємо бузер(bit_is_clear(PINB,0))    //у режим редагування

{^=1;_GotoYX(1,10);(logicEdit==1)_WriteStr("Edit");

{_WriteStr(" ");(change==1)

{    // запис у годинникC_Start(NOCONTROL);C_Address(0b1010000, I2C_W);C_SendByte(0x02);C_SendByte(second);C_SendByte(minute);C_SendByte(hour);C_Stop();

// запис в EEPROM поточного часу_minute = minute;C_Start(NOCONTROL);C_Address(adressEEPROM, I2C_W);C_SendByte(0x80);C_SendByte(second);C_SendByte(minute);C_SendByte(hour);C_Stop();

}

}=0;

}(bit_is_clear(PINB,1)) //змінюємо години

{(logicEdit==1)

{=1;(&hour);(hour==0x24) hour=0;=1;

}

}(bit_is_clear(PINB,2)) //змінюємо хвилини

{(logicEdit==1)

{=1;(&minute);(minute==0x60) minute=0;=1;

}

}(bit_is_clear(PINB,3)) //обнулюємо секунди

{(logicEdit==1)

{=1;=0;=1;

}

}(bit_is_clear(PINB,6)) // відправити іншому МК часовий штамп

{C_Start(NOCONTROL);C_Address(adressI2c^1, I2C_W);C_SendByte(4);C_SendByte(adressI2c);C_SendByte(second);C_SendByte(minute);C_SendByte(hour);C_ReStart();C_Address(adressI2c^1, I2C_W);C_SendByte(51);      // команда для виводу на LCDC_Stop();

}(bit_is_clear(PINB,7)) // прочитати з іншого МК значення з буфера даних

{C_Start(I2C_Task_2|CONTROL);C_Address(adressI2c^1, I2C_W);C_SendByte(0x00);C_ReStart();C_Address(adressI2c^1, I2C_R);C_ReadByte(ACK);    //читаємо testvalue1C_ReadByte(ACK);       //читаємо testvalue2C_ReadByte(ACK);    //читаємо testvalue3C_ReadByte(NACK);     //читаємо switchvalueC_Stop();

}

_delay_ms(300);           //затримка для бузера&= ~(1<<7);          //виключаємо бузер=1;

}

}(PINB == 0xFF) //перевіряємо чи кнопка відпущена

{

_delay_ms(200);=1;

}

}

}Initializer()  //Ініціалізація заліза

{

//Ініціалізація портів

//Порт A= 0x00;= 0xFF;

//Порт B= 0x00;= 0xFF;

//Порт С -- I2C= 0x00;= 0xFF;

//Порт D= 0b10000000;= 0b01111111;

//Ініціалізація LCD();

//Ініціалізація Таймера#1

//Режим: Скид При Співпадінні OCR1A (0.5sec) + дільник=256AH = 0x3D;AL = 0x08;A = 0x00;B = (1<<WGM12)|(1<<CS12);

//дозвіл на переривання по співпадінню T1|= 1<<OCIE1A;

//Ініціалізація I2C

//100KHz (8MHz)C_Init(adressI2c,0);

// вивід адреси МК на дисплей_GotoYX(1,15);_WriteStr( utoa(adressI2c ,Sbuf,16) );

}BCDplus1(unsigned char *bcd)

{char bcdl=(*bcd)&0x0F, bcdh=(*bcd)>>4;++;(bcdl==10)

{ bcdl=0; bcdh++; }

*bcd = (bcdh<<4) | bcdl;

}LCDout()

{_GotoYX(1,1);_WriteLetter(tenchar[hour >> 4]);_WriteLetter(tenchar[hour & 0x0F]);_WriteLetter(':');_WriteLetter(tenchar[minute >> 4]);_WriteLetter(tenchar[minute & 0x0F]);_WriteLetter(':');_WriteLetter(tenchar[second >> 4]);_WriteLetter(tenchar[second & 0x0F]);

}TimeStampToLCD()

{char second_buf, minute_buf, hour_buf, master_buf;_buf=ReadI2C_BUFdata_adr(4);_buf=ReadI2C_BUFdata();_buf=ReadI2C_BUFdata();_buf=ReadI2C_BUFdata();_GotoYX(2,1);_WriteStr( utoa(master_buf ,Sbuf,16) );_WriteLetter('>');_WriteLetter(tenchar[hour_buf >> 4]);_WriteLetter(tenchar[hour_buf & 0x0F]);_WriteLetter(':');_WriteLetter(tenchar[minute_buf >> 4]);_WriteLetter(tenchar[minute_buf & 0x0F]);_WriteLetter(':');_WriteLetter(tenchar[second_buf >> 4]);_WriteLetter(tenchar[second_buf & 0x0F]);_WriteLetter(' ');_WriteLetter(' ');_WriteLetter(' ');_WriteLetter(' ');_WriteLetter(' ');

}TestValueToLCD()

{_GotoYX(2,1);_WriteStr( utoa(test1 ,Sbuf,16) );_WriteLetter('-');_WriteStr( utoa(test2 ,Sbuf,16) );_WriteLetter('-');_WriteStr( utoa(test3 ,Sbuf,16) );_WriteLetter('-');_WriteStr( utoa(switchvalue ,Sbuf,2) );

}

Похожие работы на - Дослідження та реалізація мультимайстерного режиму для I2C-інтерфейсу

 

Не нашли материал для своей работы?
Поможем написать уникальную работу
Без плагиата!