Добавил:
інстаграм _roman.kob, курсові роботи з тєрєхова в.в. для КІ Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

1

.pdf
Скачиваний:
2
Добавлен:
31.05.2020
Размер:
782.19 Кб
Скачать

29

else TIMSK=0x80;

 

30

TCNT1=0;

//Обнулення таймера

31

flz=0;

//Скидання прапора затримки

32

#asm(“sei”);

//Дозволяємо переривання

33

if(kodz!=2) while(flz==0);

//

 

}

 

 

//

 

34void main (void)

{

35

unsigned char ii;

//Показник масива

36

unsigned char i;

//Допоміжний показник

37

unsigned int cods;

//Старий код

38

PORTB=0xE7;

// Порт В

39

DDRB=0x1B;

 

40

PORTD=0x7F;

//Порт D

41

DDRD=0x00;

 

42

TCCR1A=0x00;

//Таймер/Лічильник1

43

TCCR1B=0x03;

 

44

TCNT1=0;

 

//Обнулення розрахункового регістра

45

OCR1A=kzad;

//Ініціалізація регістра співпадіння

46

ACSR=0x80;

 

//Аналоговий компаратор

47

While (1)

 

 

 

{

 

 

48

m1:

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

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

50ii=0;

51

m2:

#asm("cli");

//Забороняє переривання

52

 

wait(1);

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

53

 

codS=incod();

//Ввід коду і запис, як старого

54

 

bufr[ii++]=codS;

//Запис наступного коду в буфер

- 21 -

55

 

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;

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

 

//--------------------------------------

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

63

comp:

if (klen!=ii) goto ml;

//Перевірка довжини коду

64

 

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). Перша константа має

- 22 -

ім'я 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

нашої програми повинні виглядати приблизно так:

- 23 -

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

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

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

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

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

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

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

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

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

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

- 24 -

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

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

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

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

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

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

- 25 -

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 -

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]