Добавил:
інстаграм _roman.kob, курсові роботи з тєрєхова в.в. для КІ Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
курсова.docx
Скачиваний:
22
Добавлен:
31.05.2020
Размер:
359.07 Кб
Скачать
    1. Розробка функціональної схеми

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

Можливий варіант схеми замку наведено на рис. 1.1. кнопки Sl-S10 служать для набору коду. Перемикач S11 призначена для вибору режиму роботи. Якщо контакт перемикача S11 замкнутий, замок переходить в режим «Запис». розімкнуті контакти відповідають режиму «Робота».

Рис. 1.1. Схема кодового замка

    1. Алгоритм роботи схеми

При складанні даного алгоритму нам не обійтися без такого поняття, як «код стану клавіатури». Що таке код стану?. Всі кнопки клавіатури підключаються до мікроконтролеру за допомогою портів введення-виведення. Для підключення десяти кнопок (Кнопки «О» - «9») одного порту недостатньо. кілька кнопок доведеться підключити до другого.

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

У момент включення живлення всі кнопки замку повинні бути відпущені. Якщо це не так, то виникає невизначеність в роботі замку. Тому наш

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

Процедура введення ключової комбінації являє собою багатократно повторюваний процес, періодично зчитує код стану клавіатури. Щоразу після чергового зчитування коду програма перевіряє, чи не змінився цей код. Як тільки код зміниться, нове його значення записується в чергову колонку ОЗУ. В результаті, поки стан клавіатури не змінюється, програма знаходиться в режимі очікування.

Як тільки стан змінився, відбувається запис нового значення коду стану в пам'ять. Тому ключова комбінація, записана в ОЗУ, буде являти собою перерахування всіх значень коду стану клавіатури, яке він приймав в процесі введення ключової комбінації. Тривалість же утримання кнопок в кожному з станів в пам'ять не записується. Однак це лише приблизний алгоритм процедури введення ключової комбінації. Так би мовити, її кістяк. Насправді алгоритм трохи складніше. Виявивши зміна стану клавіатури, програма не відразу записує новий код в ОЗУ. З метою боротьби з дребезгом контактів, а також для компенсації неточності одночасного натискання кількох кнопок, програма спочатку витримує спеціальну захисну паузу, потім повторно рахує код стану клавіатури і лише після цього записує новий код в ОЗУ.

Тривалість захисної паузи обрано рівної 48 мс. така пауза особливо корисна в разі, якщо при наборі ключової комбінації ви хочете використовувати одночасне натискання кнопок. Як би ви не намагалися натиснути кнопки одночасно, вам цього не вдасться.

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

Якщо не вжити спеціальних заходів, то в момент такого натискання програма зафіксує не одне, а кілька послідовних змін коду стану клавіатури. Якщо отримана таким проразом кодова комбінація буде записана в ЕЕРЯОМ, то відкрити такий замок буде практично неможливо. При спробі повторити ті ж натискання, замикання контактів будуть відбуватися в іншому порядку. Програма сприйме його як зовсім інший код. Захисна пауза вирішує цю проблему. В якому б порядку ні замикалися контакти при одночасному натисканні декількох кнопок, після паузи всі ці процеси закінчаться. Повторне зчитування дасть вже усталений код стану клавіатури. Повторити таку комбінацію не складе труднощів.

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

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

Для формування цього проміжку застосовується таймер. Таймер повинен працювати в режимі Normal . В цьому режимі він просто рахує тактові імпульси.

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

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

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

Якщо дві ці величини не рівні, процедура перевірки коду відразу ж завершується з негативним результатом. Якщо довжина обох комбінацій однакова, то програма приступає до побайтного їх порівняно. Для цього вона по черзі витягує з EEPROM раніше записані туди байти і порівнює кожен з них з відповідними байтами в ОЗУ. При першому ж розбіжності процес порівняння також завершується. І завершується негативно.

І тільки в тому випадку, якщо всі байти в ОЗУ і в EEPROM виявляться однаковими, порівняння вважається успішним. У разі успішного порівняння програма переходить до процедури відкриття замку.

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

Електрична принципова схема містить мікроконтролер ATiny2313 D1, тактова частота якого визначається кварцовим резонатором Q1, до якого приєднані фазозсувні конденсатори С1 та С2. До виводів 2,3,6-9, 11-14, 19 приєднана клавіатура вводу коду і підтвердження, до виводу 16 через резистор R1 приєднаний транзистор, за допомогою якого, здійснюється комутація

