58. Починається цикл з глобальної заборони всіх переривань (рядок 51). Потім формується захисна пауза. Для формування паузи використовується функція wait ().
Дія цієїфункціїповністюаналогічно дії одноіменний процедури зпрограми на Асемблері. У рядку 52 формується затримка першого виду (48 мс), тобто викликається функція wait () з параметром, рівним одиниці. По закінченню затримки (рядок 53) програма повторно зчитує код стану клавіатури і записує його в змінну cods.
У рядку 54 лічений код записується в буфер ОЗУ (bufr). Одночасно покажчик буфера збільшується на одиницю. В рядку 55 перевіряється умова переповнення буфера. така перевірка примусово завершує роботу циклу при спробівведення занадто довгоюкодовоїкомбінації. Якщо значення iiперевищує величину константи bsize, значить, буфер вже повністю заповнений. У цьому випадку управління передається по мітці Ш4, тобто на кінець циклу.
Якщо значення ii не досягло кінця буфера, то перехід не проходить, і управління переходить до рядка 56. У цьому місці запускається процес формування контрольного проміжку часу. Для запуску цього процесу використовується функція wait (). В даному випадку вона формує затримку другого типу, тому викликається з параметром, рівним двом.
Так само, як і в програмі на Асемблері, затримка другого типу лише виробляє все настройки таймера, але невиконує цикл очікування. Комбінований цикл очікування перебуває поза функції затримки, а точніше в рядках 57, 58. У рядку57зчитується новий код стануклавіатуриіпорівнюєтьсязі старим, котрий зберігається в змінної cods.
Якщо коди не рівні (стан клавіатури змінилося), комбінований цикл очікування переривається, і управління передається по мітці m2. Тобто на початок циклу введення кодової комбінації. А вже там, на початку циклу, знову формується захисна затримка, і черговий код стану поміщається в буфер.
- 26 -
Якщо при перевірці в рядку 57 старий і новий коди виявилися всі самому рівні між собою, переходу не відбувається, і виконується рядок 58. У цьому рядку перевіряється значення прапора flz. якщо контрольний проміжок часу ще не закінчився, то значення прапора дорівнює нулю, і управління передається по мітці m3. Комбінований цикл триває.
Якщо ж контрольний проміжок часу вже закінчиться, значення прапора f1z дорівнює одиниці. Тому переходу не відбувається, і управління переходить до рядка 59. На цьому і комбінований цикл очікування, і цикл введення кодової комбінації закінчуються.
У рядку 59 перевіряється стан тумблера s11. В залежності від цього стану виконуєтьсяабозаписщойноприйнятоїкодовоїкомбінаціївEEPROM,абовитяг з EEPROM і порівняння двох кодових комбінацій. Для перевірки стану перемикача оцінюється значення сьомого розряду порту РВ. Якщо контакти перемикачарозімкнуті(PINB.7дорівнює одиниці), то управління передається по мітці comp (до процедури порівняння кодів). В іншому випадку виконується процедура запису.
Процедура записукоду в EEPROM займає рядки 60-62. В рядку 60 довжина кодової комбінації записується в змінну klen. Так як при описі змінної klen(див. Рядок 9) її місцем розташування обраний EEPROM, то записане в змінну значення автоматично туди і потрапляє. Мова СІ сам виконує всі необхідні для цього процедури. Як бачите, в мові СІ запис в EEPROM відбувається набагато простіше, ніж на Асемблері.
У рядку 61 знаходиться цикл, який проводить запис в EEPROM самої кодової комбінації. Цикл просто по черзі записує кожен елемент масиву bufr в відповідний елемент масиву bufе. A bufе цілком знаходиться в EEROM. Як параметр циклу використовується змінна i. По ходу роботи циклу значення цієї змінної змінюється від нуля до ii. Тобто перебираються но міра всіх елементів кодової комбінації (ii одно її довжині). Тіло циклу складає всього один
- 27 -
вислів. Цей вислів записує значення чергового елемента буфера bufr в буфер bufe.
Причому в якості покажчика для обох масивів використовується одна і та ж змінна. Томувбуферіbufeелементипотрапляютьвтіжпозиції,яківонизаймали в буфері bufе Після закінчення циклу записи управління переходить до рядка 62. У цьому рядку знаходиться оператор безумовного переходу, який передає управління у мітці zamok. Тобто до процедури відкриття замку. клацання механізма замку сповіщає про закінчення процесу запису.
Процедура перевірки займає рядки 63, 64. Нагадаємо, що до початку цієї процедуризміннаiiміститьдовжинущойно введеноїкодовоїкомбінації, абуфер bufг - саму цю комбінацію. Спочатку, в рядку 63, порівнюється значення змінної klen (довжина, записана раніше в EEPROM) і значення змінної ii. Мова СІ сам витягує значення klen з EEPROM, використовуючи всі необхідніпроцедури.
Якщо в результаті перевірки ці дві довжини виявляться не рівними, то управління передається по мітці ml. Тобто до початку всієї програми. Подальше порівняння кодів не проводиться, і замок не відкривається. Якщо обидва значення однакові, то програма переходить до порівняння кодових комбінацій. Цикл, що виробляє це порівняння, знаходиться в рядку 64. Цей цикл
вякості параметра теж використовує змінну і.
Впроцесі роботи циклу значення цієї змінної також змінюється від нуля до ii. У тілі циклу виконується оператор порівняння if Цей оператор порівнює значення елементів двох масивів, один з яких (bufr) знаходиться в ЕЕРROM, а другий (bufе) в ОЗУ. При першому ж розбіжності кодів оператор безумовного переходу передає управління у мітці ш1. У цьому випадку цикл перевірки достроково переривається, і замок не відкривається. Якщо в процесі роботи циклу перевірки всі коди виявилися однаковими, то цикл завершується нормальним чином, і управління переходить до рядка 65. Тобто до процедури відкриття замку.
- 28 -
Процедура відкриття замку дуже проста. Вона займає рядки 65-67. У рядку 65 подається команда, що відкриває механізм замку (в четвертий розряд порту РВ записується одиниця). Потім викликається затримка третього типу (рядок 66). Після закінчення затримки відкриває сигнал знімається (рядок 67). Із закінченням процедури відкриття замку закінчується тіло основного циклу програми. Так як основний цикл нескінченний, то управління передається на його початок. Тобто на рядок 48. Робота програми починається спочатку.
Тепер повернемося до допоміжних функцій програми, котрі мипропустили на початку цього опису. Почнемо по порядку.
Урядках12,13і14,15розміщенідвірізнізаназвою,але однаковізазмістом функції. Перша з них є процедурою обробки переривання по переповнення таймера / лічильника!. А друга - процедурою обробки переривання за випадковим збігом в каналі А того ж таймера.
Упрограмі на Асемблері обидва види переривань викликали одну і ту ж загальну процедуру. Дана версія мови СІ не дозволяє використовувати одну і ту
жфункцію в якості процедури обрамлення двох різних видів переривань. У тілі кожної з функцій є всього один рядок. У цьому рядку присвоюється одиниця змінної Те ж саме робить процедура обробки переривання в програмі на Асемблері.
Рядки 16-26 займає функція введення стану клавіатури. Алгоритм роботи цієї функції трохи відрізняється від алгоритму роботи аналогічної процедури на Асемблері. Функція inod () в програмі на мові СІ виробляє лише зчитування вмісту портів, накладення маски і антидребезговий алгоритм.
Операція порівняння в тілі цієї функції не виконується. Так функція incod () повинна повертати код стану клавіатури, тип значення визначено як unsigned int (Див. Рядок 16). Функція не має параметрів, - на що вказує слово void.
Розглянемо докладніше, як працює функція incod (). У рядках 17-19 проводиться опис локальних змінних. Змінні cod0 i codl використовуються для
- 29 -
зберігання проміжних значень коду стану клавіатури. Причому змінна codl використовується для зберігання нового значення коду, а змінна cod0 – для зберігання старого значення (не плутайте з буфером cods основний програми). При описі змінної cod0 (рядок 17) однотимчасово виробляється її ініціалізація (присвоюється нульове значення). Цей нуль необхідний для правильногопочаткуциклуантидребезга. Длятогощобприпершомупорівнянні новий код не дорівнював старому. Ще одна змінна з ім'ям до використовується в якості параметра циклу антидребезга.
Основу функції incod() становить цикл антидребезга (рядки 20-25). По суті, тіло функціїскладаєтьсятільки з цього циклу. Завдання циклуввести код стану клавіатури задану кількість раз (визначається константою kandr). В даному випадку використовується стандартний цикл for (див. рядок 20).
Цикл виконається повністю (потрібну кількість разів) в тому випадку, якщо за час його роботи код стану клавіатури не зміниться.Якщо в процесі виконання циклу стан кнопок змінюється, то спеціальні команди всередині циклу перезапускають його роботу спочатку. Обчислення коду стану проводиться в рядках21 і22.Оператор if(рядок23)порівнюєстареіновезначеннякодів. Якщо ці значення не рівні, виконуються команди перезапуску циклу (рядки 24, 25). Після закінчення роботи циклу антидребезга команда return визначає значення, що повертається (Рядок 26). На цьому функція завершується.
Розберемося з окремими елементами циклу антидребезга докладніше. І почнемо з рядків 21 та 22, де, як уже говорилося, відбувається формування коду стану клавіатури. суть вироблених обчислень наочно проілюстрована на рис. 1.18. джерелом інформації для цих обчислень є вміст регістрів PINBіPIND, які, як відомо, безпосередньо підключені до висновків портів РВ і PD.
На вміст обох портів накладаються відповідні маски, а потім все це об'єднується в одне Шістнадцятирозрядне число і поміщається в регістр codi. Вираз в рядку 21 відповідає першому етапу на рис. 1.18. У правій частині
- 30 -