Bölüm-4 Kütükler (Registers) ve Kesme Yordamları

Durum Kütüğü (Status Register)

Mikrodenetleyicinin çalışma durumunu kontrol etmek için kullanılan özel veri belleği alanlarına kütük veya kaydedici denir. Her mikrodenetleyicide çeşitli kütükler bulunur. PIC mikrodenetleyicilerinde de Genel Amaçlı Kütükler (General Purpose Registers) ve Özel İşlev Kütükleri (Special Function Registers) bulunur. Mikrodenetleyicinin kesme işlemlerini, matematiksel işlemlerini, zaman işlemlerini, veri yazma ve okuma işlemlerini kontrol etmek için kullanılan kütüklere Özel İşlev Kütükleri denir. Bunlardan başlıca en önemlileri şunlardır:

  1. Durum Kütüğü (Status Register)
  2. Tercih Kütüğü (Option Register)
  3. Kesme Kontrol Kütüğü (INTCON - Interrupt Control Register)

PIC mikrodenetleyicilerinde bu kütükler dört banktan oluşan veri belleğinde (Data Memory) yer alır.

Bank0: 00h-7Fh
Bank1: 80h-FFh
Bank2: 100h-17Fh
Bank3: 180h-1FFh
adres aralığında yer alır. Banklara erişim durum kütüğündeki RP0 ve RP1 bitleriyle gerçekleştirilir.

Durum kütüğü Bank0’da 03h, Bank1’de 83h, Bank2’de 103h ve Bank3’te 183h adreslerinde yer alır. Tercih kütüğü Bank1’de 81h ve Bank3’te 181h adreslerinde yer alır. Kesme kontrol kütüğü ise 0Bh, 8Bh, 10Bh ve 18Bh adresleri olmak üzere 4 bankta da yer alır. Kullanılacak mikrodenetleyicinin veri yapraklarından (datasheet) bellek adresleriyle ilgili ayrıntılı bilgi alınabilir.

Durum kütüğü ALU’nun aritmetik işlem durumunu, RESET durumunu ve banklardan oluşan veri belleğinin banklarını seçmek için kullanılan 8 bitlik bir SFR kütüğüdür. (TO) ve (PD)bitleri yazılamaz bitlerdir. Mikrodenetleyicilerde önemli bir konu olan uyku modunda çalışma durumunu izlemek için kullanılırlar.

bit 7: IRP: Kaydedici Bank seçim biti (dolaylı adresleme için kullanılır)
Bu bit 16F84A mikrodenetleyicisinde kullanılmaz
bit 6-5: RP1:RP0: Kaydedici Bank seçim biti (doğrudan adresleme için kullanılır)
00 = Bank 0 (00h – 7Fh)
01 = Bank 1 (80h – FFh)
10 = Bank 2 (100h – 17Fh)
11 = Bank 3 (180h – 1FFh)
Her bir bank 128 byte’dır.
bit 4:TO : Zaman aşımı (Time-out) biti
1 = Besleme verildikten, CLRWDT komutu, ya da SLEEP komutu kullanıldıktan sonra
0 = Bir WDT (Watchdog Timer) zaman aşımı oluştu durumu
bit 3:PD : Power-down biti
1 = Besleme verildikten sonra ya da CLRWDT komutuyla
0 = SLEEP komutunun işletilmesiyle
bit 2: Z: Zero biti
1 = Bir aritmetik ya da lojik işlem sonucunun sıfır olması durumu
0 = Bir aritmetik ya da lojik işlem sonucunun sıfır olmaması durumu
bit 1: DC: Digit carry/borrow biti (ADDWF, ADDLW, SUBLW ve SUBWF assembly komutlarının kullanımında) (Ödünç durumu için polarite ters çevrilir)
1 = Sonucun 4’üncü düşük seviye bitinden bir taşma meydana gelmesi durumu
0 = Sonucun 4’üncü düşük seviye bitinden bir taşma meydana gelmemesi durumu
bit 0: C: Carry/borrow bit (ADDWF, ADDLW, SUBLW ve SUBWF assembly komutlarının kullanımında)
1 = Sonucun en yüksek seviyeli bitinden bir taşma meydana gelmesi durumu
0 = Sonucun en yüksek seviyeli bitinden taşma oluşmaması durumu

NOT: borrow için, polarite ters çevrilir. Çıkartma işlemi, ikinci operandın 2’ye göre tümleyeni alınmış hali toplanarak yapılır. RRF, RLF döndürme komutları için kaynak kütüğünün düşük ya da yüksek düzeyli bitinden biriyle yüklenir.

Kısaltmaların Anlamları
R =Okunabilir bitU = Uygulanmamış bitx = Bit belirsiz
W = Yazılabilir bit ‘1’ = Bit kurulur (set edilir)‘0’ = Bit temizlenir

Tercih Kütüğü (Option Register)

Tercih kütüğü çeşitli kontrol bitlerini konfigüre etmek için kullanılan okunabilir ve yazılabilir 8 bitlik bir SFR kütüğüdür. Timer0 zaman sayacı kesmesi (TMR0) ve vardiya zamanlayıcısı (WDT-Watchdog Timer) için önölçekleyici (prescaler), harici INT kesmesi, Timer0 kesmesi ve PORTB için pull-up ayarlarını içerir.

bit 7 RBPU: PORTB Pull-up aktifleştirme biti
1 = PORTB pull-uplar etkin değil (disabled)
0 = PORTB pull-uplar etkin (enabled)
bit 6 INTEDG: Interrupt kenar seçme biti
1 = RB0/INT girişinin yükselen kenarında kesme oluşur
0 =RB0/INT girişinin düşen kenarında kesme oluşur
bit 5 T0CS: TMR0 için saat kaynağı seçme biti
1 = RA4/T0CKI Clock In girişinin seçilmesi (Böylece harici saat darbesi girişi seçilmiş olur ve harici sinyalin her durum değişiminde sayaç değeri bir artırılır. Örnek uygulama için bkz.4.8)
0 =Dâhili komut çevrim darbesi (CLKOUT) (Zaman sayacı mikrodenetleyicinin dâhili çalışma frekansı hızıyla orantılı bir hızda çalışır.)
bit 4 T0SE: TMR0 kaynağı kenar seçme biti
1 = RA4/T0CKI girişindeki sinyalin yüksekten (1) alçağa (0) geçişi durumunda sayaç değerinin bir artması
0 = RA4/T0CKI girişindeki sinyalin alçaktan (0) yükseğe (1) geçişi durumunda sayaç değerinin bir artması
bit 3 PSA: Önölçekleyici (Prescaler) atama biti. Atanan Önölçekleyici değeri ile 2'nin katlarında bir yavaşlama katsayısı elde edilir. Böylece sayma işlemi belli bir oranda yavaşlatılabilir.
1 = Önölçekleyici WDT için tahsis edilir
0 = Önölçekleyici Timer0 modülü için tahsis edilir
bit 2-0 PS2:PS0: Önölçekleyici Oranı Seçme Bitleri

Bit DeğeriTMR0 DeğeriWDT Değeri
0001:21:1
0011:41:2
0101:81:4
0111:161:8
1001:321:16
1011:641:32
1101:1281:64
1111:2561:128

Kesme Kontrol Kütüğü

The INTCON kütüğü okunabilir ve yazılabilir 8 bitlik bir SFR kütüğüdür. Kesme kaynaklarını kontrol etmek için kullanılır. PIC16F628A mikrodenetleyicisinin veri belleğinin Bank 0 bölgesinin 0Bh, Bank 1 bölgesinin 8Bh, Bank2 bölgesinin 10Bh ve Bank3 bölgesinin 18Bh adreslerinde yer alır.

bit 7: GIE: Evrensel kesme etkinleştirme biti
1 = Tüm maskesiz kesmeler etkinleştirilir
0 = Tüm kesmeler pasifleştirilir
bit 6 PEIE: Çevresel Kesme etkinleştirme biti
1 = Tüm maskesiz çevresel kesmeleri etkinleştirir
0 = Tüm çevresel kesmeleri pasifleştirir
bit 5 T0IE: TMR0 taşma kesmesi etkinleştirme biti
1 = TMR0 kesmesi etkinleştirilir
0 = TMR0 kesmesi pasifleştirilir
bit 4 INTE: RB0/INT harici kesme etkinleştirme biti
1 = RB0/INT harici kesmesi etkinleştirilir
0 = RB0/INT harici kesmesi pasifleştirilir
bit 3 RBIE: RB Portu durum kesmesi etkinleştirme biti
1 = RB portundaki değişimi izleyen kesme etkinleştirilir
0 = RB portundaki değişimi izleyen kesme pasifleştirilir
bit 2 T0IF: TMR0 taşma kesmesi bayrağı biti
1 = TMR0 kaydedicisi taşma bayrağı aktif (yazılım içinde sıfırlanmalıdır). Sayaç değerinin üst sınır değerine (255) geldiği anlaşılır. Bu olaya taşma durumu denir.
0 = TMR0 kaydedicisinde taşma oluşmadı
bit 1 INTF: RB0/INT harici kesme bayrağı biti
1 = RB0/INT girişinde harici kesme oldu (yazılım içinde sıfırlanmalıdır)
0 = Harici kesme olmadı
bit 0 RBIF: RB0/INT harici kesme bayrağı biti
1 = RB7:RB4 pinlerinin en az birinde bir durum değişimi oluştu (yazılım içinde sıfırlanmalıdır)
0 = RB7:RB4 pinlerinin herhangi birinde durum değişimi olmadı

Mikrodenetleyicide Temel Kesmeler