електромагніту замка. Для захисту переходу колектор-емітер транзистора від зворотної ЕРС, що виникає під час вимкнення транзистора в результаті розмагнічування осердя електромагніту, паралельно катушці електромагніту приєднаний діод, атод якого приєднується до колектора транзистора, а катод - дод додатного виводу джерела живлення. На схемі не відображено живлення мікроконтролера, яке здійснюється від стабілізованого джерела живлення +5V. Живлення електромагніта здійснюється від окремого нестабілізованого джерела живлення +12V.

    1. Розробка програмного коду

Можливий варіант програми кодового замка на мові СІ приведений в лістингу 1.20. Програма реалізує той же самий алгоритм, що і наведена вище програма на Асемблері. У тексті цієї програми були використані кілька нових для нас елементів мови СІ. Розглянемо їх по порядку.

#define

Директива присвоєння символьного імені будь-якої константи. Це класичний елемент мови СІ, який підтримується будь версією мови. Директива має два параметри. перший параметр - ім'я константи. Другий параметр - її значення. У рядку 2 програми (лістинг 1.20) числовий константі 0x77F присвоюється ім'я klfree. Після цього в будь-якому місці програми, де потрібно використовувати число 0x77F, його можна замінити ім'ям klfree.

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

#pragma

Директива, що задає спеціальні команди для компілятора. В якості параметра в директиві зазначається задається команда. Нижче наведено ряд прикладів використання цієї директиви.

Включення / відключення повідомлень про помилки. #pragma warn- // Вимикає попереджувальні повідомлення. #pragma warn + // Включає попереджувальні повідомлення.

Включення / відключення оптимізації результуючого коду. #pragma opt- // Вимикає оптимізацію.

#pragma opt + // Включає оптимізацію.

Включення / відключення оптимізації щодо мінімального розміру результуючого коду.

#pragma optsize- // Вимикає оптимізацію за розміром. #pragma optsize + // Включає оптимізацію за розміром.

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

«Препроцесор» ( «The Preprocessor»).

eeprom

Керуючий слово, яке використовується при описі змінних (масивів), яке вказує транслятора, що дана змінна (Масив) буде розташовуватися в незалежній пам'яті даних (Берн). Наприклад, в рядку 9 програми знаходиться опис змінної к1еn, призначеної для зберігання довжини кодової комбінації, а в рядку 10

описується масив, в якому буде зберігатися сама комбінація. І змінна, і масив розміщуються в ЕЕРROM.

return

Команда повернення значення. Якщо функція мови СІ повинна повертати значення, останньою командою в тілі цієї функції повинна бути команда return. Як параметр цієї команди вказується значення, що повертається.

Прикладом може служити функція incod(), що займає в нашій програмі (лістинг 1.20) рядка 16-26. Функція виробляє визначення коду стану клавіатури з використаням процедури антидребезга. За результатами своєї роботи функція повинна повертати код стану клавіатури »Тому остання команда в тілі функції (рядок 26) - це команда return. В якості параметра ця команда використовує змінну codl, яка і містить сформований код стану.

Крім нових команд, в тексті програми (лістинг 1.20) використовується один, поки ще не знайомий нам цікавий прийом. подивіться, будь ласка, на рядок 54 програми. У цьому рядку записано вираз, який присвоює елементу масиву bufr значення змінної codS. Однак в якості номера елемента масиву використовується не просто змінна ii, а вираз ii + +. це і є ще одна оригінальна особливість мови СІ.

Мова СІ допускає одночасно використовувати змінну в будь-якому вираженні і змінювати її значення. Так, при обчисленні вираження bufг [ii + +] = codS спочатку елементу масиву з номером ii присвоюється значення cods, а потім значення змінної ii збільшується на одиницю. Такий же прийом допускається при використанні змінних в якості параметрів функцій або в складі будь-яких інших виразів. Крім команди збільшення, можна використовувати команду зменшення, а також змінювати порядок обчислень. Ось кілька прикладів таких виразів:

a = MyBuffer [++ ii] ; b = MyFunction (ii--) ; c = 85 + (- -ii) / 2;

У будь-якому випадку, при використанні даного прийому виконуються такі правила:

ii ++ означає: використовувати значення, а потім збільшити його на одиницю.

++ іі означає: збільшити значення на одиницю, а потім використовувати його.

