МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ “ЛЬВІВСЬКА ПОЛІТЕХНІКА”
Кафедра САПР
Лабораторна робота № 6
“Передача даних з використанням послідовного
комунікаційного порта”
Виконав:
ст. гр. КН-24
Перевірив:
КолесникК.К,
Львів 2007
1. МЕТА РОБОТИ
Мета роботи – створення програмного забезпечення для передачі даних з використанням послідовного порту RS-232.
2. КОРОТКІ ТЕОРЕТИЧНІ ВІДОМОСТІ
При асинхронному зв'язку машина посилає або приймає байти інформації порціями по одному біту. Тимчасові інтервали між байтами при цьому несуттєві, але дуже важливі є інтервали між окремими бітами байта. Сигнал на лінії може бути високого або низького рівня, що відповідає логічним нулю і одиниці, і кажуть, що лінія відмічена (marking), коли рівень високий, і пуста (spacing), коли рівень низький. Лінія підтримується у відміченому стані, коли по ній не передають даних. На початку передачі байта даних сигнал падає у 0, відмічаючи стартовий біт. Потім слідують вісім бітів даних (іноді менше) у вигляді набору високих і низьких рівнів. Останній біт даних може супроводжуватися бітом парності, що використовується для виявлення помилок, а потім у послідовність включаються 1 або більше стоп-біти, яким відповідає високий рівень. Ці стоп-біти починають відмічений стан, який буде зберігатися до тих пір, поки не почнеться передача наступного байта даних; число стоп-бітів суттєве, оскільки вони встановлюють мінімальний час, який повинен пройти перед наступним стартовим бітом. На рис. 1 представлена ця послідовність. Звичайно, передаюча і приймальна станції повинні застосовувати один і той же протокол для ланцюжків бітів і працювати з однією і тією ж швидкістю обміну (що вимірюється у бітах за секунду, які також називаються бодами). Під час обміну можуть легко виникати помилки, тому комунікаційне обладнання надає різносторонню інформацію про статус як самого порту, так і про приєднаного до нього модему. Задачею модему є перетворення сигналу, що генерується портом комунікації, в акустичний сигнал, який може потім бути переданий по телефонному каналу. Більшість модемів надає також додаткові комунікаційні можливості, такі, як автоматичний виклик і відповідь, які не підтримуються самим портом комунікації.
Рис.1. Передача одного байта послідовних даних.
2.1. Програмування мікросхеми UART 8250
Послідовний зв'язок настільки складний, що були розроблені спеціальні мікросхеми. Вони виконують роботу з формування і синхронізації рядків бітів, що складають послідовні дані. Такі мікросхеми називають універсальним асинхронним приймачем-передавачем (universal asynchronous receiver transmitter або UART). IBM PC використовує UART 8250 фірми Intel. Так як операційна система підтримує 2 порти комунікації, то в машині є 2 мікросхеми. Їх базові адреси зберігаються в комірках 0040:0000 для СОМ1 і 0040:0002 для COM2. (Базова адреса - це двобайтова адреса порту, яка є молодша із групи адрес портів, що дають доступ до UART.) На всіх машинах, крім PCjr, COM1 має базову адресу 3F8H, а COM2 - 2F8H; PCjr має свій внутрішній модем за адресою 3F8H, а COM1 - за адресою 2F8H. Для зручності ми надалі будемо завжди нумерувати регістри 3FxH, але все сказане в рівній мірі можна застосовувати і до регістрів 2FxH. Мікросхема 8250 має 10 програмованих однобайтових регістрів, за допомогою яких керується і контролюється порт комунікації. Більшість з них займається ініціалізацією порту, процесом, в якому виникає багато ускладнень. Доступ до цих 10 регістрів здійснюється через сім адрес портів з номерами 3F8H - 3FEH (або 2F8H - 2FEH). У п'яти випадках регістр, до якого отримуємо доступ через даний порт, залежить від того, як встановлений біт 7 в регістрі контролю лінії, який є єдиним регістром з адресою порту 3FBH. Ось ці регістри:
3F8H (OUT, біт 7 = 0 в 3FBH)
Регістр зберігання передавача
3F8H (IN, біт 7 = 0 в 3FBH)
Регістр даних приймача
3F8H (OUT, біт 7 = 1 в 3FBH)
Дільник швидкості обміну (молодший)
3F9H (IN, біт 7 = 1 в 3FBH)
Дільник швидкості обміну (старший)
3F9H (OUT, біт 7 = 0 в 3FBH)
Регістр дозволу переривання
3FAH (IN)
Регістр ідентифікації переривання
3FBH (OUT)
Регістр управління лінії
3FCH (OUT)
Регістр управління модемом
3FDH (IN)
Регістр статусу лінії
3FEH (IN)
Регістр статусу модему
Із десяти регістрів тільки шість необхідні для простого послідовного зв'язку. Регістр зберігання передавача містить байт даних, які будуть надіслані [6.], а регістр даних приймача - останній отрийнятий байт даних [7.]. Регістри управління і статусу лінії ініціалізують і управляють лінією зв'язку, використовуючи швидкість обміну, що міститься у двох регістрах дільника швидкості обміну [2.]. З чотирьох регістрів, що залишилися, регістри управління і статусу модему необхідні тільки для зв'язку через модем [5.], а два регістри, пов'язаних з перериваннями - тільки в процедурах, керованих перериваннями [8. ].
Переривання при зв'язку використовують в цілях ефективності. Звичайна комунікаційна процедура безперервно перевіряє регістр статусу лінії, чекаючи символа, що вводиться або вказівки, що все готове для передачі наступного байта даних. Оскільки процесор працює дуже швидко, в порівнянні із звичайними швидкостями, з якими передаються послідовні дані, то цей метод марно витрачає процесорний час, який може використовуватися для обробки даних, що поступають або передаються. З цієї причини мікросхема 8250 може бути встановлена в режим, що спричиняє переривання при появі символа, виникненні помилки і т.п. Це переривання вмить викличе процедуру вашої програми, яка, скажемо, буде передавати наступний символ з комунікаційного буфера.
2.2. Ініціалізація послідовного порту
При ініціалізації ( "відкритті") порту комунікації встановлюються всі його параметри. Ці параметри включають в себе довжину слова, число стоп-бітів, установку парності і швидкість обміну. Довжина слова - це число бітів, яке утворює основну одиницю даних. Хоч зазвичай працюють з порціями по 8 біт, але для стандартних файлів ASCII (в яких всі символи мають коди, що не перевищують ASCII 128) досить 7 біт, а для передачі числових даних - всього 4 біт.
Середній рівень
Функція 0 переривання 14Н BIOS ініціалізує порт комунікації. У DX повинен знаходитися номер комунікаційного каналу (COM1 = 0, COM2 = 1). У AL повинен міститися байт, що ініціалізує дані, значення бітів якого може бути наступним:
біти 1-0 довжина слова. 10 = 7 біт, 11 = 8 біт
2 число стоп-бітів. 0 = 1, 1 =2
4-3 парність. 00 або 10 = немає, 01 = непарн., 11 = парн.
7-5 швидкість обміну.
000 = 110 бод
001 = 150 бод
010 = 300 бод
011 = 600 бод
100 = 1200 бод
101 = 2400 бод
110 = 4800 бод
111 = 9600 бод
У даному прикладі порт ініціалізується зі словом, рівним 8 бітам, одним стоп-бітом і парною парністю. Швидкість обміну -1200 бод.
; присвоюємо значення параметрів змінним
MOV WORDLENGTH,00000011В ;довжина слова 8 біт
MOV STOPBITS, 00000000B ;1 стоп-біт
MOV PARITY, 00011000В ;парна парність
MOV BAUDRATE,10000000В ;швидкість 1200 бод
;ініціалізувати СОМ1
MOV AL,0 ;чистимо AL
OR AL,WORDLENGTH ;встановлюємо потрібні біти
OR AL,STOPBITS
OR AL,PARITY
OR AL,BAUDRATE
MOV AH, 0 ;функція ініціалізації порту
MOV DX, 0 ;вибераємо СОМ1
INT 14H ;ініціалізувати порт
Низький рівень
Незалежно від того, займаємося ми вводом або виводом, як мінімум, 4 регістри мікросхеми 8250 повинні бути ініціалізованими для операцій обміну. Це регістри дільника швидкості обміну, регістр контролю лінії і регістр дозволу переривання.
Ініціалізація швидкості обміну. Дільник швидкості обміну – це число, на яке треба розділити частоту системних годин (1190000 Гц), щоб отримати бажану швидкість обміну. Наприклад, для швидкості обміну 1200 бод дільник швидкості обміну повинен бути рівний 96, оскільки 1190000/96 приблизно дорівнює 1200. Чим більший дільник, тим менша швидкість обміну. Швидкість обміну 300 бод і менше вимагає двобайтового числа для дільника. Старший байт посилається в 3F9H (або 2F9H), а молодший - в 3F8H (2F8H). У обох випадках біт 7 регістра управління лінії повинен бути встановлений в 1 перед засиланням значення, в іншому випадку за цими двома адресами значення будуть адресовані в інші регістри . Ось деякі значення, необхідні для звичайних швидкостей обміну:
Швидкість обміну
3F9H
3F8H
110
04H
17H
300
01H
80H
600
00H
C0H
1200
00H
60H
1800
00H
40H
2400
00H
30H
3600
00H
20H
4800
00H
18H
9600
00H
0CH
Завжди встановлюйте регістри швидкості обміну першими, оскільки вони єдині, які вимагають установки біта 7 в регістрі контролю лінії. Після цього треба змінити вміст регістра контролю лінії, скидаючи біт 7, щоб всі інші доступи до регістрів були правильними. Оскільки регістр контролю лінії є регістром тільки для запису, то немає способу повернути біт 7 назад в 1 без одночасної установки всіх інших бітів цього регістра. Зазначимо, що PCjr використовує інших дільників, опис яких ви можете знайти в технічному керівництві.
Ініціалізація регістра контролю лінії. Значення бітів регістра контролю лінії, адреса порту якого рівна 3FBH (або 2FBH), можуть бути наступними:
біти 1-0 довжина символа. 00 = 5 біт, 01=6 біт, 10=7 біт, 11=8 біт
2 число стоп-бітів. 0 = 1, 1 = 1,5, якщо довжина символів рівна п'яти, інакше - 2
3 парність. 1 = генерується біт парності, 0 = немає
4 тип парності. 0 = непарна, 1 = парна
5 фіксація парності. Примушує біт парності завжди бути 0 або 1.
0 = відмінена
1 = завжди 1, якщо біт 3 = 1 & біт 4=0
або 1 = завжди 0, якщо біт 3 = 1 & біт 4 = 1 або
1 = немає парності, якщо біт 3 = 0
6 установка перерви. Викликає виведення строки нулів як сигнал віддаленої станції. 0 = заборонено, 1 = перерва
7 міняє адреси портів інших регістрів
Зазвичай биті 5-7 скинені в 0. Інші описують значення, що визначаються протоколом обміну.
Регістр дозволу переривання. Навіть якщо ви не використовуєте переривання, все одно треба зробити запис в регістр дозволу переривання, щоб бути упевненим, що переривання заборонені. Просто вмістіть в цей регістр 0. Регистр ідентифікації переривання можна ігнорувати.
Ініціалізація інших регістрів пов'язана з модемами. Ясно, що модеми потрібні тільки для зв'язку з віддаленими пристроями, а не для управління сусідніми, такими, як послідовний принтер. У [5] пояснено, як ініціалізувати регістр контролю модему.
У наступному прикладі з області даних BIOS береться базова адреса СОМ1, після чого різні регістри ініціалізуються для швидкості обміну 1200 бод, семибітових даних, парної парності і одного стоп-біта.
;отримуємо базову адресу СОМ1
MOV AX, 40H ;ES вказує на область даних BIOS
MOV ES, AX
MOV DX, ES:[0] ;отримуємо базову адресу СОМ 1
; ініціалізувати регістри дільника швидкості обміну на 1200 бод
ADD DX, 3 ;вказуємо на регістр контролю лінії
MOV AL, 10000000В ;встановлюємо біт 7
OUT DX, AL ;посилаємо байт
DEC DX ;вказуємо на старший байт дільника
DEC DX ;швидкості обміну
MOV AL, 0 ;старший байт для 1200 бод
OUT DX, AL ;посилаємо старший байт для 1200 бод
DEC DX ;вказуємо на молодший байт дільника
MOV AL, 60H ;молодший байт дільника для 1200 бод
OUT DX, AL ;посилаємо молодший байт
;ініціалізувати регістр контролю лінії
MOV AL, 0 ;обнулюємо AL
OR AL, 10B ;довжина даних 7 біт
OR AL, 000B ;1 стоп-біт
OR AL,1000B ;генерується біт парності
OR AL,10000B ;парна парність
ADD DX, 3 ;вказуємо на регістр контролю лінії
OUT DX, AL ;посилаємо значення ініціалізації
;ініціалізувати регістр дозволу переривання
DEC DX ;вказуємо на регістр дозволу
DEC DX ;переривання
MOV AL, 0 ;забороняємо переривання
OUT DX, AL ;посилаємо байт
2.3. Установка поточного комунікаційного порту
Є два способи, за допомогою яких програма може визначити, який з комунікаційних портів повинен використовуватися. Один з них – вказівка номера каналу в операторі програми. Другий спосіб – написання програми для обміну через порт СОМ1, але зміна комунікаційного адаптера, доступ до якого йде через СОМ 1. Область даних BIOS містить місце для чотирьох двобайтовий змінних, в яких знаходяться базові адреси комунікаційних каналів (MS-DOS підтримує тільки перші два з них). Базова адреса порту - це молодша з групи адрес портів, через які можна отримати доступ до даного комунікаційного каналу. Базова адреса для СОМ1 зберігається в комірці 0040:0000, а для COM2 - в комірці 0040:0002. Для зміни комунікаційних портів треба просто поміняти ці два значення. Повторна зміна значень приведе до початкового призначення портів.
Середній рівень
Якщо програма звертається до комунікаційного порту через переривання 14Н BIOS, то СОМ-порт визначається в DX, що дорівнює 0 або 1 (для СОМ1 або COM2). Замість того щоб присвоювати DX безпосереднє значення, заповнюйте його зі змінної, якій може бути присвоєне значення 0 або 1. Программи, які використовують комунікаційні функції 3 і 4 переривання 21Н, завжди адресуються до СОМ1. У цьому випадку треба поміняти базові адреси:
; обмін базових адрес для СОМ1 і COM2
MOV AX, 40H ;ES вказує на область даних BIOS
MOV ES, AX
MOV DX, ES:[0] ;поміщуємо 1-у базову адресу в DX
MOV AX, ES:[2] ;поміщуємо 2-у базову адресу в AX
MOV ES: [0], АХ ;обмінюємо адреси
MOV ES:[2], DX
2.4. Визначення статусу комунікаційного порту
Регістр статусу лінії мікросхеми UART 8250 визначає протокол зв'язку. Цей регістр має адресу порту на 5 більшу, ніж базова адреса даного каналу. Звичайно він постійно переглядається в процесі комунікаційного обміну. При передачі даних регістр повідомляє, що попередній символ вже посланий, дозволяючи програмі записати новий символ. При прийомі даних регістр інформує програму про надходження наступного символу, з тим щоб програма могла прочитати його перед тим, як він буде знищений наступним прибулим. Значення бітів цього регістра наступні:
біт 0 1 = байт даних отриманий
1 1 = отримані дані були перезаписані (попередній символ не був вчасно прочитаний)
2 1 = помилка парності (ймовірно, через шум в лінії)
3 1 = помилка оточення (передача не синхронізована)
4 1 = виявлена перерва (отриманий довгий рядок одиниць, який відображає, що інша станція запитує кінець передачі)
5 1 = регістр збереження передавача пустий (в цей регістр повинні вміщуватися дані, що передаються )
6 1 = регістр зсуву передавача пустий (цей регістр отримує дані з регістра зберігання і перетворює їх в послідовний вид)
7 1 = тайм-аут (пристрій не зв'язаний з машиною)
Середній рівень
Функція 3 переривання 14Н BIOS повертає в АН регістр статусу лінії (AL отримує регістр статусу модему [5]). При вході DX повинен містити номер комунікаційного порту, до якого здійснюється доступ, де СОМ1 = 0, а COM2 = 1. Перевіряється наявність перерви:
MOV AH, 3 ;номер функції
MOV DX, 1 ;вибираємо COM2
INT 14H ;отримуємо байт статусу
TEST AH, 10000В ;виявлена перерва?
JNZ BREAK_DETECT ;якщо так, то переходимо до процедури обробки
Низький рівень
З області даних BIOS прочитується базова адреса комунікаційного каналу, до нього додається 5, а потім з отриманої адреси порту прочитується байт статусу.
MOV AX, 40H ;ES вказує на область даних BIOS
MOV ES, AX
MOV DX, ES:[2] ;отримуємо базову адресу COM2
ADD DX, 5 ;додаємо 5 для регістра статусу
IN AL, DX ;отримуємо байт статусу
TEST AL, 10000B ;біт 5 встановлений?
JNZ BREAK_DETECT ;якщо так, то переходимо до обробки перерви
2.5. Ініціалізація і управління модемом
Є 6 ліній, по яких модеми зв'язуються з комп'ютером (вдосконалені моделі можуть мати додаткові лінії по інтерфейсу RS-232). Ось їх назви, скорочення і функцій:
Від комп'ютера до модему
Data Terminal Ready (DTR) Інформує модем, що комп'ютер включений і готовий до зв'язку
(готовність комп'ютера)
Request To Send (RTS) Інформує модем, що комп'ютер чекає посилання даних
(запит на посилку)
Від модему до комп'ютера
Data Set Ready (DSR) Інформує комп'ютер, що модем включений і готовий
(готовність модему)
Clear To Send (CTS) Інформує комп'ютер, що модем готовий почати передачу даних
(готовність до посилки)
Data Carrier Detect (DCD) Інформує комп'ютер, що модем пов'язаний з іншим модемом
(виявлений носій даних)
Ring Indicator (RI) Інформує комп'ютер, що телефонна лінія, до якої приєднаний модем, має (індикатор дзвінка) дзвінок
Спочатку комп'ютер встановлює сигнал DTR, а потім інструктує модем зв'язатися з віддаленою станцією. Після того як модем встановив зв'язок, він встановлює сигнал DSR. Цей сигнал інформує комп'ютер, що модем готовий до зв'язку і в цей момент комп'ютер може встановити сигнал RTS. І якщо модем відповість сигналом CTS, почнеться передача.
Дві стандартні лінії, по яких комп'ютер управляє модемом, доступні через регістр контролю модему мікросхеми UART 8250. Цей регістр має адресу порту на 4 більшу, ніж базова адреса комунікаційного каналу, що використовується. Значення його бітів такі:
Регістр контролю модему
біти 7-5 (завжди 0)
4 1 = вихід UART замкнутий на вхід
3 додатковий користувач призначений на вихід #2
2 додатковий користувач призначений на вихід #1
1 1 = "запит на посилку" активний
0 1 = "готовність комп'ютера" активна
Зазвичай биті 0 і 1 регістра контролю модему встановлені, а інші - рівні 0. Біт 2 рівний 0, за винятком випадків, коли виробник модему призначив його для спеціальних потреб. Біт 3 встановлений тільки у випадку, коли використовуються переривання [8]. Нарешті, біт 4 надає можливість тестування комунікаційних програм без встановлення реального зв'язку. Вихідний сигнал мікросхеми UART подається на вхід, ніби UART приймає послідовні дані. Цю властивість можна застосовувати для тестування правильності роботи самої мікросхеми. Однак при використанні комунікаційних процедур переривання 14Н BIOS вона недоступне.
Чотири лінії, по яких модем посилає інформацію комп'ютеру, керуються регістром статусу модему. Цей регістр розташований за адресою порту на 6 більшою, ніж базова адреса комунікаційного адаптера, що використовується. Ось значення його бітів:
Регістр статусу модему
біт 7 1 = DCD
6 1 = RI
5 1 = DSR
4 1 = CTS
3 1 = зміна в DCD
2 1 = зміна в RI
1 1 = зміна в DSR
0 1 = зміна в CTS
Програма безперервно перевіряє ці біти в ході комунікаційних операцій. Зазначимо, що 4 молодших біта паралельні старшим чотирьом бітам. Ці біти встановлюються в 1 тільки тоді, коли відбувається зміна в статусі відповідного старшого біта з моменту, коли регістр читався останній раз. Всі 4 молодших біта автоматично скидаються при читанні регістра. Програми будь-якого рівня можуть безпосередньо читати цей регістр. Іншою можливістю є використання функції 3 переривання 14Н BIOS, яка повертає регістр статусу модему в AL (при цьому в AH буде міститися регістр статусу лінії). При вході DX повинен містити номер комунікаційного каналу (0 або 1).
Багато які модеми мають значно більше можливостей в порівнянні з тими, що відображені в двох пов'язаних з модемом регістрах. Є можливості автоматичного зв'язку і автоматичної відповіді, які контролюються керуючим рядком. Цей рядок посилається в модем у вигляді звичайних даних. Модем виділяє керуючий рядок з даних по спеціальному символу, що використовується тільки для вказівки початку керуючого рядка. Цей символ може бути попередньо визначений (часто використовується код Esc - ASCII 27) або вибираним користувачем. Модем здатний визначити, наскільки довгим повиннен бути кожний рядок, тому по закінченні рядка він знову розглядає вхідний потік інформації як дані. Кожний модем має свій набір команд. Як приклад розглянемо команди, що використовуються внутрішнім модемом PCjr:
Символ
Значення
Застосування
А
відповідь
вхід в режим відповіді
Bn
перерва
посилає сигнал перерви n × 100 мс
Cn
відлік n
відлічує n дзвінків до відповіді
Dn...n
виклик
посилає рядок чисел n...n
Fn
формат
встановлює протокол зв'язку
Н
розрив
припиняє зв'язок з машиною
I
ініціалізація
ініціалізувати модем
LR
довга відповідь
міняє кодову систему, що використовується
М
режим
модем приймає символи як дані
Nn
новий
міняє командний символ на n
O
originate
вхід в режим originate
Р
pick-up
вхід в режим голосу
Q
запит
запит статусу модему
R
повтор
повторити команду зв'язку
Sn
швидкість
вибір швидкості обміну
Tn...n
прозорість
ігнорувати керуючі рядки в наступних n...n байтах
V
голос
перевести модем в режим голосу
W
очікування
нічого не робити до наступної команди
X
передати
передача тону виклику
Z
тест
проводить діагностику обладнання
У відповідь на команду запиту модем видає інформацію про свій стан, посилаючи її в UART як звичайні дані. Крім іншої інформації може повідомлятися, що лінія зайнята. Щоб правильно використати команди управління модемом і інформацію про його статус, треба ретельно вивчити документацію на даний модем. Модем PCjr описаний в технічному керівництві по PCjr. Приведений нижче приклад дають тільки загальну схему встановлення зв'язку через модем.
Низький рівень
Схема зв'язку через модем на мові асемблер виглядає так:
;встановлюємо сигнал DTR
MOV DX, BASADR ;починаємо з базової адреси
ADD DX, 4 ;вказуємо на регістр контролю модему
MOV AL, 1 ;встановлюємо біт 1
OUT DX,AL ;посилаємо в порт
;посилаємо керуючий рядок модему для виклику
.
(цей код різний для різних типів модемів)
.
;чекаємо поки буде встановлений сигнал DSR
INC DX ;вказуємо на регістр статусу модему
INC DX
TRYAG: IN AL, DX ;отримуємо вміст
TEST AL, 10B ;перевіряємо другий біт
JZ TRYAG ;чекаємо поки він не буде рівний 1
;встановлюємо біт RTS
DEC DX ;повертаємося до регістра управління
DEC DX
MOV AL,3 ;встановлюємо сигнал RTS
OUT DX,AL ;посилаємо в порт
;чекаємо сигналу CTS
INC DX ;повертаємося до регістра статусу
INC DX
ON_MO: IN AL,DX ;отримуємо байт статусу
TEST AL,1 ;перевіряємо біт CTS
JZ ON_МО ;не продовжуємо, поки він не встановлений
;тепер можна посилати дані
2.6. Передача даних
Передача даних простіша, ніж їх прийом, оскільки програма повністю контролює склад даних і швидкість, з якою вони повинні посилатися. Проте процедури передачі можуть бути досить складними, якщо вони обробляють дані по мірі того, як вони посилаються. Можуть бути також проблеми з синхронізацією при використанні протоколу XON/XOFF. Цей протокол використовує коди ASCII 17(XON) і 19(XOFF), для того щоб сигналізувати приймаючій станції, що передавач хоче продовжити передачу тимчасово перерваного потоку даних. Щоб прийняти ці сигнали, програма повинна безперервно аналізувати символи, що приймаються при передачі (у повнодуплексном режимі, в якому зазвичай працюють модеми, сигнали одночасно йдуть в обидві сторони по телефонному каналу). Крім того, щоб виявити, що віддалена станція посилає рядок нулів як сигнал перерви, повинен безперервно аналізуватися статус біта перерви (номер 4) регістра статусу лінії [4].
Внаслідок цих причин представлені тут процедури, окремо передаючі дані, є штучними. Але їх можна скомбінувати з процедурами прийому даних, описаними в [7], для створення загального уявлення. Ясно, що для створення діючої процедури необхідно затратити великі зусилля, особливо в частині виявлення і виправлення помилок при передачі даних.
Середній рівень
Функція 1 переривання 14Н BIOS посилає символ, що знаходиться в AL, в комунікаційний канал. При вході DX містить номер порту (0 або 1). При поверненні AH отримує байт статусу, в якому біт 7 = 1, якщо операція неуспішна. У цьому випадку мають значення наступні біти:
біт 4 виявлений перерва (сигнал "стоп" від приймаючої станції)
5 регістр зсуву передавача пустий
6 регістр зберігання передавача пустий
MS-DOS має функцію для передачі по комунікаційному каналу символа, що вміщується в DL. Це функція номер 4 переривання 21Н, але у неї немає ніяких переваг перед функцією BIOS; вона не повертає статусної інформації і не дозволяє призначати, який з комунікаційних портів треба використати (це завжди СОМ1).
Щоб вивести рядок даних, скористайтеся функцією 40Н переривання 21Н. Це звичайна функція виводу для всіх файлів і пристроїв методом доступу дескриптора файлів. СОМ1 має визначений номер - #3. Вмістіть номер файла в BX, а число байтів, що передаються в CX. Нехай DS:DX вказують на буфер даних, що виводяться, потім викликайте функцію.
MOV AH,40H ;номер функції
MOV BX,3 ;наперед визначений номер файла для СОМ 1
MOV CX,50 ;виводимо 50 байт
LEA DX,BUFER ;DS:DX вказують на буфер даних
INT 21Н ;посилаємо дані
JC COM_ERROR ;відхід на обробку помилки
Зазначимо, що при використанні визначених номерів файлів їх не треба відкривати. Якщо сталася помилка, встановлюється прапор переносу, а в АХ повертається 5, якщо комунікаційний порт не готовий, і 6 при вказівці неправильного номера файла.
Низький рівень
Коли байт даних вміщується в регістр зберігання передавача, то він автоматично виводиться в послідовний канал через регістр зсуву передавача, якого серіалізує дані. Немає необхідності в імпульсі біта стробу, як це робиться у разі паралельного адаптера. Біт 5 регістру статусу лінії показує, чи вільний регістр зберігання передавача для прийому даних. Регістр постійно перевіряється доти, поки біт 5 не стане рівним 1. Після цього в регістр зберігання передавача посилається черговий байт. У процесі передачі біт 5 рівний 0, і тільки коли він знову стане рівним 1, в регістр зберігання передавача може бути посланий наступний символ. Цей процес повторюється доти, поки в цьому є необхідність.
У наступному прикладі дані основні поняття про цю процедуру. Звичайно, вона може бути створена надзвичайно складної (зокрема, програмування зв'язку вимагає особливо ретельних процедур виявлення помилок і відновлення при збоях). У прикладі передбачається, що комунікаційний порт і модем вже ініціалізовані, як показано в [2] і [5]. Перша частина це цикл перевірки помилок і прийому символів. У [7] приведений код для процедури прийому даних.
; чекаємо, поки все буде готове для посилки символа
KETRY: MOV DX, BASADR ;базова адреса
ADD DX,5 ;вказуємо на регістр статусу лінії
IN AL,DX ;отримуємо байт статусу
TEST AL,00011110B ; перевіряємо на помилку
JNZ ERRROUT ;якщо є, то на процедуру обробки помилки
TEST AL,00000001B ;перевіряємо, чи отримані дані
JNZ RECEIVE ;якщо так, то на процедуру прийому
TEST AL,00100000B ;перевіряємо готовність до передачі
JZ KETRY ;якщо немає, то повертаємося назад
;передаємо символ, що приймається з клавіатури
MOV AH, 1 ;функція перевірки натиснення клавіші
INT 16H ;переривання клавіатури BIOS
JZ KETRY ;повернення, якщо не було натиснення
MOV AH,0 ;функція отримання коду з клавіатури
INT 16H ;тепер потрібний символ в AL
SUB DX, 5 ;адреса регістра зберігання передавача
OUT DX, AL ;посилаємо символ
JMP SHORT KETRY ;повертаємося на початок циклу
2.7. Отримання даних
Як тільки ініціалізувати комунікаційний порт [2] і встановлений зв'язок з віддаленою станцією [5] - комунікаційна програма готова приймати дані. Прийом даних ніколи повністю не відділений від їх передачі, оскільки програмі може стати потрібним послати сигнал XOFF (ASCII 19), щоб зупинити потік даних, якщо вони поступають дуже швидко і вона не встигає їх обробляти. Код XON (ASCII 17) повідомляє віддаленій станції, що можна продовжити передачу. Зазначимо, що PCjr не може приймати дані під час дискових операцій; щоб зняти це обмеження, треба застосовувати XON і XOFF.
У залежності від складності протоколу обміну дані, що приймаються можуть вимагати простої або складної обробки. Може бути отриманий будь-який код з набору керуючих кодів. Ті з них, які є обмежувачами даних, частіше виявляються при синхронному обміні. При виведенні отримуваних символів на екран враховуйте вплив символів переведення рядка (ASCII 10), оскільки деякі мови автоматично вставляють їх після кожного символа повернення каретки; в цьому випадку виключайте символи переведення рядка з даних, що приймаються, щоб уникнути пустих рядків при виведенні. На мал. 7.2 показана комунікаційна процедура, що включає також код передачі, який обговорюється в [6].
Середній рівень
Функція 2 переривання 14Н BIOS чекає символ з послідовного порту, вміщує його в AL при отриманні і потім повертається в програму. При вході треба помістити номер порту (0-1) в DX. При поверненні АХ рівний нулю, якщо не було помилки. Якщо AH не рівний 0, то може бути повернений байт статусу, в якому мають значення тільки 5 біт. Це наступні біти:
біт 1 помилка переповнення (новий символ поступив раніше, ніж був видалений старий)
2 помилка парності (ймовірно, через проблеми в лінії)
3 помилка оформлення (стартовий або стоп-біти невірні)
4 виявлена перерва (отриманий довгий рядок бітів 0)
5 помилка тайму-ауту (не отриманий сигнал DSR)
MS-DOS також надає комунікаційну функцію для прийому одного символа - функцію 3 переривання 21Н. Вона чекає символ з СОМ1 і вміщує його в AL. Зазначимо, що при цьому немає функції ініціалізації порту, яку треба робити за допомогою процедури BIOS або безпосередньо, як показано в [2]. По замовчуванні порт ініціалізується зі значеннями 2400 бод, немає контролю парності, один стоп-біт і 8 біт на символ. Ця функція не має ніяких переваг в порівнянні з функцією BIOS і не повертає інформації про статус.
Низький рівень
При отриманні даних без використання комунікаційного переривання [8] програма повинна постійно перевіряти регістр статусу лінії, адресу порту якого на 5 більша базової адреси комунікаційного адаптера, що використовується. Біт 0 цього регістра буде рівний нулю, поки не буде отриманий символ в регістрі даних приймача. Коли біт 0 стає рівним 1, треба негайно зчитати його з регістра, з тим щоб на нього не наклався наступний символ, що приймається. Після того як символ прочитаний, біт 0 знову стає рівним 0 і залишається таким, поки не прибуде новий символ.
Хоч про це ще не згадувалося, але ви повинні знати, що комунікаційні процедури звичайно створюють циклічний буфер для збору поступаючих символів. Ви повинні також знати, що якщо поступаючі дані подавати на екран з швидкістю 1200 бод, то процедура зсуву екрана BIOS не буде устигати і станеться переповнення. Просте розв'язання цих проблем складається у використанні комунікаційного переривання.
У наступному прикладі частково повторюється вміст попереднього параграфа, що відноситься до передачі символів. Як і в тому випадку, код починається з нескінченного циклу. Об'єднайте ці дві процедури з процедурами ініціалізації з [2] і [5] для створення закінченої процедури введення/виведення через комунікаційний канал.
KETRY: MOV DX, BASADR ;базова адреса
ADD DX, 5 ;вказуємо на регістр статусу лінії
IN AL, DX ;отримуємо байт статусу
TEST AL, 00011110В ;перевіряємо на помилку
JNZ ERRROUT ;якщо так, то на обробку помилки
TEST AL,00000001B ;перевіряємо, чи отримані дані
JNZ RECVE ;на процедуру прийому даних
TEST AL,00100000B ;перевіряємо готовність до передачі
JZ KETRY ;якщо немає, то на початок циклу
.
(тут розташована процедура передачі )
.
; отримуємо дані і виводимо їх на екран
RECVE: MOV DX,BASE_ADDRESS ;базова адреса
IN AL,DX ;читаємо отриманий символ
CMP AL,19 ;перевірка на XOFF
JE XOFF_ROUTINE
; (і т.д.)
MOV DL,AL ;готуємо символ для виведення на екран
MOV AH,2 ;функція виведення
INT 21Н ;виводимо його
JMP SHORT KETRY ;повертаємося на початок циклу
2.8. Передача/отримання даних за допомогою комунікаційного переривання
Ретельно продумана комунікаційна програма має занадто багато обов'язків, щоб присвятити себе цілком введенню/виведенню. Поступаючі дані повинні аналізуватися, дані, що передаються повинні збиратися, а великі блоки даних можуть записуватися на диск або прочитуватися з нього. Комунікаційне переривання дозволяє програмі не тратити на введення/виведення більше часу, ніж він того вимагає. Наприклад, після установки переривання управління передається процедурі передачі даних тільки в тому випадку, якщо регістр зберігання передавача пустий, і повертається програмі, як тільки посланий байт даних, дозволяючи їй продовжувати свою роботу доти, поки регістр зберігання передавача не буде знов готовий. IBM PC відводить два апаратних переривання для комунікаційних каналів, номери 3 (СОМ1) і 4 (COM2). Зазначимо, що у PCjr вбудований модем має номер 3, а СОМ1 - номер 4. Мікросхема UART 8250 допускає 4 класи переривань для кожного каналу, використовуючи наступні двійкові кодові числа:
00 зміна в регістрі статусу модему
01 регістр зберігання передавача пустий
10 отримані дані
11 помилка прийому, або отримана умова перерви
Ці коди містяться в бітах 2-1 регістра ідентифікації переривання, адреса порту якого на 2 більша, ніж базова адреса комунікаційного адаптера, що використовується. Біт 0 цього регістра встановлюється при виникненні переривання, а інші біти не використовуються і завжди рівні 0.
Щоб вибрати одне або більше переривань, треба запрограмувати регістр дозволу переривання, адреса якого на 1 більша базової адреси. Значення його бітів можуть бути такими:
біт 0 1 = переривання при отриманні даних
1 1 = переривання, коли регістр зберігання передавача пустий
2 1 = переривання при помилці прийому даних
3 1= переривання при зміні регістра статусу модему
7-4 не використовуються, завжди 0
Коли одна з цих подій відбувається, ініціюється апаратне переривання, виникаюче в мікросхемі обробки переривань 8259 по каналу 3 для СОМ1 і по каналу 4 для COM2. Процедура обробки переривань передає управління тому коду, на який вказує відповідний вектор переривання. Оскільки це апаратне переривання, то воно може бути масковане. Пам'ятайте, що процедура обробки переривання повинна завершуватися стандартним кодом виходу з апаратного переривання MOV AL, 20H/OUT 20H, AL. На рис. 2 показане комунікаційне переривання.
Одночасно можливе будь-яке число типів переривання. Але якщо дозволений більш ніж один тип, процедура обробки переривання повинна сама визначати, який з типів переривання стався, перевіряючи регістр ідентифікації переривання. Одночасно можуть відбуватися більш ніж одне переривання, тому біт 0 регістра ідентифікації повідомляє про те, що поступило ще одне переривання. Коли два або більше перериваннь поступають в один і той же момент, то вони обробляються в порядку, вказаному в приведеній нижче таблиці. Додаткові переривання повинні бути оброблені до завершення процедури обробки переривання. Умови попередніх переривань "відміняються" за допомогою дій, що пропонуються в правому стовпці наступної таблиці:
Код
Тип
Дії для “сбросу”
11
помилка або перерва
читання регістру статусу лінії
10
отримані дані
читання регістру приймача даних
01
передавач готовий
виведення символа в регістр зберігання передавача
00
зміна статусу модему
читання регістра статусу модему
Рис. 2. Комунікаційне переривання
Низький рівень
Приведемо загальну форму програми, що обробляє комунікаційні переривання:
;установка вектора комунікаційного перериванні
PUSH DS ;зберігаємо DS
MOV DX,OFFSET IOIN ; DS:DX вказують на процедуру
MOV AX, SEG IOIN
MOV DS,AX
MOV AL,0BH ;номер вектора для СОМ1
MOV AH,25H ;функція зміни вектора
INT 21H ;міняємо вектор переривання
;ініціалізація регістра дозволу переривання (СОМ1)
MOV AX,40H ;DS вказує на дані BIOS
MOV DS,AX
MOV DX,DS:[0] ;отримуємо базову адресу СОМ1
INC DX ;вказуємо на регістр дозволи
MOV AL,3 ;переривань і дозволяємо переривання
OUT DX, AL ;прийому і передачі
POP DS ;відновлюємо регістр
;процедура обробки переривання - спочатку визначаємо його тип
IOIN PROC FAR
NEXIN: MOV DX, BASADR ;базова адреса
INC DX ;вказуємо на регістр ідентифікації
INC DX ;переривання
IN AL,DX ;читаємо його значення
TEST AL,10B ;це переривання передавача?
JNZ TRANSMIT ;якщо так, то на передачу
RECEIVE: ;інакше - на прийом
JMP SHORT ANOT ;перевіряємо, чи немає іншого переривання
TRANSMIT: ;починаємо процедуру передачі символу
; перед виходом перевіряємо, чи немає іншого переривання
ANOT: MOV DX, BASADR ;базова адреса
INC DX ;вказуємо на регістр ідентифікації
INC DX ;переривання
IN AL,DX ;читаємо його значення
TEST AL,1 ;перевіряємо біт 1
JNZ NEXT_INT ;якщо він встановлений, то на початок
MOV AL,20H ;иначе, код завершення апаратного
OUT 20H,AL ;перериванні
IRET
IO_INT ENDP
4. ЛАБОРАТОРНЕ ЗАВДАННЯ
Розробити дві програми, які реалізують алгоритм передачі та алгоритм прийому даних через послідовний комунікаційний порт, а саме:
1. Для програми передачі даних:
а) визначити базову адресу комунікаційного порту (3f8h);
б) виконати ініціалізацію комунікаційного порту;
в) підготувати масив даних для передачі;
г) передати підготовлений масив даних для передачі;
д) вивести повідомлення про помилки, що виникли при передачі.
2. Для програми прийому інформації:
а) визначити базову адресу комунікаційного порту (3f8h);
б) виконати ініціалізацію комунікаційного порту;
в) відновити значення масиву даних шляхом читання з порту;
г) вивести отриманий масив даних на екран;
д) вивести повідомлення про помилки.
Текст-програми
Програма передавач
DATA SEGMENT
com1 dw ?
DATA ENDS
CODE SEGMENT
assume cs:code, ds:data
mov ax,data
mov ds,ax
start: mov ax,40h
mov es,ax
mov dx,es:[00]
mov com1,dx
add dx,3
mov al, 80h
out dx, al ; Робоча швидкість - 4800 Кбод
dec dx
dec dx ; DХ=адресі старшого байта дільника швидкості
mov al, 0
out dx, al
dec dx ; DХ=адресі молодшого байта дільника швидкості
mov al,18h ; установка молодшого байта дільника
out dx,al
;------------------------------------------------------------
add dx, 3 ; DХ=адресі регістра керування
mov al, 00011011b ; DLAB=0, парність, 1 стоп-бита, 8 біт/слово
out dx, al
dec dx
dec dx ; DХ=адресі регістра дозволу переривань
mov al,00h ; Переривання заборонені
out dx,al
;------------------------------------------------------------------
mov dx,com1
add dx,5
vvid:
in al, dx ; читання байта стану
test al,40h
jz vvid
sub dx,5 ;адреса регістра зберігання передавача
mov ah,1 ;функція отримання коду з клавіатури
int 21h
cmp al,1bh
je exit
out dx,al
jmp start
exit:
mov ax,4c00h
int 21h
code ends
end start
Програма приймач
DATA SEGMENT
com1 dw ?
DATA ENDS
CODE SEGMENT
assume cs:code, ds:data
mov ax,data
mov ds,ax
start: mov ax,40h
mov es,ax
mov dx,es:[00]
mov com1,dx
add dx,3
mov al, 80h
out dx, al ; Робоча швидкість - 4800 Кбод
dec dx
dec dx ; DХ=адресі старшого байта дільника швидкості
mov al, 0
out dx, al
dec dx ; DХ=адресі молодшого байта дільника швидкості
mov al,18h ; установка молодшого байта дільника
out dx,al
;-----------------------------------------------------------------
add dx, 3 ; DХ=адресі регістра керування
mov al, 00011011b ; DLAB=0, парність, 1 стоп-бита, 8 біт/слово
out dx, al
dec dx
dec dx ; DХ=адресі регістра дозволу переривань
mov al,00h ; Переривання заборонені
out dx,al
;-----------------------------------------------------------------------------
mov dx,com1
add dx,5
dal: in al, dx ; читання байта стану
test al,01h ; Біт 1="1" (прийнятий байт)
jz dal
sub dx, 5 ; DХ=адресі регістра приймача
in al, dx ; читання прийнятого байта
mov ah,02h
mov dl,al
int 21h
jmp start
exit: mov ah, 04Ch
int 21h
code ends
END Start
Висновок: Я навчився створенню програмного забезпечення для передачі даних з використанням послідовного порту RS-232.