Побудова модуля управління системи контролю доступу на AVR-мікроконтролерах. Робота з інтерфейсами 1-Wire, I2C, SPI

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

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

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

Рік:
2024
Тип роботи:
Звіт до лабораторної роботи
Предмет:
Мікропроцесори

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

МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ "ЛЬВІВСЬКА ПОЛІТЕХНІКА" ІНСТИТУТ КОМП’ЮТЕРНИХ ТЕХНОЛОГІЙ, АВТОМАТИКИ ТА МЕТРОЛОГІЇ КАФЕДРА ”ЗАХИСТ ІНФОРМАЦІЇ”  Звіт до лабораторної роботи № 5 з курсу: "Мікропроцесори в системах технічного захисту інформації" на тему: “ Побудова модуля управління системи контролю доступу на AVR-мікроконтролерах. Робота з інтерфейсами 1-Wire, I2C, SPI ” Варіант – 17 Львів – 2011р. Мета роботи: Ознайомитись з принципами побудови модулів управління систем контролю доступу. Вивчити правила обміну інформацією через інтерфейси 1-Wire, I2C, SPI та набути навиків з їх програмної реалізації для AVR-мікроконтролерів на мові С в середовищі CodeVisionAVR. Повний текст завдання: Домашня підготовка до роботи: 1. Вивчити теоретичний матеріал. 2. Вивчити основні властивості інтерфейсів 1-Wire, I2C, SPI та правила обміну даними по них, принципи роботи з мікросхемами DS1990A, DS1307, 25LC256, принципи побудови та функціонування СКД необхідні для виконання лабораторної роботи. 3. Підготовити програму функціонування модуля управління СКД згідно індивідуального завдання в Табл. 8. Алгоритм функціонування модуля управління СКД аналогічний описаному в пункті 2. Виконати в лабораторії 1. Створити проект в CodeVisionAVR, ввести свою програму, провести її компіляцію. 2. Відкрити файл LR_5.dsn в програмі Proteus, внести зміни у схему відповідно до свого індивідуального завдання, підключити до МК отриманий в CodeVisionAVR hex-файл. 3. Запустити режим симуляції схеми та перевірити правильність функціонування модуля управління СКД у всіх режимах роботи: очікування, пред’явлення зареєстрованого ключа, пред’явлення незареєстрованого ключа, натискання кнопки виходу. № Кількість записів, Nevent Кількість зареєстрованих ключів Час відкриття дверей tвідкр, сек Формат реєстраційного запису Початкова дата та час  17 50 2 3 Номер ключа, місяць, число, година, хвилина, секунда, тип події (вхід/вихід) 16.05.09 14:14:29   Лістинг програми одержаної в AVR Studio та необхідні розрахунки: // Блок управління СКД на МК АТ90S2313 з iButton DS1990А, ГРЧ DS1307 та EEPROM 25LC256 // Тактова частота МК 7.3728 МГц //////////////////////////////////////////////////////////////////////////////////// // Порт для підключення iButton DS1990 (PORTB, PB5) #asm .equ __w1_port = 0x18 .equ __w1_bit = 5 #endasm //////////////////////////////////////////////////////////////////////////////////// // Порт для підключення I2C-RTC DS1307 (PORTB, PB2, PB1) #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> #include <stdio.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 50 //******************************************************************// // Розмір одного запису в байтах #define Record_Size 16 //******************************************************************// // Адреса початку записів в EEPROM 25LC256 #define Record_Addr 0x40 //******************************************************************// // Адреса лічильника записів в EEPROM #define Record_Count_Addr 0x30 //******************************************************************// // Час відкривання дверей в мілісекундах #define T_msec 3000 //******************************************************************// // Кількість зареєстрованих ключів #define N_Key 2 //******************************************************************// // Тип запису #define Input_Record 0 #define Output_Record 1 //******************************************************************// /*----------------------------------------------------------------*/ // Підпрограма обслуговування зовнішнього переривання по виводу INT0 // Викликається при натисканні кнопки виходу interrupt [2] void ext_interrupt0(void); /*----------------------------------------------------------------*/ // Ініціалізація виводів void Pin_Init(void); /*----------------------------------------------------------------*/ // Функції для роботи з ГРЧ // Ініціалізація ГРЧ DS1307 void DS1307_Init(void); // Читання даних з ГРЧ DS1307 void DS1307_Read(DS1307_Data* arg1); // Запис даних в ГРЧ DS1307 void DS1307_Write(DS1307_Data* arg1); /*----------------------------------------------------------------*/ // Функції для роботи з SPI EEPROM-пам'ттю 25LC256 // Обмін одним байтом через інтерфейс SPI byte SPI_Send_Byte(byte data); // Відправка однобайтової команди через інтерфейс SPI void SPI_Send_CMD1(byte cmd); // Читання регістра статусу EEPROM-пам'ті 25LC256 byte SPI_Read_SR(void); // Читання в масив buffer n байт з EEPROM-пам'ті, починаючи з адреси address void SPI_Read_Data(int address, byte* buffer, byte n); // Запис масиву buffer розміром n байт в EEPROM-пам'ть, починаючи з адреси address void SPI_Write_Data(int address, byte* buffer, byte n); // Функція для занесення реєстраційного запису в EEPROM-пам'ять void Save_Record(DS1307_Data* arg1, byte* code, byte type); ///////////////////////////////////////////////////////////////////////////////////// void main(void) { byte temp, ii, jj, temp1; // Масив в ОЗП для зберігання ID зареєстрованих в системі N_Key ключів iButton byte iButton_Arrary[N_Key][8]; // Налаштування виводів СКД Pin_Init(); // Ініціалізація заданими часом і датою: 16-05-09 14:14:29 DS1307_1.Second = 0x29; DS1307_1.Minute = 0x14; DS1307_1.Hour = 0x14; DS1307_1.Day = 0x07; DS1307_1.Date = 0x16; DS1307_1.Month = 0x05; DS1307_1.Year = 0x09; // Ініціалізація I2C інтерфейсу DS1307_Init(); // Запис дати і часу в ГРЧ DS1307_Write(&DS1307_1); // Прочитати зареєстровані ключі з EEPROM-пам'ті в ОЗП for(ii = 0; ii < N_Key; ii++) SPI_Read_Data(0x0000 + (ii << 3), &iButton_Arrary[ii][0], 8); // Налаштувати зовнішнє переривання INT0 від кнопки виходу GIMSK = GIMSK | 0x40; // Дозволити переривання INT0 MCUCR = MCUCR | 0x02; // Переривання по спадаючому фронту // Вічний цикл опитування зчитувачів iButton while(1) { #asm("cli") // Заборонити переривання temp = w1_search(SEARCH_ROM, &ROM_Code[0]); // Чи є торкання зчитувача ключом iButton if (temp == 0) // Якщо немає - дозволити переривання { #asm("sei") } else // Якщо виявлено DS1990A { // Пошук серед зареєстрованих в СКД ключів for(ii = 0; ii < N_Key; ii++) // Для кожного ключа { temp1 = 0; for(jj = 0; jj < 8; jj++) // Порівняти його 8-байтний ID з зареєстрованими ключами { if(ROM_Code[jj] != iButton_Arrary[ii][jj]) { temp1 = 1; // Якщо хоча б 1 байт неспівпадає break; // Перейти до перевірки наступного ключа } } if(temp1 == 0) // Якщо ключ знайдено - вийти з циклу break; } if(temp1 == 0) // Якщо ключ знайдено { DS1307_Read(&DS1307_1); // Прочитати поточні час і дату Save_Record(&DS1307_1, &ROM_Code[0], Input_Record); // Сформувати реєстраційний запис і записати в EEPROM-пам'ять 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(10); // Через 10 мс знову повернутися до опитування зчитувачів }; }; /////////////////////////////////////////////////////////////////////////////////////// // Ініціалізація І2С шини та режиму роботи годинника реального часу DS1307 void DS1307_Init(void) { i2c_start(); // Сформувати умову START на шині І2С i2c_write(0xd0); // Задати адресу DS1307 та операцію запису (R/W=0) i2c_write(0x07); // Задати внутрішню адресу з якої почнеться запис-регістр Control i2c_write(0b00000000); // Вихід SQW/OUT - неактивний, з логічним 0 i2c_stop(); // Сформувати умову STОР на шині І2С }; /////////////////////////////////////////////////////////////////////////////////////// // Функція зчитування з ГРЧ DS1307 часу і дати // Вхідні параметри: // arg1 - структура, в яку записуються поточні час і дата. void DS1307_Read(DS1307_Data* arg1) { i2c_start(); // Сформувати умову START на шині І2С i2c_write(0xd0); // Задати адресу DS1307 та операцію запису (R/W=0) i2c_write(0x00); // Записати внутрішню адресу DS1307 з якої почнеться читання i2c_stop(); // Сформувати умову STОР на шині І2С i2c_start(); // Сформувати умову START на шині І2С i2c_write(0xd1); // Задати адресу DS1307 та операцію читання (R/W=1) arg1->Second = i2c_read(1) & 0x7F; // Прочитати регістр секунд, сформувати біт ACK arg1->Minute = i2c_read(1) & 0x7F; // Прочитати регістр хвилин, сформувати біт ACK arg1->Hour = i2c_read(1) & 0x3F; // Прочитати регістр годин, сформувати біт ACK arg1->Day = i2c_read(1) & 0x07; // Прочитати регістр днів, сформувати біт ACK arg1->Date = i2c_read(1) & 0x3F; // Прочитати регістр числа, сформувати біт ACK arg1->Month = i2c_read(1) & 0x1F; // Прочитати регістр місяця, сформувати біт ACK arg1->Year = i2c_read(0); // Прочитати регістр року, сформувати біт NACK i2c_stop(); // Сформувати умову STОР на шині І2С }; ///////////////////////////////////////////////////////////////////////////////////// // Функція запису в ГРЧ DS1307 часу і дати // Вхідні параметри: // arg1 - структура, яка містить задані час і дату void DS1307_Write(DS1307_Data* arg1) { i2c_start(); // Сформувати умову START на шині І2С i2c_write(0xd0); // Задати адресу DS1307 та операцію запису (R/W=0) i2c_write(0x00); // Задати внутрішню адресу DS1307 з якої почнеться запис i2c_write(arg1->Second); // Записати в регістр секунд і запустити відлік часу i2c_write(arg1->Minute); // Записати в регістр хвилин i2c_write(arg1->Hour); // Записати в регістр годин i2c_write(arg1->Day); // Записати в регістр дня i2c_write(arg1->Date); // Записати в регістр числа i2c_write(arg1->Month); // Записати в регістр місяця i2c_write(arg1->Year); // Записати в регістр року i2c_stop(); // Сформувати умову STОР на шині І2С }; //////////////////////////////////////////////////////////////////////////////////// // Функція обміну байтом через інтерфейс SPI // Вхідні параметри: // data - байт для передачі через SPI. // Вихідні параметри: // Прийнятий байт через SPI. byte SPI_Send_Byte(byte data) { byte ii, temp, result = 0, mask = 0x80; for(ii = 0; ii < 8; ++ii) // Цикл для передачі і прийому 8 біт через SPI { temp = PIN_EEPROM & (1<<SO); // Прочитати стан сигналу на лінії SO if(temp != 0) // Якщо SO=1, занести 1 у черговий біт результату result = result | mask; PORT_EEPROM.SI = (data & mask) && 1; // Виставити на лінію SI черговий біт #asm("nop"); PORT_EEPROM.SCK = 1; // Сформувати тактовий імпульс mask = mask >> 1; // Зсунути маску на 1 розряд PORT_EEPROM.SCK = 0; // Зняти тактовий імпульс } return result; // Повернути прийнятий байт }; ////////////////////////////////////////////////////////////////////////////////////// // Функція здійснює налаштування виводів МК відповідно до схеми СКД // Виводи підключені до зчитувача iButton та ГРЧ DS1307 ініціалізуються компілятором void Pin_Init(void) { // Виводи підключені до мікросхеми EEPROM-пам'яті 25LC256 PORT_EEPROM.CS = 1; // На лінії лог. 1 - мікросхема EEPROM-пам'яті 25LC256 неактивна PORT_EEPROM.SCK = 0; // На лінії логічний 0 PORT_EEPROM.SI = 0; // На лінії логічний 0 PORT_EEPROM.SO = 0; // Внутрішній підтягуючий резистор відключений DDR_EEPROM.CS = 1; // Вихід сигналу #SS інтерфейсу SPI DDR_EEPROM.SCK = 1; // Вихід сигналу SCLK інтерфейсу SPI DDR_EEPROM.SI = 1; // Вихід сигналу MОSІ інтерфейсу SPI DDR_EEPROM.SO = 0; // Вхід сигналу MISO інтерфейсу SPI // Вивід підключений до електронного замка PORT_Switch.Switch = 0; // На лінії логічний 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; // Внутрішній підтягуючий резистор відключений }; ////////////////////////////////////////////////////////////////////////////////////// // Функція здійснює запис масиву байт в EEPROM-пам'ять 25LC256 // Вхідні параметри: // address - адреса в EEPROM-пам'яті з якої почнеться запис; // buffer - масив з даними для запису; // n - кількість байт для запису. void SPI_Write_Data(int address, byte* buffer, byte n) { byte ii; PORT_EEPROM.CS = 0; // Активізувати мікросхему EEPROM-пам'яті SPI_Send_Byte(EEPROM_WRITE); // Відправти в EEPROM команду запису SPI_Send_Byte(address>>8); // Відправити в EEPROM ст. байт адреси початку запису SPI_Send_Byte(address); // Відправити в EEPROM мол. байт адреси початку запису for(ii = 0; ii < n; ii++) // Цикл запису n байт в EEPROM-пам'ять SPI_Send_Byte(buffer[ii]); PORT_EEPROM.SI = 0; // Перевести лінію SI в неактивний стан PORT_EEPROM.CS = 1; // Відключити мікросхему EEPROM-пам'яті }; /////////////////////////////////////////////////////////////////////////////////////// // Функція здійснює читання масиву байт з EEPROM-пам'яті 25LC256 // Вхідні параметри: // address - адреса в EEPROM-пам'яті з якої почнеться читання; // buffer - масив для зберігання прочитаних даних; // n - кількість байт для читання. void SPI_Read_Data(int address, byte* buffer, byte n) { byte ii; PORT_EEPROM.CS = 0; // Активізувати мікросхему EEPROM-пам'яті SPI_Send_Byte(EEPROM_READ); // Відправти в EEPROM-пам'ять команду читання SPI_Send_Byte(address>>8); // Відправити в EEPROM ст. байт адреси початку читання SPI_Send_Byte(address); // Відправити в EEPROM мол. байт адреси початку читання for(ii = 0; ii < n; ii++) // Цикл читання n байт з EEPROM-пам'яті buffer[ii] = SPI_Send_Byte(0); PORT_EEPROM.SI = 0; // Перевести лінію SI в неактивний стан PORT_EEPROM.CS = 1; // Відключити мікросхему EEPROM-пам'яті }; /////////////////////////////////////////////////////////////////////////////////////// // Функція відсилає однобайтову команду в EEPROM-пам'ять 25LC256 // Вхідні параметри: // cmd - код команди. void SPI_Send_CMD1(byte cmd) { PORT_EEPROM.CS = 0; // Активізувати мікросхему EEPROM-пам'яті SPI_Send_Byte(cmd); // Відправти в EEPROM-пам'ять код команди PORT_EEPROM.SI = 0; // Перевести лінію SI в неактивний стан PORT_EEPROM.CS = 1; // Відключити мікросхему EEPROM-пам'яті }; /////////////////////////////////////////////////////////////////////////////////////// // Функція читає регістр статусу EEPROM-пам'яті 25LC256 та повертає його значення // Вихідні параметри: // Вміст регістра статусу. byte SPI_Read_SR(void) { byte temp; PORT_EEPROM.CS = 0; // Активізувати мікросхему EEPROM-пам'яті SPI_Send_Byte(EEPROM_RDSR); // Відправти в EEPROM команду читання регістра статусу temp = SPI_Send_Byte(0); // Прочитати регістр статусу PORT_EEPROM.SI = 0; // Перевести лінію SI в неактивний стан PORT_EEPROM.CS = 1; // Відключити мікросхему EEPROM-пам'яті return temp; // Повернути вміст регістру статусу }; /////////////////////////////////////////////////////////////////////////////////////// // Функція обслуговування зовнішнього переривання INT0 з виводу PD2 // Переривання викликається при натисканні кнопки виходу всередині приміщення interrupt [2] void ext_interrupt0(void) { byte ii; delay_ms(10); // Затримка 10 мс для захисту від тремтіння контактів кнопки виходу if(PIN_Out_Key.Out_Key == 0) // Якщо кнопка дійсно натиснута { DS1307_Read(&DS1307_1); // Прочитати поточні час і дату for(ii = 0; ii < 8; ii++) // Обнулити код ID ROM_Code[ii] = 0; // Сформувати реєстраційний запис і занести його в EEPROM-пам'ять 25LC256 Save_Record(&DS1307_1, &ROM_Code[0], Output_Record); PORT_Led.Led = 0; // Включити світлодіод - доступ дозволено PORT_Switch.Switch = 1; // Включити електронний замок - двері відкриті delay_ms(T_msec); // Затримка на час відкриття дверей PORT_Led.Led = 1; // Виключити світлодіод PORT_Switch.Switch = 0; // Виключити електронний замок - двері закриті } }; /////////////////////////////////////////////////////////////////////////////////////// // Функція формування і занесення в EEPROM-пам'ять реєстраційного запису // Вхідні параметри: // arg1 - структура, яка містить поточні час і дату; // code - масив, який містить 8-байтний ID код ключа iButton; // type - тип події: 0 - вхід, 1 - вихід. void Save_Record(DS1307_Data* arg1, byte* code, byte type) { byte temp, temp1; int start; // Очікувати готовності EEPROM до запису while((temp = SPI_Read_SR()) & 0x01) {}; // Прочитати значення лічильника подій в змінну temp1 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 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 {}; // Записати 7 байт часу і дати SPI_Write_Data(start + 8, arg1, 3); while((temp = SPI_Read_SR()) & 0x01) // Очікувати готовності EEPROM {}; SPI_Send_CMD1(EEPROM_WREN); // Дозволити запис в EEPROM while((temp = SPI_Read_SR()) & 0x01) // Очікувати готовності EEPROM {}; SPI_Write_Data(start + 12, &(arg1->Date), 2); while((temp = SPI_Read_SR()) & 0x01) // Очікувати готовності EEPROM {}; SPI_Send_CMD1(EEPROM_WREN); // Дозволити запис в EEPROM while((temp = SPI_Read_SR()) & 0x01) // Очікувати готовності EEPROM {}; 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 {}; // Записати нове значення лічильника реєстраційних записів SPI_Write_Data(Record_Count_Addr, &temp1, 1); }; ///////////////////////////////////////////////////////////////////////////////////// Схема симуляції в Proteus:  Часові діаграми передачі інформації по інтерфейсах 1-Wire, I2C, SPI:       Висновок: Під час виконання даної лабораторної роботи ми ознайомились з принципами побудови модулів управління систем контролю доступу. Вивчили правила обміну інформацією через інтерфейси 1-Wire, I2C, SPI та набули навиків з їх програмної реалізації для AVR-мікроконтролерів на мові С в середовищі CodeVisionAVR. Система контролю доступу (СКД) – це сукупність програмно-технічних засобів і організаційно-методичних заходів, за допомогою яких вирішується завдання контролю і управління відвідуванням окремих приміщень, а також завдання оперативного контролю за персоналом і часом його знаходження на території об’єкту. Для проектування цифрових систем, в яких передбачається передача чи обмін інформацією між цифровими пристроями часто використовуються такі інтерфейси як 1-Wire, I2C та SPI, які хоч і доволі прості, проте для вирішення поставлених цілей є достатньо ефективними.
Антиботан аватар за замовчуванням

12.02.2013 22:02-

Коментарі

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

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

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

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

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

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

Admin

26.02.2023 12:38

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