Giriş
Çevre birimlerinin kontrolü ile ilgiligerçekleştirilecek projeler için PC’nin paralelportu (printer portu) hala çok ucuz ve güçlü birplatform özelliğindedir. Printer portu bize sekiz TTLçıkış, beş giriş ve dört iki yönlü uç sağlar.
Buyazı, printer portunun nasıl kullanılacağı veprogramlanacağı hakkında bilgi verir.
Printer Portunun Temelleri
Port Tanımları
Herbir printer portu üç adresten oluşur: veri, durum vekontrol portu. Bu adresler sıralı şekildedir. Yani,eğer veri portu adresi 0x0378’de ise ilgili durumportu 0x0389’da ve ilgili kontrol portu da0x037A’dadır.
Printer | Veri Portu | Durum Portu | Kontrol Portu |
LPT1 | 0x03BC | 0x03BD | 0x03BE |
LPT2 | 0x0378 | 0x0379 | 0x037A |
LPT3 | 0x0278 | 0x0279 | 0x027A |
Paralelport numarası farklı adreslerde olabilir. Bunun içinBIOS'a ait olan BPB (Bios Parameter Block) içerisindekesme vektörlerinin hemen üstündeki 0x0040:0x0008adresten ikişer byte okuyarak printer portlarınınadresleri elde edilebilir. Eğer adres 0 ise başka portyok demektir. Bu arada buranın formatını debugüzerinde gösterelim:
E:\>debug
-d 0:400
0000:0400 F8 03 F8 02 E8 03 E8 02-BC 03 78 03 78 02 00 00 ..........x.x...
0000:0410 23 C8 00 80 02 80 00 20-00 00 2E 00 2E 00 64 20 #...... ......d.
0000:0420 20 39 30 0B 3A 35 34 05-30 0B 30 0B 0D 1C 00 00 90.:54.0.0......
0000:0430 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0440 D1 00 C3 00 00 00 00 00-00 03 50 00 00 10 00 00 ..........P.....
0000:0450 00 0A 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0460 0F 0C 00 D4 03 29 30 03-00 00 C0 00 4D 80 16 00 .....)0.....M...
0000:0470 00 00 00 00 00 00 00 00-14 14 14 14 01 01 01 01 ................
-q
Burada ilk satırdaki bilgiye baktığımızda. BC 03 görüyoruz. Bunu çevirecek olursak, 0x03BC olduğunugörürüz. Bu paralel port adresidir. Yani bizimkullanacağımız adres 0x3BC portudur. Bu arada eğerLPT1 adresi değişirse yeni adreste burada yerinialacaktır. Eğer buradan okuyarak işimizi hallederseksorun çıkmaz.
Printer | Veri Portu |
Durum Portu |
Kontrol Portu |
LPT1 |
0x03BC |
0x03BD |
0x03BE |
LPT2 |
0x0378 |
0x0379 |
0x037A |
LPT3 |
0x0278 |
0x0279 |
0x027A |
LPT4 |
YOK |
||
Aşağıdaki C programı, printer portlarının adreslerini elde etmek için bu hafıza yerleşiminin nasıl okunacağını gösterir.
#include
<stdio.h>
#include <dos.h>
void
main(void)
{
unsigned int far *ptraddr; /* Pointer to
location of Port Addresses */
unsigned int address; /* Address of Port
*/
int a;
ptraddr=(unsigned int far *)0x00000408;
for (a = 0; a < 3; a++)
{
address = *ptraddr;
if (address == 0)
printf("No port found for LPT%d \n",a+1);
else
printf("Address assigned to LPT%d is %Xh\n",a+1,address);
*ptraddr++;
}
}
LPT atamalarını görmek için alternatif bir teknik ise Microsoft Diagnostics (MSD.EXE) programınıçalıştırmaktır.
Çıkışlar
Lütfen Şekil 1 – Bacak Tanımları ve Şekil 2 –Port Tanımları’nı inceleyiniz. Bu iki şekil 25bacaklı konektörün bacak tanımları ile üç portunbit tanımlarını gösterir.

Şekil 1. Bacak Tanımları