і + і - означає: використовувати значення, а потім зменшити його на одиницю.

--іі означає: зменшити значення на одиницю, а потім використовувати його.

Природно, замість змінної ii може використовуватися будь-яка інша змінна.

Опис програми (лістинг 1.20)

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

Наприклад, для зберігання різних варіантів коду стану клавіатури в програмі використовується кілька змінних:

cod0 - рядок 17; codl - рядок 18;

codS - рядок 37. Лістинг 1.20

/******************************************* Project : Зразок 10

Version : 1

Date : 07/=.03.2006.

Author : Belov Company : Home Comments :

Кодовий замок

Chip type : ATtiny2313 Clock frequency : 4, 000000 MHz Memory model : Tiny

Data Stack size 32

********************************************/

      1. # include <tiny2313.h>

      1. #define klfree 0x77F //Код стану при повністю відпущених кнопках

      2. #define kzad 3000 //Код затримки при скануванні

      3. #define kandr 20 //Константа антидребезга

      4. #define bsize 30 //Розмір буфета для зберігання коду

      1. unsigned char flz; //Прапор затримки

      2. unsigner int bufr [bsize]; //Буфер в ОЗУ для зберігання коду

      3. #pragma warn –

      4. eeprom unsigned char klen ; //Комірки для зберігання довжини коду

      5. eeprom unsigned int bufe [bsize]; //Буфер в EEPROM для зберігання коду

      6. #pragma warn-

// Переривання по переповненні таймера 1

      1. interrupt [TIM1_0VF] void timer1_ovf_isr(void)

{

      1. flz=1;

}

//Переривання по співпадінню в каналі А Таймера 1

      1. interrupt [TIM1_COMPA] void timer1_compa_isr(void)

{

      1. flz=1;

}

//Функція запиту клавіатури і антидребезга

      1. unsigned int incod (void)

{ //Створюємо локальні змінні

      1. unsigned int cod0=0; //Допоміжна змінна

      2. unsigned int cod1; //Ще одна допоміжна змінна

      3. unsigned char k; //Параметр циклу антидребзга

      1. for (k=0; k<kandr; k++) // Цикл антидребезга

{

      1. cod1=PINB&0x7; //Формує перший байт коду

      2. cod1=(cod1<<8)+(PIND&0x7F); //Формує повний код стану клавіатур

      3. if (cod0!=cod1) //Порівнюємо з початковим кодом

{

      1. k=0; //Якщо не рівні , скидаємо лічильник

      2. cod0=cod1 ; //Нове значення початкового коду

}

}

      1. return cod1;

}

//Процедура формування затримки

      1. void wait (unsigned char kodz)

{

      1. if (kodz==1) TIMSK=0x40; //Вибір маски переривань по таймеру

      2. else TIMSK=0x80;

      3. TCNT1=0; //Обнулення таймера

      4. flz=0; //Скидання прапора затримки

      5. #asm(“sei”); //Дозволяємо переривання

      6. if (kodz!=2) while(flz==0); //

}

//

      1. void main (void)

{

      1. unsigned char ii; //Показник масива

      2. unsigned char i; //Допоміжний показник

      3. unsigned int cods; //Старий код

      1. PORTB=0xE7; // Порт В

      2. DDRB=0x1B;

      1. PORTD=0x7F; //Порт D

      2. DDRD=0x00;

      1. TCCR1A=0x00; //Таймер/Лічильник 1

      2. TCCR1B=0x03;

      3. TCNT1=0; //Обнулення розрахункового регістра

      4. OCR1A=kzad; //Ініціалізація регістра співпадіння

      1. ACSR=0x80; //Аналоговий компаратор

      1. While (1)

{

      1. m1: while (incod() != klfree); //Очікування відпускання кнопок

      2. while (incod() == klfree); //Очікування натиску кнопок

50 ii=0;

  1. m2: #asm("cli"); //Забороняє переривання

  2. wait(1); //Затримка 1-го типу

  3. codS=incod(); //Ввід коду і запис, як старого

  4. bufr[ii++]=codS; //Запис наступного коду в буфер

  5. if (ii>=bsize) goto m4; //Перевірка кінця буфера

56

wait(2), //Затримка 2-го типу

57

m3:

if (incod() 1 = codS) goto m2; //Перевірка, чи не змінився стан

58

if (flz==0) goto m3; //Перевірка прапора закінчення затримки

59 m4: if (PINB 7==1) goto comp, //

// Запис коду в EEPROM

60

klen=ii;

//Запис довжини коду

61

for (i=0;i <ii; i++) bufe[i]=bufr[i];

//Запис всіх байтів коду

62

goto zamok;

//До процедури відкривання замка

// Перевірка коду

  1. comp: if (klen!=ii) goto ml; //Перевірка довжини коду

  2. for (i=0; i<ii; i++) if (bufe[i]! =bufr[i]) goto m1; //Перевірка коду

// Відкривання замка

65

zamok:

PORTB.4=1;

//Відкриваємо замок

66

zamok: PORTB.4=1;

//Затримка 3-го типу

67

P0RTB.4=0;

//Закриваємо замок

}

}