Kesmeler bir programın daha önemli başka bir görevin yerine getirilmesi için kesilmesine izin veren bir mekanizmadır. Bu görevler mikrodenetleyicinin ilgili portuna bağlı bir butonun tetiklenmesi, portlarından birine bağlı bir sensörün aktif olması veya dâhili zaman sayacının önceden tanımlı bir değere ulaşması gibi işlemler olabilir. Kesmeler tarafından idare edilecek olaylar sadece donanım tasarımcılarının hayal gücüyle sınırlıdır. mikroC programında kesme işlemlerinin yürütülmesi için “void interrupt()” kesme hizmet programı yer alır. Mikrodenetleyicinin özelliğine bağlı olarak kullanılacak kesme işlemleri bu rutin içine yazılan kodlarla gerçekleştirilir. Kesme hizmet programı kendisini tetikleyen kesme tarafından belirtilmiş olan uygun işlemleri gerçekleştiren bir prosedürdür. Kesme Hizmet Programı aynı zamanda kesme işleyici veya kesme programı diye de adlandırılabilir.

PIC 16F628A serisi mikrodenetleyicilerde 10 adet kesme kaynağı vardır. Başlıca kesmeler şunlardır:

  1. Harici kesme RB0/INT
  2. TMR0 taşma kesmesi
  3. PORTB <7-4> değişim algılama kesmesi
  4. Karşılaştırıcı kesmesi
  5. USART TX kesmesi
  6. USART RX kesmesi
  7. CCP kesmesi
  8. TMR1 kesmesi
  9. TMR2 kesmesi
  10. Veri EEPROM belleği kesmesi

PIC 16F628A’da kesmeler INTCON, PIE1 ve PIR1 kütükleriyle kontrol edilir ve izlenir. Bu bölümde Harici kesme, port değişim algılama kesmesi ve TMR0 kesmeleri açıklanacaktır. Diğer kesmeler bir sonraki bölümde açıklanacaktır. Şekil 4.1’de PIC16F628A mikrodenetleyicisi için kesmelerin nasıl işlediğini gösteren lojik şema resmedilmiştir.

Şekil-4.1 PIC16F628A'da kesme lojiği

Harici Kesme (RB0/INT)

Harici kesme girişi B portunun 0'ıncı pinidir. B portunun 0'ıncı pini normal giriş çıkış olarak kullanılabileceği gibi kesme girişi olarak da kullanılır. Harici kesmenin çalışma ilkesi kısaca şu şekildedir: Bu girişde bir durum değişimi algılanırsa, yani eğer giriş 0 seviyesinde olup 1 seviyesine çıkarsa ya da tersi durumda, o an çalışan program durdurulur, harici kesme işlemiyle birlikte yürütülecek prosedür (program, hizmet, uygulama, işlem, vb.) gerçekleştirilir. İşlem gerçekleştirildikten sonra program kaldığı yerden devam ettirilir.

PIC16F628A'da B portu için aşağıdaki komut yazılırsa,

TRISB = 0x00;

B portunun tüm pinleri (RB0 - RB7 numaralı toplam 8 pini) çıkış olarak ayarlanmış olur. Harici kesmenin kullanılabilmesi için öncelikle B0 pininin giriş olarak ayarlanması gerekir. Bunun için,

TRISB = 0x01;

Komutu verilir. Böylece B portunun RB0 pini giriş olarak ayarlanmış olur. Artık bundan sonra bu pine bağlanacak bir buton ya da algılayıcı yardımıyla, denetleyicinin çalıştırdığı program dışarıdan gelecek bir tetiklemeyle kesilebilir. Ancak harici kesmeyi aktif hale getirmek için bu işlem yeterli değildir. Bunun için aşağıdaki kodun da yazılması gerekir.

INTCON.INTE = 1; //Harici kesme aktifleştirme biti 1 yapılarak harici kesme aktifleştirilir.

Harici kesme aktif olduğunda INTCON kaydedicisinin INTF bayrağı 1 olur. Böylece harici kesme oluştuğu mikrodenetleyiciye bildirilir.

TMR0 Zaman Kesmesi

TMR0 8 bitlik bir zaman sayacıdır. Sayaç değeri yazılabilir ya da okunabilir. Tüm mikrodenetleyicilerde bu özellik vardır. Daha önceden kurulan bir değer mikrodenetleyicinin çalışma frekansı hızıyla orantılı bir hızda 255 değerine kadar sayar. 255 değeri her aşıldığında INTCON kaydedicisinin T0IF bayrağı 1 olur. Ardından sayaç tekrar daha önce kurulmuş değerden başlayarak 255'e kadar sayar. Bu işlem sürekli olarak devam eder. Sayma işlemi her bittiğinde zaman sayacının yeniden kurulması ve T0IF bayrağının 0 yapılması gerekir.

Zaman sayacının T0IF bayrağının 1 olduğu ana kadar geçen süre kontrol edilerek birbirinden bağımsız olarak çalışan zamana bağlı uygulamalar yapılabilir.

Bu sayacın en güzel yanlarından biri de dâhili saat darbesinin yanında harici darbe girişiyle de kontrol edilebilmesidir. Böylece başka bir kaynağın hızına göre çalışan bir zaman sayacı tasarlayabilirsiniz.

Zaman kesmesini kullanabilmek için;

INTCON.T0IE = 1; kodu kullanılmalıdır. Ardından, TMR0 = 125; gibi TMR0 kaydedicisine 0-255 arası bir değer ataması yapılır.

Program içinde INCON.T0IF bayrağının 1 olup olmadığı kontrol edilir. Eğer 1 ise ilgili işlem gerçekleştirilir ve T0IF bayrağı tekrar 0 yapılır. TMR0 kaydedicisine yeniden değer ataması yapılmalıdır. Aksi taktirde sayma işlemi 0'dan başlar. Sayma hızı mikrodenetleyicinin frekansına ya da harici tetikleme girişinin hızına bağlıdır.

Vardiya Zamanlayıcısı (WDT-WatchDog Timer ve Uyku Modu)

Tüm PIC mikrodenetleyicilerinin en önemli özelliklerinden biri de vardiya zamanlayıcısıdır. PIC mikrodenetleyicisi vardiya zamanlayıcısı (watchdog timer - WDT) olarak ayarlandığında dâhili bir RC osilatörü devreye girer. Bu osilatörün periyodik darbelerinin süresine göre mikrodenetleyiciye reset işlemi uygulanır ve program kodu baştan başlar. Genel olarak bu süre minimum 18 msn kadardır. WDT’nin kullanım amaçlarından birisi mikrodenetleyicinin çalışıp çalışmadığından emin olmak ve kilitlenme problemlerinin önüne geçmektir. Timer0 modülünün önölçekleyicisi kullanılarak bu süre uzatılabilir. 8 bitlik Timer0 modülüne sahip MCU’larda bu süre 128 katı kadar uzatılarak yaklaşık 2,3 sn’ye kadar çıkılabilir. Bu süre PIC16F887’de 268 sn ve PIC18F2550’de 131 sn olabilmektedir. Bu süreler, MCU’nun VDD beslemesindeki kararsızlıklar ya da değişimler ve dâhili RC osilatörünün (bazılarında 31 kHz LFINTOSC) ortam sıcaklığına bağlı kararsızlığı nedeniyle değişiklik gösterebilmektedir. Olumsuz koşullar altında genellikle hesap edilen sürenin üstüne çıkılmaktadır.

Ana programın WDT reset süresinden daha uzun sürdüğü durumlarda vardiya zamanlayıcısının program içinde belli aralıklarla sıfırlanması istenebilir. WDT’nin sıfırlanması ya da resetlenmesi sonrası vardiya zamanlayıcısı süresi yeniden başlar. Toplam program süresinin hesaplanması için mikroC program editöründe hata ayıklayıcı (Debugger) kullanılabilir (Bkz. Şekil 2.10). Program kodu adım adım işletilerek programın nerelerinde WDT’nin sıfırlanacağı belirlenir. WDT’nin normal çalışma modundayken sıfırlanma işlemi CLRWDT Assembly komutuyla yapılır. MikroC program editöründe WDT’yi resetleyecek Assembly kodu yazmak için aşağıda gösterilen yazım tekniği kullanılabilir.

asm CLRWDT;

PIC mikrodenetleyicileri batarya ve pil gibi zamanla enerjisi biten kaynaklardan beslendiklerinde enerji tasarrufu büyük önem arz eder. PIC mikrodenetleyicileri sınıfına ve modeline bağlı olarak çok geniş bir güç yönetim ve osilatör tercihlerine sahiptir. İlgili kaydedicileri doğru ayarlamak suretiyle 10’larca hatta 100’lerce misle varan enerji tasarrufu sağlanabilir. PIC mikrodenetleyicileri sürekli olarak aktif durumda olmalarını gerektirmeyen ve enerji tasarrufunun önemli olduğu durumlarda uyku moduna (sleep mode) alınır.

Uyku modunda mikrodenetleyicinin osilatör girişleri/çıkışları (OSI/OSO), harici saat darbesi girişi (T0CKI) ve eğer etkinse dâhili osilatörü kapatılır. Timer0 modülünün mikrodenetleyiciyi uyku modundan çıkartma özelliği yoktur. Bu nedenle, sistemin periyodik olarak uyanması istenen uyku modu uygulamalarında, Timer0 önölçekleyicisi WDT için tahsis edilir. Bunun için mikroC program editöründe Project→Edit Project penceresinde ilgili mikrodenetleyicinin vardiya zamanlayıcısı etkinleştirilir. Bu pencerede, mikrodenetleyicilerin çeşitli donanımsal özelliklerini ayarlamayı sağlayan ve CONFIGURATION WORD olarak adlandırılan CONFIG sözcüklerinin bitleri ayarlanır (Bkz. Ek-D3, Ek-E3 ve Ek-F3). Açılan pencerede Watchdog Timer yazılı alanda “Enabled” seçeneği seçildiğinde ve derleyici tekrar çalıştırıldığında WDT etkinleştirilmiş olur.