Şekil 2. Port Tanımları
Veri portunda sekiz çıkış (Data 7(msb) – Data 0) ve Kontrol portunda dört ek çıkış (/SELECT_IN, INIT, /AUTO FEED ve /STROBE) bulunduğuna dikkat ediniz.
Veri portundaki tüm çıkışlar “true” lojik esasına göre çalışır. Yani, bir bite lojik bir yazmak ilgili çıkışın “high” olmasına neden olur. Fakat Kontrol portundaki /SELECT_IN, /AUTOFEED ve /STROBE çıkışları ters lojik esasına göre çalışır.Yani, bir bite lojik bir göndermek ilgili çıkışın lojik sıfır olmasına neden olur. Bu, printer portunun kullanımına biraz karmaşıklık getirir. Bununla beraber, çıkıştan önce basitçe bu bitlerin XOR işlemiyle tersini almak bizi çözüme götürür.
Veri portunda gönderilecek val1 verisinin ve Kontrol portunda da val2 verisinin bulunduğunu varsayalım:
#define
DATA 0x03bc
#define STATUS DATA+1
#define CONTROL DATA+2
...
int val1, val2;
...
val1
= 0x81; /* 1000 0001 */ /* Data bits 7 and 0 at one */
outportb(DATA, val1);
val2 = 0x08; /* 0000 1000 */
outportb(CONTROL, VAL2^0x0b);
/* SELECT_IN = 1, INIT = 0, /AUTO_FEED = 0, /STROBE = 0 */
val2’nin sadece düşük değerli dört bitinin anlamlı olduğuna dikkat ediniz. Son kod satırı ile /SELECT_IN, /AUTO_FEED ve /STROBE çıkışlarınındonanımla uyumu sağlamak için XOR işlemiyle tersi alınır.
Örneğin, 1 0 0 0 değerini tersini almadan düşük değerli bitlerden göndermek isteseydik, donanım 3, 1 ve 0 bitlerinin tersini alacaktı. Çıkıştaki sonuçise bizim istediğimiz değerle hiç alakası olmayan 0 0 1 1 sonucu olacaktı. XOR kullanarak 1 0 0 0 porta 0 0 1 1 olarak gönderilir. Daha sonra donanım 3, 1 ve 0bitlerinin tersini alır ve çıkışta istediğimiz 1 0 0 0 değerini olur.
Girişler
Durum portunu gösteren diyagramda printerdan gelen beş durumucu olduğu görünüyor. (BSY, /ACK, PE (paper empty),SELECT, /ERROR). Bu girişler Durum portunun yüksekdeğerli beş biti okunarak elde edilir.
Bununla beraber, printer arabirimini tasarlayanlar BSY ile ilgili biti donanım yoluyla ters çevirmişler.Yani, BSY girişinde lojik sıfır olduğunda, bit gerçekte lojik bir olarak okunur. Normalde biz “true” lojik kullanmak isteriz ve bu bitin de tersini alırız.
Aşağıdaki program parçası yüksek değerli beş bitin “true” lojik kullanarak okunmasını gösterir.
#define
DATA 0x03bc
#define STATUS DATA+1
...
unsigned int in_val;
...
in_val = ((inportb(STATUS)^0x80) >> 3);
Durum portu okunur ve BSY ucunun karşılığı olan en yüksek değerli bitin tersi XOR işlemiyle alınır. Daha sonra, sonuç, üst beş bit alt beş bitin yerini alacak şekilde kaydırılır.
0 0 0 BUSY /ACK PE SELECT /ERROR
Bu noktada, en az 12 çıkışın olduğunu görüyoruz: Veri portunda sekiz, Kontrol portunun düşük değerli kısmında dört. Aynı zamanda, beş giriş mevcut: Durum portunun yüksek değerli beş bitinde. Kontrol portundaki üç bit ile Durum portundaki bir bit donanım tarafından ters çevrilir; fakat XOR işlemi vasıtasıyla istenen bitin tersi alınarak kolayca bunun üstesinden gelinir.
Örnek
Şekil 3‘de BUSY girişinde (Durum portu, Bit 7) okunan normalde açık bir “push” butonu ile Veri portundaki 0 biti tarafından kontrol edilen bir LED görülmektedir. “Push” butonu basıldığında LED’in yanmasını sağlayan C dili programı aşağıda verilmiştir. Lojik sıfır çıkışı LED’in yanmasını sağlar.
/*
File: LED_FLSH.C
**
** Illustrates simple use of printer port. When
switch is
** depressed LED flashes. When switch is not
depressed, LED is
** turned off.
**
** P.H. Anderson, Dec 25, '95
*/
#include
<stdio.h>
#include <dos.h> /* required for delay
function */
#define
DATA 0x03bc
#define STATUS DATA+1
#define CONTROL DATA+2
void
main(void)
{
int in;
while(1)
{
in = inportb(STATUS);
if (((in^0x80)&0x80)==0)
/* if BUSY bit is at 0 (sw closed)
*/
{
outportb(DATA,0x00); /*
turn LED on */
delay(100);
outportb(DATA, 0x01); /*
turn it off */
delay(100);
}
else
{
outportb(DATA,0x01);
/* if PB not depressed,
turn LED off */
}
}
}