І всі вони мають тип unsigned char. При цьому сам цей код представляє собою шістнадцятирозрядне двійкове число, старші вісім розрядів відповідають вмісту порту РВ, а молодші вісім розрядів - вмісту порту PD (на все це накладена маска).

Починається наша програма, як і всі попередні, з приєднання бібліотечного файлу (рядок 1). Далі йде блок опису констант (рядки 2-5). Перша константа має

ім'я klfree і значення 0x77F. Це значення є код стану клавіатури при відпущених кнопках. Константа використовується в операціях порівняння.

Наступні три константи: kzad (код затримки), kandr (константа антидребезга) і bsize (розмір буфера для кодової комбінації) за своїм призначенням аналогічні відповідним константам в програмі на Асемблері. У них навіть значення однакові. Відмінність тільки в значенні константи bs iz e. У нашому випадку вона дорівнює не 60, а 30.

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

У рядках 6-11 знаходиться блок опису змінних і масивів. Всі змінні і масиви мають свої аналоги в програмі на Ассемблері. У рядку 6 описується змінна flz, яка використовується як прапор затримки. У рядку 7 описується масив для оперативного зберігання ключової комбінації. Всі значення цього масиву будуть розміщені в ОЗУ (буфер в ОЗУ). довжина масиву вибирається рівною bsize.

У рядках 9,10 описуються змінна і масив, які будуть зберігатися в EEPROM. Мінлива klen призначена для зберігання довжини кодової комбінації. Масив bufе призначений для зберігання самої цієї комбінації.

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

Якщо дотримуватися зазначені вище вимоги, то рядки 9 і 10 нашої програми повинні виглядати приблизно так:

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

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

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

«Warning» (попередження). Воно буде виникати кожен раз при трансляції програми. Можна, звичайно, просто не звертати на нього увагу.

Однак більш правильно буде тимчасово відключити повідомлення про допомогу директиви #program і команди warn, як це і зроблено в програмі на лістингу 1.20. У рядку 8 висновок попереджень відключається, а в рядку 11 включається знову. відключати попередження назавжди не рекомендується. Так можна пропустити інші, важливіші попередження.

Далі в програмі починається опис всіх складових її функцій. Дана програма складається з п'яти функцій:

    • дві функції обробки переривань ( рядки 12,13 та 14,15);

    • функція введення коду стану клавіатури ( рядки 16 - 26);

    • функція формування затримки ( рядки 27 - 33);

    • головна функція програми ( рядки 34 - 67).

Розгляд даної програми зручно починати з головної функції main.

Функція main починається з опису локальних змінних (Рядки 35-37). Крім змінної cods, призначеної для тимчасового зберігання коду стану клавіатури, тут визначаються ще дві допоміжні змінні з іменами i і ii. Після опису змінних

починається блок ініціалізації (рядки 38-46). Блок ініціалізації даної програми по виконуваних діям повністю повторює аналогічний блок в програмі на Ассемблері.

Ці дії зводяться до налаштування портів введення-виведення, таймера і компаратора. Під час налаштування таймера не тільки вибирається його режим роботи, а й обнуляється значення рахункового регістра TCNT1(Рядок 44), а в регістр збіги OCR1A записується код затримки kzad (рядок 45).

Основний цикл програми займає рядки 47-67. Розглянемо докладніше його роботу. У рядку 48 знаходиться цикл очікування відпускання кнопок. Він являє собою порожній цикл whi1е. тіло циклу повністю відсутня. За непотрібністю не поставлені навіть фігурні дужки. Весь цикл складається лише з оператора while і вирази в круглих дужках, що визначає умову продовження цього циклу.

