PC'de Paralel Port Düzeni |
Çevre birimlerinin kontrolü ile ilgili gerçekleştirilecek projeler için PC’nin paralel portu (printer portu) hala çok ucuz ve güçlü bir platform özelliğindedir. Printer portu bize sekiz TTL çıkış, beş giriş ve dört iki yönlü uç sağlar. Bu yazı, printer portunun nasıl kullanılacağı ve programlanacağı hakkında bilgi verir.
Her bir printer portu üç adresten oluşur: veri, durum ve kontrol portu. Bu adresler sıralı şekildedir. Yani, eğer veri portu adresi 0x0378’de ise ilgili durum portu 0x0389’da ve ilgili kontrol portu da 0x037A’dadır.
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ğunu görürüz. Bu paralel port adresidir. Yani bizim kullanacağımız adres 0x3BC portudur. Bu arada eğer LPT1 adresi değişirse yeni adreste burada yerini alacaktır. Eğer buradan okuyarak işimizi halledersek sorun çıkmaz.
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> void main(void) ptraddr=(unsigned int far *)0x00000408; LPT atamalarını görmek için alternatif bir teknik ise Microsoft Diagnostics (MSD.EXE) programını çalıştırmaktır. Başa geri dönÇıkışlarLütfen Şekil 1 – Bacak Tanımları ve Şekil 2 – Port Tanımları’nı inceleyiniz. Bu iki şekil 25 bacaklı konektörün bacak tanımları ile üç portun bit 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 ... int val1, val2; ... val1 = 0x81; /* 1000 0001 */ /* Data bits 7 and 0 at one */ /* 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ın donanı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 0 bitlerinin tersini alır ve çıkışta istediğimiz 1 0 0 0 değerini olur. Başa geri dönGirişlerDurum portunu gösteren diyagramda printerdan gelen beş durum ucu olduğu görünüyor. (BSY, /ACK, PE (paper empty), SELECT, /ERROR). Bu girişler Durum portunun yüksek değ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 ... 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. Başa geri dönÖ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 #include <stdio.h> #define DATA 0x03bc void main(void) while(1) Şekil 3 – Temel Bir Uygulama Ş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 #include <stdio.h> #define DATA 0x03bc /* for the PC I used */ void main(void) outportb(DATA,0x00); /* turn on all LEDs on Data Port */ /* now turn off each LED on Data Port in turn by positioning a logic for (n=7; n>=0; n++) /* now turnoff each LED on control port in turn outportb(CONTROL, 0x08^0x0b); /* bit 3 */ outportb(CONTROL, 0x00); /* Continuously scan switches and print result in hexadecimal */ while(1) printf("%x\n", in); Başa geri dönTekrar Ş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. Başa geri dönSadece 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 */ data değ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 */ 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); Başa geri dön
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. Başa geri dön
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. Başa geri dön |