Bölüm 10: Aygıt Kontrolü
Giriş
Öğrenme Çıktıları
IN ve OUT komutlarının biçimlerini ve sınırlarını bilmek.
Bir porttaki her bitin bir lambaya, mıknatısa ya da duruma karşılık geldiğini çözümlemek.
Aygıtın hazır bitini bekleyen döngüler yazmak.
INT 15h / AH = 86h ile mikrosaniye cinsinden bekleme süresi hesaplamak.
Trafik ışıkları, step motor, LED ekran, termometre, yazıcı, robot ve test aygıtını programlamak.
Programın ROM'dan RAM'e yüklenip çalıştırılma ilkesini açıklamak.
Giriş
emu8086'ya Bağlı 7 Sanal Aygıt
| Aygıt | Port(lar) | Yön | Veri |
|---|---|---|---|
| Trafik lambaları (traffic lights) | 4 | OUT | sözcük: 12 lamba biti |
| Step motor (stepper motor) | 7 | OUT / IN | bit 0–2 mıknatıslar, bit 7 hazır |
| Robot | 9, 10, 11 | OUT / IN | komut, veri, durum |
| Test aygıtı (simple io test) | 110, 112 | IN / OUT | bayt (110), sözcük (112) |
| Termometre ve ısıtıcı | 125, 127 | IN / OUT | sıcaklık, ısıtıcı aç/kapa |
| Yazıcı (printer) | 130 | OUT | karakter (INT 21h/05h ile) |
| LED ekran (LED display) | 199 | OUT | sözcük: işaretli sayı |
Aygıtlar emu8086'da virtual devices menüsünden açılır; programın başına #start=Traffic_Lights.exe# gibi bir direktif yazılırsa öykünücü aygıtı kendisi başlatır.
G/Ç Temelleri
Aygıt Kontrolü
- x86 ailesi CPU'lar geniş bir aygıt yelpazesini denetleyebilir. Temel G/Ç port numaraları sistemden sisteme farklılık gösterebilir ve uygun bir donanımla (adres çözücü, “tricky” elektronik devre) değiştirilebilir.
- Gömülü bir sistemde derlenen
.bindosyası Salt Okunur Bellek (ROM) yongasına yazılır. - Sistem açılınca programı ROM'dan okur, RAM'e yükler ve yürütür. Bu ilke birçok modern cihazda (çamaşır makinesi, yazıcı, modem…) kullanılır.
G/Ç Temelleri
IN ve OUT Komutları
| Biçim | Anlamı | Port aralığı |
|---|---|---|
IN AL, port | porttan 1 bayt oku | 0–255 (sabit) |
IN AX, port | porttan 1 sözcük oku | 0–255 (sabit) |
IN AL, DX / IN AX, DX | port numarası DX'te | 0–65 535 |
OUT port, AL / OUT port, AX | porta yaz | 0–255 (sabit) |
OUT DX, AL / OUT DX, AX | port numarası DX'te | 0–65 535 |
OUT 4, BX veya IN CL, 7 geçersizdir.MOV DX, 300 yazılır, sonra OUT DX, AL. Bu derste tüm emu8086 portları 255'in altındadır.G/Ç Temelleri
Port Eşlemeli ve Bellek Eşlemeli G/Ç
- 8086'nın ayrı bir 64 K'lık G/Ç adres uzayı vardır.
- Erişim yalnızca
IN/OUTile; M/IO̅ pini G/Ç döngüsünü belirtir. - Bellek adreslerini tüketmez.
- emu8086'nın sanal aygıtlarının hepsi böyledir.
- Aygıt yazmaçları bellek adreslerinde durur.
- Her MOV/ADD/CMP komutu kullanılabilir.
- Örnek: PC metin ekranı B800:0000'dan başlar; oraya yazılan bayt ekranda görünür.
G/Ç Temelleri
8255 Programlanabilir Çevre Arayüzü (PPI)
- Üç 8 bitlik port (A, B, iki 4 bitlik yarıya ayrılabilen C) ve bir kontrol yazmacı; yazmaç A1, A0 ile seçilir, C̅S̅ adres çözücüden gelir.
- RESET sonrası tüm portlar giriştir; önce kontrol sözcüğü yazılır.
| A1 A0 | Yazmaç | Adres (taban 310h) |
|---|---|---|
| 0 0 | port A | 310h |
| 0 1 | port B | 311h |
| 1 0 | port C | 312h |
| 1 1 | kontrol yazmacı | 313h |
DX ile.G/Ç Temelleri
8255 Kontrol Sözcüğü (Mod 0)
| D7 | D6 D5 | D4 | D3 | D2 | D1 | D0 |
|---|---|---|---|---|---|---|
| 1 = mod seçimi | A grubu modu 00 = mod 0 | port A | PC7–PC4 | B grubu modu 0 = mod 0 | port B | PC3–PC0 |
| yön bitleri: | 1 = giriş, 0 = çıkış (D4, D3, D1, D0) | |||||
1 00 0 0 0 1 0b = 82h
İstenen: A çıkış (LED/röle), B giriş (anahtar), C'nin iki yarısı çıkış, hepsi mod 0.
D7 = 1: mod seçimi · D6 D5 = 00 ve D2 = 0: mod 0
Mod 0 el sıkışmasız basit G/Ç'dir; mod 1 ve 2 el sıkışmalı (strobe) aktarım içindir.
D4 = 0 (A çıkış) · D3 = 0 (C üst çıkış)
D1 = 1 (B giriş) · D0 = 0 (C alt çıkış)
Sonuç 1000 0010b = 82h. Örneğin A giriş, B çıkış, C giriş için 1001 1001b = 99h olur.
D7 = 0 ise bit kur/sil (BSR):
D3–D1 = C'nin bit numarası, D0 = yeni değer
0Fh (0000 1111b) → PC7 = 1, 0Eh → PC7 = 0. Diğer C bitleri değişmez.
mov dx, 313h ; kontrol yazmacı mov al, 82h ; A çık, B gir, C çık out dx, al mov dx, 311h ; port B in al, dx ; anahtarları oku mov dx, 310h ; port A out dx, al ; LED'lere yaz mov dx, 313h mov al, 0Fh ; BSR: PC7 = 1 out dx, al
G/Ç Temelleri · Kodu adım adım çalıştır
8255: Kontrol Sözcüğü, Okuma, Yazma, BSR
org 100h mov dx, 313h ; kontrol yazmacı mov al, 82h ; A,C çık; B gir out dx, al mov dx, 311h ; port B in al, dx ; anahtarları oku mov dx, 310h ; port A out dx, al ; LED'lere yaz mov dx, 313h mov al, 0Fh ; BSR: PC7 = 1 out dx, al ret
RESET sonrası üç port da giriş. Port B'ye bağlı anahtarlar 1001 0110b = 96h konumunda (port sözlüğünde 311h = 96h). DX = 313h, AL = 82h.
OUT 313h ← 82h = 1 00 0 0 0 1 0b: mod 0; A çıkış, C üst çıkış, B giriş, C alt çıkış.
DX = 311h: port B. 311h > 255 olduğundan port numarası DX'te verilir.
IN AL, DX: anahtarlar okunur → AL = 96h.
DX = 310h: port A.
OUT 310h ← 96h: port A çıkış olduğundan LED'ler anahtarları kopyalar (yanan: bit 7, 4, 2, 1).
DX = 313h, AL = 0Fh = 0000 111 1b: D7 = 0 → mod sözcüğü değil, bit kur/sil (BSR).
OUT 313h ← 0Fh: D3–D1 = 111 → PC7, D0 = 1 → PC7 = 1. Port yönleri (82h) değişmez, diğer C bitleri korunur.
Port değerleri yorumlayıcının G/Ç kaydından (anahtar girişi 96h örnek). BSR sözcüğü yalnız seçilen C bitini değiştirir.
G/Ç Temelleri
Etkileşimli 8255 Kontrol Sözcüğü
Port yönüne tıklanınca yön değişir; kutuya doğrudan bir değer de yazılabilir (ör. 9B, 80, 0F).
Trafik Işıkları
Trafik Lambaları (Port 4)
- Kavşakta 4 direk, her direkte 3 lamba: toplam 12 lamba = port 4'e yazılan sözcüğün bit 0–11'i.
- Bit = 1 → lamba yanar, 0 → söner. Bit 12–15 kullanılmaz.
- Her direkte (k = 0…3): bit 3k kırmızı, 3k+1 sarı, 3k+2 yeşil.
- Örnek:
0000_0011_0000_1100b→ bit 2 ve 8 (yeşil), bit 3 ve 9 (kırmızı).
| Direk | Bitler |
|---|---|
| sağ alt | 0 1 2 |
| sağ üst | 3 4 5 |
| sol üst | 6 7 8 |
| sol alt | 9 A B |
Trafik Işıkları
Durum (Situation) Tablosu
; FEDC_BA98_7654_3210 situation dw 0000_0011_0000_1100b s1 dw 0000_0110_1001_1010b s2 dw 0000_1000_0110_0001b s3 dw 0000_1000_0110_0001b s4 dw 0000_0100_1101_0011b sit_end = $ all_red equ 0000_0010_0100_1001b
| Ad | Hex | Lambalar |
|---|---|---|
situation | 030Ch | sağ alt: yeşil; sağ üst: kırmızı; sol üst: yeşil; sol alt: kırmızı |
s1 | 069Ah | sağ alt: sarı; sağ üst: kırmızı + sarı; sol üst: sarı; sol alt: kırmızı + sarı |
s2 | 0861h | sağ alt: kırmızı; sağ üst: yeşil; sol üst: kırmızı; sol alt: yeşil |
s3 | 0861h | sağ alt: kırmızı; sağ üst: yeşil; sol üst: kırmızı; sol alt: yeşil |
s4 | 04D3h | sağ alt: kırmızı + sarı; sağ üst: sarı; sol üst: kırmızı + sarı; sol alt: sarı |
all_red | 0249h | sağ alt: kırmızı; sağ üst: kırmızı; sol üst: kırmızı; sol alt: kırmızı |
s2 ve s3 aynıdır: yan yol yeşili iki aralık (10 s) sürer. s1 ve s4 sarı geçişleridir (kırmızı + sarı = “hazırlan”).
Trafik Işıkları
Durumlar Adım Adım
all_red = 0249h → sağ alt: kırmızı; sağ üst: kırmızı; sol üst: kırmızı; sol alt: kırmızı
situation = 030Ch → sağ alt: yeşil; sağ üst: kırmızı; sol üst: yeşil; sol alt: kırmızı
s1 = 069Ah → sağ alt: sarı; sağ üst: kırmızı + sarı; sol üst: sarı; sol alt: kırmızı + sarı
s2 = 0861h → sağ alt: kırmızı; sağ üst: yeşil; sol üst: kırmızı; sol alt: yeşil
s3 = 0861h → sağ alt: kırmızı; sağ üst: yeşil; sol üst: kırmızı; sol alt: yeşil
s4 = 04D3h → sağ alt: kırmızı + sarı; sağ üst: sarı; sol üst: kırmızı + sarı; sol alt: sarı
Program önce tüm yönleri kırmızı yapar, sonra situation → s1 → s2 → s3 → s4 → situation… diye 5 saniyelik aralıklarla döner.
Trafik Işıkları
INT 15h / AH = 86h ile Bekleme
; 5 saniye bekle (5 milyon µs) mov cx, 4Ch ; 004C4B40h = 5 000 000 mov dx, 4B40h mov ah, 86h int 15h
- BIOS işlevi INT 15h, AH = 86h: CX:DX mikrosaniye bekler.
- CX yüksek sözcük, DX düşük sözcük: 32 bitlik bekleme süresi.
5 s = 5 × 1 000 000 = 5 000 000 µs
Süre mikrosaniyeye çevrilir.
5 000 000 ÷ 16 = 312 500 kalan 0
312 500 ÷ 16 = 19 531 kalan 4
19 531 ÷ 16 = 1 220 kalan 11 (B)
1 220 ÷ 16 = 76 kalan 4
76 ÷ 16 = 4 kalan 12 (C)
4 ÷ 16 = 0 kalan 4
Ardışık 16'ya bölme: kalanlar sondan başa okunur → 4C4B40h.
0 0 4 C | 4 B 4 0
CX = 004Ch · DX = 4B40h
32 bitlik değer 0000 0000 0100 1100 0100 1011 0100 0000b ikiye bölünür.
1 s → 1 000 000 = 000F4240h → CX = 000Fh, DX = 4240h
Başka bir örnek: 1 saniyelik bekleme.
Trafik Işıkları
Yazılımla Gecikme: LOOP ve Saat Turu
; ≈ 1 ms gecikme (4,77 MHz 8086) mov cx, 281 ; 4 çevrim bekle: loop bekle ; 280 × 17 + 1 × 5 çevrim
| Komut | Saat turu |
|---|---|
MOV CX, sabit | 4 |
LOOP (CX ≠ 0, atlar) | 17 |
LOOP (CX = 0, atlamaz) | 5 |
Toplam = 4 + 17(N − 1) + 5 = 17N − 8 saat turu.
4,77 MHz: 1 saat turu ≈ 0,2096 µs
1 ms = 4 770 saat turu
Süre, saat turu sayısının saat frekansına bölümüdür.
17N − 8 = 4 770 → N ≈ 281,06
N = 281 → 4 769 saat turu ≈ 0,9998 ms
CX'e tam sayı yazılabildiği için en yakın değer seçilir.
5 MHz: 1 ms = 5 000 saat turu → N ≈ 294,6
N = 295 → 5 007 saat turu ≈ 1,0014 ms
Aynı N = 281 5 MHz'de yalnızca 0,954 ms sürer: gecikme saat hızına bağlıdır.
En uzun: CX = 0 → 65 536 tur
17 · 65 536 − 8 = 1 114 104 saat turu ≈ 233,6 ms
Daha uzun bekleme için iç içe döngü gerekir. Prosedür olarak çağrılırsa CALL (19) ve RET (8) saat turu da eklenir.
Trafik Işıkları · Kodu adım adım çalıştır
Gecikme Döngüsünde Saat Turlarını Saymak
org 100h mov cx, 4 ; 4 saat turu bekle: loop bekle ; 17 tur, sonuncu 5 ret
CX = 4. mov cx, sabit 4 saat turu sürer; 4,77 MHz'de 1 tur ≈ 0,2096 µs.
1. LOOP: CX = 3 ≠ 0 → atlar (aynı komuta döner): 17 tur. Toplam 21.
2. LOOP: CX = 2, yine 17 tur. Toplam 38.
3. LOOP: CX = 1, 17 tur. Toplam 55.
4. LOOP: CX = 0 → atlamaz: yalnız 5 tur. Toplam 60 = 17 · 4 − 8 tur.
60 tur ÷ 4,77 MHz ≈ 12,6 µs. CX'i N yapınca süre 17N − 8 turdur; 1 ms için N = 281 bulunmuştu.
Tur sayıları 8086 komut sürelerinden; yorumlayıcı yalnız CX ve atlama davranışını doğrular (emu8086 zamanlamayı modellemez).
Trafik Işıkları · Kodu adım adım çalıştır
Trafik Işıkları Programı
Tablo 0124h'de varsayıldı (ORG 100h; adres derleyiciye göre değişebilir). sit_end = 012Eh.
AX = all_red = 0249h (sabit, EQU).
Port 4'e yaz: tüm yönler kırmızı.
SI = 0124h: tablonun başı (situation).
AX ← [SI] = 030Ch.
OUT 4, AX: lambalar yeni duruma geçer (SI = 0124h).
CX = 004Ch (bekleme süresinin yüksek sözcüğü).
DX = 4B40h (düşük sözcük).
AH = 86h: BIOS bekleme işlevi.
INT 15h: 5 saniye bekle.
SI = 0126h: sonraki sözcük.
CMP SI, sit_end (012Eh): SI < sit_end → CF = 1.
JB: CF = 1, next'e dön.
… bekleme ve SI artırma … OUT 4, AX: SI = 0126h → port 4 = 069Ah.
… bekleme ve SI artırma … OUT 4, AX: SI = 0128h → port 4 = 0861h.
… bekleme ve SI artırma … OUT 4, AX: SI = 012Ah → port 4 = 0861h.
… bekleme ve SI artırma … OUT 4, AX: SI = 012Ch → port 4 = 04D3h.
CMP SI, sit_end (012Eh): SI = sit_end → CF = 0.
JB: CF = 0, atlama yok: tablo bitti.
SI = 0124h: tabloya baştan başla.
JMP next: sonsuz döngü.
… bekleme ve SI artırma … OUT 4, AX: SI = 0124h → port 4 = 030Ch.
#start=Traffic_Lights.exe# mov ax, all_red out 4, ax mov si, offset situation next: mov ax, [si] out 4, ax mov cx, 4Ch ; 5 s bekle mov dx, 4B40h mov ah, 86h int 15h add si, 2 ; sonraki durum cmp si, sit_end jb next mov si, offset situation jmp next
Döngü hiç bitmez: gömülü sistemlerde ana program genellikle sonsuz bir döngüdür.
Trafik Işıkları
Etkileşimli Trafik Bit Düzenleyici
Bir bite tıklanınca o lamba yanar ya da söner (F…0). Bit 12–15 kullanılmaz.
Step Motor
Step Motor (Port 7)
- Motor hem saat yönünde (CW) hem de tersine (CCW) döndürülebilir.
- Port 7'ye yazılan baytın bit 0, 1, 2'si üç elektromıknatısı açar/kapatır.
- Yarı adım 11,25°, tam adım 22,5°'dir.
- Yarı adım: çift mıknatıs, ardından tek mıknatıs açılarak döndürülür.
- Tam adım: çift mıknatıs, çift mıknatıs, tek mıknatıs şeklinde devam eder.
- Motor yeni komut almaya hazır olduğunda porttan okunan baytın bit 7'sini 1 yapar.
Step Motor
Step Motor Veri Tabloları
| Tablo | Anlam | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
datcw | CW yarı adım | 110 | 100 | 011 | 010 |
datccw | CCW yarı adım | 011 | 001 | 110 | 010 |
datcw_fs | CW tam adım | 001 | 011 | 110 | 000 |
datccw_fs | CCW tam adım | 100 | 110 | 011 | 000 |
- Tablolar bellekte arka arkaya durur: her biri 4 bayt. Bu yüzden
add bx, 4bir sonraki tabloya geçirir. - Program 32 (20h) tur sonra tabloyu değiştirir: CW yarı → CCW yarı → CW tam → CCW tam → başa.
- Bayt değerindeki bitler mıknatısları gösterir:
110b= mıknatıs 2 ve 1 açık;000b= hepsi kapalı. - Kaynak koddaki biçim:
datcw db 0000_0110bve alt satırlardadb 0000_0100b… (alt çizgi yalnızca okunabilirlik içindir).
Step Motor
Mıknatıs Dizileri Adım Adım
- Yarı adım dizisi (datcw): çift → tek → çift → tek mıknatıs.
- Tam adım dizisi (datcw_fs): tek, çift, çift ve “hepsi kapalı” bayt.
- Her OUT komutundan sonra motor yeni konumuna gidene kadar meşguldur; bu yüzden program her bayttan önce bit 7'yi yoklar.
CW yarı adım, 1. bayt: açık mıknatıslar → 2, 1
CW yarı adım, 2. bayt: açık mıknatıslar → 2
CW yarı adım, 3. bayt: açık mıknatıslar → 1, 0
CW yarı adım, 4. bayt: açık mıknatıslar → 1
CW tam adım, 1. bayt: açık mıknatıslar → 0
CW tam adım, 2. bayt: açık mıknatıslar → 1, 0
CW tam adım, 3. bayt: açık mıknatıslar → 2, 1
CW tam adım, 4. bayt: açık mıknatıslar → hiçbiri
Step Motor
Step Motor Kontrol Programı
ORG 100h steps_before_direction_change = 20h jmp start datcw db 110b,100b,011b,010b datccw db 011b,001b,110b,010b datcw_fs db 001b,011b,110b,000b datccw_fs db 100b,110b,011b,000b start: mov bx, offset datcw mov si, 0 mov cx, 0 ; tur sayacı
- Yoklama (wait): bit 7 = 0 ise motor meşgul, tekrar oku.
[bx][si]= [BX + SI]: BX tablonun başı, SI sıra (0–3).- 4 bayt gönderilince SI = 0, CX +1; CX = 20h olunca BX 4 artar, son tablodan sonra başa döner.
steps_before_direction_change = 20hbir sabittir (EQU gibi), bellekte yer kaplamaz.
next_step: wait: in al, 7 test al, 10000000b jz wait mov al, [bx][si] out 7, al inc si cmp si, 4 jb next_step mov si, 0 inc cx cmp cx, steps_before_direction_change jb next_step mov cx, 0 add bx, 4 ; sonraki tablo cmp bx, offset datccw_fs jbe next_step mov bx, offset datcw jmp next_step
Step Motor · Kodu adım adım çalıştır
Step Motor: İlk Tur
ORG 100h, steps_before_direction_change = 20h. Port 7 önce 00h (meşgul), sonra 80h (hazır) döndürecek.
Veri tablolarının üzerinden atla.
BX = 0102h: datcw tablosu (CW yarı adım).
SI = 0: tablonun ilk baytı.
CX = 0: tur sayacı.
IN AL, 7 → AL = 00h (bit 7 = 0, motor meşgul).
TEST AL, 80h → ZF = 1.
JZ: ZF = 1 → tekrar bekle.
IN AL, 7 → AL = 80h (bit 7 = 1, hazır).
TEST AL, 80h → ZF = 0.
JZ: ZF = 0 → devam.
AL ← [BX+SI] = [0102h] = 110b.
OUT 7, AL: mıknatıslar 110b → motor yarım adım (11,25°) döner.
SI = 1.
CMP SI, 4 → CF = 1.
JB: SI < 4 → next_step.
IN AL, 7 → AL = 80h (bit 7 = 1, hazır).
TEST AL, 80h → ZF = 0.
JZ: ZF = 0 → devam.
AL ← [BX+SI] = [0103h] = 100b.
OUT 7, AL: mıknatıslar 100b → motor yarım adım (11,25°) döner.
SI = 2.
CMP SI, 4 → CF = 1.
JB: SI < 4 → next_step.
IN AL, 7 → AL = 80h (bit 7 = 1, hazır).
TEST AL, 80h → ZF = 0.
JZ: ZF = 0 → devam.
AL ← [BX+SI] = [0104h] = 011b.
OUT 7, AL: mıknatıslar 011b → motor yarım adım (11,25°) döner.
SI = 3.
CMP SI, 4 → CF = 1.
JB: SI < 4 → next_step.
IN AL, 7 → AL = 80h (bit 7 = 1, hazır).
TEST AL, 80h → ZF = 0.
JZ: ZF = 0 → devam.
AL ← [BX+SI] = [0105h] = 010b.
OUT 7, AL: mıknatıslar 010b → motor yarım adım (11,25°) döner.
SI = 4.
CMP SI, 4 → CF = 0.
JB: SI = 4: tablo bitti.
SI = 0: tabloyu baştan oku.
CX = 1: bir tur (4 adım) tamamlandı.
CMP CX, 20h → CF = 1 (henüz 32 tur olmadı).
JB next_step: aynı tabloyla devam. 32 turdan sonra add bx, 4 sonraki tabloya geçer.
jmp start ; tablolar 0102h-0111h start: mov bx, offset datcw mov si, 0 mov cx, 0 ; tur sayacı next_step: wait: in al, 7 test al, 10000000b jz wait mov al, [bx][si] out 7, al inc si cmp si, 4 jb next_step mov si, 0 inc cx cmp cx, steps_before_direction_change jb next_step
Step Motor
Gerçek Donanım: Unipolar Step Motor ve ULN2003
- Unipolar motorda iki orta uçlu sargı vardır: dört sargı yarısı A, B, A̅, B̅; orta uçlar +V'ye bağlanır (5 ya da 6 tel).
- Sargı akımı (yüzlerce mA) port ucunun sürebileceğinden çok büyüktür; araya ULN2003 konur: 7 Darlington kanalı, kanal başına 500 mA'e kadar.
- Giriş = 1 → çıkış toprağa çeker → o sargı yarısından akım geçer.
- Akım kesilince sargıda oluşan ters gerilim, COM ucu +V'ye bağlanarak ULN2003'ün iç diyotlarıyla sönümlenir.
- Motor açık çevrimdir: “hazır” biti yoktur, hızı adımlar arası bekleme belirler. Çok kısa beklemede motor adım kaçırır.
Step Motor
Gerçek Motor: Uyarma Dizileri
| Sürüş | Port A dizisi (B̅ A̅ B A = bit 3…0) |
|---|---|
| Tek faz (dalga), tam adım | 01h 02h 04h 08h |
| İki faz, tam adım | 03h 06h 0Ch 09h |
| Yarım adım | 01h 03h 02h 06h 04h 0Ch 08h 09h |
- İki faz sürüşte her an iki sargı yarısı akım çeker: tork daha yüksektir.
- Yarım adım iki diziyi sırayla karıştırır: adım açısı yarıya iner (ör. 1,8° → 0,9°).
- Dizi tersten uygulanırsa motor ters yönde döner.
- emu8086'nın sanal motoru 3 mıknatıslı basit bir modeldir (bit 0–2, bit 7 hazır); onun tabloları (110b, 100b, …) 4 fazlı gerçek motora uygulanmaz.
; 82h ile port A çıkış yapılmış olsun yarim db 01h,03h,02h,06h db 04h,0Ch,08h,09h adim dw 0 ileri: inc adim ; geri için: dec adim mov bx, adim and bx, 7 ; dizin 0–7 mov al, yarim[bx] mov dx, 310h ; port A out dx, al call bekle ; adım aralığı = hız jmp ileri
Step Motor · Kodu adım adım çalıştır
Gerçek Motor: Yarım Adım Dizisini Sürmek
org 100h ileri: inc adim ; geri: dec adim mov bx, adim and bx, 7 ; dizin 0–7 mov al, yarim[bx] mov dx, 310h ; port A out dx, al call bekle ; adım aralığı jmp ileri bekle: ret ; (gecikme) yarim db 01h,03h,02h,06h db 04h,0Ch,08h,09h adim dw 6
Sargılar: bit 0 = A, bit 1 = B, bit 2 = A̅, bit 3 = B̅. adim = 6 iken INC → 7; AND BX, 7 dizini 0–7'de tutar → BX = 7.
AL ← yarim[7] = 09h = 1001b → B̅ ve A sargıları: alan ikisinin arasına (≈ 315°) döner. Port A'ya yazılır.
CALL bekle / RET: adımlar arası bekleme motorun hızını belirler. JMP ileri.
adim = 8 → AND 7 → BX = 0: dizi başa sarar.
yarim[0] = 01h → yalnız A: alan 0°'ye geldi (yarım adım).
Bekle ve tekrar.
adim = 9 → BX = 1.
yarim[1] = 03h → A + B: 45°. Her OUT alanı bir yarım adım (45° sargı açısı) ilerletir; dizi tersten okunursa motor geri döner.
Port 310h'e yazılan baytlar (09h, 01h, 03h …) yorumlayıcının G/Ç kaydından alındı; bekle burada yalnız RET'tir.
LED Ekran
LED Ekran (Port 199)
- Port 199'a yazılan sözcük 5 basamaklı onluk sayı olarak gösterilir.
- Değer işaretli (ikiye tümleyen) yorumlanır: −32 768 … 32 767.
- −5678 = 10000h − 162Eh = E9D2h; ekranda -5678 görünür.
- Yalnızca
OUT 199, AXkullanılır (199 ≤ 255 olduğundan sabit port yeterli). #make_bin#: DOS'a bağlı olmayan düz ikili (.bin) dosya üretilir.
LED Ekran · Kodu adım adım çalıştır
LED Ekran Kontrolü
Ekran başlangıçta 00000 gösterir.
AX = 1234 (onluk) = 04D2h.
OUT 199, AX: ekranda 1234.
AX = −5678 = E9D2h (ikiye tümleyen).
OUT 199, AX: ekranda -5678.
AX = 0: sayaç.
OUT 199, AX: ekranda 0.
AX = 1.
JMP x1: sonsuz döngü (alttaki HLT'ye hiç ulaşılmaz).
OUT 199, AX: ekranda 1.
AX = 2.
JMP x1: sonsuz döngü (alttaki HLT'ye hiç ulaşılmaz).
OUT 199, AX: ekranda 2.
AX = 3.
JMP x1: sonsuz döngü (alttaki HLT'ye hiç ulaşılmaz); sayaç 32767'den sonra −32768'e geçer.
#start=led_display.exe# mov ax, 1234 out 199, ax mov ax, -5678 out 199, ax ; port'a sonsuz döngüde yaz: mov ax, 0 x1: out 199, ax inc ax jmp x1 hlt ; hiç çalışmaz
emu8086'da adım gecikmesi (step delay) 0 iken sayılar çok hızlı akar; döngüye INT 15h/86h ile bekleme eklenebilir.
LED Ekran
Gerçek Donanım: 7 Bölütlü Gösterge
- Ortak katot (CC): ortak uç toprakta, bit = 1 bölütü yakar.
- Ortak anot (CA): ortak uç +5 V'ta, bit = 0 yakar: kod CC kodunun tersidir (
NOT AL). - Her bölüte akım sınırlayıcı direnç bağlanır.
- emu8086'nın port 199 LED ekranı sayıyı kendisi çözer; gerçek göstergede kodu program üretir.
| Rakam | Yanan bölütler | CC | CA |
|---|---|---|---|
| 0 | a b c d e f | 3Fh | C0h |
| 1 | b c | 06h | F9h |
| 2 | a b d e g | 5Bh | A4h |
| 3 | a b c d g | 4Fh | B0h |
| 4 | b c f g | 66h | 99h |
| 5 | a c d f g | 6Dh | 92h |
| 6 | a c d e f g | 7Dh | 82h |
| 7 | a b c | 07h | F8h |
| 8 | a b c d e f g | 7Fh | 80h |
| 9 | a b c d f g | 6Fh | 90h |
LED Ekran
Kod Tablosu, XLAT ve Çoklamalı Tarama
; rakamı (0–9) bölüt koduna çevir mov bx, offset kod mov al, 3 ; rakam xlat ; AL = [BX + AL] = 4Fh ; not al ; ortak anot ise mov dx, 310h ; 8255 port A out dx, al kod db 3Fh,06h,5Bh,4Fh,66h db 6Dh,7Dh,07h,7Fh,6Fh
- Çoklama: 4 basamağın bölüt uçları ortak port A'ya, ortak uçları ayrı transistörlerle port C'ye bağlanır.
- Her an tek basamak yanar; basamak başına ≈ 4 ms → tam tur 16 ms ≈ 62 Hz. Göz titremeyi görmez (≈ 50 Hz üstü).
- Basamağı değiştirmeden önce tümü kapatılır; yoksa önceki kod yan basamakta soluk görünür (gölge).
tara: mov si, 0 hane: mov dx, 312h ; port C: hane seçimi mov al, 0 out dx, al ; önce tüm haneler sönük mov al, rakam[si] mov bx, offset kod xlat mov dx, 310h ; port A: bölütler out dx, al mov al, secim[si] ; 01h, 02h, 04h, 08h mov dx, 312h out dx, al ; yalnız bu hane yanar call bekle_4ms inc si cmp si, 4 jb hane jmp tara rakam db 1, 2, 3, 4 secim db 01h, 02h, 04h, 08h
LED Ekran · Kodu adım adım çalıştır
Çoklamalı Tarama: 2026 Gösterimi
org 100h mov bx, offset kod mov si, 0 hane: mov dx, 312h ; port C (hane) mov al, 0 out dx, al ; tümü sönük mov al, rakam[si] xlat ; bölüt kodu mov dx, 310h ; port A (bölüt) out dx, al mov al, secim[si] mov dx, 312h out dx, al ; tek hane yanar inc si cmp si, 4 jb hane ret kod db 3Fh,06h,5Bh,4Fh,66h db 6Dh,7Dh,07h,7Fh,6Fh rakam db 2, 0, 2, 6 secim db 01h, 02h, 04h, 08h
BX = tablo başı, SI = 0. Gösterilecek sayı 2026 (rakam dizisi); 4 hanenin bölüt uçları ortak port A'ya bağlı.
1. hane: önce port C ← 00h (hepsi sönük, gölge olmasın). AL = rakam[0] = 2; XLAT → AL = 5Bh.
Port A ← 5Bh (bölütler), port C ← 01h: yalnız 1. hane yanar. INC SI, CMP, JB → sonraki hane.
2. hane: önce port C ← 00h (hepsi sönük, gölge olmasın). AL = rakam[1] = 0; XLAT → AL = 3Fh.
Port A ← 3Fh (bölütler), port C ← 02h: yalnız 2. hane yanar. INC SI, CMP, JB → sonraki hane.
3. hane: önce port C ← 00h (hepsi sönük, gölge olmasın). AL = rakam[2] = 2; XLAT → AL = 5Bh.
Port A ← 5Bh (bölütler), port C ← 04h: yalnız 3. hane yanar. INC SI, CMP, JB → sonraki hane.
4. hane: önce port C ← 00h (hepsi sönük, gölge olmasın). AL = rakam[3] = 6; XLAT → AL = 7Dh.
Port A ← 7Dh (bölütler), port C ← 08h: yalnız 4. hane yanar. INC SI, CMP, JB → SI = 4, döngü biter.
Dört hane sırayla birer kez yandı. Her hane ≈ 4 ms yansa tam tur 16 ms (≈ 62 Hz): göz dördünü birlikte görür.
Ortak katot kodları; port değerleri yorumlayıcının G/Ç kaydından. Gerçekte her hane ≈ 4 ms yanık tutulur.
Termometre
Termometre ve Isıtıcı (Port 125, 127)
IN AL, 125: anlık hava sıcaklığını (°C, işaretli bayt) okur.OUT 127, AL: AL = 1 ısıtıcıyı açar, AL = 0 kapatır.- Isıtıcı açıkken sıcaklık yavaşça artar, kapalıyken düşer.
- Amaç: sıcaklığı 60–80 °C arasında tutan bir termostat.
- Sıcaklık eksi olabileceği için karşılaştırmalar işaretli atlamalarla (
JL,JLE,JG) yapılır.
Termometre · Kodu adım adım çalıştır
Termostat Programı
Port 125 sırayla 55, 70 ve 85 °C döndürecek. Isıtıcı başlangıçta kapalı.
AX = CS = 0700h.
DS = 0700h (kesim yazmacına sabit doğrudan yazılamaz).
IN AL, 125 → sıcaklık 55 °C.
CMP AL, 60: 55 − 60 → SF = 1, OF = 0.
JL (SF ≠ OF): 55 < 60 → low.
AL = 1.
OUT 127, AL: ısıtıcı açıldı.
JMP ok.
JMP start: yeni ölçüm.
IN AL, 125 → sıcaklık 70 °C.
CMP AL, 60: 70 − 60 → SF = 0, OF = 0.
JL (SF ≠ OF): atlama yok.
CMP AL, 80 → ZF = 0, SF = 1.
JLE: 60 ≤ 70 ≤ 80 → ok (ısıtıcıya dokunma).
JMP start: yeni ölçüm.
IN AL, 125 → sıcaklık 85 °C.
CMP AL, 60: 85 − 60 → SF = 0, OF = 0.
JL (SF ≠ OF): atlama yok.
CMP AL, 80 → ZF = 0, SF = 0.
JLE: atlama yok.
JG: 85 > 80 → high.
AL = 0.
OUT 127, AL: ısıtıcı kapatıldı.
JMP start: yeni ölçüm.
; DS'yi CS'ye eşitle: mov ax, cs mov ds, ax start: in al, 125 cmp al, 60 jl low cmp al, 80 jle ok jg high low: mov al, 1 out 127, al ; ısıtıcı açık jmp ok high: mov al, 0 out 127, al ; ısıtıcı kapalı ok: jmp start ; sonsuz döngü
jg high yerine jmp high da yazılabilirdi: JLE atlamadıysa sıcaklık zaten 80'den büyüktür.
Termometre
Etkileşimli Termostat
Yazıcı
Yazıcı (Printer, Port 130)
- emu8086 yazıcısı port 130'a bağlıdır; ama program porta doğrudan yazmak yerine DOS işlevini kullanır:
INT 21h,AH = 05h: DL'deki karakteri yazıcıya (PRN) gönderir.- Kontrol karakterleri yazıcıyı yönetir:
| Kod | Ad | Etki |
|---|---|---|
| 0Ah (10) | LF | bir satır aşağı |
| 0Dh (13) | CR | satır başına dön |
| 09h (9) | HT | yatay sekme (tab) |
| 0Ch (12) | FF | yeni sayfa (form feed) |
db 13, 9: 13 = CR (satır başı), 9 = yatay sekme (HT). Dikey sekme (VT) 11 = 0Bh'dir.0Ah, 0Dh sırası LF + CR'dir; alışılmış sıra CR + LF'tir, ama ikisi birlikte aynı sonucu verir.Yazıcı
Yazıcı Programı: Veri
org 100h jmp start msg db "Hello, Printer!", 0Ah, 0Dh db "***************" db 13, 9 ; CR ve yatay sekme (HT) db "Have a nice printing day!" msg_end db 0 msg2 db "press any key to eject the page.$"
offset msg_end - offset msg derleme zamanında hesaplanır: 15 + 2 + 15 + 2 + 25 = 59 = 3Bh bayt.'$' ile biter: INT 21h / AH = 09h ekrana yazdırırken $'a kadar gider.Yazıcı · Kodu adım adım çalıştır
Yazıcı Programı: Yazdırma Döngüsü
Çıktı paneli yazıcı kâğıdını gösterir: LF satır atlar, CR satır başına döner, TAB 8 sütunluk sekmeye gider.
DL = 12 (0Ch): form feed.
AH = 05h: DOS yazıcı çıkışı.
INT 21h: yazıcı yeni sayfaya geçer.
SI = 0102h: msg'nin adresi.
CX = 59 (003Bh): karakter sayısı.
DL ← [SI] = 'H'.
AH = 05h: DOS yazıcı çıkışı.
INT 21h: 'H' yazıcıya gider.
SI = 0103h.
LOOP: CX = 58 → devam.
DL ← [SI] = 'e'.
AH = 05h: DOS yazıcı çıkışı.
INT 21h: 'e' yazıcıya gider.
SI = 0104h.
LOOP: CX = 57 → devam.
DL ← [SI] = 'l'.
AH = 05h: DOS yazıcı çıkışı.
INT 21h: 'l' yazıcıya gider.
SI = 0105h.
LOOP: CX = 56 → devam.
… INT 21h: 'l' yazıldı (CX = 56).
… INT 21h: 't' yazıldı (CX = 48).
… INT 21h: '*' yazıldı (CX = 40).
… INT 21h: '*' yazıldı (CX = 32).
… INT 21h: 'a' yazıldı (CX = 24).
… INT 21h: 'c' yazıldı (CX = 16).
… INT 21h: 'i' yazıldı (CX = 8).
DL ← [SI] = '!'.
AH = 05h: DOS yazıcı çıkışı.
… INT 21h: '!' yazıldı (CX = 1).
SI = 013Dh.
LOOP: CX = 0 → 59 karakter bitti.
start: mov dl, 12 ; form feed: yeni sayfa mov ah, 5 int 21h mov si, offset msg mov cx, offset msg_end - offset msg print: mov dl, [si] mov ah, 5 ; DOS yazıcı işlevi int 21h inc si ; sonraki karakter loop print
CR (13) LF olmadan gelince üçüncü metin yıldızların üzerine basılır (panelde üzerine yazma olarak gösterildi). Döngüden sonra: mov dx, offset msg2 / mov ah, 9 / int 21h ekrana mesaj yazar; int 16h (AH = 0) bir tuş bekler; son form feed sayfayı yazıcıdan çıkarır.
Robot
Robot (Port 9, 10, 11)
- Robot bir ızgara dünyasında hareket eder; duvarları ve lambaları algılayabilir, lambaları yakıp söndürebilir.
- Port 9 komut (OUT), port 10 veri (IN), port 11 durum (IN). Dünya, aygıt penceresindeki araç kutusuyla düzenlenir.
Robot
Robot Komutları ve Durum Bitleri
| Komut (port 9) | Etki |
|---|---|
| 0 | hiçbir şey yapma |
| 1 | ileri git |
| 2 | sola dön |
| 3 | sağa dön |
| 4 | önündekini incele (examine) |
| 5 | lambayı yak |
| 6 | lambayı söndür |
| Veri (port 10) | Önündeki |
|---|---|
| 255 (FFh) | duvar |
| 0 | boş |
| 7 | yanan lamba |
| 8 | sönük lamba |
| Durum (port 11) | 1 ise |
|---|---|
| bit 0 | veri yazmacında yeni veri var |
| bit 1 | robot meşgul (komut sürüyor) |
| bit 2 | son komutta hata |
Robot
Robot Programı: Lambayı Bul ve Yak
#start=robot.exe# dongu: CALL hazir_bekle MOV AL, 4 ; incele OUT 9, AL CALL veri_bekle IN AL, 10 CMP AL, 0FFh ; duvar? JE don CMP AL, 8 ; sönük lamba? JNE ilerle CALL hazir_bekle MOV AL, 5 ; yak OUT 9, AL JMP dongu don: MOV AL, 3 ; sağa dön JMP gonder ilerle: MOV AL, 1 ; ileri gonder: PUSH AX ; komutu koru CALL hazir_bekle POP AX OUT 9, AL JMP dongu
- Her komuttan önce meşgul biti (bit 1) sıfır olana kadar beklenir.
- İncele (4) komutundan sonra veri hazır biti (bit 0) beklenir, sonra port 10 okunur.
- Duvarsa sağa dön, sönük lambaysa yak, yoksa ilerle.
- Bekleme yordamları
CALLile çağrılır: dönüş adresi yığında.
Robot
Robot: Bekleme Yordamları ve Dikkat Edilecekler
hazir_bekle PROC b1: IN AL, 11 TEST AL, 010b ; meşgul? JNZ b1 RET hazir_bekle ENDP veri_bekle PROC v1: IN AL, 11 TEST AL, 001b ; yeni veri? JZ v1 RET veri_bekle ENDP
hazir_bekle AL'yi IN ile ezer. gonder yolunda AL komut değerini taşıdığı için yordamdan önce PUSH AX, sonra POP AX yapılır; aksi hâlde porta durum baytı gönderilirdi.Robot
Basit G/Ç Test Aygıtı (Port 110, 112)
- Port 110: bir bayt; port 112: bir word.
- Pencereye yazılan değerler programa giriş olur (hex için
hsoneki), programın yazdıkları pencerede görünür. - Giriş portları her 100 ms'de güncellenir.
- IN/OUT'u denemek ve hata ayıklamak için idealdir.
IN AL, 110 ; ör. A7h okunur INC AL OUT 110, AL ; A8h yazılır IN AX, 112 ; ör. 1234h ADD AX, 1 OUT 112, AX ; 1235h
Robot · Kodu adım adım çalıştır
Test Aygıtı: Bayt ve Sözcük G/Ç
org 100h in al, 110 ; bayt oku inc al out 110, al ; bayt yaz in ax, 112 ; sözcük oku add ax, 1 out 112, ax ; sözcük yaz ret
Test aygıtı penceresine girilen değerler: port 110 = FFh, port 112 = 7FFFh. IN AL, 110 → AL = FFh.
INC AL: FFh + 1 = 00h (8 bitte taşar). ZF = 1; INC, CF'yi değiştirmez.
OUT 110, AL: pencerede port 110 = 00h.
IN AX, 112: 16 bit okuma → AX = 7FFFh (+32 767).
ADD AX, 1 → 8000h: iki pozitifin toplamı negatif oldu → OF = 1, SF = 1; işaretsiz taşma yok, CF = 0.
OUT 112, AX: pencerede port 112 = 8000h.
RET: program biter.
Giriş değerleri yorumlayıcının port sözlüğüne verildi; çıkışlar G/Ç kaydından okundu.
Özet
Özet
| Aygıt | Port | Anahtar fikir |
|---|---|---|
| Trafik lambaları | 4 | Her bit bir lamba; durum tablosu + INT 15h/86h bekleme. |
| Step motor | 7 | Bit 0–2 mıknatıs, bit 7 hazır; yarı adım 11,25°, tam adım 22,5°. |
| LED ekran | 199 | Sözcük, işaretli onluk gösterim. |
| Termometre | 125, 127 | Okuma + işaretli karşılaştırma + ısıtıcı aç/kapa. |
| Yazıcı | 130 | INT 21h/05h; kontrol karakterleri LF, CR, HT, FF. |
| Robot | 9, 10, 11 | Komut, veri, durum; meşgul/veri bitlerini yokla. |
| Test aygıtı | 110, 112 | Bayt ve sözcük G/Ç denemesi. |
| 8255 PPI (gerçek) | 310h–313h | Kontrol sözcüğü (ör. 82h) port yönlerini belirler; port > 255 → DX. |
Ortak desen: durum oku → bit test et → hazırsa veri yaz/oku → döngü. IN/OUT yalnızca AL/AX ile, port > 255 ise DX ile.
Özet
Alıştırmalar
- Tüm yönlerde yalnızca sarı lambaları yakan port 4 değeri nedir?
- 2,5 saniyelik bekleme için CX ve DX ne olmalıdır?
- LED ekranda −1 göstermek için AX'e hangi onaltılık değer yazılır?
- Termostatı 20–25 °C aralığına göre değiştirin; sıcaklık −10 °C iken
JBkullanılsaydı ne olurdu? - Step motor programında motoru yalnızca saat yönünde, tam adımla döndürmek için hangi satırlar değişmeli?
Cevaplar
- Bit 1, 4, 7, 10 → 0000_0100_1001_0010b = 0492h.
- 2 500 000 = 002625A0h → CX = 0026h, DX = 25A0h.
- FFFFh.
cmp al, 20 / jl low / cmp al, 25 / jle ok / .... −10 = F6h; işaretsiz JB için 246 > 20 olur ve ısıtıcı açılmazdı.mov bx, offset datcw_fsve tablo değiştiren kısım (inc cx…jmp next_step) kaldırılıpjmp next_stepyazılır.
Özet
Alıştırmalar (devam)
- Yazıcıya “Merhaba” yazıp sayfayı çıkaran en kısa programı yazın.
- 8 MHz'lik bir 8086'da
mov cx, N/loopile yaklaşık 1 ms gecikme için N kaçtır? - 8255'te A giriş, B çıkış, C'nin tamamı giriş (mod 0) için kontrol sözcüğü nedir?
- Ortak anotlu göstergede '5' ve 'H' harfinin kodları nedir (dp g f e d c b a sırası)?
Cevaplar
- Her karakter için
MOV DL, 'M'/MOV AH, 5/INT 21h(veya döngü), sonunda DL = 12 ile form feed. - 17N − 8 = 8 000 → N ≈ 471 (7 999 saat turu).
- 1 00 1 1 0 0 1b = 99h.
- '5': CC 6Dh → CA 92h; 'H' (b c e f g): CC 76h → CA 89h.
Özet
Kaynaklar
- emu8086 yardım belgeleri: I/O ports and hardware interrupts, Virtual devices ve örnek programlar (traffic_lights.asm, stepper_motor.asm, led_display_test.asm, thermometer.asm, printer.asm, robot.asm).
- Intel, The 8086 Family User's Manual, 1979 — IN/OUT komutları, G/Ç adres uzayı ve komut süreleri.
- Intel, 8255A Programmable Peripheral Interface veri sayfası; Texas Instruments, ULN2003A veri sayfası.
- M. Bodur, Mikroişlemcilere Giriş: Assembler ile Yazılım ve Arayüz, EMO, 2014.
- R. Brown, Ralf Brown's Interrupt List — INT 15h/86h, INT 21h/05h, INT 16h/00h.
- B. B. Brey, The Intel Microprocessors, 8. baskı, Pearson, 2009 — Bölüm 11 (Temel G/Ç arayüzü).