Інформація про навчальний заклад

ВУЗ:
Національний університет Львівська політехніка
Інститут:
Не вказано
Факультет:
Не вказано
Кафедра:
Не вказано

Інформація про роботу

Рік:
2009
Тип роботи:
Лабораторна робота
Предмет:
Інші
Група:
ІБ-42

Частина тексту файла (без зображень, графіків і формул):

Міністерство освіти та науки України Національний університет “Львівська політехніка”  Звіт про виконання лабораторної роботи №5 з курсу “Мікропроцесорні пристрої ” Виконав: ст. гр. ІБ – 42 Львів – 2009        // Блок управління системи контролю доступу на МК АТ90S2313 з iButton DS1990, I2C-RTC DS1307 та // SPI-EEPROM 25LC256 (32Kx8) // Тактова частота МК 7.3728 МГц //////////////////////////////////////////////////////////////////////////// // Порт для підключення iButton DS1990 #asm .equ __w1_port = 0x18 .equ __w1_bit = 5 #endasm //////////////////////////////////////////////////////////////////////////// // Порт для підключення I2C-RTC DS1307 #asm .equ __i2c_port = 0x18 .equ __scl_bit = 2 .equ __sda_bit = 1 #endasm //////////////////////////////////////////////////////////////////////////// #include <90S2313.h> #include <1wire.h> #include <i2c.h> #include <delay.h> //////////////////////////////////////////////////////////////////////////// // Оголошення типу даних - байт typedef unsigned char byte; //////////////////////////////////////////////////////////////////////////// // Структура дати і часу typedef struct { byte Second; byte Minute; byte Hour; byte Day; byte Date; byte Month; byte Year; } DS1307_Data; ///////////////////////////////////////////////////////////////////////////// // Глобальні змінні // Оголошення змінної для збереження поточного часу і дати DS1307_Data DS1307_1; // Оголошення змінної для збереження ідентифікаційного номера iButton DS1990A byte ROM_Code[9]; //////////////////////////////////////////////////////////////////////////// //******************************************************************// // Виводи SPI-EEPROM 25LC256 #define PORT_EEPROM PORTD #define DDR_EEPROM DDRD #define PIN_EEPROM PIND #define CS 3 #define SCK 4 #define SI 5 #define SO 6 //******************************************************************// // Виводи I2C-RTC DS1307 #define PORT_RTC PORTB #define DDR_RTC DDRB #define PIN_RTC PINB #define SDA 1 #define SCL 2 //******************************************************************// // Виводи iButton DS1990A #define PORT_iButton PORTB #define DDR_iButton DDRB #define PIN_iButton PINB #define Data_iButton 5 //******************************************************************// // Виводи електронного замка #define PORT_Switch PORTB #define DDR_Switch DDRB #define PIN_Switch PINB #define Switch 7 //******************************************************************// // Виводи світлодіоду #define PORT_Led PORTB #define DDR_Led DDRB #define PIN_Led PINB #define Led 6 //******************************************************************// // Виводи кнопки виходу #define PORT_Out_Key PORTD #define DDR_Out_Key DDRD #define PIN_Out_Key PIND #define Out_Key 2 //******************************************************************// // Коди команд EEPROM 25LC256 #define EEPROM_READ 0x03 #define EEPROM_WRITE 0x02 #define EEPROM_WRDI 0x04 #define EEPROM_WREN 0x06 #define EEPROM_RDSR 0x05 #define EEPROM_WRSR 0x01 //******************************************************************// // Коди команд iButton DS1990 #define SEARCH_ROM 0xF0 //******************************************************************// // Адреса сімейства iButton #define DS1990_FAMILY_CODE 0x01 //******************************************************************// // Кількість подій в системі #define N_Record 100 //******************************************************************// // Розмір одного запису в байтах #define Record_Size 16 //******************************************************************// // Адреса початку записів в EEPROM 25LC256 #define Record_Addr 0x40 //******************************************************************// // Адреса лічильника записів в EEPROM #define Record_Count_Addr 0x30 //******************************************************************// // Час відкривання дверей в мілісекундах #define T_msec 7000 //******************************************************************// // Кількість зареєстрованих ключів #define N_Key 2 //******************************************************************// // Тип запису #define Input_Record 0 #define Output_Record 1 //******************************************************************// // E8C52A // 3D2C90 /*----------------------------------------------------------------*/ // Підпрограма обслуговування зовнішнього переривання по виводу INT0 interrupt [2] void ext_interrupt0(void); /*----------------------------------------------------------------*/ void Pin_Init(void); // Функції нижнього рівня роботи з ГРЧ void DS1307_Init(void); void DS1307_Read(DS1307_Data* arg1); void DS1307_Write(DS1307_Data* arg1); byte SPI_Send_Byte(byte data); void SPI_Send_CMD1(byte cmd); byte SPI_Read_SR(void); byte SPI_Read_Data(int address, byte* buffer, byte n); byte SPI_Write_Data(int address, byte* buffer, byte n); void Save_Record( byte* code,DS1307_Data* arg1, byte type); /////////////////////////////////////////////////////////////////////////// void main(void) { byte temp, ii, jj, temp1; byte iButton_Arrary[N_Key][8]; Pin_Init(); DS1307_1.Second = 0x21; // Початкова дата: 10-07-08 23:55:55 DS1307_1.Minute = 0x56; DS1307_1.Hour = 0x15; DS1307_1.Day = 0x02; DS1307_1.Date = 0x07; DS1307_1.Month = 0x07; DS1307_1.Year = 0x09; DS1307_Init(); DS1307_Write(&DS1307_1); // Прочитати зареєстровані ключі з EEPROM-пам'ті for(ii = 0; ii < N_Key; ii++) temp = SPI_Read_Data(0x0000 + ii * 8, &iButton_Arrary[ii][0], 8); // Налаштувати зовнішнє переривання INT0 від кнопки виходу GIMSK = GIMSK | 0x40; MCUCR = MCUCR | 0x02; while(1) { #asm("cli") temp = w1_search(SEARCH_ROM, &ROM_Code[0]); if (temp == 0) { #asm("sei") } else { // Пошук for(ii = 0; ii < N_Key; ++ii) { temp1 = 0; for(jj = 0; jj < 8; ++jj) { if(ROM_Code[jj] != iButton_Arrary[ii][jj]) { temp1 = 1; break; } } if(temp1 == 0) break; } if(temp1 == 0) { DS1307_Read(&DS1307_1); Save_Record( &ROM_Code[0],&DS1307_1, Input_Record); PORT_Led.Led = 0; PORT_Switch.Switch = 1; delay_ms(T_msec); PORT_Led.Led = 1; PORT_Switch.Switch = 0; } else #asm("sei"); } delay_ms(1); }; }; ////////////////////////////////////////////////////////////////////////// void DS1307_Init(void) { // Ініціалізація І2С шини та режиму роботи годинника реального часу (RTC) byte temp; temp = i2c_start(); // Сформувати умову START temp = i2c_write(0xd0); // Задати адресу пристрою та операцію запису (R/W=0) temp = i2c_write(0x07); // Задати адресу регістра управління 0х07 temp = i2c_write(0b00000000); // Включити RTC i2c_stop(); // Сформувати умову STOP }; /////////////////////////////////////////////////////////////////////////// void DS1307_Read(DS1307_Data* arg1) { // Зчитування часу та дати з RTC byte temp2; temp2 = i2c_start(); // Сформувати умову START temp2 = i2c_write(0xd0); // Задати адресу пристрою та операцію запису (R/W=0) temp2 = i2c_write(0x00); // Задати початкову адресу регістра 0х00 i2c_stop(); // Сформувати умову STOP temp2 = i2c_start(); // Сформувати умову START temp2 = i2c_write(0xd1); // Задати адресу пристрою та операцію читання (R/W=1) arg1->Second = i2c_read(1) & 0x7F; // Прочитати регістр секунд arg1->Minute = i2c_read(1) & 0x7F; // Прочитати регістр хвилин arg1->Hour = i2c_read(1) & 0x3F; // Прочитати регістр годин arg1->Day = i2c_read(1) & 0x07; // Прочитати регістр дня arg1->Date = i2c_read(1) & 0x3F; // Прочитати регістр числа arg1->Month = i2c_read(1) & 0x1F; // Прочитати регістр місяця arg1->Year = i2c_read(0); // Прочитати регістр року та сформувати біт NACK i2c_stop(); // Сформувати умову STOP }; ////////////////////////////////////////////////////////////////////////// void DS1307_Write(DS1307_Data* arg1) { // Запис часу та дати в RTC byte temp2; temp2 = i2c_start(); // Сформувати умову START temp2 = i2c_write(0xd0); // Задати адресу пристрою та операцію запису (R/W=0) temp2 = i2c_write(0x00); // Задати початкову адресу регістра 0х00 temp2 = i2c_write(arg1->Second); // Записати значення в регістр секунд temp2 = i2c_write(arg1->Minute); // Записати значення в регістр хвилин temp2 = i2c_write(arg1->Hour | 0b00000000); // Записати значення в регістр годин temp2 = i2c_write(arg1->Day); // Записати значення в регістр днів temp2 = i2c_write(arg1->Date); // Записати значення в регістр дати temp2 = i2c_write(arg1->Month); // Записати значення в регістр місяця temp2 = i2c_write(arg1->Year); // Записати значення в регістр року i2c_stop(); // Сформувати умову STOP }; ////////////////////////////////////////////////////////////////////////// byte SPI_Send_Byte(byte data) { byte ii, temp, result = 0, temp1 = 0x80; for(ii = 0; ii < 8; ++ii) { temp = PIN_EEPROM; temp = temp & (1<<SO); if(temp != 0) result = result | temp1; PORT_EEPROM.SI = (data & temp1) && 1; #asm("nop"); PORT_EEPROM.SCK = 1; temp1 = temp1 >> 1; PORT_EEPROM.SCK = 0; } return result; }; ////////////////////////////////////////////////////////////////////////// void Pin_Init(void) { PORT_EEPROM.CS = 1; PORT_EEPROM.SCK = 0; PORT_EEPROM.SI = 0; PORT_EEPROM.SO = 0; DDR_EEPROM.CS = 1; DDR_EEPROM.SCK = 1; DDR_EEPROM.SI = 1; DDR_EEPROM.SO = 0; PORT_Switch.Switch = 0; DDR_Switch.Switch = 1; PORT_Led.Led = 1; DDR_Led.Led = 1; PORT_Out_Key.Out_Key = 0; DDR_Out_Key.Out_Key = 0; }; ////////////////////////////////////////////////////////////////////////// byte SPI_Write_Data(int address, byte* buffer, byte n) { byte ii, result; PORT_EEPROM.CS = 0; SPI_Send_Byte(EEPROM_WRITE); SPI_Send_Byte(address>>8); SPI_Send_Byte(address); for(ii = 0; ii < n; ++ii) SPI_Send_Byte(buffer[ii]); PORT_EEPROM.SI = 0; PORT_EEPROM.CS = 1; return result; }; ////////////////////////////////////////////////////////////////////////// byte SPI_Read_Data(int address, byte* buffer, byte n) { byte ii, result; PORT_EEPROM.CS = 0; SPI_Send_Byte(EEPROM_READ); SPI_Send_Byte(address>>8); SPI_Send_Byte(address); for(ii = 0; ii < n; ii++) buffer[ii] = SPI_Send_Byte(0); PORT_EEPROM.SI = 0; PORT_EEPROM.CS = 1; return result; }; ///////////////////////////////////////////////////////////////////////// void SPI_Send_CMD1(byte cmd) { PORT_EEPROM.CS = 0; SPI_Send_Byte(cmd); PORT_EEPROM.SI = 0; PORT_EEPROM.CS = 1; }; ////////////////////////////////////////////////////////////////////////// byte SPI_Read_SR(void) { byte temp; PORT_EEPROM.CS = 0; temp = SPI_Send_Byte(EEPROM_RDSR); temp = SPI_Send_Byte(0); PORT_EEPROM.SI = 0; PORT_EEPROM.CS = 1; return temp; }; ////////////////////////////////////////////////////////////////////////// interrupt [2] void ext_interrupt0(void) { byte ii; delay_ms(10); // Затримка 10 мс для усунення явища тремтіння контактів if(PIN_Out_Key.Out_Key == 0) // Якщо натиснуто кнопку відкривання дверей { DS1307_Read(&DS1307_1); // Прочитати часі і дату з RTC for(ii = 0; ii < 8; ++ii) ROM_Code[ii] = 0; // В поле коду iButton занести 0 Save_Record( &ROM_Code[0], &DS1307_1, Output_Record); // Зробити запис PORT_Led.Led = 0; // Включити світлодіод PORT_Switch.Switch = 1; // Включити електронний замок delay_ms(T_msec); // Затримка PORT_Led.Led = 1; // Виключити світлодіод PORT_Switch.Switch = 0; // Виключити електронний замок } }; /////////////////////////////////////////////////////////////////////////// void Save_Record( byte* code, DS1307_Data* arg1, byte type) { byte temp, temp1; int start; while((temp = SPI_Read_SR()) & 0x01) // Очікувати готовності EEPROM ; // Прочитати значення лічильника подій в змінну temp1 temp = SPI_Read_Data(Record_Count_Addr, &temp1, 1); if(temp1 == N_Record) // Якщо досягнуто максимального значення { temp1 = 1; // Почати заново start = Record_Addr; } else // Інакше обчислити адресу наступного запису { start = Record_Addr + Record_Size * (int)temp1; temp1++; // Збільшити кількість записів на 1 } SPI_Send_CMD1(EEPROM_WREN); // Дозволити запис в EEPROM while((temp = SPI_Read_SR()) & 0x01) // Очікувати готовності EEPROM ; // Записати 8 байт ідентифікаційного номеру DS1990A temp = SPI_Write_Data(start, code, 8); while((temp = SPI_Read_SR()) & 0x01) // Очікувати готовності EEPROM ; SPI_Send_CMD1(EEPROM_WREN); // Дозволити запис в EEPROM while((temp = SPI_Read_SR()) & 0x01) // Очікувати готовності EEPROM ; temp = SPI_Write_Data(start + 8, arg1, 6); // Записати час і дату події while((temp = SPI_Read_SR()) & 0x01) // Очікувати готовності EEPROM ; SPI_Send_CMD1(EEPROM_WREN); // Дозволити запис в EEPROM while((temp = SPI_Read_SR()) & 0x01) // Очікувати готовності EEPROM ; temp = SPI_Write_Data(start + 15, &type, 1); // Записати тип події: вхід чи вихід while((temp = SPI_Read_SR()) & 0x01) // Очікувати готовності EEPROM ; SPI_Send_CMD1(EEPROM_WREN); // Дозволити запис в EEPROM while((temp = SPI_Read_SR()) & 0x01) // Очікувати готовності EEPROM ; temp = SPI_Write_Data(Record_Count_Addr, &temp1, 1); // Записати нове значення лічильника }; Висновок: на лабораторній роботі я ознайомився з принципами побудови модулів управління систем контролю доступу. Вивчив правила обміну інформацією через інтерфейси  та ознайомився з їх програмною реалізацією для AVR-мікроконтроллерів на мові C в середовищі CodeVisionAVR.
Антиботан аватар за замовчуванням

01.01.1970 03:01-

Коментарі

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

Ділись своїми роботами та отримуй миттєві бонуси!

Маєш корисні навчальні матеріали, які припадають пилом на твоєму комп'ютері? Розрахункові, лабораторні, практичні чи контрольні роботи — завантажуй їх прямо зараз і одразу отримуй бали на свій рахунок! Заархівуй всі файли в один .zip (до 100 МБ) або завантажуй кожен файл окремо. Внесок у спільноту – це легкий спосіб допомогти іншим та отримати додаткові можливості на сайті. Твої старі роботи можуть приносити тобі нові нагороди!
Нічого не вибрано
0%

Оголошення від адміністратора

Антиботан аватар за замовчуванням

Подякувати Студентському архіву довільною сумою

Admin

26.02.2023 12:38

Дякуємо, що користуєтесь нашим архівом!