Konfigürasyon sözcüğünde ilgili ayar yapıldıktan sonra OPTION ya da OPTION_REG kaydedicisinin PSA biti kurulur ve önölçekleyici WDT için ayarlanmış olur. Kısaca WDT;

  • Normal çalışma modu,
  • Uyku modu, olmak üzere iki farklı modda çalıştırılır.

Normal çalışma modunda reset işlemi sonrası mikrodenetleyicinin program sayıcısı (PC) 0000h adresine, diğer bir ifadeyle başlangıç adresine gider. Eğer uyku modunda çalışma durumu söz konusu ise PC+1 program adresine gidilir ve uyku modu komutunun verildiği adresten hemen sonraki program adımı işletilir. Uyku komutu da WDT zaman sayacını sıfırlar, ancak söylendiği gibi sistem bu durumda resetlenmez. Eğer WDT etkinken mikrodenetleyicinin uyku moduna alınması ve WDT’nin zaman aşımı sonrası uyanması isteniyorsa aşağıdaki Assembly kod bloğu kullanılabilir.

    
        asm{
         SLEEP;
         NOP;
        }
    
    

Dikkat edileceği gibi SLEEP komutunun ardından NOP (1 çevrim süresi kadar bekleme) komutu kullanılmıştır. SLEEP komutunun ardından NOP kullanımı tavsiye edilir. Böylece programın kaldığı adrese geri dönmesi öncesinde MCU’nun hazır hale gelmesi için bir bekleme yapılmış olur.

Tablo 4.1’de vardiya zamanlayıcısının uyku modunda kullanımına örnek gösterilmiştir. Uygulamada PIC16F628A mikrodenetleyicisi kullanılmıştır. MCU’nun RA0 pinine bir LED bağlanmış ve LED’in vardiya zamanlayıcısı kullanılarak fasılalı yanıp sönmesi gerçekleştirilmiştir. Öncelikle proje editörü penceresinden WDT etkinleştirilmiştir. Program ilk başlatıldığında, OPTION kaydedicisi 0Fh değeriyle yüklenmiş ve böylece önölçekleyici WDT için tahsis edilmiştir. Ön ölçekleme değeri olarak 128 ayarlanmış ve 2,3 sn’lik reset süresi elde edilmiştir.

Tablo 4.1 WDT'nin uyku modunda kullanımı

#define KONTROL PORTA.RA0 // A portunun 0. pinine (RA0) KONTROL ismi veriliyor
void main() {
 OPTION_REG = 0x0F; // Ön ölçekleyici WDT'ye ayarlanıyor (1:128)
 TRISA = 0; // Tüm A portları çıkış yapılıyor
 TRISB = 0; // Tüm B portları çıkış yapılıyor
 PORTA = 0; // Portlar temizleniyor
 PORTB = 0;
 KONTROL = 1; // RA0 lojik-1 yapılıyor
 Delay_ms(250); // 250ms sonra lojik-0 yapılıyor
 KONTROL = 0;
 asm{ // Assembly kod bloğu açılıyor
  SLEEP; // Mikrodenetleyici uyku moduna alınıyor
     NOP;
 }// Assembly kod bloğu kapatılıyor
}


İlgili kaydedici ayarları yapıldıktan sonra RA0 pini lojik-1 yapılmakta ardından 250 msn’lik bir bekleme sonrası lojik-0 seviyesine çekilmektedir. Daha sonra Assembly kod bloğu açılarak “SLEEP” komutuyla mikrodenetleyici uyku moduna sokulmaktadır. Bu uygulama PROTEUS-ISIS®’te kuracağınız devrede çalıştırıldığı zaman “Simulation Log” penceresinde vardiya zamanlayıcısının 4,86 saniye aralıklarla zaman aşımına gittiği görülecektir. Eğer programınızdan, uyku moduna almayı sağlayan kod bloğunu çıkartıp yeni baştan derleyerek devrenizi çalıştırırsanız 2,30 sn’lik aralıklarla zaman aşımının gerçekleştiği görülür. SLEEP komutunun yerine CLRWDT komutunu yazacak olursanız zaman aşımları arasındaki sürenin 2,55 saniye olacağı görülecektir (program içindeki 250 msn’lik bekleme nedeniyle).

Uyku modu ve normal çalışma modlarında mikrodenetleyicinin 4 MHz dâhili çalışma frekansı altında çektiği akım değerleri ölçülmüş ve aşağıdaki değerler gözlemlenmiştir:

Uyku Modu
WDT ile uyanıp LED yandığında Uykuya girip LED söndüğünde
2 - 7 mA 0,34 mA
Normal Çalışma Modu
WDT ile resetlenip LED yandığında LED söndüğünde
6 - 7 mA 1,52 mA

Dikkat edileceği üzere uyku modunda çok daha az akım tüketimi vardır. Ancak mikrodenetleyicinin uyanma sırasındaki çektiği akım çok farklılık göstermektedir. Bu durum, iç donanımların besleme dengesine oturmasına kadar geçen süreyle ilgilidir. Bu gibi elektriksel özellikler ilgili mikrodenetleyicilerin “Elektriksel Özellikleri” başlığı altında açıklanmıştır. Ayrıca kullanılan ölçü aletinin hassasiyet kalitesi (yüksek hassasiyet gerektiren işlemlerde Fluke kullanımı tavsiye edilir) gibi durumlar da ölçüm değerlerinin farklı çıkmasına yol açabilir. Kesin tespit için nanoamper seviyesinde akım ölçümü yapabilen cihazlar kullanılmalıdır.

Yeni nesil 8-bit mikrodenetleyicileriyle birlikte WWDT (Windowed Watch Dog Timer) denilen bir tasarım tanıtılmıştır. Bu tasarıma göre CLRWDT komutu yalnızca zaman-aşımı sırasında belli bir pencere içinde gerçekleşirse kabul edilir. PIC16(L)F18424-44 mikrodenetleyicisinde WWDT zaman aşımı süresi 1 msn – 256 sn arasında ayarlanabilmektedir. Bunun yanında klasik mikrodenetleyicilerden farklı olarak %12.5 - %100 arasında ayarlanabilen bir pencere genişliği vardır.

Pencereli modda, CLRWDT komutu WDT periyodunun izin verilen penceresi içinde gerçekleşmelidir. Aksi durumda, bu pencere aralığı dışında gerçekleşen bir CLRWDT komutu pencere ihlâli durumunu tetikler ve aynı WWDT zaman aşımı resetinde olduğu gibi WWDT reseti gerçekleşmesine neden olur. Bu durum Şekil 4.2’de gösterilmiştir. Kısacası, WWDT resetinin kapatılması için CLRWDT komutunun şekilde gösterilen “Pencere Açık” yazılı süre içinde verilmesi gerekir.

Şekil-4.2 WWDT Resetinin gerçekleşmesi

PORTB <7-4> Değişim Algılama Kesmesi

PIC16F628A'nın B portunun 7,6,5 ve 4'üncü pinlerinin durum değişimini kontrol etmek için kullanılan bir kesmedir. Bu pinlerden herhangi birinde durum değişimi algılanırsa INTCON.RBIF bayrağı 1 olur. Bu kesmeyi kullanmak için;

INTCON.RBIE = 1; kodu yazılmalıdır.

Harici Kesme İle Kontrol Edilen Elektronik Rulet Devresi

Şekil 4.3'teki devrede PIC16F628A ile yapılmış bir yürüyen ışık ve buzer devresi gösterilmiştir. Devrenin 5V düzgün DC ile çalışmasının sağlanması için 9V'luk pil beslemesi 5V'luk regülatör üzerinden yapılmıştır. Devrede 2 adet buton bulunmaktadır. Butonlardan biri devrenin resetlenmesi için diğeri ise INTCON kesme kütüğünün harici kesme izleyicisi INTE bitini kontrol etmek için kullanılan butondur. Böylece mikrodenetleyiciye harici kesme gönderilerek program nerede olursa olsun yarıda kesilerek kesme işlemi için tanımlanmış görevi yerine getirir. Görev tamamlandığında yarıda kesilen programa kaldığı yerden devam edilir.

Şekil-4.3 Harici kesme kontrollü Elektronik Rulet devresi

Dikkat edilirse LED denetleyici portlarına sıralı şekilde bağlanmamıştır. Bunun nedeni baskı devre uygulamasında çakışmaların en aza indirgenmesi ve devre boyutunun olabildiğince küçük bir alana sığmasını sağlamaktır. Şekil 4.4’te devrenin baskı devresi görülmektedir.

Şekil-4.4 Devrenin baskı yolları

Şekilden görüleceği üzere bu haliyle yalnızca iki yerden atlama yapılmıştır. Şekil 4.5’te aynı devrenin 3 boyutlu görüntüsü görülmektedir.

Şekil-4.5 Devrenin üç boyutlu görüntüsü

Tablo 4.2’de ve Tablo 4.3’te devre için yazılmış iki ayrı program kodu örneği gösterilmiştir. Belli bir tarama hızıyla A ve B portunun ilgili pinlerine bağlanmış LED'ler sırayla sürülür ve 6 numaralı RB0/INT harici kesme giriş bitine bağlı buton ile tarama durdurulur. Kesme butonuna basıldığında kesme rutini çalıştırılır. Kesme rutininde program belli bir süre bekletilir, bekleme süresi dolunca tarama işlemi kaldığı yerden devam eder. Programda mikroC’nin Ses (Sound) kütüphanesinden de yararlanılmıştır. Böylece istenilen frekansta ve belli bir süre aralığında ses sinyali uygulanabilmektedir.

Tablo 4.2 Elektronik Rulet devresinde LED'lerin sıralı yanmasını sağlayan mikroC kodu

