Önceki yazımızın başlığını giriş çıkış işlemleri olarak koymuştuk ama açıkça görülebildiği üzere, yalnızca çıkış işlemleri üzerinde durduk 🙂 Bu yazıda, vadedileni tamamlayarak PIC mikrokontrolörlerinde giriş işlemlerini nasıl yaparız ona değineceğiz.
PIC programlama yazı dizisinin asıl amaç seti, gömülü sistemlerin programlanması hususunda temel oluşturup, sürecin iç dinamiklerini de anlatmak olduğundan yine bir kütüphane kullanmadan devam edeceğiz. Giriş işlemleri üzerinden gidebilmemiz için, mikrokontrolörün pinlerine bağlayacağımız elemanların, pinde oluşturacağı gerilimsel seviyeyi okumamız gerekir. Buna göre buton ve switch uygulamaları, mevzuyu anlatmakta kullanılabilecek iki güzel ve basit eleman oluyor. Butona daha sonra da değineceğiz. Şimdi mevzuyu anlatmak için switch üzerinden gidelim. Butonun basit kullanımı switch’den çok farklı değil ama bouncing gibi problemlere de önlem alacağımız için butonu timer’dan sonra anlatacağız. Neyse 🙂
Öncelikle daha kolay olandan başlayalım. Switch yani anahtar elemanının kullanımına değinelim. Anahtar’ın adı üzerinde, elektriksel akımı açıp kapatabilen devre elemanı. Buna göre, iki durumlu bir anahtar için; anahtar bir konumdayken açık devre, diğer konumdayken kısa devre davranışı gösterecektir.
Wikipedia sayfasında daha fazla bilgi bulabilir, çeşitli switch’lerin fotoğraflarını da görebilirsiniz.
Şimdi gelelim bu anahtarın PIC16 ile kullanılmasına. Çok basit bir uygulama olacak olsa da, anahtar ile PIC’i aracı yaparak LED sürelim. LED’i normal şartlar altında PIC’siz de sürebiliriz ama mevzunun basit yoldan anlaşılması için böyle anlamsız bir uygulama üzerinden gitmek mantıklı olacak diye düşünüyorum. Bir sarı ve bir kırmızı olmak üzere iki LED, bir anahtar ve bir de PIC olan bir devre düşünelim (Direnc, kondansatör gibi elemanları saymıyorum). Birazcık da olsa farklılık yaratmak için anahtar bir konumda iken sarı LED’i yakıp kırmızı LED’i söndüreceğiz. Diğer durumda ise kırmızı ledi yakıp sarı ledi söndüreceğiz. Tabi bu basit işi yaparken bile, kodu ibretlik şekilde yazacağız. Haydi işe koyulalım 🙂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
/* * File: main.c * Author: ozenozkaya * * Created on 02 Haziran 2015 Sali, 12:47 */ #define F_OSC (1000000UL) #define REG_TRISB_ADDR (0x86) #define REG_TRISB (*( volatile unsigned char*)REG_TRISB_ADDR) #define TRIS_PIN_OUTPUT (0) #define TRIS_PIN_INPUT (1) #define TRIS_PORT_OUTPUT (0) #define TRIS_PORT_INPUT (0xFF) #define REG_PORTB_ADDR (0x06) #define REG_PORTB (*( volatile unsigned char*)REG_PORTB_ADDR) #define PORT_PIN_LOW (0) #define PORT_PIN_HIGH (1) #define PORT_ALL_LOW (0) #define PORT_ALL_HIGH (0xFF) typedef struct { //one bit is stored in one BYTE unsigned char pin0:1; unsigned char pin1:1; unsigned char pin2:1; unsigned char pin3:1; unsigned char pin4:1; unsigned char pin5:1; unsigned char pin6:1; unsigned char pin7:1; }tris_port_pin_t; typedef union { tris_port_pin_t pins; volatile unsigned char port; }tris_port_t,*tris_port_ptr_t; void main() { tris_port_t *portb_ptr=(tris_port_ptr_t)REG_PORTB_ADDR; tris_port_t *trisb_ptr=(tris_port_ptr_t)REG_TRISB_ADDR; trisb_ptr->port = TRIS_PORT_INPUT; trisb_ptr->pins.pin1 = TRIS_PIN_OUTPUT; trisb_ptr->pins.pin2 = TRIS_PIN_OUTPUT; portb_ptr->port = PORT_ALL_LOW; while(1) { switch(portb_ptr->pins.pin0) { case PORT_PIN_LOW: portb_ptr->pins.pin1 = PORT_PIN_HIGH; portb_ptr->pins.pin2 = PORT_PIN_LOW; break; case PORT_PIN_HIGH: portb_ptr->pins.pin1 = PORT_PIN_LOW; portb_ptr->pins.pin2 = PORT_PIN_HIGH; break; default: break; } } } |
Kodu açıklamadan önce, bir define hinliği ile, daha şeker hale getirelim diyorum. Misal aşağıdaki gibi yapsak, kodun yaptığı iş daha iyi anlaşılacak sanki.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
/* * File: main.c * Author: ozenozkaya * * Created on 02 Haziran 2015 Sali, 12:47 */ #define F_OSC (1000000UL) #define REG_TRISB_ADDR (0x86) #define REG_TRISB (*( volatile unsigned char*)REG_TRISB_ADDR) #define TRIS_PIN_OUTPUT (0) #define TRIS_PIN_INPUT (1) #define TRIS_PORT_OUTPUT (0) #define TRIS_PORT_INPUT (0xFF) #define REG_PORTB_ADDR (0x06) #define REG_PORTB (*( volatile unsigned char*)REG_PORTB_ADDR) #define PORT_PIN_LOW (0) #define PORT_PIN_HIGH (1) #define PORT_ALL_LOW (0) #define PORT_ALL_HIGH (0xFF) #define SWITCH_PIN pins.pin0 #define RED_LED_PIN pins.pin1 #define YELLOW_LED_PIN pins.pin2 #define LED_ON (PORT_PIN_HIGH) #define LED_OFF (PORT_PIN_LOW) typedef struct { //one bit is stored in one BYTE unsigned char pin0:1; unsigned char pin1:1; unsigned char pin2:1; unsigned char pin3:1; unsigned char pin4:1; unsigned char pin5:1; unsigned char pin6:1; unsigned char pin7:1; }tris_port_pin_t; typedef union { tris_port_pin_t pins; volatile unsigned char port; }tris_port_t,*tris_port_ptr_t; void main() { tris_port_t *portb_ptr=(tris_port_ptr_t)REG_PORTB_ADDR; tris_port_t *trisb_ptr=(tris_port_ptr_t)REG_TRISB_ADDR; trisb_ptr->port = TRIS_PORT_INPUT; trisb_ptr->SWITCH_PIN = TRIS_PIN_INPUT; trisb_ptr->RED_LED_PIN = TRIS_PIN_OUTPUT; trisb_ptr->YELLOW_LED_PIN = TRIS_PIN_OUTPUT; portb_ptr->port = PORT_ALL_LOW; while(1) { switch(portb_ptr->SWITCH_PIN) { case PORT_PIN_LOW: portb_ptr->RED_LED_PIN = LED_ON; portb_ptr->YELLOW_LED_PIN = LED_OFF; break; case PORT_PIN_HIGH: portb_ptr->RED_LED_PIN = LED_OFF; portb_ptr->YELLOW_LED_PIN = LED_ON; break; default: break; } } } |
Tabi kodu yazdık öyle ama kısa bir açıklama da yapacağız. Ayrıca birinci kod ile ikincisi arasındaki farkları da ele almakta fayda var. Ancak bundan önce kodun Proteus ISIS ortamındaki çıktılarını bir paylaşalım.
Gördüğünüz gibi kodumuz çiçek gibi çalışıyor. Şimdi gelelim kod hakkında konuşma faslına. Malumunuz bu kod çok farklı şekillerde yazılabilirdi ama yine özgün bir iş yapalım istedik. Bu sebeple gittik her bir pini struct bitfield olarak tanımladık. Bu sayede port üzerindeki her pine tek tek, bir değişken üzerinden erişmek mümkün oldu. Tanımladığımız union ile, registerlara hem pin bazlı (tek tek) hem de port bazlı (topluca) erişim imkanı sağladık. Bu işin ekmeğini de kodu yazarken yedik; kodumuz hem çok anlaşılır hem de çok genişletilebilir oldu.
İkinci kodda yaptığımız trick ise, kodun okunurluğunu çok artırdı. Switch ve ledlerin hangi pinlere bağlı olduğunu define ile tanımlayarak, kodun okunurluğunu epeyce artırmış olduk. Bu sayede ikinci kodu okuyan birisi artık kodun fiziksel olarak ne iş yaptığını kolayca anlayabilir durumu geldi. Her kod bir hikaye anlatır malum. Birinci kod hikayeyi mikrokontrolörün perspektifinden anlatırken, ikinci kod hikayeyi insan gözü perspektifinden anlatmış oldu.
Bu yazı bu kadar olsun 🙂 Bir başka yazıda yine devam edeceğiz. Yazıları beğendiyseniz, faydalanabilecek tanıdıklarınızla paylaşmayı unutmayınız.
Önceki Sayfa Sonraki Sayfa