Умова проста: цикл виконується весь час, поки код стану клавіатури і константа klfree не рівні між собою. Значення константи одно коду стану клавіатури при всіх відпущених кнопках. Для визначення коду стану клавіатури використовується функція incod () .Функція incod () виконує ті ж самі деії, що однойменна процедура з програми на Асемблері. То зчитує стан портів, накладає маски і застосовує при цьому Антидребезгова алгоритм. Детальніше роботу функції ми розглянемо в кінці цього розділу.

Як тільки всі кнопки будуть відпущені, цикл в рядку 48 завершується, і програма переходить до рядка 49, у якій знаходиться цикл очікування натискання будь-якої кнопки. Цей цикл дуже схожий на попередній. Змінилося тільки умова. Знак! = (Не дорівнює) змінений на == (дорівнює). Як тільки буде натиснута будь-яка кнопка, цикл в рядку 49 закінчується, і управління переходить до рядка 50.

Тепер пора починати цикл введення ключової кодової комбінації. Але спочатку потрібно обнулити змінну ii, яка буде використуватися як лічильник прийнятих кодів і покажчик поточного елемента в буфері bufr. Обнулення виконується в рядку 50. Цикл введення кодової комбінації займає рядки 51-

58. Починається цикл з глобальної заборони всіх переривань (рядок 51). Потім формується захисна пауза. Для формування паузи використовується функція wait ().

Дія цієї функції повністю аналогічно дії одноіменний процедури з програми на Асемблері. У рядку 52 формується затримка першого виду (48 мс), тобто викликається функція wait () з параметром, рівним одиниці. По закінченню затримки (рядок 53) програма повторно зчитує код стану клавіатури і записує його в змінну cods.

У рядку 54 лічений код записується в буфер ОЗУ (bufr). Одночасно покажчик буфера збільшується на одиницю. В рядку 55 перевіряється умова переповнення буфера. така перевірка примусово завершує роботу циклу при спробі введення занадто довгою кодової комбінації. Якщо значення ii перевищує величину константи bsize, значить, буфер вже повністю заповнений. У цьому випадку управління передається по мітці Ш4, тобто на кінець циклу.

Якщо значення ii не досягло кінця буфера, то перехід не проходить, і управління переходить до рядка 56. У цьому місці запускається процес формування контрольного проміжку часу. Для запуску цього процесу використовується функція wait (). В даному випадку вона формує затримку другого типу, тому викликається з параметром, рівним двом.

Так само, як і в програмі на Асемблері, затримка другого типу лише виробляє все настройки таймера, але не виконує цикл очікування. Комбінований цикл очікування перебуває поза функції затримки, а точніше в рядках 57, 58. У рядку 57 зчитується новий код стану клавіатури і порівнюється зі старим, котрий зберігається в змінної cods.

Якщо коди не рівні (стан клавіатури змінилося), комбінований цикл очікування переривається, і управління передається по мітці m2. Тобто на початок циклу введення кодової комбінації. А вже там, на початку циклу, знову формується захисна затримка, і черговий код стану поміщається в буфер.

Якщо при перевірці в рядку 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 одно її довжині). Тіло циклу складає всього один

вислів. Цей вислів записує значення чергового елемента буфера 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. Тобто до процедури відкриття замку.

Процедура відкриття замку дуже проста. Вона займає рядки 65-67. У рядку 65 подається команда, що відкриває механізм замку (в четвертий розряд порту РВ записується одиниця). Потім викликається затримка третього типу (рядок 66). Після закінчення затримки відкриває сигнал знімається (рядок 67). Із закінченням процедури відкриття замку закінчується тіло основного циклу програми. Так як основний цикл нескінченний, то управління передається на його початок. Тобто на рядок 48. Робота програми починається спочатку.

Тепер повернемося до допоміжних функцій програми, котрі ми пропустили на початку цього опису. Почнемо по порядку.

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

У програмі на Асемблері обидва види переривань викликали одну і ту ж загальну процедуру. Дана версія мови СІ не дозволяє використовувати одну і ту ж функцію в якості процедури обрамлення двох різних видів переривань. У тілі кожної з функцій є всього один рядок. У цьому рядку присвоюється одиниця змінної Те ж саме робить процедура обробки переривання в програмі на Асемблері.