void Ton1() {
  Sound_Play(1000, 20);   // Frekans = 1000Hz, süre = 20ms
}
void main()
{
  int n=0, a=1, b=0;
  TRISA = 0X00; // PORT A portu çıkış olarak ayarlanıyor
  TRISB = 0X01; /* PORT B portunun RB0 portu hariç diğer tüm portları çıkış yapılıyor*/
  PORTA = 0X01; // PORT A'nın 0'ıncı portuna bağlı LED aktif yapılıyor
  PORTB = 0X00; // Bu arada PORTB çıkışları 0 durumunda
  CMCON = 0x07; // Karşılaştırıcı modülleri dijitale ayarlandı
  OPTION_REG.INTEDG = 1; /* Kesme girişi için yükselen kenar tetiklemesi etkinleştiriliyor */
  INTCON.GIE = 1; // Evrensel kesme aktif yapılıyor
  INTCON.INTE = 1; // Harici kesme INTE etkinleştiriliyor
  Sound_Init(&PORTB,7); /* PORTB'nin 7'inci pinine bağlı transistöre 1kHz'lik sinyal gönderiliyor */
  while(1){  //Sonsuz döngü
  while(a==1)
  {
    Ton1();
    PORTA=0X01<<n; //PORTA'nın pinleri sırayla sola doğru ötelenerek
    n++;           //etkinleştiriliyor
    Delay_ms(1000); /*Her bir LED'nin yanma süre aralığı 1sn olarak ayarlanıyor */
    if(n==4){
     n=0;
     a=0;
     b=1;
    }
  }
  PORTA=0x00; /* PORTA'nın tüm pinleri sırayla aktif olduğunda çıkışları sıfırlanıyor */
  while(b==1){
   Ton1();
   PORTB=0X02<<n;/* PORTB'nin 1'inci pininden itibaren sırayla sola doğru çıkışları */
   n++;          //etkinleştiriliyor
   Delay_ms(1000);
   if(n==6){
    n=0;
    a=1;
    b=0;
   }
  }
  PORTB=0x00; //PORTB'nin de tüm pinleri aktif olduktan sonra sıfırlanıyor
  }
}

void interrupt() //  Kesme rutini
{
 INTCON.INTF=0; /* Kesme bayrağı bir sonraki kesme işlemi için temizleniyor */
 Delay_ms(5000); // Bekleme süresi 5sn olarak ayarlanıyor
}


Programın rastgele çıkışlar üretmesi istendiğinde mikroC’nin Math kütüphanesinin rastgele sayı üreteci kullanılır. Bunun için bir sayı değişkeni (n) ayarlanır. Bu değişkenin değerine göre tohum değeri üreten ‘srand(n)’ fonksiyonu kullanılır. Bu fonksiyonun ürettiği tohum değerini kullanan ‘rand()’ fonksiyonu ile 0 – 32767 arasında rastgele bir sayı üretilir. Bu sayının 10’a göre modu alınırsa devremizde kullanılan 10 çıkış için 10 farklı değer elde edilmiş olur. Bu uygulamanın kodu Tablo 4.3’te gösterilmiştir. Ayrıca bu uygulamada harici kesme butonuna her basıldığında tarama süresi kademeli olarak azaltılmakta ve ses frekansı değiştirilmektedir. Bu işlemin kontrolü kesme rutini içinden yapılmaktadır. Bekleme süresinin tamsayı değişken değeriyle değiştirilmesi için MikcoC’nin ‘VDelay_ms()’ fonksiyonu kullanılmıştır.

Tablo 4.3 Elektronik Rulet devresinde LED'lerin rastgele yanmasını sağlayan mikroC kodu

unsigned int sayac=0, bekleme=500, ses=100, n;
short rast;
void Ton1() {
  Sound_Play(ses, 20);   // Frekans = 1000Hz, süre = 20ms
}
void Bekle(){
    VDelay_ms(bekleme);
}
void main()
{
  TRISA = 0X00;
  TRISB = 0X01; // Yalnızca harici kesme portu giriş yapılıyor
  PORTA = 0X01;
  PORTB = 0X00;
  CMCON = 0x07; // Karşılaştırıcı modülleri dijitale ayarlandı
  OPTION_REG.INTEDG = 1; // Kesme için yükselen kenar tetiklemesi
  INTCON.GIE = 1; // Evrensel kesme etkinleştiriliyor
  INTCON.INTE = 1; // Harici kesme etkinleştiriliyor
  Sound_Init(&PORTB,7);
  while(1){
   n++;
   srand(n);
   rast=rand()%10;
   PORTA=0X00;
   PORTB=0X00;
   switch(rast){
    case 0:PORTA = 0X01; break;    //0 sayısı
    case 1:PORTA = 0X02; break;    //1 sayısı
    case 2:PORTA = 0X04; break;    //2 sayısı
    case 3:PORTA = 0X08; break;    //3 sayısı
    case 4:PORTB = 0x02; break;    //4 sayısı
    case 5:PORTB = 0x04; break;    //5 sayısı
    case 6:PORTB = 0x08; break;    //6 sayısı
    case 7:PORTB = 0x10; break;    //7 sayısı
    case 8:PORTB = 0x20; break;    //8 sayısı
    case 9:PORTB = 0x40;    //9 sayısı
   }
   Ton1();
   Bekle();
  }
}
void interrupt() //  ISR (interrupt service routine) - kesme hizmet rutini
{
sayac++;
if(sayac>=10){
 sayac=0;
 }
switch(sayac){
 case 0: bekleme=500;ses=100;break;
 case 1: bekleme=450;ses=200;break;
 case 2: bekleme=400;ses=300;break;
 case 3: bekleme=350;ses=400;break;
 case 4: bekleme=300;ses=500;break;
 case 5: bekleme=250;ses=600;break;
 case 6: bekleme=225;ses=700;break;
 case 7: bekleme=200;ses=800;break;
 case 8: bekleme=175;ses=900;break;
 case 9: bekleme=150;ses=1000;
 }
 INTCON.INTF=0; // kesme bayrağo temizleniyor
 PORTB.RB7=0;
 Delay_ms(1000);
}


Zaman Ayarlı 4 Kanal Kontrol Devresi

Bu devrede 4 ayrı kanalın tek bir zaman kesmesi üzerinden bağımsız olarak kontrol edilmesi gösterilmiştir. Bu uygulamada Timer0, EXINT ve RB7:4 kesmeleri kullanılmıştır. RB7:4 pinlerinin her birine buton bağlanmıştır. Hangi kanalın butonu aktif olursa o kanala karşılık gelen çıkış hattı aktif yapılmaktadır. Çıkışın aktif olma durumu LED’ler ile izlenmektedir. Butonlar yerine hareket algılayıcısı takılarak kontrol işlemi harekete bağlı olarak yapılabilir. Her çıkış için birbirinden bağımsız zaman değeri tutulmaktadır. Bu işlem için TMR0 kaydedicisi kullanılmaktadır.

Acil durumlar için, örneğin aynı anda tüm ışıkların yanması istendiği zaman harici kesme butonuna basılarak tüm kanallar aktif ya da pasif yapılabilmektedir. Dolayısıyla bu uygulamada mikrodenetleyicinin 3 önemli kesmesi de kullanılmıştır. Şekil 4.6’da PIC16F628A kullanılarak yapılmış bir uygulama devresi görülmektedir.

Şekil-4.6 Zaman ayarlı 4 kanallı kontrol devresi

Tablo 4.4’te yer alan program kodunda yine farklı bir teknik kullanılmıştır. “#define” tanımlamasıyla denetleyicinin portlarına isimler verilmiştir. Böylece program içinde bu isimler çağrılarak işlem yapılmaktadır. Port ve kesme ayarları “ayar()” prosedürü içinde yapılmaktadır. Kontrol edilecek her bir çıkışın ne kadar süreyle aktif kalacağı şu şekilde hesaplanmaktadır:

Öncelikle TMR0 kütüğü için osilatör kaynağı olarak neyin kullanıldığı belirlenir. Varsayılan olarak PIC’e bağlı dâhili osilatör kullanılır ve devremiz için bu 4 MHz’dir. PIC bu frekansın ¼’ünü kullanır. Dolayısıyla,
Mikrodenetleyici komut süresi=1/1.000.000 = 1 usn olarak hesaplanır.

OPTION_REG = 0X03; komutuyla Timer0 için önölçekleyici değeri 16 olarak ayarlanır. Bu Timer0 kesmesinin 16 kat yavaşlatılması anlamına gelir. Timer0’a 156 değeri yüklenir. Böylece başlangıç değeri 156 yapılmış olduğundan 256-156 = 100 saydıktan sonra kesme bayrağı 1 olur. Kısaca 1sn’lik bekleme süresini elde etmek için şu formülü kullanabiliriz:

Denklem 4.1

Burada ‘sayac’ değeri arzu ettiğimiz süreyi bulmak için kullanacağımız bir çarpan değeridir. Bu değer kadar sayan bir sayaç döngüsü yaparsak istenilen süreyi hesaplayabiliriz. 1sn’yi elde etmek için ‘sayac’ değeri 625 olarak hesaplanır. Süre = 100 x 16 x 625/1.000.000 = 1 sn olarak elde edilir. Her bir kat için ‘saniye’ isimli değişkenler vardır. Kaç saniye beklenmesi isteniyorsa ilgili değişkenler o değer kadar artırılır. İstenen değere ulaşıldığında sıfırlanırlar.

Tablo 4.4 Zaman ayarlı 4 kanallı kontrol devresi mikroC kodu

