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

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

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

Рік:
2015
Тип роботи:
Лабораторна робота
Предмет:
Інші
Група:
ІБ-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.
Антиботан аватар за замовчуванням

2015

Коментарі

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

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

Нічого не вибрано
0%

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

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

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

Admin

26.02.2023 12:38

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