
2 Постановка задачі дослідження
2.1 Аналіз мови Borland C++
Одним із найбільш досконалих інструментів створення прикладних програм являється мова програмування Borland C++, включаючи її можливості. Не зважаючи на її гнучкість та великі потенціальні можливості застосування, вона являється однією з самих важких інструментів програмування.
Як і в інших мовах програмування, в мові С++ потрібно видавати назву програми, особливості виконання, структури та призначення окремих фрагментів програми, для того щоб сам розробник чи користувач вільно могли орієнтуватися в програмному коді. Дуже часто виникає нужда при написанні програми описувати особливості програмних блоків чи даних. Для цього в Borland С++ введені коментарії, які не обробляються компілятором і, відповідно, не беруться до виконання процесором. Позначаються коментарії відповідним обмеженням символів «/» і «*» з обох сторін – наприклад: /*Перша програма на С*/, або двома символами «/» для коментування тільки в одній лінійці – наприклад // текст коментарію. Після кожного оператора чи команди в кінці лінійки використовується символ «;».
Всяка програма повинна вміщати підключення основної бібліотеки – директиви процесора. Підключення потрібно здійснювати спочатку програми, через символ «#» і слово include (включити). Назва бібліотеки з розширенням h береться в <ім’я_файла> для довільної та в "ім’я_файла" для поточної директорій - наприклад: #include <windows.h>. Всякий код програми повинен включати головну програму main, яка повинна представляти собою заголовок, з відповідним описом вхідних і вихідних даних. Опис вихідного значення програми main описується перед службовим словом, а опис вхідних даних – в круглих дужках після службового слова main, наприклад: int main(). Вхідні параметри часто також відсутні, так як дана програма включає в себе скелет або план «всіх доріг», тобто фундаментальні розгалуження, напрямки звернень, підключення допоміжних функцій, файлів, можливостей вводу-виводу, чи можливостей реалізації. Тіло любої допоміжної, підпрограми чи функції, написаної іншими програмістами може включати свою програму main з параметрами, описаними вище. Всяке тіло програми, процедури, функції чи класу заключається в фігурні дужки: {тіло програми, функції чи класу}.
В С++ всяке тіло програми повинно повертати значення, а тому закінчується оператором return значення_повернення, де значення_повернення - ціле число (додатне чи від’ємне або 0), яке сповіщає закінчення процесу програми, функції чи класу. За значенням повернення функції main бувають типу int або рідше void.
В програмуванні термін потік (англ. stream) використовується в кількох значеннях, але у всіх випадках посилаються на послідовність елементів даних, що стають доступними через якийсь час. В Unix і споріднених системах, заснованих на мові програмування C++, потік — це джерело або призначення даних, зазвичай індивідуальних байтів або знаків.
Потоки — це абстракція, що використовується наприклад при читанні або записі файлів, або при зв'язку з вузлами мережі. Три стандартні потоки передвизначені і доступні для всіх програм. В мові C++ концепція потоків реалізована у бібліотеці iostream і низці похідних від неї. Файлова система може підтримувати багато іменнованих незалежних потоків для одного файлу. Є один головний потік, який передає нормальні дані з файлу. Додаткові потоки можуть використовуватися, щоб запам'ятати іконки, короткий звіт і індексацію інформації, зональну інформацію (для файлів, що завантажуються) тощо. Конвеєри можуть також розумітися, як потоки, також як і будь-яка необмежена (не упакована) інформація, що постачається периферійним пристроєм. У мові програмування Scheme і деяких інших, потік — ліниво оцінена або затримана послідовність елементів даних. Потік може використовуватися так само як список, але останні елементи обчислюються тільки тоді, коли потрібно. Тому потоки можуть представити нескінченні послідовності. Поточні обчислення - в паралельному виконанні, особливо в графічній обробці, термін потік застосовується і до апаратних засобів, і до програмного забезпечення. Ним позначають квазі-безперервний потік даних, які обробляються на потоковій мові програмування, щойно програмний стан задовольняє початковій умові потоку.
Написати програму, керуючу пристроєм через COM-порт, для MS DOS не так складно. З платформою Win32 справа йде складніше. Але тільки на перший погляд. Звичайно напряму працювати з регістрами портів не можна, Windows це не дозволяє, зате можна не звертати уваги на тонкості різних реалізацій (i8055, 16450, 16550A) і не возитися з обробкою переривань.
З послідовними і паралельними портами в Win32 працюють як з файлами. Для відкриття порту використовується функція CreateFile. Ця функція надається Win32 API. Її прототип виглядає так:
HANDLE CreateFile(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDistribution,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
Функція CreateFile створює або відкриває каталог, фізичний диск, тому, буфер консолі (CONIN $ або CONOUT $), пристрій на магнітній стрічці, комунікаційний ресурс, поштовий слот або іменований канал. Функція повертає дескриптор, який може бути використаний для доступу до об'єкта. Функція CreateFile може створити дескриптор консольного введення даних (CONIN $). Якщо процес має відкритий дескриптор для нього, як результат наслідування чи дублювання, він може також створити і дескриптор активного екранного буфера (CONOUT $). Викликаючий процес повинен бути приєднаний до успадкованої консолі або консолі призначеної функцією AllocConsole.
Приклад закриття і відкриття послідовного COM-порту:
#include <windows.h>
//. . .
HANDLE Port;
Port = CreateFile("\\\\.\\COM2", GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, 0, NULL);
if (Port == INVALID_HANDLE_VALUE) {
MessageBox(NULL, "Невозможно открыть последовательный порт", "Error", MB_OK);
ExitProcess(1);
}
//. . .
CloseHandle(Port);
//. . .
У даному прикладі відкривається порт СОМ2 для читання і запису, використовується синхронний режим обміну. Перевіряється успішність відкриття порту, при помилці виводиться повідомлення і програма завершується. Якщо порт відкритий успішно, то він закривається.
Прийом і передача даних для послідовного порту може виконаються в синхронному або асинхронному режимах. Асинхронний режим дозволяє реалізувати роботу щодо подій, в той час як синхронний позбавлений цієї можливості, але є більш простим у реалізації. Для роботи в синхронному режимі, порт повинен бути відкритий таким чином:
CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0, NULL);
Передостанній параметр dwFlagsAndAttributes повинен бути дорівнює 0. Після успішного відкриття порту, дані можуть бути лічені або записані за допомогою функцій ReadFile () і WriteFile ().
HANDLE port = CreateFile("COM1", GENERIC_READ |
GENERIC_WRITE, 0, NULL,OPEN_EXISTING, 0, NULL);
unsigned char dst[1024] = {0};
unsigned long size = sizeof(dst);
if(port!= INVALID_HANDLE_VALUE)
if(ReadFile(port,dst,size, &size,0))
printf("\nRead %d bytes",size);
Недоліком цього способу є те, що викликаючи функцію ReadFile (), ми не знаємо чи є дані для читання. Можна циклічно перевіряти їх наявність, але це призводить до додаткових витрат часу ЦП. Тому на практиці часто зручніше використовувати асинхронний режим. Для цього при виклику функції CreateFile () параметр dwFlagsAndAttributes має дорівнювати FILE_FLAG_OVERLAPPED.
CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);