#define buton1 PORTB.RB4   //sabit tanımlamaları yapılıyor
#define buton2 PORTB.RB5
#define buton3 PORTB.RB6
#define buton4 PORTB.RB7
#define lamba1 PORTA.RA0
#define lamba2 PORTA.RA1
#define lamba3 PORTA.RA2
#define lamba4 PORTA.RA3
unsigned int sayac;//evrensel değişkenler rutinler dışında tanımlanıyor
unsigned short saniye1, saniye2, saniye3, saniye4;
//Dört kanal için dört ayrı saniye tutucu ayarlanıyor
void ayar(){
  TRISA = 0X00; // PORT A portu çıkış olarak ayarlanıyor
  TRISB = 0XF1; // RB1-RB3 çıkış, RB0 ve RB4-RB7 giriş yapılıyor
  PORTA = 0X00; // PORT A'nın tüm çıkışları 0 yapılıyor
  OPTION_REG  = 0x03;   /* Ön ölçekleyici (prescaler) 16
                  olarak ayarlanıyor. Dâhili pull-up lar aktif */
  CMCON = 0X07; //Analog çıkışlar kapatılıyor.
  INTCON.GIE = 1; // Evrensel kesme aktif yapılıyor
  INTCON.INTE = 1;  //Harici kesme
  INTCON.RBIE = 1; // B4-B7 portları kesmesi etkinleştiriliyor
  INTCON.T0IE = 1; // Timer0 kesmesi aktifleştirildi
  TMR0 = 156; //Timer0 değeri 156 olarak ayarlanıyor
  sayac = 0;
  saniye1, saniye2, saniye3, saniye4 = 0;
}
void main()
{
  ayar();
  while(1){ //sonsuz döngü
  if(saniye1>=5){  //5 saniyeye ulaşıldımı? Ulaşıldıysa resetleniyor
    lamba1=0;
    saniye1=0;
   }
  if(saniye2>=5){
    lamba2=0;
    saniye2=0;
   }
  if(saniye3>=5){
    lamba3=0;
    saniye3=0;
   }
  if(saniye4>=5){
    lamba4=0;
    saniye4=0;
   }
  }
}
void interrupt()//TMR0 veya RB4-7 kesmesi sonucu gerçekleşecek dallanma
{
 if(INTCON.RBIF){  //RB4-7 kesmesi mi?
 if(!buton1){      //butona basıldığı anda
   lamba1=1;
  }
  if(!buton2){
   lamba2=1;
  }
  if(!buton3){
   lamba3=1;
  }
  if(!buton4){
   lamba4=1;
  }
  INTCON.RBIF=0; //B4-B7 kesme bayrağı temizleniyor
 }
 if(INTCON.INTF){
  PORTA = ~PORTA;  //Harici kesme oluştuğunda çıkışları tersle
  INTCON.INTF=0;  // Harici kesme bayrağı temizleniyor
 }
 if(INTCON.T0IF){ //Timer0 kesmesi mi?
 sayac++;
 if(sayac > 625){  //prescaler sayacı
   if(lamba1){    //kanal1'in saniyesi işletiliyor
    saniye1++;
   }
   if(lamba2){    //kanal2'nin saniyesi işletiliyor
    saniye2++;
   }
   if(lamba3){    //kanal3'ün saniyesi işletiliyor
    saniye3++;
   }
   if(lamba4){    //kanal4'ün saniyesi işletiliyor
    saniye4++;
   }
   sayac=0;
 }
 INTCON.T0IF=0; //TMR0 bayrağı siliniyor ki tekrar kesme gerçekleşebilsin
 TMR0=156;     //TMR0 sayacı değeri tekrar yükleniyor 0 255 arası
 }
}


Uygulamada kontrol işlemi LED’ler ile gösterilmiş olup, çıkışlara transistör ve röle bağlayarak zayıf akımla yüksek akımlı sistemlerin kumandası sağlanabilir (Bkz. Ek C-2).

Harici Timer0 Saat Darbesi Girişiyle (T0CKI) Tetiklenen 7 Segment Göstergeli Saat

Tercih kütüğü olan OPTION_REG kaydedicisinin 5.biti aktif yapıldığında PIC mikrodenetleyicilerinin T0CKI girişi ile harici zaman tetiklemesi sağlanır. Kitapta kullanılan PIC mikrodenetleyicileri için T0CKI girişleri sırasıyla şu şekildedir:

  • PIC12F675 için 5 numaralı GP2 pini
  • PIC12F1840 için 5 numaralı RA2 pini
  • PIC16F628A için 3 numaralı RA4 pini
  • PIC16F887 için 6 numaralı RA4 pini
  • PIC18F2550 İÇİN 6 numaralı RA4 pini (NOT: PIC18F24/25/44/4550 serilerinde T0CKI girişinin etkinleştirilmesi için T0CON kaydedicisi kullanılır.)

Bazı durumlarda mikrodenetleyici için harici zaman kaynağının kullanılması istenir. Örneğin bir trafik sinyalizasyon sisteminde birden fazla mikrodenetleyicinin eşzamanlı olarak aynı frekansta çalışması istendiğinde, mikrodenetleyicilerden birinin OSCOUT hattından elde edilen frekans diğer MCU’lara beslenebilir. Ya da gerçek zaman frekansına dayalı uygulamalarda MCU’nun çekirdek frekansının kullanılması istenmeyebilir. MCU’nun yükünü hafifletmek ve doğru değeri sağlamak için iyi kalibre edilmiş harici saat darbesine ihtiyaç olunabilir.

Bu bölümde 4 adet 7 segment gösterge kullanılarak bir saat devresi tasarlanmıştır. Bunun için çıkışı değil (NOT Gate) olan 7447 BCD-7segment sürücü entegresi ve 4 adet ortak anotlu gösterge kullanılmıştır. Mikrodenetleyici için gerekli saat darbesi RA4/T0CKI pini üzerinden harici olarak uygulanmıştır. Bu uygulamada 555 osilatör entegresi kullanılarak 2Hz frekansında kare dalga üreteci yapılmıştır. Frekansın 2Hz olarak seçilmesinin nedeni, Timer0 için süre hesabının yapıldığı Denklem 4.1’de 1 sn’lik zamanın elde edilmesidir. MCU’ya düşük frekanslı sinyal uygulandığı için 4 çarpan değeri uygulanmaz. Ayrıca düşük frekanslı zaman kesmesi sağlandığı için program içinde “sayac” isimli bir değişken yardımıyla ek bir geciktirmeye gerek olmamıştır. 1sn’lik değerin elde edilmesi için OPTION_REG kaydedicisinde önölçekleyici (prescaler) değeri 1:2 olacak şekilde ayarlanmıştır.

Uygulama devresi Şekil 4.7’de gösterildiği gibidir.

Şekil-4.7 Harici saat darbeli 4 adet 7 segment göstergeli saat devresi

Kare dalga sinyalin çıkışı PROTEUS-ISIS® programının sunduğu dijital osiloskop ile izlenebilir. 555 kare dalga saat darbesi üreteci devresinde yer alan trimpot ile frekans ayarı yapılabilir. Böylece saat devresi için hassas zaman kalibrasyonu elle sağlanabilir. Devrede dakika ve saat değerlerini ayarlamak için RB4:7 portunun sahip olduğu durum değişim kesmesi kullanılmıştır. Böylece saat çalışırken istenildiği anda saat değeri ayarlanabilmektedir.

Bu uygulama elektronik olarak 9 mm’lik 7 segment göstergeler için tasarlanmıştır. Eğer devrenizi uzak mesafeden de görülebilecek şekilde 100 mm’lik göstergelere göre tasarlamak isterseniz Şekil 4.8’de gösterilene benzer bir dönüşüm yapabilirsiniz. 100 mm’lik göstergeler 8-15 V aralığında çalışır ve dolayısıyla daha yüksek bir beslemeye ihtiyaç duyarlar. 5 V ile çalışan MCU devre kartına ikinci bir besleme kaynağı bağlamanız gerekir. Bu yüksek DC kaynağını 5 V’luk beslemeden ayrı olarak göstergelere sürmek için UDN2981 sürücü entegresi kullanılabilir. Örnek dönüşüm, ortak katot sürücüsü olan 7448 ve ortak katot göstergesi kullanılarak yapılmıştır. Ayrıca dikkat edildiği üzere, BC serisi TO-92 kılıflı transistör yerine TO-220 kılıflı daha yüksek akım sürme özelliğine sahip BDX53 transistörü kullanılmıştır.

Şekil-4.8 Yüksek güçlü 7 segment göstergenin sürülmesi

Tablo 4.5 Harici saat darbeli 4 adet 7 segment göstergeli saat devresinin mikroC kodu

#define kodlayici_aktif PORTB.RB0 //7447'yi kontrol eden pin
#define buton1 PORTB.RB4 //saat ayarını yapacak butonlar
#define buton2 PORTB.RB5
#define buton3 PORTB.RB6
#define buton4 PORTB.RB7
#define A PORTA.RA0
#define B PORTA.RA1
#define C PORTA.RA2
#define D PORTA.RA3
#define dakika1_K PORTA.RA6  //dakikanın birler hanesini açan port
#define dakika10_K PORTA.RA7 //dakikanın onlar hanesini açan port
#define saat1_K PORTB.RB1    //saatin birler hanesini açan port
#define saat10_K PORTB.RB2   //saatin onlar hanesini açan port
unsigned short saniye, dakika, saat, dakika1, dakika10, saat1, saat10;