Şekil 3. Temel Bir Uygulama
Test Devresi
Şekil 4, printer portu donanımında ne gibi değişmeler meydana geldiğini anlamak için basit bir test fikstürü sunuyor. Test_prt.c programı 12 LED’in her birini sırasıyla yakar ve söndürür. Daha sonra girişteki anahtarların durumunu göstermek için döngüye girer.

Şekil 4 – Printer Portu Test Devresi
/*
File TEST_PRT.C
**
** Program to exercise 12 outputs and five
inputs.
**
** Program sequentially turns off LEDs on Bits 7,
6, 5, ... 0 on the
** Data Port, and then Bits #, 2, 1 and 0 on the
Control Port. Each
** LED is held off for nominally 1 second. Note
that an LED is turned
** off with a logic one. This process is executed
once.
**
** Program then loops, scanning the highest five
bits on the Status Port
** and continuously displays the content in
hexadecimal.
**
** P.H. Anderson, Dec 25, '95 */
#include
<stdio.h>
#include <dos.h> /* required for delay
function */
#define
DATA 0x03bc /* for the PC I used */
#define STATUS DATA+1
#define CONTROL DATA+2
void
main(void)
{
int in, n;
outportb(DATA,0x00); /* turn on all LEDs on Data
Port */
outportb(CONTROL, 0x00^0x0b); /* same with
Control Port */
/* now turn off each LED on Data Port in turn by
positioning a logic
one in each bit position and outputing. */
for (n=7; n>=0; n++)
{
outportb(DATA, 0x01 << n);
delay(1000);
}
outportb(DATA, 0x00);
/* now turnoff each LED on control port in turn
** note exclusive-or to compensate for
hardware inversions */
outportb(CONTROL, 0x08^0x0b); /* bit 3 */
delay(1000);
outportb(CONTROL, 0x04^0x0b); /* bit 2 */
delay(1000);
outportb(CONTROL, 0x02^0x0b); /* bit 1 */
delay(1000);
outportb(CONTROL, 0x01^0x0b); /* bit 0 */
delay(1000);
outportb(CONTROL, 0x00);
/* Continuously scan switches and print result in hexadecimal */
while(1)
{
in =
(inportb(STATUS)^0x80)&0xf8;
/* Note that BUSY (msbit) is
inverted and only the
** five most significant bits on
the Status Port are displayed. */
printf("%x\n", in);
}
}
Kesmeler
Tekrar Şekil 2 – Bacak Tanımları’na bir göz atalım. Kontrol portundaki 4 bitinin IRQ Enable olarak adlandırıldığı görülüyor. Normalde bu bit sıfırdır.
Fakat, bazen kesmeler çok önem taşır. Kesme, o an çalışmakta olan programın yaptığı işi geçici olarak durdurup yapılması istenen işleme atlamasını sağlayan bir donanım olayından başka bir şey değildir. Bu işlem tamamlandığında program çalışmasına kaldığı yerden devam eder.
Printer portunun kullanımında IRQ Enable lojik bir ise, ACK girişi lojik birden lojik sıfıra giderken bir kesme meydana gelir. Örneğin, ACK girişi meskene zorla girme alarmı için kullanılabilir. Program devamlı sıcaklığı denetler. Fakat, ACK sıfıra gittiğinde sıcaklık denetlemesini kesip alarmı etkinleştirecek kodu çalıştırır. Bittiğinde, program sıcaklık denetlemesine devam eder.
Sadece Seçili Bitlerin Değiştirilmesi
Çoğu zaman, programcı çıkışa gönderilen byte’ın sadece bir kısmıyla ilgilenir ve diğer bitlerin ne olduğunu hatırlamak sıkıntı verir. Aşağıdaki örnekte 2 biti 100ms için “high” konumunda kalır ve sonra “low” konumuna getirilir.
int data;
...
data=data
| 0x04; /* bring bit 2 high */
outportb(DATA,data);
delay(100);
data=data & 0xfb; /* bring bit 2 low */
outportb(DATA,data);
datadeğişkeninin çıkış portunun geçerli durumunu takip ettiğine dikkat ediniz. Her bit işlemi data üzerinde yapılır ve ondan sonra data değişkeni çıkışa gönderilir.
Belirli bir biti lojik bir yapmak için bu bit lojik bir değeriyle OR işlemine sokulur (değerleri lojik sıfırla). Belirli bir biti lojik sıfır yapmak için ise bu bit lojik sıfır değeriyle AND işlemine sokulur (diğerleri lojik birle). Bu değeri hesaplamak yorucu olabilir. Şu alternatif düşünülebilir:
data=data & 0xfb; /* hard to calculate */
data=data & (~0x04); /* the same but a lot
easier */
Bu gerçekten de fazla zor değil. XX01 X100 olmasını istediğimiz XXXX XXXX verisinin olduğunu var sayalım.
data=data& (~0x20) | 0x10 | 0x04 & (~0x02) & (~0x01);
Printer Portlarındaki Farklar
Yukarıda anlatılanlar geneldir; yani, bütün imalatçılar için ortaktır. “Neden farklı olsunlar ki, WordPerfect gibi programların bütün makinalarda çalışması gerekir.” diye düşünenler olabilir. Cevap şu: WordPerfect gibi programlar yazan programcılar donanımın bu ayrıntısına inmezler. Bunun yerine, PC’nin BIOS’u vasıtasıyla arabirimle haberleşirler.
BIOS (Basic Input-Output System), bütün PC’lerin aynı görünmesini sağlayan PC’nin içindeki ROM’dur.
Bu, her üreticinin kendi tasarımını esnek bir şekilde geliştirmesi için iyi bir yoldur. Buna bir örnek yukarıda bahsedilen port tanımlarıdır. Bu veri PC açılırken BIOS ROM’undan okunur ve 0040:0008 adresinden başlayan hafıza yerleşimlerine yazılır. Böylece WordPerfect’in tasarımcıları port tanımları hakkında endişe etmezler. Sadece uygun hafıza yerleşimini okurlar.
Aynı şekilde, yazdırma işlemi için de BIOS kullanılır. Örneğin; programcı bir karakter yazdırmak isterse, AH kaydedicisi sıfır yapılır, yazdırılacak karakter AL’ye yüklenir, port (LPT1, LPT2, vb) DX kaydedicisine yüklenir ve BIOS’daki INT 17h çalıştırılır. Bundan sonra program kontrolü düşük seviyeli donanım işlevlerini yerine getirecek olan BIOS’a bırakılır. Bir karakteri yazdırmak için gerekli bit işlemleri tamamladığında BIOS durum bilgisini AH kaydedicisine yazarak kontrolü tekrar programa bırakır.
Sonuç
Sonuç olarak, printer portu diş devrelerle çalışmak için çok basit bir teknik sağlar. Sekizi Veri portunda ve dördü Kontrol portunun düşük değerli bitlerinde olmak üzere on iki çıkış mevcut. Kontrol portundaki üç bitin evirilmesi gerekir. Durum portunda beş giriş var. Bu bitleri okurken ise bir yazılım evirmesi gerekir.
- Yorum yazmak için giriş yapın veya kayıt olun