Цифровий дозиметр
p align="left">3. РОЗРОБКА ПРОГРАМНОГО ЗАБЕЗПЕЧЕННЯ3.1 Розробка алгоритму роботи Цифровий дозиметр з трьома режимами вимірювання і світлозвуковою реалізації випромінювання працює наступним чином: За допомогою одновібратора зібраного на DD1 перетворюються імпульси з датчика в імпульс потрібний за часом і амплітуди для контролера DD2. Перемичка J1 (за умовчанням не стоїть), вмикає другий датчик і служить для збільшення чутливості приладу але при цьому слід виконати коректування. Перемичка J1 (за умовчанням стоїть) включає акустичний випромінювач. Перемикання режимів виконується кнопками «<» «>» (SB2/SB3). Вмикання/вимикання режимів кнопками «V» «X» (SB1/SB4). Спочатку вибраний режим одиничного виміру, натискуємо SB1 виконується виміри за час 1хв, після чого результат заноситься в буфер для подальшого запису значення і перегляду попереднього виміру. Для вмикання режиму безперервного виміру необхідно перейти в меню «режим 1-тест/2-цикл» натиснути «X»-режим 2, «V»-режим 1. Для збереження результату вибираємо меню «Зона1 або зона2» натискуємо «V» Запис з буфера, натискуємо «X» прочитуємо з комірки пам'яті. Для вмикання підсвічування вибираємо меню «Підсвічування вкл/викл»- «X»-викл, «V»-вкл. Регулювання рівня тривожної сигналізації виконується в меню «Тревога/Рівень», кнопками «X»--1, «V»-+1 змінюємо рівень і записуємо в пам'ять. Рівень змінюється в одиницях ПРФ, При збігу вибраного рівня з рівнем вимірюваним включається тривожний звуковий сигнал і на екрані висвічується «Внимание высокий уровень радиации!». У сплячому режимі виконується вимірювання із зниженим енергоспоживанням, блокинг генератор працює в імпульсному режимі, відключається підсвічування, на екрані через кожні 10сек виводиться «сканування», в цьому режимі не записуються ніякі значення, лише реагує на перевищення рівня радіації, звуковим сигналом. Світлодіод HL1 і резонатор HA1 сигналізує про попадання радіоактивної частки на датчик. Граф-схема алгоритму функціонування пристрою приведена на додатку Б. 3.2 Організація пам'яті та розподіл адресного простору Регістровий файл зі швидким доступом містить 32 x 8-розрядних робочих регістрів загального призначення з однотактовим циклом доступу. Завдяки цьому досягнута однотактність роботи АЛП. При звичайній роботі в АЛП спочатку з регістрового файлу завантажується два операнда, потім виконується операція, а після результат відправляється назад у регістровий файл і все це відбувається за один машинний цикл. Шість регістрів з 32 можуть використовуватися як три 16-розрядних регістра непрямої адреси для ефективної адресації в межах пам'яті даних. Один з цих покажчиків адреси може також використовуватися як покажчик адреси для доступу до таблиці перетворення у флеш-пам'яті програм. Дані 16-разр. регістри називаються X-регістр, Y-регістр і Z-регістр. АЛП підтримує арифметичні і логічні операції між регістрами, а також між константою і регістром. Крім того, АЛП підтримує дії з одним регістром. Після виконання арифметичної операції регістр статусу (прапорів) обновлюється для відображення результату виконання операції. Прапори цього регістра в більшості випадків дозволяють відмовитися від використання інструкцій порівняння, роблячи код програми більш компактним і швидким. Крім того, архітектурою МК підтримуються операції множення зі знаком і без знака і дробовим форматом. Кожна арифметико-логічна операція встановлює прапори в регістрі прапора (див. рис. 3.1). Рисунок 3.1 - Регістр прапора контролера I - прапор дозволу переривання; T - прапор-охоронець біта - встановлюється і аналізується лише спецінструкціями; H - прапор додаткового перенесення з 3-го розряду в 4-й; S - прапор знаку результату; V - прапор переповнювання; N - прапор негативного результату операції; Z - прапор нуля; C - прапор перенесення. Підтримується апаратний стек у внутрішньою статичною пам'яттю. Структура регістрового файлу показана на рис. 3.2. Рис. 3.2 - Структура регістрового файлу AVR Як видно, 6 старших регістрів утворюють регістрові пари - індексні регістри. Ядро процесора за допомогою цих регістрів допускають автоінкрементну, автодекрементну адресацію і адресацію з малим зсувом. Для розгалуження програми підтримуються інструкції умовних і безумовних переходів і викликів процедур, що дозволяють безпосередньо адресуватися в межах адресного простору. Більшість інструкцій являють собою одне 16-розрядне слово. Кожна адреса пам'яті програм містить 16- або 32-розрядну інструкцію. Пам'ять програм розділена на два сектори: сектор програми початкового завантаження і сектор прикладної програми. Обидва сектори мають роздільні біти захисту від запису і читання/запису. Оскільки всі AVR-інструкції є 16 або 32-розрядними, флеш-пам'ять організована як 1 кбайт х 16. Програмний лічильник РС у МК є 16-розрядним, тому дозволяє адресувати до 64 кбайт пам'яті програм. Flash-пам'ять програм. ATmega8 містить 8 кб пам'яті для завантаження програм. Команда контроллера займає 16 або 32 біта, тому флеш-память програм організована у вигляді масиву 4К 16-ти бітових слів. Флеш-память розділена на дві секції - область додатків і область завантаження (що знаходиться в старших адресах). Флеш-память витримує до 10.000 циклів перезапису. EEPROM пам'ять даних ATmega8 містить постійний запам'ятовуючий пристрій для збереження даних, виконаний за технологією EEPROM, який містить 512 байт і забезпечує 100000 циклів стирання/запис. Статичний ОЗП данихОперативний запам'ятовуючий пристрій статичного типу для збереження даних (SRAM), який містить 1 Кбайт вбудованої пам'яті.Доступ до статичного ОЗП даних може бути легко здійснений через 5 різних режимів адресації архітектури AVR і виконується за два машинних цикли. При генерації переривання і виклику підпрограм адреса повернення з програмного лічильника записується в стек. Стек ефективно розподілений у статичному ОЗП пам'яті даних і, отже, розмір стека обмежений загальним розміром статичного ОЗП і використовуваним його обсягом. У будь-якій програмі відразу після скидання повинна бути виконана ініціалізація покажчика стека (SP) (тобто перед виконанням процедур обробки переривань або викликом підпрограм). Покажчик стека - SP - доступний для читання і запису у просторі введення-виведення. На рис. 3.3 показано організацію пам'яті в мікроконтролері AT mega8. Простір пам'яті введення - виведення містить 32 адреси з безпосередньою адресацією або може адресуватися як пам'ять даних. Рис. 3.3 - Структура пам'яті 3.3 Розробка програмного забезпечення Функціонування дозиметра керуються програмно за допомогою мікроконтролера. Програма написана на мові програмування С++ [3]. Текст програми пристрою має вигляд: //------------------- підготовка--------------------// //------------------- включення директив препроцесора ---------------------// #include <istream.h> #include <mega8.h> #include <delay.h> //-------------------- встановлення портів-----------------// #define key1 PIND.0 #define key2 PIND.1 #define key3 PIND.2 #define key4 PIND.3 #define pulse PIND.4 #define beep PORTC.3 //--- визначення імпульсів від датчика---// #define light PORTC.2 #define sound PORTC.1 eeprom unsigned int zone1; eeprom unsigned int zone2; unsigned int k=0; int sec=0; int rf=0; int j=0; int i=1; //кнопки < > int m_buffer=0; int memory=1; // виділення пам'яті для зони 1 int memory1=2; // виділення пам'яті для зони 2 int warn=400; // стандартний рівень радіації bit ok=0; // так bit x=0; // ні bit a1=0; bit a2=0; bit a3=0; bit a4=0; char lcd_buffer[80]; // буфер рівня LCD! //-------------------------- Переривання для таймера ------------------// interrupt [TIM1_COMPA] void timer1_comp_isr(void) { sec++; } /* void wait (void){ TCNT1=0; while (TCNT1<780){}; } */ //---------------- Буквено-цифрові функції Модуля LCD----------------// #asm .equ __lcd_port=0x18 ;PORTB #endasm #include <lcd.h> // Оголосіть свої глобальні змінні тут //----------------------Звуковий сигнал --------------------// void my_beep(void) { // ключовий звуковий сигнал beep = 0; delay_ms(30); beep = 1;} // Короткий звуковий сигнал //----------------- Довгий звуковий сигнал ---------------------// void long_beep(void) { // Ключовий звуковий сигнал beep = 0; delay_ms(55); beep = 1; delay_ms(30); beep = 0; delay_ms(30); beep = 1;} //------------------------ Ключі функцій -----------------------// void my_keys(void){ if(!key1){ok=1;}else{delay_ms(10); ok=0;} if(!key2){x=1;}else{delay_ms(10); x=0;} if(i<8){if(!key4){i++; my_beep(); lcd_clear(); delay_ms(680); }} if(i>1){if(!key3){i--; my_beep(); lcd_clear(); delay_ms(680); }} } //---------------------------- Головна програма ----------------------------// void main(void) { PORTB=0x00; DDRB=0x00; PORTC=0x7F; DDRC=0x7F; PORTC.2=0; PORTC.4=0; PORTC.5=0; PORTD=0xFF; DDRD=0x00; ACSR=0x80; SFIOR=0x00; //----------------------------- Для таймера ----------------------------// OCR1A=4000; // Для кварца TCCR1B=0x0D; TIMSK=0x10; lcd_init(16); my_beep(); // Початок delay_ms(100); my_beep(); while (1) { my_keys(); switch (i) { case 1: // Запуск меню my_keys(); lcd_gotoxy(0,0); lcd_putsf(“Menu _rogram”); lcd_gotoxy(0,1); lcd_putsf(“Enter key~ “); delay_ms(1); if(sec>=60){#asm(“cli”); m_buffer=k; } //anti kosac break; //STOP1 case 2: // Тест датчика my_keys(); lcd_gotoxy(0,0); sprintf(lcd_buffer,”fon=%4umkr Time=%2uc” “RF=%2u “,k,sec,rf);// PRINT ON LCD lcd_puts(lcd_buffer); // З буфера на LCD delay_ms(1); // потрібно обслуговувати таймери if((ok)&(a1)){delay_ms(50); #asm(“sei”);} //Start k=0; j=0; rf=0; if(x){#asm(“cli”); beep=1;} //Зупинка if(sec>=60){#asm(“cli”); a1=0;m_buffer=k; } // Авто зупинка if(sec==61){sec=0; k=0; j=0; rf=0; beep=1;} // повторний запуск if(ok){a1=1;} if(x){a1=0;} if((!pulse)&(a1)){delay_ms(10); k++; j++;} // Введіть допустиме значення радіації if(j==20){delay_us(1); rf++; j=0;} if(k==warn){delay_us(1); beep=0;} // Небезпечне випромінювання if(k==1600){delay_us(1); sec=0; k=0; j=0; rf=0; beep=1;} //Допустиме випромінювання break; case 3: // Зберігання значення в пам'яті EEPROM в зоні 1 my_keys(); lcd_gotoxy(0,0); sprintf(lcd_buffer,”Zone1=%4umkr “,memory);// TO LCD lcd_puts(lcd_buffer); lcd_gotoxy(0,1); lcd_putsf(“Save Load”); delay_ms(1); if(sec>=60){#asm(“cli”); m_buffer=k; } if((ok)&(k>=10)){ zone1=m_buffer;} // Збережіть лише значення >10 if(x){ memory=zone1;} break; case 4: // Зберігання значення в пам'яті EEPROM в зоні 2 my_keys(); lcd_gotoxy(0,0); sprintf(lcd_buffer,”Zone2=%4umkr “,memory1); lcd_puts(lcd_buffer); lcd_gotoxy(0,1); lcd_putsf(“Save Load”); delay_ms(1); // need wait on timers if(sec>=60){#asm(“cli”); m_buffer=k; } // Збережіть лише значення >10 if((ok)&(k>=10)){ zone2=k;} if(x){ memory1=zone2;} break; case 5: // Вмикання/вимикання сигнальної лампочки my_keys(); lcd_gotoxy(0,0); lcd_putsf(“Backlight “); lcd_gotoxy(0,1); lcd_putsf(“v on/off x”); if(ok){a2=1; PORTC.4=1;} if(x){a2=0; PORTC.4=0;} delay_ms(1); if(sec>=60){#asm(“cli”); m_buffer=k; } if(a2){ lcd_gotoxy(11,0); lcd_putsf(“on “); } if(!a2){ lcd_gotoxy(11,0); lcd_putsf(“off “);} break; case 6: // Вмикання/вимикання звукового резонатора my_keys(); lcd_gotoxy(0,0); lcd_putsf(“Sound “); lcd_gotoxy(0,1); lcd_putsf(“v on/off x”); if(ok){a3=1; PORTC.5=1;} if(x){a3=0; PORTC.5=0;} delay_ms(1); if(sec>=60){#asm(“cli”); m_buffer=k; } if(a3){ lcd_gotoxy(11,0); lcd_putsf(“on “); } if(!a3){ lcd_gotoxy(11,0); lcd_putsf(“off “);} break; case 7: // Попереджувальний рівень +/- my_keys(); lcd_gotoxy(0,0); sprintf(lcd_buffer,”Warning=%4umkr “,warn); lcd_puts(lcd_buffer); lcd_gotoxy(0,1); lcd_putsf(“v +/- x”); //delay_ms(1); // need wait on timers if(sec>=60){#asm(“cli”); m_buffer=k; } if(warn<1500){if(!key1){warn++; delay_ms(80); }} if(warn>10){if(!key2){warn--;delay_ms(80); }} break; case 8: // Вмикання режиму безперервного вимірювання my_keys(); lcd_gotoxy(0,0); sprintf(lcd_buffer,”Fon=%4umkr Bufer=%4u” “RF=%2u “,k,m_buffer=k,rf);// Вивід значення на LCD lcd_puts(lcd_buffer); //lcd_gotoxy(0,1); lcd_putsf(“While”); delay_ms(1); // need wait on timers if((ok)&(a4)){delay_ms(50); #asm(“sei”);} //Start k=0; j=0; rf=0; if(x){#asm(“cli”); beep=1;} // Зупинка if(sec==61){ sec=0; k=0; j=0; rf=0; beep=1;m_buffer=k;} if(ok){a4=1;} if(x){a4=0;} if((!pulse)&(a4)){delay_ms(10); k++; j++;} if(j==20){delay_us(1); rf++; j=0;} if(k==warn){delay_us(1); beep=0;} // Сигнальне вимірювання if(k==1600){delay_us(1); sec=0; k=0; j=0; rf=0; beep=1;} //максимальне значення вимірювання break; } }; 4. МОДЕЛЮВАННЯ РОБОТИ Моделювання проводилось за допомогою програми Proteus 7 Professional [4]. Так як за відсутністю програмних еквівалентів і електронних компонентів доцільно виконати моделювання роботи, яке полягає в виводі на дисплей значення вимірювання радіації, світлової та звукової індикації випромінювання, не вдалось. Замість блокинг генератора на вхід одновібратора подається прямокутній сигнал і спостерігаємо на дисплеї (Рис. 4.1) . Рисунок 4.1 - Результати моделювання 5. ВИСНОВКИ В даній роботі було розроблено цифровий дозиметр з трьома режимами вимірювання, з візуальним і звуковим оповіщенням рівня радіації, збереження даних в енергонезалежній пам'яті, збереження на дисплеї попереднього значення, вимірювання, регулювання рівня сигналізації. Також розглянули структуру мікроконтролера ATmega8, написали програму курування мікроконтролером, промоделювали пистрій в програмі Proteus 7 Professional. ЛІТЕРАТУРА 1 Офіціальний сайт www.vikipedia.ua Мікроконтролери AVR. 2 Новиков Ю.В., Скоробогатов П.К. Основы микропроцессорной техники. Курс лекций 3 Бродин В.Б., Калинин А.В. Системы на микроконтроллерах и БИС программируемой логики. -- М.: ЭКОМ, 2002. 4 Жан М. Рабаи, Ананта Чандракасан, Боривож Николич Цифровые интегральные схемы. Методология проектирования = Digital Integrated Circuits. 5 Гостев В.И. Системы управления с цифровыми регуляторами. 6 Баранов В.Н. Применение микроконтроллеров AVR. Схемы, алгоритмы, программы. 7 Трамперт. Измерение, управление и регулирование с помощью AVR микроконтроллеров_2006. 8 Угрюмов Е.П. Цифровая схемотехника. СПб.2004г.528с.ил. ДОДАТОК А Повна структура мікроконтролера ATmega8 ДОДАТОК Б Граф-схема алгоритму функціонування пристрою. ДОДАТОК Г Друкована плата пристрою. Цифрова частина схеми Високовольтна частина схеми //-------------------Підготовка--------------------// //------------------- включення директив препроцесора ---------------------// #include <stdio.h> #include <mega8.h> #include <delay.h> //-------------------- встановлення портів-----------------// #define key1 PIND.0 #define key2 PIND.1 #define key3 PIND.2 #define key4 PIND.3 #define pulse PIND.4 #define beep PORTC.3 //--- визначення імпульсів від датчика---// #define light PORTC.2 #define sound PORTC.1 eeprom unsigned int zone1; eeprom unsigned int zone2; unsigned int k=0; int sec=0; int rf=0; int j=0; int i=1; //кнопки < > int m_buffer=0; int memory=1; // виділення пам'яті для зони 1 int memory1=2; // виділення пам'яті для зони 2 int warn=400; // стандартний рівень радіації bit ok=0; // так bit x=0; // ні bit a1=0; bit a2=0; bit a3=0; bit a4=0; char lcd_buffer[80]; // буфер рівня LCD! //------------------------------------ Переривання для таймера -----------------------// interrupt [TIM1_COMPA] void timer1_comp_isr(void) { sec++; } /* void wait (void){ TCNT1=0; while (TCNT1<780){}; } */ //---------------- Буквено-цифрові функції Модуля LCD----------------// #asm .equ __lcd_port=0x18 ;PORTB #endasm #include <lcd.h> // Оголосіть свої глобальні змінні тут //----------------------Звуковий сигнал --------------------// void my_beep(void) { // ключовий звуковий сигнал beep = 0; delay_ms(30); beep = 1;} // Короткий звуковий сигнал //----------------- Довгий звуковий сигнал ---------------------// void long_beep(void) { // Ключовий звуковий сигнал beep = 0; delay_ms(55); beep = 1; delay_ms(30); beep = 0; delay_ms(30); beep = 1;} //------------------------ Ключі функцій -----------------------// void my_keys(void){ if(!key1){ok=1;}else{delay_ms(10); ok=0;} if(!key2){x=1;}else{delay_ms(10); x=0;} if(i<8){if(!key4){i++; my_beep(); lcd_clear(); delay_ms(680); }} if(i>1){if(!key3){i--; my_beep(); lcd_clear(); delay_ms(680); }} } //---------------------------- Головна програма ----------------------------// void main(void) { PORTB=0x00; DDRB=0x00; PORTC=0x7F; DDRC=0x7F; PORTC.2=0; PORTC.4=0; PORTC.5=0; PORTD=0xFF; DDRD=0x00; ACSR=0x80; SFIOR=0x00; //----------------------------- Для таймера ----------------------------// OCR1A=4000; // Для кварца TCCR1B=0x0D; TIMSK=0x10; //----------------------------------------------------------------------------------------------------// lcd_init(16); my_beep(); // Початок delay_ms(100); my_beep(); while (1) { my_keys(); switch (i) { case 1: // Запуск меню my_keys(); lcd_gotoxy(0,0); lcd_putsf("Menu programm"); lcd_gotoxy(0,1); lcd_putsf("Enter key~ "); delay_ms(1); if(sec>=60){#asm("cli"); m_buffer=k; } //anti kosac break; //STOP1 case 2: // Тест датчика my_keys(); lcd_gotoxy(0,0); sprintf(lcd_buffer,"fon=%4umkr Time=%2uc" "RF=%2u ",k,sec,rf);// PRINT ON LCD lcd_puts(lcd_buffer); // З буфера на LCD delay_ms(1); // потрібно обслуговувати таймери if((ok)&(a1)){delay_ms(50); #asm("sei");} //Start k=0; j=0; rf=0; if(x){#asm("cli"); beep=1;} //Зупинка if(sec>=60){#asm("cli"); a1=0;m_buffer=k; } // Авто зупинка if(sec==61){sec=0; k=0; j=0; rf=0; beep=1;} // повторний запуск if(ok){a1=1;} if(x){a1=0;} if((!pulse)&(a1)){delay_ms(10); k++; j++;} // Введіть допустиме значення радіації if(j==20){delay_us(1); rf++; j=0;} if(k==warn){delay_us(1); beep=0;} // Небезпечне випромінювання if(k==1600){delay_us(1); sec=0; k=0; j=0; rf=0; beep=1;} //Допустиме випромінювання break; case 3: // Зберігання значення в пам'яті EEPROM в зоні 1 my_keys(); lcd_gotoxy(0,0); sprintf(lcd_buffer,"Zone1=%4umkr ",memory);// TO LCD lcd_puts(lcd_buffer); lcd_gotoxy(0,1); lcd_putsf("Save Load"); delay_ms(1); if(sec>=60){#asm("cli"); m_buffer=k; } if((ok)&(k>=10)){ zone1=m_buffer;} // Збережіть лише значення >10 if(x){ memory=zone1;} break; case 4: // Зберігання значення в пам'яті EEPROM в зоні 2 my_keys(); lcd_gotoxy(0,0); sprintf(lcd_buffer,"Zone2=%4umkr ",memory1); lcd_puts(lcd_buffer); lcd_gotoxy(0,1); lcd_putsf("Save Load"); delay_ms(1); // need wait on timers if(sec>=60){#asm("cli"); m_buffer=k; } // Збережіть лише значення >10 if((ok)&(k>=10)){ zone2=k;} if(x){ memory1=zone2;} break; case 5: // Вмикання/вимикання сигнальної лампочки my_keys(); lcd_gotoxy(0,0); lcd_putsf("Backlight "); lcd_gotoxy(0,1); lcd_putsf("v on/off x"); if(ok){a2=1; PORTC.4=1;} if(x){a2=0; PORTC.4=0;} delay_ms(1); if(sec>=60){#asm("cli"); m_buffer=k; } if(a2){ lcd_gotoxy(11,0); lcd_putsf("on "); } if(!a2){ lcd_gotoxy(11,0); lcd_putsf("off ");} break; case 6: // Вмикання/вимикання звукового резонатора my_keys(); lcd_gotoxy(0,0); lcd_putsf("Sound "); lcd_gotoxy(0,1); lcd_putsf("v on/off x"); if(ok){a3=1; PORTC.5=1;} if(x){a3=0; PORTC.5=0;} delay_ms(1); if(sec>=60){#asm("cli"); m_buffer=k; } if(a3){ lcd_gotoxy(11,0); lcd_putsf("on "); } if(!a3){ lcd_gotoxy(11,0); lcd_putsf("off ");} break; case 7: // Попереджувальний рівень +/- my_keys(); lcd_gotoxy(0,0); sprintf(lcd_buffer,"Warning=%4umkr ",warn); lcd_puts(lcd_buffer); lcd_gotoxy(0,1); lcd_putsf("v +/- x"); //delay_ms(1); // need wait on timers if(sec>=60){#asm("cli"); m_buffer=k; } if(warn<1500){if(!key1){warn++; delay_ms(80); }} if(warn>10){if(!key2){warn--;delay_ms(80); }} break; case 8: // Вмикання режиму безперервного вимірювання my_keys(); lcd_gotoxy(0,0); sprintf(lcd_buffer,"Fon=%4umkr Bufer=%4u" "RF=%2u ",k,m_buffer=k,rf);// Вивід значення на LCD lcd_puts(lcd_buffer); //lcd_gotoxy(0,1); lcd_putsf("While"); delay_ms(1); // need wait on timers if((ok)&(a4)){delay_ms(50); #asm("sei");} //Start k=0; j=0; rf=0; if(x){#asm("cli"); beep=1;} // Зупинка if(sec==61){ sec=0; k=0; j=0; rf=0; beep=1;m_buffer=k;} if(ok){a4=1;} if(x){a4=0;} if((!pulse)&(a4)){delay_ms(10); k++; j++;} if(j==20){delay_us(1); rf++; j=0;} if(k==warn){delay_us(1); beep=0;} // Сигнальне вимірювання if(k==1600){delay_us(1); sec=0; k=0; j=0; rf=0; beep=1;} //максимальне значення вимірювання break; } }; }
Страницы: 1, 2
|