void ayar(){
  TRISA = 0x10; // PORT A portu çıkış olarak ayarlanıyor
  TRISB = 0xF0; /* PORT B portunun RB0-RB3 portları çıkış, RB4-RB7 giriş yapılıyor*/
  PORTA = 0x00; // PORT A'nın tüm çıkışları 0 yapılıyor
  PORTB = 0x00;
  OPTION_REG  = 0b00110000;   /*Ön ölçekleyici (prescaler) 2 olarak ayarlanıyor,
                      harici saat darbesi için T0CKI girişi aktif */
  CMCON = 0X07; //Analog çıkışlar kapatılıyor
  INTCON.GIE = 1; // Evrensel kesme aktif yapılıyor
  INTCON.INTE = 1;  //Harici kesme
  INTCON.RBIE = 1; // B4-B7 portları kesmesi etkinleştiriliyor
  INTCON.T0IE = 1; // Timer0 kesmesi aktifleştirildi
  TMR0 = 255; //Timer0 değeri 255 olarak ayarlanıyor
  saniye, dakika1, dakika10, saat1, saat10 = 0;
}
void main()
{
  ayar();
  while(1){ //sonsuz döngü
   kodlayici_aktif = 1;
   PORTA = dakika1;
   dakika1_K = 1; //dakikanın birler hanesi göstergesi aktif
   dakika10_K = 0;
   saat1_K = 0;
   saat10_K = 0;
   delay_ms(40); //Tarama için gecikme
   
   PORTA = dakika10;
   dakika1_K = 0;
   dakika10_K = 1; //dakikanın onlar hanesi göstergesi aktif
   saat1_K = 0;
   saat10_K = 0;
   delay_ms(40);
   
   PORTA = saat1;
   dakika1_K = 0;
   dakika10_K = 0;
   saat1_K = 1; //saatin birler hanesi göstergesi aktif
   saat10_K = 0;
   delay_ms(40);
   
   PORTA = saat10;
   dakika1_K = 0;
   dakika10_K = 0;
   saat1_K = 0;
   saat10_K = 1; //saatin onlar hanesi göstergesi aktif
   delay_ms(40);
   
   if(saniye>59){
    saniye=0;
    dakika++;
    if(dakika>59){
     dakika = 0;
     saat++;
     if(saat>23){
      saat=0;
     }
    }
   }
   dakika1 = dakika%10; //dakika değerinin modu alınıyor
   dakika10 = (dakika/10)%10;//birler ve onlar haneleri elde ediliyor
   saat1 = saat%10;//saat değerinin modu alınıyor
   saat10 = (saat/10)%10; //birler ve onlar haneleri elde ediliyor
  }
}
void interrupt()/* TMR0 veya RB4-7 kesmesi sonucu 
                    gerçekleşecek dallanma rutini */
{
 if(INTCON.RBIF){  //RB4-7 kesmesi mi?
  if(!buton1){ //butona basıldığı anda dakika değerini azalt
   if(dakika>0) dakika--;
   else if (dakika==0) dakika=59;
  }
  if(!buton2){ //butona basıldığı anda dakika değerini arttır
   if(dakika<59) dakika++;
   else if(dakika==59) dakika=0;
  }
  if(!buton3){ //butona basıldığı anda saat değerini azalt
   if(saat>0) saat--;
   else if(saat==0) saat=23;
  }
  if(!buton4){ //butona basıldığı anda saat değerini arttır
   if(saat<23) saat++;
   else if(saat==23) saat=0;
  }
  INTCON.RBIF=0; //B4-B7 kesme bayrağı temizleniyor
 }
 if(INTCON.T0IF){ //Timer0 kesmesi mi?
  saniye++;
  INTCON.T0IF=0; //TMR0 bayrağı siliniyor ki tekrar kesme gerçekleşebilsin
  TMR0=255; //TMR0 sayacı değeri tekrar yükleniyor 0 255 arası
 }
}


Timer0 Kesmesiyle Servo Motor Kumandası

Mikrodenetleyiciler ile motor kumandasının anlatıldığı 3. Bölümde “Servo Motor Kumandası” başlığı altında servo motorun kumandasının nasıl yapıldığı anlatılmıştı. Bu kısımda Timer0 kesmesi kullanılarak daha kararlı çalışan bir uygulama gösterilmiştir. Uygulamada harici kesme girişine bağlı bir buton yardımıyla, butona her basışta servo motor sırasıyla CCW (Counter-Clock Wise) ve CW (Clock Wise) yönlerinde döndürülmektedir. Şekil 4.9’da örnek uygulama devresi gösterilmiştir.

Şekil-4.9 Servo motorun Timer0 kaydedicisi ile kontrol edilmesi

Tablo 4.6 Servo motorun Timer0 kaydedicisi ile kontrolünü sağlayan mikroC kodu

sbit BASLA at RB0_bit;
sbit Control at RB1_bit;
unsigned short i=7, delay, start;
void ayar(){
 CMCON = 0x07;// Karşılaştırıcılar kapatılıyor
 TRISA = 0X00;
 PORTA = 0;
 TRISB = 0X01;
 PORTB = 0;
 OPTION_REG = 0x07;// Ön ölçekleyici TMR0'a ve 256 değerine ayarlanıyor
 TMR0 = 178;  /* T0 zamanlayıcısı 180'den 255'e sayacak şekilde */
 INTCON = 0xB0; /* TMR0, INTE ve Evrensel kesme aktif ediliyor. */
}
void main() {
 ayar();
}
void interrupt() {
 if(INTCON.INTF){
  start=~start;
  INTCON.INTF=0;
 }
 if(INTCON.T0IF){
  if(start && BASLA){
   i=24;
   delay = i*10;
   Control = 1;
   Delay_Cyc(delay);/* 10*delay değerine eşit uzunlukta
               saat çevrimi üretir */
   Control = 0;
   Delay_Cyc(100);
  }
  if(!start && BASLA){
   i=7;
   delay = i*10;
   Control = 1;
   Delay_Cyc(delay);
   Control = 0;
   Delay_Cyc(100);
  }
  TMR0 = 178;  // TMR0 ilk değerine döndürülüyor
  INTCON.T0IF = 0; /* T0 bayrağı temizleniyor,
          böylece yeni kesme algılanabilir */
 }
}


Yazılan kodun ilgili devrede çalıştırılması için dâhili OSC 4 MHz olarak ayarlanır. Bunun için mikroC program menüsünde Project --> Edit Project penceresinden INTOSC değeri seçilir ve mikrodenetleyicinin program belleğinin 2007h adresinde yer alan konfigürasyon sözcüğü (CONFIG) 2178h değerine ayarlanır. Böylece OSC saat darbesi çıkış (Clock Out) hattı RA6 pini ve OSC saat darbesi giriş (Clock In) hattı RA7 pini normal I/O portu olarak ayarlanmış olur (Ayrıntılı bilgi için bkz. Ek-D3).

DİKKAT: PROTEUS-ISIS® ortamı ile gerçek uygulama ortamında OSC frekansları farklı çalışabilir. Ayrıca ayarladığınız konfigürasyon seçenekleri simülasyon ortamında gerçeklenmeyebilir. Simülasyon programında osilatör bağlamasanız ve OSC tercihi yapmasanız bile MCU “Edit Properties” üzerinden yaptığınız çalışma frekansını kabul eder. Dolayısıyla simülasyon ortamında yapılan zaman temelli uygulamalarda gerçek sonuç alınamaz. Zaman temelli uygulamalarınızı gerçek hayatta çalıştırmak istediğinizde bu durumu göz önünde bulundurmanız tavsiye edilir.

Program kodunda “Delay_Cyc(x)” isimli mikroC fonksiyonu kullanılmıştır. Bu fonksiyonun içine yazılan “x” değeri 3-255 arasında olmalıdır. Fonksiyonun içine yazılan değer 10 ile çarpılır ve MCU’nun çevrim hızının bu değer kadar katı alınarak bekleme elde edilir.

Örnekte dâhili OSC 4 MHz olarak ayarlandığından bir çevrim hızı 1 MHz (1 us)’dir. Bu uygulamada temel ilke, servo motoru kontrol etmek için kullanılan 20 msn’lik bekleme süresinin yaklaşık olarak elde edilmesidir. Timer0 kaydedicisi kullanılarak 20 msn’lik bekleme şu şekilde hesaplanır:

Zaman = (256 – T0) * prescaler * 4 /FOSC

Burada T0 değeri kurma değeridir ve bu uygulama için 178 olarak hesaplanmıştır. Önölçekleyici (prescaler) değeri OPTION_REG kaydedicisi yardımıyla 256 olarak ayarlanmıştır. Böylece,

Zaman = (256 – 178) * 256 * 1*10-6 = 19.968x10-6s = 19,968 ms olarak yaklaşık 20 ms hesaplanır.

Bundan sonra yapılması gereken servo motoru CW ve CCW yönlerinde döndürmeyi sağlayacak darbe genişliklerinin elde edilmesidir. Gerçek uygulamada kullanılan RS tip servo motor için CW değeri 2,4 ms, CCW değeri 0,7 ms olarak tespit edilmiştir. Bu nedenle program için ‘i’ ve ‘delay’ isimli değişkenlerle bu değerler ayarlanmaktadır. Timer0 zaman kesmesi “interrupt()” rutini ile izlenmektedir. Zaman kesmesi gerçekleştiğinde motorun döneceği yöne göre ‘i’ değişkeni 24 ya da 7 değerini almaktadır. Ardından bu değer 10 ile çarpılmakta ve “delay” değeri elde edilmektedir. Delay_Cyc fonksiyonuyla, elde edilen bu değerin 10 katı alınır. Sonuç olarak 2400 çevrimlik (cycle) ya da 700 çevrimlik darbe genişlikleri elde edilir. MCU’nun bir çevrimi 1us olduğundan 2,4 ms ya da 0,7 ms değerleri elde edilir.

Harici kesme girişine bağlı butona basıldığında kesme rutini içinde harici kesme bayrağı kontrol edilir ve ‘start’ isimli değişkenin değeri terslenir. Böylece, servo motor tek butonla CW ve CCW yönlerinde hareket ettirilir.

Timer0 Kesmesiyle PWM Üretimi ve AC Yük Kumandası

Daha önce de kısaca bahsedilen Pulse Width Modulation kelimelerinin kısaltması olan PWM bir çeşit darbe modülasyonudur. Mikrodenetleyicili sistemlerde 5V’luk DC genliğin belli bir frekansta lojik-1 ve lojik-0 seviyelerinde değiştirilmesiyle elde edilir. Lojik-1 seviyesinin bir periyotluk sinyale oranı “duty cycle” olarak adlandırılır ve % oranıyla ifade edilir. Mikrodenetleyicilerde yaygın olarak bu yüzdelik oranı elde etmemizi sağlayan 8 bitlik bir kaydedici vardır ve 0-255 aralığında değeri değiştirilerek %0 - %100 arasında istenilen bir görev çevrimi elde edilir. Şekil 4.10’da farklı “duty cycle-görev çevrimi” oranları için kaydedicinin aldığı değerler gösterilmiştir.