Рядки 16-26 займає функція введення стану клавіатури. Алгоритм роботи цієї функції трохи відрізняється від алгоритму роботи аналогічної процедури на Асемблері. Функція inod () в програмі на мові СІ виробляє лише зчитування вмісту портів, накладення маски і антидребезговий алгоритм.

Операція порівняння в тілі цієї функції не виконується. Так функція incod () повинна повертати код стану клавіатури, тип значення визначено як unsigned int (Див. Рядок 16). Функція не має параметрів, - на що вказує слово void.

Розглянемо докладніше, як працює функція incod (). У рядках 17-19 проводиться опис локальних змінних. Змінні cod0 i codl використовуються для

зберігання проміжних значень коду стану клавіатури. Причому змінна 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. У правій частині

виразу виконується операція логічного множення (операція «І») між вмістом порту РВ і маскою 0x07. результат виразу записується в змінну codl.

Вираз в рядку 22 об'єднує етапи 2 і 3. Права частина цього вираження являє собою суму двох доданків. Перше доданок являє собою операцію логічного зсуву змісту змінної codl на вісім розрядів вліво. цей зсув відповідає етапу номер

2 на малюнку. В результаті зсуву вісім молодших розрядів числа стають старшими.

Другий доданок - це ще одна операція логічного множення. На цей раз множиться вміст порту PD і константа 0x7F, що представляє собою маску для цього порту. Результатом складання двох цих складових є шуканий код стану клавіатур, який записується в змінну codl. Обчислення другого доданка і складання їх обох і відповідає етапу но заходів 3 на рис. 1.18. Символом «X» на малюнку позначаються розряди, значення яких не визначено. Розряди, значення яких залежить від тієї або іншої кнопки клавіатури, позначається назвою цієї кнопки. Решта розряди рівні або «0», або «1».

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

У рядку 23 цей код порівнюється зі старим значенням, яке зберігається в змінної cod0. Якщо коди не рівні, то виконуються команди перезапуску циклу (рядки 24, 25). У рядку 24 змінної до (параметру циклу) присвоюється нульове значення. В рядку 25 значення змінної codl записується в змінну cod0. Тепер нове, щойно отримане значення коду стає старим.

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

Як і процедура на Асемблері, функція wait() формує три виду затримки. Параметр, що визначає номер затримки, має ім'я kodz і тип unsigner

char. Робота функції починається з визначення значення маски переривань. Для цього в рядках 28, 29 оцінюється значення змінної kodz. Якщо значення kodz

Рис. 1.18. Формування коду стану клавіатури

дорівнює 1, то в регістр маски переривань TIMSK записується код 0x40. Цей код дозволяє переривання за випадковим збігом в каналі А.

Якщо kodz НЕ дорівнює одиниці, то регістру TIMSK присвоюється значення 0x80 (переривання по переповнення). Таким чином, в режимі 1 буде працювати переривання за випадковим збігом в каналі А. При цьому формується затримка тривалістю 48 мс. У інших режимах (2, 3) використовується

переривання по переповнення таймера. У цьому випадку формується затримка тривалістю в одну секунду.

У рядку 30 обнуляється значення рахункового регістр таймера. З моменту обнулення таймера починається формування заданого тимчасового інтервалу. У рядку 31 обнуляється значення прапора затримки. У рядку 32 виконується команда глобального дозволу переривань. На цьому настройка таймера і системи переривань закінчуються. Тепер залишається лише організувати цикл очікування.

Цикл очікування, презначений для роботи в режимах 1 і 3,

організований в рядку 33. Це порожній цикл, організований при допомоги оператора while. Як умова продовження циклу вибрано рівність прапора flz нулю. Тобто поки flz дорівнює нулю, цикл очікування триватиме. А закінчиться він в той момент, коли процедура обробки переривання змінить значення прапора flz на одиничне.

У режимі 2 використовується інший цикл очікування, який знаходиться поза функцією wait (). Тому в рядку 33, крім циклу очікування, є оператор порівняння if. Він перевіряє значення змінної kodz. Завдяки оператору порівняння, цикл очікування в рядку 33 виконується тільки в тому випадку, коли kodz НЕ дорівнює двом.

ВИСНОВОК

У даній курсовій роботі було здійснено розробку схеми кодового замка.

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

Здійснено вибір елементної бази.

Також здійснений докладний опис роботи схеми.

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

  1. Белов А.В. Создаем устройства на микроконтроллерах, 2007.

  2. https://shematok.ru/transistor/kt315