Şekil-4.10 Farklı oranlarda PWM sinyalleri

AC Motor, solenoid yüklü AC aydınlatma elemanları ya da diğer solenoid yüklerin (DC motor, vb.) devirli kotrolü endüstriyel uygulamalarda sıkça karşılaşılan bir durumdur. Bu tür yüklerin mikrodenetleyiciler tarafından kumandasında çeşitli yazılımsal ve elektronik uygulama teknikleri mevcuttur. Bu uygulamada örnek olarak, 220V ACrms/50Hz şehir şebekesinde çalışan solenoid yüklü bir AC aydınlatma sisteminin Timer0 ile üretilen PWM tekniğiyle devirli kumandası gerçekleştirilmiştir. Bunun için BT012 triyak, MOC3021 optokuplör ile MCU üzerinden sürülmüştür.

DİKKAT: AC yüklerin MCU’lar ile kumandasında karşılaşılacak riskler ve devre şemasının kurulumunda dikkat edilmesi gerekenler ile ilgili olarak Ek C-2 (Mikrodenetleyicilerde Anahtarlama Elemanlarının Kullanımı) başlığını mutlaka incelemeniz tavsiye edilir. Uygulama AC şebekenin trafo kullanılmadan doğrudan direnç ve köprü diyot grubu üzerinden çalıştırılmasını içermektedir. Dolayısıyla çalışma sırasında çok dikkatli olunmalıdır. Kullanıcı kaynaklı zararlar karşısında sorumluluk kullanıcıya aittir.

Şekil-4.11 Timer0 kesmesiyle PWM üretimi ve AC yük kumandası

AC yüklerin mikrodenetleyiciler ile kontrolünde sinüsoydal şebeke frekansından dolayı senkronizasyon işlemi yapılması gerekir. Şekil 4.11’deki uygulama devresine dikkat edileceği üzere iki adet optokuplör kullanılmıştır. MOC3021 optik triyaklı tetikleme bileşenidir ve triyak gibi AC yük sürme elemanlarını dijital devreler (MCU, vb.) üzerinden tetiklemek için kullanılır. 4N25 ise transistör çıkışlı optokuplördür ve dijital sistemleri tetiklemek için kullanılır.

Senkronize AC yük kontrolünde “zero crossing – sıfır kesimi” denilen bir teknikten yararlanılır. Bilindiği üzere triyaklar “gate” ayaklarından tetiklendiklerinde AC gerilimin bir sonraki sıfıra gidişine kadar iletimde kalır. Yeniden iletime sokulması için kesime gittikten sonra tekrar tetiklenmesi gerekir. Selenoid yüklü AC lambalarda titreşim (flickering) olayının oluşmaması için mikrodenetleyicinin AC sinyalin sıfır noktalarını referans alarak tetikleme işlemini yapması gerekir. Bunun için AC şebeke gerilimi dirençler üzerinden düşürülmüş ve 1N4007 diyot grubuyla yapılmış bir köprü doğrultma devresine uygulanmıştır. Doğrultulan gerilim 4N25 optokuplöre uygulanır ve optokuplör çıkışı PIC16F628A’nın harici kesme girişi RB0/INT pinine yükselen kenar tetiklemesi modunda verilir.

Sonuçta Şekil 4.12’deki gibi bir kontrol diyagramı elde edilmiştir.

Şekil-4.12 0o ve 180o'lerde zero crossing darbesi

Yazılımsal olarak harici kesmenin oluştuğu anlar kontrol edilir. Triyakın ne kadar süre sonra tetiklenmesi Timer0 kesmesiyle elde edilen zaman diyagramına bağlı olarak gerçekleştirilir. Bunun için tetiklemesi yapılacak AC şebekenin frekansının ve buna bağlı periyodunun da hesaba katılması gerekir. 50 Hz şehir şebekesinin tam bir periyodu = 1/50 = 20 ms’dir. Tam dalga doğrultma yapılmış olup her bir alternansın periyodu 10ms kadardır. Yazılımsal olarak öncelikle PWM skalası 0-100 aralığında olacak şekilde belirlenmiştir. Ardından 0.1 msn’lik zaman kesmesi periyodunda PWM genişliğinin 0-100 aralığında artırılıp azaltılmasıyla 0-10 ms arasında değişen genişlikte bir tetikleme sinyali elde edilmiş olur. Skalayı genişletmek suretiyle daha yüksek çözünürlükte bir PWM aralığı elde etmeniz mümkündür. Ancak bu durumda Timer0 kesmesinin kesme periyodunu yeniden ayarlamanız gerekir.

Dikkat edileceği üzere bu uygulamada PWM darbesi, triyakın iletime geçirilmek istenen süre sonrasında üretilmektedir. Gerçekte istenen süre sonrası PWM darbesi üretildiğinde artık darbenin birsonraki zero-crossing noktasına kadar lojik-1 seviyesinde tutulmasına gerek yoktur. Ancak bu şekilde yapılmasının sebebi aynı anda LED üzerinden de PWM durumunu görebilmektir. Ayrıca üretilen PWM darbesinin kesilmesi için tam 10 msn’lik sürenin tamamlanması beklenmemektedir. %10’luk bir koruma payı bırakılarak triyakın kontrolümüz dışında iletime girmesi engellenmektedir.

Tablo 4.7 Timer0 kesmesiyle PWM üretimi ve AC yük kumandası devresi mikroC kodu

#define kontrol PORTA.RA0
#define AC_PWM PORTB.RB3
#define duty_artir PORTB.RB6
#define duty_azalt PORTB.RB7
unsigned short current_duty, sayac, saniye, i, kesme;
unsigned int buton_sure;
void main() {
  CMCON = 0X07;  //Karşılaştırıcılar kapatılıyor.
  OPTION_REG = 0B01000000;/*ön ölçekleyici 1:2,
                  dâhili pull-up'lar etkin*/
  TRISA = 0;
  TRISB = 0X0F1;
  PORTA = 0;
  PORTB = 0;
  INTCON.GIE=1;
  INTCON.INTE=1;
  INTCON.TMR0IE=1;
  INTCON.RBIE=1;
  TMR0=206;
  Delay_ms(10);
  for(i=0;i<5;i++){ // MCU çalışıyor mu?
   kontrol = ~kontrol; //kontrolünü sağlayan kısım
   delay_ms(100);
  }
  kontrol=0;
  current_duty=0;
  while(1){
   if(duty_artir && duty_azalt) buton_sure=0;
   if(!duty_artir){
    if(buton_sure>100 && current_duty<100){
     current_duty++;
     buton_sure=0;
    }
   }
   if(!duty_azalt){
    if(buton_sure>100 && current_duty>0){
     current_duty--;
     buton_sure=0;
    }
   }
  }
}
void interrupt(){
 if(INTCON.INTF){
   AC_PWM = 0;
   sayac = 0;
   kesme = 1; /*harici kesmenin oluştuğu
       timer0 kesmesine bildiriliyor */
   INTCON.INTF=0;
 }
 if(INTCON.TMR0IF){ //(256-206)*2/1.000.000 = 0.1msn elde ediliyor
  sayac++;
  buton_sure++;
  if(sayac<(100-current_duty)) AC_PWM=0;
  if(sayac>=(100-current_duty) && kesme) AC_PWM=1; 
  if(sayac>=90){ //%10'luk bir pay bırakılmak suretiyle
   kesme=0;  //triyakın tam olarak kesime gitmesi
  }        //ve flickering olayının engellenmesi sağlanıyor.
  TMR0=206;
  INTCON.TMR0IF=0;
 }
 if(INTCON.RBIF){
  if(!duty_artir){
   if(current_duty<100) current_duty++;
  }
  if(!duty_azalt){
   if(current_duty>0) current_duty--;
  }
  INTCON.RBIF=0;
 }
}

Bu uygulamada görüldüğü üzere AC sinyalin kesim noktalarının tespit edilebilmesi için harici olarak iki farklı optokuplör kullanılması gerekmiştir. Yeni nesil PIC16(L)F18424-44 ve PIC18F24-25Q10 8-bitlik mikrodenetleyicilerde bu özelliğe dâhili olarak yer verilmiştir (DS40002000A veri kılavuzu sayfa 395 ve DS40001945B veri kılavuzu sayfa 374).

Para Okuyucu Kullanarak Otomat Tasarımı

Bu uygulamada, piyasada çeşitli tiplerde bozuk paralarla çalışan otomatların kontrol devresinin nasıl tasarlandığı gösterilecektir. Piyasada MCU kullanılarak tasarlanan bu cihazların pek çoğunda 8 bacaklı PIC12F675 giriş seviyesi mikrodenetleyicisi kullanılmaktadır. Bu MCU’da aktif olarak kullanılabilen 6 I/O hattı bulunmaktadır. A, B, C, vb. isimlendirmelerle gösterilecek sayıda portu olmadığından portların kumandası için kullanılan kaydedicileri de diğer MCU’lardan farklı olarak isimlendirilmiştir. Portun I/O hatlarının giriş/çıkış kontrolü TRISIO kaydedicisiyle, porta bilgi gönderilmesi ise GPIO kaydedicisiyle yapılmaktadır.

Şekil 4.13’te PIC12F675 kullanılarak tasarlanmış bir OTOMAT cihazı kumanda devresi gösterilmiştir. Para okuyucuya bozuk para atıldığında sistem çalışmaya başlar. Haznenin içinde yer alan topları düşürmeyi sağlayan mekanizma, DC motor sürücü devresiyle kumanda edilen motor ile çalıştırılır. Bu sırada bir adet top QRD1114 optik sensörünün yer aldığı hazneye düşer ve motor durdurulur. Para okuyucunun sinyal çıkış hattı 7400 VEDEĞİL entegresinin kapı girişlerinden birine bağlanır. Devrede bu durum SWITCH elemanıyla gösterilmiştir. PROTEUS-ISIS® programında durumu canlandırmak için QRD1114 sensörünün 220 Ω direnç hattına anahtar bağlanmıştır. Gerçek uygulamada 220 Ω direnç doğrudan 5 V besleme hattına bağlanacaktır.

Uygulama programında Timer0 kaydedicisi ile zaman sayacı da bulunmaktadır. Haznede top bitmiş olması durumunda motorun boş yere dönmemesi için yaklaşık 10sn’lik bir zaman beklemesi yapılmıştır. Süre dolunca motor durdurulmaktadır. Ayrıca, sensörün bulunduğu alanda top olması durumunda da motor yeniden çalıştırılmamaktadır. Bir diğer ifadeyle eğer daha önceden herhangi bir sebepten dolayı sensörün algılama yapmasına neden olan bir cisim varsa sistem çalışmaz. Tablo 4.8’de uygulama programı gösterilmiştir.

Şekil-4.13 Para okuyuculu OTOMAT cihazı kumanda devresi

PIC12F675 mikrodenetleyicisinde tüm port hatlarının “Interrupt-On-Change” özelliği bulunmaktadır. Bu özellik yardımıyla girişlerde oluşan değişim durumu algılanabilmektedir. Bu durum PIC16F628A’nın RB4:7 kesmesine benzemektedir. Topun algılanması durumu bu değişim algılama kesmesiyle denetlenmektedir. Bu işlemin aktif olabilmesi için IOC isimli kaydedicinin ilgili port hattının lojik-1 yapılması gerekir. Para okuyucuya para atılması durumu ise harici kesme girişi özelliğine sahip olan GP2 piniyle izlenmektedir. Bu MCU analog/dijital dönüştürme özelliğine sahip olduğundan program içinde ANSEL kaydedicisi ile analog modülünün kapatılması ve giriş/çıkışların dijital I/O olarak ayarlanması gerekir. Analog işlemlerle ilgili ayrıntılı bilgi için 7.bölüme bakınız.

Para okuyucu donanımı internet üzerinden satın alabileceğiniz bir donanımdır (Bkz. Şekil 4.14). Farklı modelleri mevcuttur ve genellikle 12 V besleme altında çalışırlar. Para haznesinden içindeki örnek paraya eş para atıldığında kısa süreli kısa devre durumu oluşturanlar olduğu gibi voltaj çıkışı veren modelleri de vardır. Örnek uygulamada algılama sırasında çıkışı kısa devre olan bir model kullanılmıştır.

Şekil-4.14 Örnek bir bozuk para algılayıcısı

Tablo 4.8 Para okuyuculu OTOMAT cihazı kumanda devresi için mikroC kodu

sbit para at GP2_bit;
sbit top at GP4_bit;
sbit motor at GP0_bit;
unsigned short aktif, saniye, sayac;

void kur(){
 TRISIO = 0X14; // Port G2 ve G4 giriş
 GPIO = 0X00;
 INTCON.GIE=1;   // Evrensel kesme aktif
 INTCON.INTE=1;  // Harici kesme aktif
 INTCON.GPIE=1;  // Port değişim kesmesi aktif
 INTCON.T0IE=1;  //Timer kesmesi aktif
 TMR0=125; // Timer0 için başlangıç değeri
 IOC = 0B00010000; /* Interrupt-On-Change GP4 pini için aktif */
 CMCON = 0X07; // Karşılaştırıcılar kapatıldı
 ADCON0 = 0X00; // Analog modülü kapatıldı
 ANSEL = 0X00; // Analog girişler dijital I/O olarak ayarlandı
 OPTION_REG = 0B01000111; /* Dâhili pull-up aktif, yükselen kenar
 tetiklemesi, Prescaler 1:256 Timer0 */
 WPU = 0B00010100; // Bireysel GP4 ve GP2 için weak pull-up aktif
 aktif, saniye, sayac=0;
}
void bitti(){ // motorun durdurulması sonrası yapılacak işlemler
 GPIO = 0X00;
 saniye=0;
 aktif =0;
}
void devam(){
  if(saniye<=10){
   motor=1;
  }
  if(saniye>10){
   bitti();
  }
}
void main(){
 kur(); // Başlangıç ayarları yükleniyor
 while(1){
  if(aktif){
   devam();
  }
  if(!aktif){/*Motor durduruluyor,
              denetleyici uyku moduna alınıyor*/
   GPIO = 0X00; 
    asm{
     sleep
    }
  }
 }
}
void interrupt(){
 if(INTCON.INTF){//Harici kesmenin izlendiği bölüm
  if(!top){
   sayac=0;
   aktif=1;//aktif değişkeni 1 ise motora sinyal uygulanıyor
  }
   INTCON.INTF=0;
 }
 if(INTCON.GPIF){//Port değişim kesmesinin izlendiği bölüm
  if(top){
   aktif=0;
  }
  INTCON.GPIF=0;
 }
 if(INTCON.T0IF){//Timer0 kesmesinin izlendiği bölüm
   sayac++;
   if(sayac>32){
    saniye++;
    sayac=0;
   }
   INTCON.T0IF=0;
   TMR0=125;
 }
}


Bu uygulamayla birlikte ilk kez görülen bazı kaydediciler bulunmaktadır. Bu bölüm kapsamına giren kaydediciler şunlardır:

  • GPIO: Genel amaçlı (General Purpose) giriş/çıkış (I/O) kaydedicisi
  • TRISIO: Yüksek empedanslı Tri-State kontrol kaydedicisi
  • WPU: Zayıf çekme dirençleri (Weak Pull-Up) kaydedicisi
  • IOC: Port değişim kesmesi (interrupt-on-change) GPIO kaydedicisi

GPIO KAYDEDİCİSİ (ADRES: 05h) – Genel amaçlı giriş/çıkış port kaydedicisidir. Bu kaydedici 6 bit genişliğinde, çift yönlü bir porttur. Portların giriş ya da çıkış olması TRISIO kaydedicisi ile belirlenir. İlgili TRISIO biti lojik-1 yapıldığında karşılık gelen pin giriş, lojik-0 yapıldığında çıkış olur. GP3 pini yalnızca giriş olarak kullanılabilir. Bu nedenle GP3 pininin TRISIO biti her zaman ‘1’ olarak okunur. Portlara veri yazılması karşılık gelen portun tutma belleğine (LATCH) yazma işlemi gerçekleşmesi demektir. Dolayısıyla porta veri yazılması işlemi aynı zamanda bir okuma işlemidir. Master Clear hattının da olduğu GP3 pininde MCLREN = 1 olduğunda lojik-0 değeri okunur. Proje editörü penceresinde (Edit Project) “GP3/MCLR pin function select” tercihi “Enabled” yapılırsa GP3 pini reset olarak kullanılmış olur.

TRISIO KAYDEDİCİSİ (ADRES: 85h) – Giriş/çıkış portlarının yönünü belirlemekte kullanılan kaydedicidir. Dijital elektronikte Tri-State deyiminden gelmektedir. Bir giriş/çıkış hattını yüksek empedans durumuna sokma kabiliyeti olan lojik sistemler için kullanılan bir deyimdir. TRISIO ile giriş yapılan bir portun devrenin diğer katlarına etkisi yüksek empedans durumu sayesinde azaltılır.

WPU KAYDEDİCİSİ (ADRES: 95h) – Weak Pull-Up kaydedicisidir. Bireysel olarak GP3 pini hariç diğer pinler için dâhili pull-up’lar etkinleştirilebilir ya da pasifleştirilebilir. OPTION kaydedicisindeki pull-up etkinleştirme bitinden farklı olarak, bu kaydedici ile her bir port tek tek kontrol edilebilir. Bu kaydediciyi kullanabilmek için OPTION kaydedicisindeki (GPPU) ̅ bitinin etkinleştirilmesi gerekir. Kaydedicideki ilgili bit lojik-1 yapıldığında pull-up etkin, lojik-0 yapıldığında pull-up pasif olur. Eğer bir pin TRISIO kaydedicisi ile çıkış olarak ayarlanmışsa (lojik-0), pull-up’lar otomatik olarak pasifleştirilir.

IOC KAYDEDİCİSİ (ADRES: 96h) – Interrupt-On-Change kaydedicisidir. Portun pinlerindeki durum değişimlerini algılamayı sağlayan bir kesme kaydedicisidir. PIC12F675 için tüm portların durum değişim kesmesi vardır. Bağımsız olarak her bir pin için IOC kesmesinin etkinleştirilmesi için öncelikle INTCON kaydedicisindeki GPIE bitinin kurulması (set edilmesi) gerekir. IOC kesmesi aktif edildiğinde portun bir önceki kaydedilen değeri güncel olanla karşılaştırılır. Fark varsa (mismatch) INTCON kaydedicisindeki GPIF bayrağı lojik-1 olur. İlgili GPIO pininden okuma yapıldığında ya da ilgili pine bilgi yazıldığında, eşleşmeme durumu ortadan kalkar ve GPIF bayrağı temizlenir. Ancak her ihtimale karşın, kesme oluştuktan sonra yazılım içinde bayrak bitinin temizlenmesinde fayda vardır. Bu kesme de harici kesme gibi cihazı uyku modundan çıkartma özelliğine sahiptir.

DİKKAT: İlgili I/O pininden okuma sırasında (OSC frekansının Q2 çevriminde. Bkz. 1.3.2) bir değişim meydana gelirse, GPIF bayrağı set olmayabilir.