{"id":432,"date":"2015-07-20T00:51:03","date_gmt":"2015-07-19T21:51:03","guid":{"rendered":"http:\/\/ozenozkaya.com\/blog\/?p=432"},"modified":"2015-07-20T00:51:03","modified_gmt":"2015-07-19T21:51:03","slug":"pic-programlama-6-kesmeler-interrupts","status":"publish","type":"post","link":"http:\/\/ozenozkaya.com\/blog\/?p=432","title":{"rendered":"PIC Programlama \u2013 6 \u2013 Kesmeler (Interrupts)"},"content":{"rendered":"<p><a href=\"http:\/\/ozenozkaya.com\/blog\/?p=422\" target=\"_blank\">\u00d6nceki yaz\u0131m\u0131zda<\/a> PIC16F84A&#8217;n\u0131n pinlerini kontrol etmeyi i\u015flemi\u015ftik. Elbette ki buraya kadarki bilgilerle \u00e7ok say\u0131da uygulama yapmak m\u00fcmk\u00fcn ancak bu yaz\u0131 dizisi altyap\u0131 olu\u015fturma amac\u0131 ta\u015f\u0131d\u0131\u011f\u0131ndan \u015fimdilik farkl\u0131 uygulamalar\u0131 gelece\u011fe b\u0131rakarak altyap\u0131 \u00e7al\u0131\u015fmalar\u0131na devam diyoruz. Mikrokontrol\u00f6r&#8217;\u00fcn giri\u015f \u00e7\u0131k\u0131\u015f aray\u00fczlerini detayl\u0131ca inceledikten sonra s\u0131ra geldi kesmelere. \u00d6nce genel manada kesmelerin ne oldu\u011funa de\u011finip, ard\u0131ndan da port ve pin kesmeleri ile devam edece\u011fiz. Mikrokontrol\u00f6r&#8217;\u00fcn \u00e7evresellerinden baz\u0131lar\u0131 farkl\u0131 tipte kesmeler destekler. \u00d6rne\u011fin zamanlay\u0131c\u0131 kesmelerine, zamanlay\u0131c\u0131 mod\u00fcl\u00fcnde de\u011finece\u011fiz. Haz\u0131r port\/pin kontrol\u00fcn\u00fc g\u00f6rm\u00fc\u015fken bu yaz\u0131da port\/pin kesmelerine de\u011finece\u011fiz.<\/p>\n<p>Kesme nedir demeden \u00f6nce, mikrokontrol\u00f6r ve CPU aras\u0131ndaki farklar\u0131 hat\u0131rlayal\u0131m. CPU (i\u015flemci, merkezi i\u015flem birimi) mikrokontrol\u00f6r i\u00e7erisindeki bir mod\u00fcld\u00fcr. Mikrokontrol\u00f6r i\u00e7inde, CPU&#8217;ya ek olarak bellek ve \u00e7evreseller (perihperal) bulunur. CPU i\u00e7erisinde genelde aritmetik\/lojik i\u015flemleri yapan bir mod\u00fcl (ALU) bulunur. Hemen PIC16F84A&#8217;n\u0131n yap\u0131s\u0131n\u0131 inceleyelim. Bu blog diyagram PIC16F84A&#8217;n\u0131n veri ka\u011f\u0131d\u0131ndan al\u0131nd\u0131.<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/ozenozkaya.com\/blog\/wp-content\/uploads\/pic16f84a_block_diag.png\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-433\" src=\"https:\/\/i0.wp.com\/ozenozkaya.com\/blog\/wp-content\/uploads\/pic16f84a_block_diag.png?resize=601%2C495\" alt=\"pic16f84a_block_diag\" width=\"601\" height=\"495\" \/><\/a><\/p>\n<p>Diyagramda ALU&#8217;ya dikkat ediniz. Onu CPU olarak d\u00fc\u015f\u00fcnebilirsiniz. ALU&#8217;dan W reg&#8217;e giden yolda sa\u011fa do\u011fru bir kanal oldu\u011funu g\u00f6receksiniz. O kanal I\/O portlar\u0131na, TMR (timer, zamanlay\u0131c\u0131) mod\u00fcllerine ve daha nice yerlere gidiyor. Bu ka\u00e7ak kanal, olas\u0131 bir kesme sinyalinin ALU&#8217;ya m\u00fcdahale edebildi\u011finin bir kan\u0131t\u0131. Bu yaz\u0131n\u0131n sonunda da resmin sa\u011f alt k\u0131sm\u0131nda yer alan RB0\/INT&#8217;in ne oldu\u011fu\u00a0anlat\u0131lacak.<\/p>\n<p><strong>Kesme Nedir?<\/strong><\/p>\n<p>Kesmeleri tan\u0131mlamak uygulamada g\u00f6stermekten zor bir i\u015ftir ama \u015f\u00f6yle bir tan\u0131m yapmak m\u00fcmk\u00fcn: Kesme (interrupt), CPU&#8217;nun d\u0131\u015f\u0131ndaki bir d\u0131\u015f etken taraf\u0131ndan olu\u015fturulan ve olu\u015ftu\u011funda CPU&#8217;nun yapt\u0131\u011f\u0131 i\u015fi durdurup, \u00a0ayr\u0131 bir \u00f6zel kod par\u00e7ac\u0131\u011f\u0131n\u0131n i\u015fletilmesini (y\u00fcr\u00fct\u00fclmesini) sa\u011flayan elektriksel bir i\u015farettir. Kesme \u00a0olu\u015ftu\u011funda i\u015fletilen bu koda genelde kesme servis rutini (interrupt service routine, ISR) denir. Kesme olu\u015ftu\u011fu anda, ISR&#8217;ye gitmeden \u00f6nce, CPU program i\u015fletiminde kald\u0131\u011f\u0131 yeri kaydeder. ISR&#8217;nin i\u015fletimi bitti\u011fi anda da CPU bu kay\u0131tl\u0131 noktadan yani kald\u0131\u011f\u0131 yerden program\u0131 i\u015fletmeye devam eder.<\/p>\n<p>Kesme asenkron ger\u00e7ekle\u015fen bir olayd\u0131r, yani ne zaman ger\u00e7ekle\u015fece\u011fini CPU \u00f6nceden bilmez. G\u00fcndelik hayattan \u00a0buna benzer bir s\u00fcre\u00e7 \u00f6rne\u011fi verecek olursak; kap\u0131 zilinin ya da telefonun \u00e7almas\u0131 durumlar\u0131n\u0131 \u00f6rnek verebiliriz. Diyelim yemek yap\u0131yorsunuz, zil \u00e7ald\u0131; yemek yapmay\u0131 b\u0131rak\u0131p kap\u0131y\u0131 a\u00e7\u0131p yemek yapmaya devam ederiz. Zil \u00e7al\u0131nca, yahu\u00a0dur s\u0131ras\u0131 m\u0131yd\u0131 demeyiz. Ya da s\u00fcrekli kap\u0131y\u0131 kontrol etmeden zilin ne zaman \u00e7alaca\u011f\u0131n\u0131 bilemeyiz. Bununla birlikte, kap\u0131n\u0131n \u00e7al\u0131\u015f\u0131n\u0131 duymazdan gelmeniz bir se\u00e7enektir tabi ki. Ayn\u0131 \u015feyler\u00a0kesmeler i\u00e7in de ge\u00e7erli \ud83d\ude42<\/p>\n<p>Kesmeler, g\u00f6m\u00fcl\u00fc sistemlerde \u00e7ok \u00e7ok \u00f6nemli bir yere sahiptir. Kesmeler&#8217;in d\u00fczg\u00fcn kullan\u0131m\u0131 ile tasarlanm\u0131\u015f bir sistem daha verimli, daha duyarl\u0131 (responsive) ve daha anla\u015f\u0131l\u0131r \u015fekilde tasarlanabilir. Kesmeler d\u00fczg\u00fcn kullan\u0131lmazsa da &#8220;yaa b\u00f6yle olmamas\u0131 laz\u0131md\u0131 ama, \u00e7ok sa\u00e7ma, b\u00f6yle \u00e7al\u0131\u015fmamas\u0131 laz\u0131md\u0131 ama&#8221; s\u00f6zleri havada u\u00e7u\u015fur, i\u015fin i\u00e7inden \u00e7\u0131k\u0131lmaz. Halbuki dostlar, her \u015fey deterministik \ud83d\ude42 \u00c7ok g\u00fc\u00e7l\u00fc ama biraz da tehlikeli olduklar\u0131ndan baz\u0131 yaz\u0131l\u0131mc\u0131lar kesmelerden korkar ama g\u00f6m\u00fcl\u00fc sistem programc\u0131s\u0131 kesmeden korkmamal\u0131, kesmelerle\u00a0samimi olmal\u0131, onlar\u0131 son derece i\u015feyarar ve g\u00fc\u00e7l\u00fc bir arkada\u015f olarak g\u00f6rmelidir. Zira, etraf\u0131n\u0131zda g\u00f6rd\u00fc\u011f\u00fcn\u00fcz g\u00f6m\u00fcl\u00fc sistemlerden en az bir kesme kullanmayan\u0131 bulmak s\u0131rad\u0131\u015f\u0131 bir olayd\u0131r. S\u00f6z\u00fcn \u00f6z\u00fc, kesme cand\u0131r.<\/p>\n<p>Farkl\u0131 mikrokontrol\u00f6r mimarilerinde kesmeler farkl\u0131 \u015fekillerde ele al\u0131n\u0131r. \u015eimdi PIC&#8217;ten ba\u015flayal\u0131m. Yine ibretlerle dolu bir uygulama yapaca\u011f\u0131z.<\/p>\n<p><strong>Switch ve Led Uygulamas\u0131<\/strong><\/p>\n<p><a href=\"http:\/\/ozenozkaya.com\/blog\/?p=422\" target=\"_blank\">Bir \u00f6nceki yaz\u0131m\u0131za<\/a> yapt\u0131\u011f\u0131m\u0131z uygulamada, while d\u00f6ng\u00fcs\u00fcn\u00fcn i\u00e7erisinde switch&#8217;in durumunu s\u00fcrekli kontrol etmi\u015ftik. Buna polling deniyor ve ekstrem derecede verimsiz bir y\u00f6ntemdir bu. Bunun yerine kesme kullansayd\u0131k, sadece anahtar\u0131n durumu de\u011fi\u015fti\u011finde ledlerin durumuna m\u00fcdahale edebilece\u011fimiz bir senaryo olu\u015facakt\u0131. Bu da ileride \u00f6zellikle g\u00fc\u00e7 t\u00fcketimi anlam\u0131nda da bize avantajlar sa\u011flayacakt\u0131. Haydi sa\u011flas\u0131n madem.\u00a0Uygulamay\u0131 bu defa kesme kullanarak yapaca\u011f\u0131z. Yine switch\u00a0bir konumda iken k\u0131rm\u0131z\u0131 yanar\u00a0sar\u0131 s\u00f6ner durumda olacak, switch di\u011fer konumdayken sar\u0131 yanar k\u0131rm\u0131z\u0131 s\u00f6ner durumda olacak. Yine bu uygulamada da kod yaz\u0131m\u0131m\u0131z\u0131 bir ka\u00e7 ad\u0131m \u00f6teye ta\u015f\u0131yaca\u011f\u0131z ancak \u00f6nce kald\u0131\u011f\u0131m\u0131z yerden devam edelim \ud83d\ude42<\/p>\n<pre class=\"lang:c decode:true\" title=\"RB0\/INT KESME\">\/* \n * File:   main.c\n * Author: ozenozkaya\n *\n * Created on 02 Haziran 2015 Sali, 12:47\n *\/\n#define F_OSC (1000000UL)\n\n#define REG_TRISB_ADDR (0x86)\n#define REG_TRISB (*( volatile unsigned char*)REG_TRISB_ADDR)\n#define TRIS_PIN_OUTPUT (0)\n#define TRIS_PIN_INPUT  (1)\n#define TRIS_PORT_OUTPUT (0)\n#define TRIS_PORT_INPUT  (0xFF)\n\n#define REG_PORTB_ADDR (0x06)\n#define REG_PORTB (*( volatile unsigned char*)REG_PORTB_ADDR)\n#define PORT_PIN_LOW  (0)\n#define PORT_PIN_HIGH (1)\n#define PORT_ALL_LOW  (0)\n#define PORT_ALL_HIGH (0xFF)\n\n#define SWITCH_PIN pins.pin0\n#define RED_LED_PIN pins.pin1\n#define YELLOW_LED_PIN pins.pin2\n\n#define LED_ON (PORT_PIN_HIGH)\n#define LED_OFF (PORT_PIN_LOW)\n\n#define REG_INTCON_ADDR (0x0B)\n#define REG_INTCON (*( volatile unsigned char*)REG_INTCON_ADDR)\n#define INT_ENABLE (1)\n#define INT_DISABLE (0)\n#define INT_FLAG_CLEAR (0)\n\n#define REG_OPTION_ADDR (0x81)\n#define REG_OPTION (*( volatile unsigned char*)REG_OPTION_ADDR)\n#define INT_EDGE_FALLING (0)\n#define INT_EDGE_RISING  (1)\n\n#define BIT_TOGGLE(x) (x^=1)\n\ntypedef struct \n{\n    unsigned char pin0:1;\n    unsigned char pin1:1;\n    unsigned char pin2:1;\n    unsigned char pin3:1;\n    unsigned char pin4:1;\n    unsigned char pin5:1;\n    unsigned char pin6:1;\n    unsigned char pin7:1;\n}tris_port_pin_t;\n\ntypedef struct\n{\n    unsigned char RBIF:1;\n    unsigned char INTF:1;\n    unsigned char T0IF:1;\n    unsigned char RBIE:1;\n    unsigned char INTE:1;\n    unsigned char T0IE:1;\n    unsigned char EEIE:1;\n    unsigned char GIE:1;\n}intcon_reg_t,*intcon_reg_ptr_t;\n\ntypedef struct\n{\n    unsigned char PS:3;\n    unsigned char PSA:1;\n    unsigned char T0SE:1;\n    unsigned char T0CS:1;\n    unsigned char INTEDG:1;\n    unsigned char RBPU:1;\n}option_reg_t,*option_reg_ptr_t;\n\ntypedef union\n{\n    tris_port_pin_t pins;\n    volatile unsigned char port;\n}tris_port_t,*tris_port_ptr_t;\n\ntris_port_t *portb_ptr=(tris_port_ptr_t)REG_PORTB_ADDR;\ntris_port_t *trisb_ptr=(tris_port_ptr_t)REG_TRISB_ADDR;\nintcon_reg_t *intcon_reg_ptr= (intcon_reg_ptr_t)REG_INTCON_ADDR;\noption_reg_t *option_reg_ptr = (option_reg_ptr_t)REG_OPTION_ADDR;\n    \nstatic void interrupt global_isr_handler()\n{\n    if(intcon_reg_ptr-&gt;INTF)\n    {\n        switch(portb_ptr-&gt;SWITCH_PIN)\n            {\n                case PORT_PIN_LOW:\n                    portb_ptr-&gt;RED_LED_PIN = LED_ON;\n                    portb_ptr-&gt;YELLOW_LED_PIN = LED_OFF;\n                    break;\n                case PORT_PIN_HIGH:\n                    portb_ptr-&gt;RED_LED_PIN = LED_OFF;\n                    portb_ptr-&gt;YELLOW_LED_PIN = LED_ON;    \n                    break;\n                default:\n                    break;        \n            }\n        BIT_TOGGLE(option_reg_ptr-&gt;INTEDG);\n        intcon_reg_ptr-&gt;INTF=INT_FLAG_CLEAR;\n    }\n}\n\n\nvoid main() {\n    trisb_ptr-&gt;port = TRIS_PORT_INPUT;\n    trisb_ptr-&gt;SWITCH_PIN = TRIS_PIN_INPUT;\n    trisb_ptr-&gt;RED_LED_PIN = TRIS_PIN_OUTPUT;\n    trisb_ptr-&gt;YELLOW_LED_PIN = TRIS_PIN_OUTPUT;\n    \n    portb_ptr-&gt;port = PORT_ALL_LOW;\n    \n    \n    intcon_reg_ptr-&gt;INTF = INT_FLAG_CLEAR;\n    intcon_reg_ptr-&gt;INTE = INT_ENABLE;\n    intcon_reg_ptr-&gt;GIE = INT_ENABLE;\n    \n    option_reg_ptr-&gt;INTEDG = INT_EDGE_RISING; \n      \n    while(1);\n}\n<\/pre>\n<p>Kodun \u00e7al\u0131\u015ft\u0131r\u0131laca\u011f\u0131 devre bir <a href=\"http:\/\/ozenozkaya.com\/blog\/?p=422\" target=\"_blank\">\u00f6nceki yaz\u0131dakilerle<\/a> ayn\u0131. Yani \u00e7\u0131kt\u0131 a\u015fa\u011f\u0131daki gibi olacak.<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/ozenozkaya.com\/blog\/wp-content\/uploads\/switch2.png\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-424\" src=\"https:\/\/i0.wp.com\/ozenozkaya.com\/blog\/wp-content\/uploads\/switch2.png?resize=600%2C600\" alt=\"switch2\" width=\"600\" height=\"600\" \/><\/a><\/p>\n<p><a href=\"https:\/\/i0.wp.com\/ozenozkaya.com\/blog\/wp-content\/uploads\/switch1.png\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-423\" src=\"https:\/\/i0.wp.com\/ozenozkaya.com\/blog\/wp-content\/uploads\/switch1.png?resize=601%2C598\" alt=\"switch1\" width=\"601\" height=\"598\" \/><\/a><\/p>\n<p>\u015eimdi gelelim fas\u00fclyenin faydalar\u0131na.\u00a0Kesmeyi nas\u0131l kullanaca\u011f\u0131m\u0131z\u0131 nereden bildik? PIC16F84A&#8217;n\u0131n veri ka\u011f\u0131d\u0131n\u0131n 6.8 Interrupts ba\u015fl\u0131kl\u0131 k\u0131sm\u0131nda hangi registerlar\u0131 nas\u0131l konfig\u00fcre etmemiz gerekti\u011fi a\u00e7\u0131k\u00e7a yaz\u0131yor. Bildi\u011finiz gibi bu yaz\u0131 dizisinde kendi yazd\u0131klar\u0131m\u0131zdan ba\u015fka bir k\u00fct\u00fcphane kullanm\u0131yoruz. Bunun amac\u0131 her \u015feyi temelinden anlamakt\u0131. Do\u011fal olarak kullanaca\u011f\u0131m\u0131z yeni registerlar i\u00e7in de tan\u0131mlamalar\u0131 yap\u0131yoruz. A\u015fa\u011f\u0131da OPTION ve INTCON k\u00fct\u00fcklerinin (registerlar\u0131n\u0131n) adres tan\u0131mlar\u0131n\u0131 ve yard\u0131mc\u0131 etiketleri g\u00f6rebilirsiniz. Buna ek olarak bir de BIT_TOGGLE makrosu tan\u0131mlad\u0131k. Bu makronun amac\u0131 bir biti birse s\u0131f\u0131r, s\u0131f\u0131rsa bir yapmak. Bunu ileride kullanaca\u011f\u0131z.<\/p>\n<pre class=\"lang:c decode:true\" title=\"k\u00fct\u00fck tan\u0131mlar\">#define REG_INTCON_ADDR (0x0B)\n#define REG_INTCON (*( volatile unsigned char*)REG_INTCON_ADDR)\n#define INT_ENABLE (1)\n#define INT_DISABLE (0)\n#define INT_FLAG_CLEAR (0)\n\n#define REG_OPTION_ADDR (0x81)\n#define REG_OPTION (*( volatile unsigned char*)REG_OPTION_ADDR)\n#define INT_EDGE_FALLING (0)\n#define INT_EDGE_RISING  (1)\n\n#define BIT_TOGGLE(x) (x^=1)<\/pre>\n<p>Registerlar\u0131n modellenmesini ise a\u015fa\u011f\u0131daki gibi yapt\u0131k.<\/p>\n<pre class=\"lang:c decode:true \" title=\"k\u00fct\u00fck modelleme\">typedef struct\n{\n    unsigned char RBIF:1;\n    unsigned char INTF:1;\n    unsigned char T0IF:1;\n    unsigned char RBIE:1;\n    unsigned char INTE:1;\n    unsigned char T0IE:1;\n    unsigned char EEIE:1;\n    unsigned char GIE:1;\n}intcon_reg_t,*intcon_reg_ptr_t;\n\ntypedef struct\n{\n    unsigned char PS:3;\n    unsigned char PSA:1;\n    unsigned char T0SE:1;\n    unsigned char T0CS:1;\n    unsigned char INTEDG:1;\n    unsigned char RBPU:1;\n}option_reg_t,*option_reg_ptr_t;\n<\/pre>\n<p>Bu tan\u0131mlamalar\u0131 datasheetten bak\u0131p yapt\u0131ktan sonra INTCON ve OPTION k\u00fct\u00fcklerini g\u00f6sterecek i\u015faret\u00e7ileri a\u015fa\u011f\u0131daki gibi tan\u0131mlad\u0131k.<\/p>\n<pre class=\"lang:c decode:true \" title=\"k\u00fct\u00fck i\u015faret\u00e7ileri\">intcon_reg_t *intcon_reg_ptr= (intcon_reg_ptr_t)REG_INTCON_ADDR;\noption_reg_t *option_reg_ptr = (option_reg_ptr_t)REG_OPTION_ADDR;<\/pre>\n<p>Ard\u0131ndan gelelim ana fonksiyon(main)\u00a0i\u00e7inde yapt\u0131\u011f\u0131m\u0131z ek konfig\u00fcrasyonlara.<\/p>\n<pre class=\"lang:c decode:true\">option_reg_ptr-&gt;INTEDG = INT_EDGE_RISING; \n    \nintcon_reg_ptr-&gt;INTF = INT_FLAG_CLEAR;\nintcon_reg_ptr-&gt;INTE = INT_ENABLE;\nintcon_reg_ptr-&gt;GIE = INT_ENABLE;<\/pre>\n<p>\u00d6ncelikle kesme bayra\u011f\u0131n\u0131n temiz oldu\u011fundan emin olmak i\u00e7in onu temizledik. Ard\u0131ndan INTE ile RB0\/INT kesmesine izin verdik. Ard\u0131ndan da global kesme aktivasyonu i\u00e7in GIE bitini\u00a0etkinle\u015ftirdik. GIE ve INTE bitlerinin ikisi de 1 de\u011ferini almadan kesme ger\u00e7ekle\u015femez. Bunu da verika\u011f\u0131d\u0131ndaki a\u015fa\u011f\u0131daki \u015femadan anlayabiliyoruz.<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/ozenozkaya.com\/blog\/wp-content\/uploads\/int_logic.png\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-436\" src=\"https:\/\/i0.wp.com\/ozenozkaya.com\/blog\/wp-content\/uploads\/int_logic.png?resize=313%2C234\" alt=\"int_logic\" width=\"313\" height=\"234\" \/><\/a><\/p>\n<p>Konfig\u00fcrasyonda kesmeyi de y\u00fckselen kenarda olacak \u015fekilde ayarlad\u0131k. Buna g\u00f6re anahtar s\u0131f\u0131rdan bire \u00e7ekildi\u011finde y\u00fckselen kenar kesmesi gelecek. Ama burada bir sorun var, bize hem y\u00fckselen kenar hem d\u00fc\u015fen kenarda kesme gerekiyor. \u00c7\u00fcnk\u00fc anahtar\u0131n konumu s\u0131f\u0131rdan bire de\u011fi\u015fti\u011finde de birden s\u0131f\u0131ra de\u011fi\u015fti\u011finde de kesme almak ve LED&#8217;lerin durumunu de\u011fi\u015ftirmek istiyoruz. PIC&#8217;te b\u00f6yle do\u011frudan b\u00f6yle bir se\u00e7enek yok; ya y\u00fckselen kenar kesmesi se\u00e7ilebiliyor ya da d\u00fc\u015fen kenar. Burada beyin bedava diyoruz ve kafay\u0131 \u00e7al\u0131\u015ft\u0131rarak soruna \u00e7\u00f6z\u00fcm sunuyoruz. \u00d6nce y\u00fckselen kenar kesmesini aktive etti\u011fimizi d\u00fc\u015f\u00fcnelim, bu durumda ilk gelen y\u00fckselen kenar kesmesinin hemen ard\u0131ndan d\u00fc\u015fen kenar kesmesini aktive edersek, switchin durumu tekrar de\u011fi\u015fti\u011finde kesme alabiliriz. Yani y\u00fckselen\/d\u00fc\u015fen kenar konfig\u00fcrasyonunu, kesme olu\u015ftu\u011funda toggle etmemiz gerekiyor. Kesme tamamland\u0131\u011f\u0131nda kesme bayra\u011f\u0131n\u0131 yani INTF bitini de s\u0131f\u0131ra \u00e7ekip temizlemek gerekiyor. Kodda da bunlar\u0131 yapt\u0131k. PIC&#8217;te kesme fonksiyonu fonksiyon ad\u0131n\u0131n ba\u015f\u0131na gelen &#8220;interrupt&#8221; kelimesi ile derleyiciye anlat\u0131l\u0131r. Buna g\u00f6re kesme fonksiyonumuz a\u015fa\u011f\u0131daki gibi oluyor.<\/p>\n<pre class=\"lang:c decode:true \" title=\"kesme\">    \nstatic void interrupt global_isr_handler()\n{\n    if(intcon_reg_ptr-&gt;INTF)\n    {\n        switch(portb_ptr-&gt;SWITCH_PIN)\n            {\n                case PORT_PIN_LOW:\n                    portb_ptr-&gt;RED_LED_PIN = LED_ON;\n                    portb_ptr-&gt;YELLOW_LED_PIN = LED_OFF;\n                    break;\n                case PORT_PIN_HIGH:\n                    portb_ptr-&gt;RED_LED_PIN = LED_OFF;\n                    portb_ptr-&gt;YELLOW_LED_PIN = LED_ON;    \n                    break;\n                default:\n                    break;        \n            }\n        BIT_TOGGLE(option_reg_ptr-&gt;INTEDG);\n        intcon_reg_ptr-&gt;INTF=INT_FLAG_CLEAR;\n    }\n}\n<\/pre>\n<p>PIC&#8217;te t\u00fcm kesmeler tek bir fonksiyon i\u00e7ine d\u00fc\u015fer, bu da interrupt \u00f6n ekli fonksiyondur. Bu sebeple bu fonksiyonun ad\u0131n\u0131 global_isr_handler koyduk. Daha sonra gelen kesmenin RB0\/INT\u00a0olup olmad\u0131\u011f\u0131n\u0131 kontrol ettik ve e\u011fer o ise switch de\u011ferlendirmesi i\u015flemini yap\u0131p y\u00fckselen\/d\u00fc\u015fen kenar se\u00e7imini g\u00fcncelle\u015ftirip bayra\u011f\u0131 temizledik. INTEDG&#8217;nin toggle edilmesi ile hem d\u00fc\u015fen hem y\u00fckselen kenardaki de\u011fi\u015fimleri g\u00fczel bir oyun ile alg\u0131layabilir duruma geldik. \u00c7i\u00e7ek oldu.<\/p>\n<p>\u015eimdi gelelim bu kodun sorunlar\u0131na. Birincisi register tan\u0131mlar\u0131 giderek kabar\u0131yor ve onlar\u0131n ayr\u0131 bir *.h\u00a0dosyas\u0131\u00a0i\u00e7inde yer almas\u0131 gerekiyor art\u0131k. \u0130kincisi, ilk durumda switch&#8217;in durumuna bakmaks\u0131z\u0131n kesme konfigurasyonu yapt\u0131\u011f\u0131m\u0131z i\u00e7in ilk a\u00e7\u0131l\u0131\u015fta ledlerin ikisi de yanm\u0131yor. \u00dc\u00e7\u00fcnc\u00fcs\u00fc de \u015fu, madem her kesme ayn\u0131 fonksiyona d\u00fc\u015fecek, ileride kod daha da b\u00fcy\u00fcd\u00fc\u011f\u00fcnde kesme fonksiyonu s\u00fcrekli de\u011fi\u015ftirilecek ve e\u011fer birisi orada yanl\u0131\u015f bayraklar\u0131 temizlerse ya da kurarsa, \u00f6nceden yaz\u0131lm\u0131\u015f k\u0131s\u0131mlar da bundan etkilenecek ve kodun her yeri bozulacak. Bu \u00e7ok b\u00fcy\u00fck bir risk. Burada SDK tasar\u0131m\u0131 devreye giriyor. Ak\u0131ll\u0131ca bir se\u00e7enek, kesme fonksiyonunu kullan\u0131c\u0131 program\u0131ndan ay\u0131rmak olacakt\u0131r. Burada kesme bayraklar\u0131n\u0131n y\u00f6netiminin de otomatik yap\u0131lmas\u0131 da isabetli olacakt\u0131r. Bu olay ger\u00e7ekten bir ileri tasar\u0131m \u00f6\u011fesidir ancak ad\u0131m ad\u0131m oraya gidece\u011fiz. Kodun bir di\u011fer \u00f6nemli sorunu da k\u00fct\u00fcphane kullanmayaca\u011f\u0131z inad\u0131m\u0131zla kullanmad\u0131\u011f\u0131m\u0131z stdint k\u00fct\u00fcphanesidir. &#8220;unsigned char&#8221; gibi boyutu &#8220;hay\u0131rl\u0131s\u0131&#8221; olan bir veri tipi kullanmak yerine &#8220;uint8_t&#8221; ile modelleme yapmam\u0131z daha temiz olurdu. Nitekim amac\u0131m\u0131z PIC k\u00fct\u00fcphanelerini kullanmadan, daha iyi \u015fekilde temelden olay\u0131 yazarak olay\u0131n dinamiklerini anlamakt\u0131. Bu da stdint&#8217;e ge\u00e7i\u015fimizi engellemiyor. Bir di\u011fer eksik nokta da register tan\u0131mlar\u0131yla ilgili. <a href=\"http:\/\/ozenozkaya.com\/blog\/?p=422\" target=\"_blank\">\u00d6nceki yaz\u0131da<\/a>, sebeplerini s\u0131ralad\u0131\u011f\u0131m\u0131z \u00fczere hem bit hem de byte eri\u015fimi sa\u011flayabilmek i\u00e7in k\u00fct\u00fck modellemelerinde union kullanm\u0131\u015ft\u0131k. Yeni modelledi\u011fimiz k\u00fct\u00fcklerde de bunu uygulamakta fayda var. Bunlara g\u00f6re projemizi yine d\u00fczenleyelim \ud83d\ude42<\/p>\n<p><strong>Switch ve LED Uygulamas\u0131 v2<\/strong><\/p>\n<p>Bu projede 3 adet dosyam\u0131z olacak. Birincisi pic16f84a k\u00fct\u00fcphanemizin header dosyas\u0131. Bu dosya (pic16f84a_lib.h) a\u015fa\u011f\u0131daki gibidir.<\/p>\n<pre class=\"lang:c decode:true\" title=\"pic16f84a_lib.h\">\/* \n * File:   pic16f84a_lib.h\n * Author: ozenozkaya\n *\n * Created on 20 Temmuz 2015 Pazartesi, 00:05\n *\/\n\n#ifndef PIC16F84A_LIB_H\n#define    PIC16F84A_LIB_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n \n#include &lt;stdint.h&gt;\n\n#define F_OSC (1000000UL)\n\n#define REG_TRISB_ADDR (0x86)\n#define REG_TRISB (*( volatile unsigned char*)REG_TRISB_ADDR)\n#define TRIS_PIN_OUTPUT (0)\n#define TRIS_PIN_INPUT  (1)\n#define TRIS_PORT_OUTPUT (0)\n#define TRIS_PORT_INPUT  (0xFF)\n\n#define REG_PORTB_ADDR (0x06)\n#define REG_PORTB (*( volatile unsigned char*)REG_PORTB_ADDR)\n#define PORT_PIN_LOW  (0)\n#define PORT_PIN_HIGH (1)\n#define PORT_ALL_LOW  (0)\n#define PORT_ALL_HIGH (0xFF)\n\n#define REG_INTCON_ADDR (0x0B)\n#define REG_INTCON (*( volatile unsigned char*)REG_INTCON_ADDR)\n#define INT_ENABLE (1)\n#define INT_DISABLE (0)\n#define INT_FLAG_CLEAR (0)\n\n#define REG_OPTION_ADDR (0x81)\n#define REG_OPTION (*( volatile unsigned char*)REG_OPTION_ADDR)\n#define INT_EDGE_FALLING (0)\n#define INT_EDGE_RISING  (1)\n    \n#define MAX_INT_CALLBACK_NUM (5)\n\ntypedef struct \n{\n    uint8_t pin0:1;\n    uint8_t pin1:1;\n    uint8_t pin2:1;\n    uint8_t pin3:1;\n    uint8_t pin4:1;\n    uint8_t pin5:1;\n    uint8_t pin6:1;\n    uint8_t pin7:1;\n}_tris_port_pin_t, *_tris_port_pin_ptr_t;\n\ntypedef struct\n{\n    uint8_t RBIF:1;\n    uint8_t INTF:1;\n    uint8_t T0IF:1;\n    uint8_t RBIE:1;\n    uint8_t INTE:1;\n    uint8_t T0IE:1;\n    uint8_t EEIE:1;\n    uint8_t GIE:1;\n}_intcon_reg_t,*_intcon_reg_ptr_t;\n\ntypedef struct\n{\n    uint8_t PS:3;\n    uint8_t PSA:1;\n    uint8_t T0SE:1;\n    uint8_t T0CS:1;\n    uint8_t INTEDG:1;\n    uint8_t RBPU:1;\n}_option_reg_t,*_option_reg_ptr_t;\n\ntypedef union\n{\n    _tris_port_pin_t pins;\n    uint8_t port;\n}tris_port_t,*tris_port_ptr_t;\n\ntypedef union\n{\n  _option_reg_t bits;\n  uint8_t value;  \n}option_reg_t, *option_reg_ptr_t;\n\ntypedef union\n{\n  _intcon_reg_t bits;\n  uint8_t value;  \n}intcon_reg_t, *intcon_reg_ptr_t;\n\ntypedef void (*rb0_int_callback_t)();\n\n\nint8_t register_rb0_int_callback(rb0_int_callback_t new_cb);\nint8_t unregister_rb0_int_callback(rb0_int_callback_t cb_to_unreg);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif \/* PIC16F84A_LIB_H *\/\n<\/pre>\n<p>Yine\u00a0pic16f84a k\u00fct\u00fcphanemizin kaynak dosyas\u0131 (pic16f84a_lib.c) a\u015fa\u011f\u0131daki gibidir.<\/p>\n<pre class=\"lang:c decode:true\" title=\"pic16f84a_lib.c\">#include \"pic16f84a_lib.h\"\n\n#define BIT_TOGGLE(x) (x^=1)\n\n#ifndef NULL\n#define NULL ((void*)0)\n#endif\n\nrb0_int_callback_t rb0_int_callback_list[MAX_INT_CALLBACK_NUM];\n\nstatic void interrupt global_isr_handler()\n{\n    intcon_reg_t *intcon_reg_ptr= (intcon_reg_ptr_t)REG_INTCON_ADDR;\n    option_reg_t *option_reg_ptr = (option_reg_ptr_t)REG_OPTION_ADDR;\n    \n    uint32_t cb_index=0;\n    if(intcon_reg_ptr-&gt;bits.INTF)\n    {\n        for(cb_index=0;cb_index&lt;MAX_INT_CALLBACK_NUM; cb_index++)\n        {\n            if(NULL != rb0_int_callback_list[cb_index])\n            {\n                rb0_int_callback_list[cb_index]();\n            }\n        }\n        BIT_TOGGLE(option_reg_ptr-&gt;bits.INTEDG);\n        intcon_reg_ptr-&gt;bits.INTF=INT_FLAG_CLEAR;\n    }\n}\n\nint8_t register_rb0_int_callback(rb0_int_callback_t new_cb)\n{\n    uint32_t cb_index=0;\n    if(NULL != new_cb)\n    {\n        for(cb_index=0;cb_index&lt;MAX_INT_CALLBACK_NUM; cb_index++)\n        {\n            if(NULL == rb0_int_callback_list[cb_index])\n            {\n                rb0_int_callback_list[cb_index]=new_cb;\n            }\n        }\n        if(MAX_INT_CALLBACK_NUM == cb_index)\n        {\n            return -2; \/\/All callbacks are already registered\n        }\n    }\n    else\n    {\n        return -1; \/\/ Callback is NULL\n    }\n    return 0;\n}\n\nint8_t unregister_rb0_int_callback(rb0_int_callback_t cb_to_unreg)\n{\n    uint32_t cb_index=0;\n    if(NULL != cb_to_unreg)\n    {\n        for(cb_index=0;cb_index&lt;MAX_INT_CALLBACK_NUM; cb_index++)\n        {\n            if(cb_to_unreg == rb0_int_callback_list[cb_index])\n            {\n                rb0_int_callback_list[cb_index]=NULL;\n            }\n        }\n    }\n    else\n    {\n        return -1; \/\/ Callback is NULL\n    }\n    return 0;\n}\n<\/pre>\n<p>Ve nihayetinde ana program\u0131m\u0131z (main.c) a\u015fa\u011f\u0131daki gibidir:<\/p>\n<pre class=\"lang:c decode:true\" title=\"main.c\">\/* \n * File:   main.c\n * Author: ozenozkaya\n *\n * Created on 20 Temmuz 2015 Sali, 23:47\n *\/\n\n#include \"pic16f84a_lib.h\"\n\n#define SWITCH_PIN pins.pin0\n#define RED_LED_PIN pins.pin1\n#define YELLOW_LED_PIN pins.pin2\n\n#define LED_ON (PORT_PIN_HIGH)\n#define LED_OFF (PORT_PIN_LOW)\n\nstatic tris_port_t *portb_ptr=(tris_port_ptr_t)REG_PORTB_ADDR;\nstatic tris_port_t *trisb_ptr=(tris_port_ptr_t)REG_TRISB_ADDR;\n    \nstatic void switch_event_manager()\n{\n    switch(portb_ptr-&gt;SWITCH_PIN)\n        {\n            case PORT_PIN_LOW:\n                portb_ptr-&gt;RED_LED_PIN = LED_ON;\n                portb_ptr-&gt;YELLOW_LED_PIN = LED_OFF;\n                break;\n            case PORT_PIN_HIGH:\n                portb_ptr-&gt;RED_LED_PIN = LED_OFF;\n                portb_ptr-&gt;YELLOW_LED_PIN = LED_ON;    \n                break;\n            default:\n                break;        \n        }\n}\n\nstatic void initialize_switch_and_leds()\n{\n    trisb_ptr-&gt;port = TRIS_PORT_INPUT;\n    trisb_ptr-&gt;SWITCH_PIN = TRIS_PIN_INPUT;\n    trisb_ptr-&gt;RED_LED_PIN = TRIS_PIN_OUTPUT;\n    trisb_ptr-&gt;YELLOW_LED_PIN = TRIS_PIN_OUTPUT;\n    \n    portb_ptr-&gt;port = PORT_ALL_LOW;\n    \n    switch_event_manager();\n}\n\nstatic void initialize_switch_interrupt()\n{\n    intcon_reg_t *intcon_reg_ptr= (intcon_reg_ptr_t)REG_INTCON_ADDR;\n    option_reg_t *option_reg_ptr = (option_reg_ptr_t)REG_OPTION_ADDR;\n    \n    register_rb0_int_callback(switch_event_manager);\n    \n    option_reg_ptr-&gt;bits.INTEDG = INT_EDGE_RISING;\n        \n    intcon_reg_ptr-&gt;bits.INTF = INT_FLAG_CLEAR;\n    intcon_reg_ptr-&gt;bits.INTE = INT_ENABLE;\n    intcon_reg_ptr-&gt;bits.GIE = INT_ENABLE;     \n}\n\nvoid main() {\n\n    initialize_switch_and_leds();\n    initialize_switch_interrupt();\n      \n    while(1);\n}\n<\/pre>\n<p>Kodda, vadetti\u011fimiz t\u00fcm de\u011fi\u015fiklikleri yapm\u0131\u015f olduk. En en en en en \u00f6nemli yer, kullan\u0131c\u0131n\u0131n yani main dosyas\u0131n\u0131n kesme fonksiyonunu hi\u00e7 bir \u015fekilde g\u00f6rmeden kesme i\u015flemlerini haber almas\u0131. Bunun i\u00e7in SDK geli\u015ftiricisi olarak \u00e7\u0131kard\u0131\u011f\u0131m\u0131z fonksiyonu kullanc\u0131 a\u015fa\u011f\u0131daki \u015fekilde\u00a0\u00e7a\u011f\u0131rm\u0131\u015f oldu:<\/p>\n<pre class=\"lang:c decode:true \"> register_rb0_int_callback(switch_event_manager);<\/pre>\n<p>Bu fonksiyonun implementasyonu da tam anlam\u0131yla ibretlik. Maksimum 5 kaynak RB0\/INT kesmesine abone olabiliyor. Bu geni\u015fletilebilirlik a\u00e7\u0131s\u0131ndan \u00e7ok \u00e7ok \u00f6nemli. Biz switch kodunu yar\u0131n \u00f6b\u00fcrg\u00fcn &#8220;switch geldi\u011finde bir de d\u00fcd\u00fck \u00e7als\u0131n&#8221; isteriyle geni\u015fletmek istedi\u011fimizde d\u00fcd\u00fc\u011f\u00fc \u00e7alacak fonksiyonu da register edecersek o d\u00fcd\u00fck \u00e7al\u0131nacakt\u0131r ve bizim \u00f6nceki i\u015flerimiz asla bundan etkilenmeyecektir. Bu olaya l\u00fctfen \u00e7ok dikkat ediniz. Listeye kaydolmu\u015f fonksiyonlar\u0131n yani callback&#8217;lerin \u00e7a\u011f\u0131r\u0131ld\u0131\u011f\u0131 sat\u0131r ise a\u015fa\u011f\u0131daki sat\u0131r.<\/p>\n<pre class=\"lang:c decode:true  \">rb0_int_callback_list[cb_index]();<\/pre>\n<p>\u015eimdilik bu kadar \ud83d\ude42 Bu g\u00fcn epey fantastik mevzulara de\u011findik. PIC deyip ge\u00e7memek gerek, bu basit alet i\u00e7in bile ileri d\u00fczey tasar\u0131m yapmak m\u00fcmk\u00fcn. Nitekim daha da ilerleyece\u011fiz.\u00a0Yaz\u0131lar devam edecek.<\/p>\n<p>Yaz\u0131lar\u0131 be\u011fendiyseniz, faydalanabilecek tan\u0131d\u0131klar\u0131n\u0131zla payla\u015fmay\u0131 unutmay\u0131n\u0131z.<\/p>\n<a href=\"http:\/\/ozenozkaya.com\/blog\/?p=422\" class=\"su-button su-button-style-3d\" style=\"color:#FFFFFF;background-color:#2D89EF;border-color:#246ec0;border-radius:5px\" target=\"_self\"><span style=\"color:#FFFFFF;padding:6px 16px;font-size:13px;line-height:20px;border-color:#6cadf4;border-radius:5px;text-shadow:none\"><i class=\"sui sui-arrow-circle-o-left\" style=\"font-size:13px;color:#FFFFFF\"><\/i> \u00d6nceki Sayfa<\/span><\/a> \u00a0<a href=\"http:\/\/ozenozkaya.com\/blog\/?p=457\" class=\"su-button su-button-style-3d\" style=\"color:#FFFFFF;background-color:#2D89EF;border-color:#246ec0;border-radius:5px\" target=\"_self\"><span style=\"color:#FFFFFF;padding:6px 16px;font-size:13px;line-height:20px;border-color:#6cadf4;border-radius:5px;text-shadow:none\"><i class=\"sui sui-arrow-circle-right\" style=\"font-size:13px;color:#FFFFFF\"><\/i> Sonraki Sayfa<\/span><\/a>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u00d6nceki yaz\u0131m\u0131zda PIC16F84A&#8217;n\u0131n pinlerini kontrol etmeyi i\u015flemi\u015ftik. Elbette ki buraya kadarki bilgilerle \u00e7ok say\u0131da uygulama yapmak m\u00fcmk\u00fcn ancak bu yaz\u0131 dizisi altyap\u0131 olu\u015fturma amac\u0131 ta\u015f\u0131d\u0131\u011f\u0131ndan \u015fimdilik farkl\u0131 uygulamalar\u0131 gelece\u011fe b\u0131rakarak altyap\u0131 \u00e7al\u0131\u015fmalar\u0131na devam diyoruz. Mikrokontrol\u00f6r&#8217;\u00fcn giri\u015f \u00e7\u0131k\u0131\u015f aray\u00fczlerini detayl\u0131ca inceledikten sonra s\u0131ra geldi kesmelere. \u00d6nce genel manada kesmelerin ne oldu\u011funa de\u011finip, ard\u0131ndan da port ve <a class=\"read-more\" href=\"http:\/\/ozenozkaya.com\/blog\/?p=432\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_tr_post_content":"<a href=\"http:\/\/ozenozkaya.com\/blog\/?p=422\" target=\"_blank\">\u00d6nceki yaz\u0131m\u0131zda<\/a> PIC16F84A'n\u0131n pinlerini kontrol etmeyi i\u015flemi\u015ftik. Elbette ki buraya kadarki bilgilerle \u00e7ok say\u0131da uygulama yapmak m\u00fcmk\u00fcn ancak bu yaz\u0131 dizisi altyap\u0131 olu\u015fturma amac\u0131 ta\u015f\u0131d\u0131\u011f\u0131ndan \u015fimdilik farkl\u0131 uygulamalar\u0131 gelece\u011fe b\u0131rakarak altyap\u0131 \u00e7al\u0131\u015fmalar\u0131na devam diyoruz. Mikrokontrol\u00f6r'\u00fcn giri\u015f \u00e7\u0131k\u0131\u015f aray\u00fczlerini detayl\u0131ca inceledikten sonra s\u0131ra geldi kesmelere. \u00d6nce genel manada kesmelerin ne oldu\u011funa de\u011finip, ard\u0131ndan da port ve pin kesmeleri ile devam edece\u011fiz. Mikrokontrol\u00f6r'\u00fcn \u00e7evresellerinden baz\u0131lar\u0131 farkl\u0131 tipte kesmeler destekler. \u00d6rne\u011fin zamanlay\u0131c\u0131 kesmelerine, zamanlay\u0131c\u0131 mod\u00fcl\u00fcnde de\u011finece\u011fiz. Haz\u0131r port\/pin kontrol\u00fcn\u00fc g\u00f6rm\u00fc\u015fken bu yaz\u0131da port\/pin kesmelerine de\u011finece\u011fiz.\n\nKesme nedir demeden \u00f6nce, mikrokontrol\u00f6r ve CPU aras\u0131ndaki farklar\u0131 hat\u0131rlayal\u0131m. CPU (i\u015flemci, merkezi i\u015flem birimi) mikrokontrol\u00f6r i\u00e7erisindeki bir mod\u00fcld\u00fcr. Mikrokontrol\u00f6r i\u00e7inde, CPU'ya ek olarak bellek ve \u00e7evreseller (perihperal) bulunur. CPU i\u00e7erisinde genelde aritmetik\/lojik i\u015flemleri yapan bir mod\u00fcl (ALU) bulunur. Hemen PIC16F84A'n\u0131n yap\u0131s\u0131n\u0131 inceleyelim. Bu blog diyagram PIC16F84A'n\u0131n veri ka\u011f\u0131d\u0131ndan al\u0131nd\u0131.\n\n<a href=\"http:\/\/ozenozkaya.com\/blog\/wp-content\/uploads\/pic16f84a_block_diag.png\"><img class=\"alignnone size-full wp-image-433\" src=\"http:\/\/ozenozkaya.com\/blog\/wp-content\/uploads\/pic16f84a_block_diag.png\" alt=\"pic16f84a_block_diag\" width=\"601\" height=\"495\" \/><\/a>\n\nDiyagramda ALU'ya dikkat ediniz. Onu CPU olarak d\u00fc\u015f\u00fcnebilirsiniz. ALU'dan W reg'e giden yolda sa\u011fa do\u011fru bir kanal oldu\u011funu g\u00f6receksiniz. O kanal I\/O portlar\u0131na, TMR (timer, zamanlay\u0131c\u0131) mod\u00fcllerine ve daha nice yerlere gidiyor. Bu ka\u00e7ak kanal, olas\u0131 bir kesme sinyalinin ALU'ya m\u00fcdahale edebildi\u011finin bir kan\u0131t\u0131. Bu yaz\u0131n\u0131n sonunda da resmin sa\u011f alt k\u0131sm\u0131nda yer alan RB0\/INT'in ne oldu\u011fu\u00a0anlat\u0131lacak.\n\n<strong>Kesme Nedir?<\/strong>\n\nKesmeleri tan\u0131mlamak uygulamada g\u00f6stermekten zor bir i\u015ftir ama \u015f\u00f6yle bir tan\u0131m yapmak m\u00fcmk\u00fcn: Kesme (interrupt), CPU'nun d\u0131\u015f\u0131ndaki bir d\u0131\u015f etken taraf\u0131ndan olu\u015fturulan ve olu\u015ftu\u011funda CPU'nun yapt\u0131\u011f\u0131 i\u015fi durdurup, \u00a0ayr\u0131 bir \u00f6zel kod par\u00e7ac\u0131\u011f\u0131n\u0131n i\u015fletilmesini (y\u00fcr\u00fct\u00fclmesini) sa\u011flayan elektriksel bir i\u015farettir. Kesme \u00a0olu\u015ftu\u011funda i\u015fletilen bu koda genelde kesme servis rutini (interrupt service routine, ISR) denir. Kesme olu\u015ftu\u011fu anda, ISR'ye gitmeden \u00f6nce, CPU program i\u015fletiminde kald\u0131\u011f\u0131 yeri kaydeder. ISR'nin i\u015fletimi bitti\u011fi anda da CPU bu kay\u0131tl\u0131 noktadan yani kald\u0131\u011f\u0131 yerden program\u0131 i\u015fletmeye devam eder.\n\nKesme asenkron ger\u00e7ekle\u015fen bir olayd\u0131r, yani ne zaman ger\u00e7ekle\u015fece\u011fini CPU \u00f6nceden bilmez. G\u00fcndelik hayattan \u00a0buna benzer bir s\u00fcre\u00e7 \u00f6rne\u011fi verecek olursak; kap\u0131 zilinin ya da telefonun \u00e7almas\u0131 durumlar\u0131n\u0131 \u00f6rnek verebiliriz. Diyelim yemek yap\u0131yorsunuz, zil \u00e7ald\u0131; yemek yapmay\u0131 b\u0131rak\u0131p kap\u0131y\u0131 a\u00e7\u0131p yemek yapmaya devam ederiz. Zil \u00e7al\u0131nca, yahu\u00a0dur s\u0131ras\u0131 m\u0131yd\u0131 demeyiz. Ya da s\u00fcrekli kap\u0131y\u0131 kontrol etmeden zilin ne zaman \u00e7alaca\u011f\u0131n\u0131 bilemeyiz. Bununla birlikte, kap\u0131n\u0131n \u00e7al\u0131\u015f\u0131n\u0131 duymazdan gelmeniz bir se\u00e7enektir tabi ki. Ayn\u0131 \u015feyler\u00a0kesmeler i\u00e7in de ge\u00e7erli :)\n\nKesmeler, g\u00f6m\u00fcl\u00fc sistemlerde \u00e7ok \u00e7ok \u00f6nemli bir yere sahiptir. Kesmeler'in d\u00fczg\u00fcn kullan\u0131m\u0131 ile tasarlanm\u0131\u015f bir sistem daha verimli, daha duyarl\u0131 (responsive) ve daha anla\u015f\u0131l\u0131r \u015fekilde tasarlanabilir. Kesmeler d\u00fczg\u00fcn kullan\u0131lmazsa da \"yaa b\u00f6yle olmamas\u0131 laz\u0131md\u0131 ama, \u00e7ok sa\u00e7ma, b\u00f6yle \u00e7al\u0131\u015fmamas\u0131 laz\u0131md\u0131 ama\" s\u00f6zleri havada u\u00e7u\u015fur, i\u015fin i\u00e7inden \u00e7\u0131k\u0131lmaz. Halbuki dostlar, her \u015fey deterministik :) \u00c7ok g\u00fc\u00e7l\u00fc ama biraz da tehlikeli olduklar\u0131ndan baz\u0131 yaz\u0131l\u0131mc\u0131lar kesmelerden korkar ama g\u00f6m\u00fcl\u00fc sistem programc\u0131s\u0131 kesmeden korkmamal\u0131, kesmelerle\u00a0samimi olmal\u0131, onlar\u0131 son derece i\u015feyarar ve g\u00fc\u00e7l\u00fc bir arkada\u015f olarak g\u00f6rmelidir. Zira, etraf\u0131n\u0131zda g\u00f6rd\u00fc\u011f\u00fcn\u00fcz g\u00f6m\u00fcl\u00fc sistemlerden en az bir kesme kullanmayan\u0131 bulmak s\u0131rad\u0131\u015f\u0131 bir olayd\u0131r. S\u00f6z\u00fcn \u00f6z\u00fc, kesme cand\u0131r.\n\nFarkl\u0131 mikrokontrol\u00f6r mimarilerinde kesmeler farkl\u0131 \u015fekillerde ele al\u0131n\u0131r. \u015eimdi PIC'ten ba\u015flayal\u0131m. Yine ibretlerle dolu bir uygulama yapaca\u011f\u0131z.\n\n<strong>Switch ve Led Uygulamas\u0131<\/strong>\n\n<a href=\"http:\/\/ozenozkaya.com\/blog\/?p=422\" target=\"_blank\">Bir \u00f6nceki yaz\u0131m\u0131za<\/a> yapt\u0131\u011f\u0131m\u0131z uygulamada, while d\u00f6ng\u00fcs\u00fcn\u00fcn i\u00e7erisinde switch'in durumunu s\u00fcrekli kontrol etmi\u015ftik. Buna polling deniyor ve ekstrem derecede verimsiz bir y\u00f6ntemdir bu. Bunun yerine kesme kullansayd\u0131k, sadece anahtar\u0131n durumu de\u011fi\u015fti\u011finde ledlerin durumuna m\u00fcdahale edebilece\u011fimiz bir senaryo olu\u015facakt\u0131. Bu da ileride \u00f6zellikle g\u00fc\u00e7 t\u00fcketimi anlam\u0131nda da bize avantajlar sa\u011flayacakt\u0131. Haydi sa\u011flas\u0131n madem.\u00a0Uygulamay\u0131 bu defa kesme kullanarak yapaca\u011f\u0131z. Yine switch\u00a0bir konumda iken k\u0131rm\u0131z\u0131 yanar\u00a0sar\u0131 s\u00f6ner durumda olacak, switch di\u011fer konumdayken sar\u0131 yanar k\u0131rm\u0131z\u0131 s\u00f6ner durumda olacak. Yine bu uygulamada da kod yaz\u0131m\u0131m\u0131z\u0131 bir ka\u00e7 ad\u0131m \u00f6teye ta\u015f\u0131yaca\u011f\u0131z ancak \u00f6nce kald\u0131\u011f\u0131m\u0131z yerden devam edelim :)\n\n<pre class=\"lang:c decode:true\" title=\"RB0\/INT KESME\">\/* \n * File:   main.c\n * Author: ozenozkaya\n *\n * Created on 02 Haziran 2015 Sali, 12:47\n *\/\n#define F_OSC (1000000UL)\n\n#define REG_TRISB_ADDR (0x86)\n#define REG_TRISB (*( volatile unsigned char*)REG_TRISB_ADDR)\n#define TRIS_PIN_OUTPUT (0)\n#define TRIS_PIN_INPUT  (1)\n#define TRIS_PORT_OUTPUT (0)\n#define TRIS_PORT_INPUT  (0xFF)\n\n#define REG_PORTB_ADDR (0x06)\n#define REG_PORTB (*( volatile unsigned char*)REG_PORTB_ADDR)\n#define PORT_PIN_LOW  (0)\n#define PORT_PIN_HIGH (1)\n#define PORT_ALL_LOW  (0)\n#define PORT_ALL_HIGH (0xFF)\n\n#define SWITCH_PIN pins.pin0\n#define RED_LED_PIN pins.pin1\n#define YELLOW_LED_PIN pins.pin2\n\n#define LED_ON (PORT_PIN_HIGH)\n#define LED_OFF (PORT_PIN_LOW)\n\n#define REG_INTCON_ADDR (0x0B)\n#define REG_INTCON (*( volatile unsigned char*)REG_INTCON_ADDR)\n#define INT_ENABLE (1)\n#define INT_DISABLE (0)\n#define INT_FLAG_CLEAR (0)\n\n#define REG_OPTION_ADDR (0x81)\n#define REG_OPTION (*( volatile unsigned char*)REG_OPTION_ADDR)\n#define INT_EDGE_FALLING (0)\n#define INT_EDGE_RISING  (1)\n\n#define BIT_TOGGLE(x) (x^=1)\n\ntypedef struct \n{\n    unsigned char pin0:1;\n    unsigned char pin1:1;\n    unsigned char pin2:1;\n    unsigned char pin3:1;\n    unsigned char pin4:1;\n    unsigned char pin5:1;\n    unsigned char pin6:1;\n    unsigned char pin7:1;\n}tris_port_pin_t;\n\ntypedef struct\n{\n    unsigned char RBIF:1;\n    unsigned char INTF:1;\n    unsigned char T0IF:1;\n    unsigned char RBIE:1;\n    unsigned char INTE:1;\n    unsigned char T0IE:1;\n    unsigned char EEIE:1;\n    unsigned char GIE:1;\n}intcon_reg_t,*intcon_reg_ptr_t;\n\ntypedef struct\n{\n    unsigned char PS:3;\n    unsigned char PSA:1;\n    unsigned char T0SE:1;\n    unsigned char T0CS:1;\n    unsigned char INTEDG:1;\n    unsigned char RBPU:1;\n}option_reg_t,*option_reg_ptr_t;\n\ntypedef union\n{\n    tris_port_pin_t pins;\n    volatile unsigned char port;\n}tris_port_t,*tris_port_ptr_t;\n\ntris_port_t *portb_ptr=(tris_port_ptr_t)REG_PORTB_ADDR;\ntris_port_t *trisb_ptr=(tris_port_ptr_t)REG_TRISB_ADDR;\nintcon_reg_t *intcon_reg_ptr= (intcon_reg_ptr_t)REG_INTCON_ADDR;\noption_reg_t *option_reg_ptr = (option_reg_ptr_t)REG_OPTION_ADDR;\n    \nstatic void interrupt global_isr_handler()\n{\n    if(intcon_reg_ptr-&gt;INTF)\n    {\n        switch(portb_ptr-&gt;SWITCH_PIN)\n            {\n                case PORT_PIN_LOW:\n                    portb_ptr-&gt;RED_LED_PIN = LED_ON;\n                    portb_ptr-&gt;YELLOW_LED_PIN = LED_OFF;\n                    break;\n                case PORT_PIN_HIGH:\n                    portb_ptr-&gt;RED_LED_PIN = LED_OFF;\n                    portb_ptr-&gt;YELLOW_LED_PIN = LED_ON;    \n                    break;\n                default:\n                    break;        \n            }\n        BIT_TOGGLE(option_reg_ptr-&gt;INTEDG);\n        intcon_reg_ptr-&gt;INTF=INT_FLAG_CLEAR;\n    }\n}\n\n\nvoid main() {\n    trisb_ptr-&gt;port = TRIS_PORT_INPUT;\n    trisb_ptr-&gt;SWITCH_PIN = TRIS_PIN_INPUT;\n    trisb_ptr-&gt;RED_LED_PIN = TRIS_PIN_OUTPUT;\n    trisb_ptr-&gt;YELLOW_LED_PIN = TRIS_PIN_OUTPUT;\n    \n    portb_ptr-&gt;port = PORT_ALL_LOW;\n    \n    \n    intcon_reg_ptr-&gt;INTF = INT_FLAG_CLEAR;\n    intcon_reg_ptr-&gt;INTE = INT_ENABLE;\n    intcon_reg_ptr-&gt;GIE = INT_ENABLE;\n    \n    option_reg_ptr-&gt;INTEDG = INT_EDGE_RISING; \n      \n    while(1);\n}\n<\/pre>\n\nKodun \u00e7al\u0131\u015ft\u0131r\u0131laca\u011f\u0131 devre bir <a href=\"http:\/\/ozenozkaya.com\/blog\/?p=422\" target=\"_blank\">\u00f6nceki yaz\u0131dakilerle<\/a> ayn\u0131. Yani \u00e7\u0131kt\u0131 a\u015fa\u011f\u0131daki gibi olacak.\n\n<a href=\"http:\/\/ozenozkaya.com\/blog\/wp-content\/uploads\/switch2.png\"><img class=\"alignnone size-full wp-image-424\" src=\"http:\/\/ozenozkaya.com\/blog\/wp-content\/uploads\/switch2.png\" alt=\"switch2\" width=\"600\" height=\"600\" \/><\/a>\n\n<a href=\"http:\/\/ozenozkaya.com\/blog\/wp-content\/uploads\/switch1.png\"><img class=\"alignnone size-full wp-image-423\" src=\"http:\/\/ozenozkaya.com\/blog\/wp-content\/uploads\/switch1.png\" alt=\"switch1\" width=\"601\" height=\"598\" \/><\/a>\n\n\u015eimdi gelelim fas\u00fclyenin faydalar\u0131na.\u00a0Kesmeyi nas\u0131l kullanaca\u011f\u0131m\u0131z\u0131 nereden bildik? PIC16F84A'n\u0131n veri ka\u011f\u0131d\u0131n\u0131n 6.8 Interrupts ba\u015fl\u0131kl\u0131 k\u0131sm\u0131nda hangi registerlar\u0131 nas\u0131l konfig\u00fcre etmemiz gerekti\u011fi a\u00e7\u0131k\u00e7a yaz\u0131yor. Bildi\u011finiz gibi bu yaz\u0131 dizisinde kendi yazd\u0131klar\u0131m\u0131zdan ba\u015fka bir k\u00fct\u00fcphane kullanm\u0131yoruz. Bunun amac\u0131 her \u015feyi temelinden anlamakt\u0131. Do\u011fal olarak kullanaca\u011f\u0131m\u0131z yeni registerlar i\u00e7in de tan\u0131mlamalar\u0131 yap\u0131yoruz. A\u015fa\u011f\u0131da OPTION ve INTCON k\u00fct\u00fcklerinin (registerlar\u0131n\u0131n) adres tan\u0131mlar\u0131n\u0131 ve yard\u0131mc\u0131 etiketleri g\u00f6rebilirsiniz. Buna ek olarak bir de BIT_TOGGLE makrosu tan\u0131mlad\u0131k. Bu makronun amac\u0131 bir biti birse s\u0131f\u0131r, s\u0131f\u0131rsa bir yapmak. Bunu ileride kullanaca\u011f\u0131z.\n\n<pre class=\"lang:c decode:true\" title=\"k\u00fct\u00fck tan\u0131mlar\">#define REG_INTCON_ADDR (0x0B)\n#define REG_INTCON (*( volatile unsigned char*)REG_INTCON_ADDR)\n#define INT_ENABLE (1)\n#define INT_DISABLE (0)\n#define INT_FLAG_CLEAR (0)\n\n#define REG_OPTION_ADDR (0x81)\n#define REG_OPTION (*( volatile unsigned char*)REG_OPTION_ADDR)\n#define INT_EDGE_FALLING (0)\n#define INT_EDGE_RISING  (1)\n\n#define BIT_TOGGLE(x) (x^=1)<\/pre>\n\nRegisterlar\u0131n modellenmesini ise a\u015fa\u011f\u0131daki gibi yapt\u0131k.\n\n<pre class=\"lang:c decode:true \" title=\"k\u00fct\u00fck modelleme\">typedef struct\n{\n    unsigned char RBIF:1;\n    unsigned char INTF:1;\n    unsigned char T0IF:1;\n    unsigned char RBIE:1;\n    unsigned char INTE:1;\n    unsigned char T0IE:1;\n    unsigned char EEIE:1;\n    unsigned char GIE:1;\n}intcon_reg_t,*intcon_reg_ptr_t;\n\ntypedef struct\n{\n    unsigned char PS:3;\n    unsigned char PSA:1;\n    unsigned char T0SE:1;\n    unsigned char T0CS:1;\n    unsigned char INTEDG:1;\n    unsigned char RBPU:1;\n}option_reg_t,*option_reg_ptr_t;\n<\/pre>\n\nBu tan\u0131mlamalar\u0131 datasheetten bak\u0131p yapt\u0131ktan sonra INTCON ve OPTION k\u00fct\u00fcklerini g\u00f6sterecek i\u015faret\u00e7ileri a\u015fa\u011f\u0131daki gibi tan\u0131mlad\u0131k.\n\n<pre class=\"lang:c decode:true \" title=\"k\u00fct\u00fck i\u015faret\u00e7ileri\">intcon_reg_t *intcon_reg_ptr= (intcon_reg_ptr_t)REG_INTCON_ADDR;\noption_reg_t *option_reg_ptr = (option_reg_ptr_t)REG_OPTION_ADDR;<\/pre>\n\nArd\u0131ndan gelelim ana fonksiyon(main)\u00a0i\u00e7inde yapt\u0131\u011f\u0131m\u0131z ek konfig\u00fcrasyonlara.\n\n<pre class=\"lang:c decode:true\">option_reg_ptr-&gt;INTEDG = INT_EDGE_RISING; \n    \nintcon_reg_ptr-&gt;INTF = INT_FLAG_CLEAR;\nintcon_reg_ptr-&gt;INTE = INT_ENABLE;\nintcon_reg_ptr-&gt;GIE = INT_ENABLE;<\/pre>\n\n\u00d6ncelikle kesme bayra\u011f\u0131n\u0131n temiz oldu\u011fundan emin olmak i\u00e7in onu temizledik. Ard\u0131ndan INTE ile RB0\/INT kesmesine izin verdik. Ard\u0131ndan da global kesme aktivasyonu i\u00e7in GIE bitini\u00a0etkinle\u015ftirdik. GIE ve INTE bitlerinin ikisi de 1 de\u011ferini almadan kesme ger\u00e7ekle\u015femez. Bunu da verika\u011f\u0131d\u0131ndaki a\u015fa\u011f\u0131daki \u015femadan anlayabiliyoruz.\n\n<a href=\"http:\/\/ozenozkaya.com\/blog\/wp-content\/uploads\/int_logic.png\"><img class=\"alignnone size-full wp-image-436\" src=\"http:\/\/ozenozkaya.com\/blog\/wp-content\/uploads\/int_logic.png\" alt=\"int_logic\" width=\"313\" height=\"234\" \/><\/a>\n\nKonfig\u00fcrasyonda kesmeyi de y\u00fckselen kenarda olacak \u015fekilde ayarlad\u0131k. Buna g\u00f6re anahtar s\u0131f\u0131rdan bire \u00e7ekildi\u011finde y\u00fckselen kenar kesmesi gelecek. Ama burada bir sorun var, bize hem y\u00fckselen kenar hem d\u00fc\u015fen kenarda kesme gerekiyor. \u00c7\u00fcnk\u00fc anahtar\u0131n konumu s\u0131f\u0131rdan bire de\u011fi\u015fti\u011finde de birden s\u0131f\u0131ra de\u011fi\u015fti\u011finde de kesme almak ve LED'lerin durumunu de\u011fi\u015ftirmek istiyoruz. PIC'te b\u00f6yle do\u011frudan b\u00f6yle bir se\u00e7enek yok; ya y\u00fckselen kenar kesmesi se\u00e7ilebiliyor ya da d\u00fc\u015fen kenar. Burada beyin bedava diyoruz ve kafay\u0131 \u00e7al\u0131\u015ft\u0131rarak soruna \u00e7\u00f6z\u00fcm sunuyoruz. \u00d6nce y\u00fckselen kenar kesmesini aktive etti\u011fimizi d\u00fc\u015f\u00fcnelim, bu durumda ilk gelen y\u00fckselen kenar kesmesinin hemen ard\u0131ndan d\u00fc\u015fen kenar kesmesini aktive edersek, switchin durumu tekrar de\u011fi\u015fti\u011finde kesme alabiliriz. Yani y\u00fckselen\/d\u00fc\u015fen kenar konfig\u00fcrasyonunu, kesme olu\u015ftu\u011funda toggle etmemiz gerekiyor. Kesme tamamland\u0131\u011f\u0131nda kesme bayra\u011f\u0131n\u0131 yani INTF bitini de s\u0131f\u0131ra \u00e7ekip temizlemek gerekiyor. Kodda da bunlar\u0131 yapt\u0131k. PIC'te kesme fonksiyonu fonksiyon ad\u0131n\u0131n ba\u015f\u0131na gelen \"interrupt\" kelimesi ile derleyiciye anlat\u0131l\u0131r. Buna g\u00f6re kesme fonksiyonumuz a\u015fa\u011f\u0131daki gibi oluyor.\n\n<pre class=\"lang:c decode:true \" title=\"kesme\">    \nstatic void interrupt global_isr_handler()\n{\n    if(intcon_reg_ptr-&gt;INTF)\n    {\n        switch(portb_ptr-&gt;SWITCH_PIN)\n            {\n                case PORT_PIN_LOW:\n                    portb_ptr-&gt;RED_LED_PIN = LED_ON;\n                    portb_ptr-&gt;YELLOW_LED_PIN = LED_OFF;\n                    break;\n                case PORT_PIN_HIGH:\n                    portb_ptr-&gt;RED_LED_PIN = LED_OFF;\n                    portb_ptr-&gt;YELLOW_LED_PIN = LED_ON;    \n                    break;\n                default:\n                    break;        \n            }\n        BIT_TOGGLE(option_reg_ptr-&gt;INTEDG);\n        intcon_reg_ptr-&gt;INTF=INT_FLAG_CLEAR;\n    }\n}\n<\/pre>\n\nPIC'te t\u00fcm kesmeler tek bir fonksiyon i\u00e7ine d\u00fc\u015fer, bu da interrupt \u00f6n ekli fonksiyondur. Bu sebeple bu fonksiyonun ad\u0131n\u0131 global_isr_handler koyduk. Daha sonra gelen kesmenin RB0\/INT\u00a0olup olmad\u0131\u011f\u0131n\u0131 kontrol ettik ve e\u011fer o ise switch de\u011ferlendirmesi i\u015flemini yap\u0131p y\u00fckselen\/d\u00fc\u015fen kenar se\u00e7imini g\u00fcncelle\u015ftirip bayra\u011f\u0131 temizledik. INTEDG'nin toggle edilmesi ile hem d\u00fc\u015fen hem y\u00fckselen kenardaki de\u011fi\u015fimleri g\u00fczel bir oyun ile alg\u0131layabilir duruma geldik. \u00c7i\u00e7ek oldu.\n\n\u015eimdi gelelim bu kodun sorunlar\u0131na. Birincisi register tan\u0131mlar\u0131 giderek kabar\u0131yor ve onlar\u0131n ayr\u0131 bir *.h\u00a0dosyas\u0131\u00a0i\u00e7inde yer almas\u0131 gerekiyor art\u0131k. \u0130kincisi, ilk durumda switch'in durumuna bakmaks\u0131z\u0131n kesme konfigurasyonu yapt\u0131\u011f\u0131m\u0131z i\u00e7in ilk a\u00e7\u0131l\u0131\u015fta ledlerin ikisi de yanm\u0131yor. \u00dc\u00e7\u00fcnc\u00fcs\u00fc de \u015fu, madem her kesme ayn\u0131 fonksiyona d\u00fc\u015fecek, ileride kod daha da b\u00fcy\u00fcd\u00fc\u011f\u00fcnde kesme fonksiyonu s\u00fcrekli de\u011fi\u015ftirilecek ve e\u011fer birisi orada yanl\u0131\u015f bayraklar\u0131 temizlerse ya da kurarsa, \u00f6nceden yaz\u0131lm\u0131\u015f k\u0131s\u0131mlar da bundan etkilenecek ve kodun her yeri bozulacak. Bu \u00e7ok b\u00fcy\u00fck bir risk. Burada SDK tasar\u0131m\u0131 devreye giriyor. Ak\u0131ll\u0131ca bir se\u00e7enek, kesme fonksiyonunu kullan\u0131c\u0131 program\u0131ndan ay\u0131rmak olacakt\u0131r. Burada kesme bayraklar\u0131n\u0131n y\u00f6netiminin de otomatik yap\u0131lmas\u0131 da isabetli olacakt\u0131r. Bu olay ger\u00e7ekten bir ileri tasar\u0131m \u00f6\u011fesidir ancak ad\u0131m ad\u0131m oraya gidece\u011fiz. Kodun bir di\u011fer \u00f6nemli sorunu da k\u00fct\u00fcphane kullanmayaca\u011f\u0131z inad\u0131m\u0131zla kullanmad\u0131\u011f\u0131m\u0131z stdint k\u00fct\u00fcphanesidir. \"unsigned char\" gibi boyutu \"hay\u0131rl\u0131s\u0131\" olan bir veri tipi kullanmak yerine \"uint8_t\" ile modelleme yapmam\u0131z daha temiz olurdu. Nitekim amac\u0131m\u0131z PIC k\u00fct\u00fcphanelerini kullanmadan, daha iyi \u015fekilde temelden olay\u0131 yazarak olay\u0131n dinamiklerini anlamakt\u0131. Bu da stdint'e ge\u00e7i\u015fimizi engellemiyor. Bir di\u011fer eksik nokta da register tan\u0131mlar\u0131yla ilgili. <a href=\"http:\/\/ozenozkaya.com\/blog\/?p=422\" target=\"_blank\">\u00d6nceki yaz\u0131da<\/a>, sebeplerini s\u0131ralad\u0131\u011f\u0131m\u0131z \u00fczere hem bit hem de byte eri\u015fimi sa\u011flayabilmek i\u00e7in k\u00fct\u00fck modellemelerinde union kullanm\u0131\u015ft\u0131k. Yeni modelledi\u011fimiz k\u00fct\u00fcklerde de bunu uygulamakta fayda var. Bunlara g\u00f6re projemizi yine d\u00fczenleyelim :)\n\n<strong>Switch ve LED Uygulamas\u0131 v2<\/strong>\n\nBu projede 3 adet dosyam\u0131z olacak. Birincisi pic16f84a k\u00fct\u00fcphanemizin header dosyas\u0131. Bu dosya (pic16f84a_lib.h) a\u015fa\u011f\u0131daki gibidir.\n\n<pre class=\"lang:c decode:true\" title=\"pic16f84a_lib.h\">\/* \n * File:   pic16f84a_lib.h\n * Author: ozenozkaya\n *\n * Created on 20 Temmuz 2015 Pazartesi, 00:05\n *\/\n\n#ifndef PIC16F84A_LIB_H\n#define    PIC16F84A_LIB_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n \n#include &lt;stdint.h&gt;\n\n#define F_OSC (1000000UL)\n\n#define REG_TRISB_ADDR (0x86)\n#define REG_TRISB (*( volatile unsigned char*)REG_TRISB_ADDR)\n#define TRIS_PIN_OUTPUT (0)\n#define TRIS_PIN_INPUT  (1)\n#define TRIS_PORT_OUTPUT (0)\n#define TRIS_PORT_INPUT  (0xFF)\n\n#define REG_PORTB_ADDR (0x06)\n#define REG_PORTB (*( volatile unsigned char*)REG_PORTB_ADDR)\n#define PORT_PIN_LOW  (0)\n#define PORT_PIN_HIGH (1)\n#define PORT_ALL_LOW  (0)\n#define PORT_ALL_HIGH (0xFF)\n\n#define REG_INTCON_ADDR (0x0B)\n#define REG_INTCON (*( volatile unsigned char*)REG_INTCON_ADDR)\n#define INT_ENABLE (1)\n#define INT_DISABLE (0)\n#define INT_FLAG_CLEAR (0)\n\n#define REG_OPTION_ADDR (0x81)\n#define REG_OPTION (*( volatile unsigned char*)REG_OPTION_ADDR)\n#define INT_EDGE_FALLING (0)\n#define INT_EDGE_RISING  (1)\n    \n#define MAX_INT_CALLBACK_NUM (5)\n\ntypedef struct \n{\n    uint8_t pin0:1;\n    uint8_t pin1:1;\n    uint8_t pin2:1;\n    uint8_t pin3:1;\n    uint8_t pin4:1;\n    uint8_t pin5:1;\n    uint8_t pin6:1;\n    uint8_t pin7:1;\n}_tris_port_pin_t, *_tris_port_pin_ptr_t;\n\ntypedef struct\n{\n    uint8_t RBIF:1;\n    uint8_t INTF:1;\n    uint8_t T0IF:1;\n    uint8_t RBIE:1;\n    uint8_t INTE:1;\n    uint8_t T0IE:1;\n    uint8_t EEIE:1;\n    uint8_t GIE:1;\n}_intcon_reg_t,*_intcon_reg_ptr_t;\n\ntypedef struct\n{\n    uint8_t PS:3;\n    uint8_t PSA:1;\n    uint8_t T0SE:1;\n    uint8_t T0CS:1;\n    uint8_t INTEDG:1;\n    uint8_t RBPU:1;\n}_option_reg_t,*_option_reg_ptr_t;\n\ntypedef union\n{\n    _tris_port_pin_t pins;\n    uint8_t port;\n}tris_port_t,*tris_port_ptr_t;\n\ntypedef union\n{\n  _option_reg_t bits;\n  uint8_t value;  \n}option_reg_t, *option_reg_ptr_t;\n\ntypedef union\n{\n  _intcon_reg_t bits;\n  uint8_t value;  \n}intcon_reg_t, *intcon_reg_ptr_t;\n\ntypedef void (*rb0_int_callback_t)();\n\n\nint8_t register_rb0_int_callback(rb0_int_callback_t new_cb);\nint8_t unregister_rb0_int_callback(rb0_int_callback_t cb_to_unreg);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif \/* PIC16F84A_LIB_H *\/\n<\/pre>\n\nYine\u00a0pic16f84a k\u00fct\u00fcphanemizin kaynak dosyas\u0131 (pic16f84a_lib.c) a\u015fa\u011f\u0131daki gibidir.\n\n<pre class=\"lang:c decode:true\" title=\"pic16f84a_lib.c\">#include \"pic16f84a_lib.h\"\n\n#define BIT_TOGGLE(x) (x^=1)\n\n#ifndef NULL\n#define NULL ((void*)0)\n#endif\n\nrb0_int_callback_t rb0_int_callback_list[MAX_INT_CALLBACK_NUM];\n\nstatic void interrupt global_isr_handler()\n{\n    intcon_reg_t *intcon_reg_ptr= (intcon_reg_ptr_t)REG_INTCON_ADDR;\n    option_reg_t *option_reg_ptr = (option_reg_ptr_t)REG_OPTION_ADDR;\n    \n    uint32_t cb_index=0;\n    if(intcon_reg_ptr-&gt;bits.INTF)\n    {\n        for(cb_index=0;cb_index&lt;MAX_INT_CALLBACK_NUM; cb_index++)\n        {\n            if(NULL != rb0_int_callback_list[cb_index])\n            {\n                rb0_int_callback_list[cb_index]();\n            }\n        }\n        BIT_TOGGLE(option_reg_ptr-&gt;bits.INTEDG);\n        intcon_reg_ptr-&gt;bits.INTF=INT_FLAG_CLEAR;\n    }\n}\n\nint8_t register_rb0_int_callback(rb0_int_callback_t new_cb)\n{\n    uint32_t cb_index=0;\n    if(NULL != new_cb)\n    {\n        for(cb_index=0;cb_index&lt;MAX_INT_CALLBACK_NUM; cb_index++)\n        {\n            if(NULL == rb0_int_callback_list[cb_index])\n            {\n                rb0_int_callback_list[cb_index]=new_cb;\n            }\n        }\n        if(MAX_INT_CALLBACK_NUM == cb_index)\n        {\n            return -2; \/\/All callbacks are already registered\n        }\n    }\n    else\n    {\n        return -1; \/\/ Callback is NULL\n    }\n    return 0;\n}\n\nint8_t unregister_rb0_int_callback(rb0_int_callback_t cb_to_unreg)\n{\n    uint32_t cb_index=0;\n    if(NULL != cb_to_unreg)\n    {\n        for(cb_index=0;cb_index&lt;MAX_INT_CALLBACK_NUM; cb_index++)\n        {\n            if(cb_to_unreg == rb0_int_callback_list[cb_index])\n            {\n                rb0_int_callback_list[cb_index]=NULL;\n            }\n        }\n    }\n    else\n    {\n        return -1; \/\/ Callback is NULL\n    }\n    return 0;\n}\n<\/pre>\n\nVe nihayetinde ana program\u0131m\u0131z (main.c) a\u015fa\u011f\u0131daki gibidir:\n\n<pre class=\"lang:c decode:true\" title=\"main.c\">\/* \n * File:   main.c\n * Author: ozenozkaya\n *\n * Created on 20 Temmuz 2015 Sali, 23:47\n *\/\n\n#include \"pic16f84a_lib.h\"\n\n#define SWITCH_PIN pins.pin0\n#define RED_LED_PIN pins.pin1\n#define YELLOW_LED_PIN pins.pin2\n\n#define LED_ON (PORT_PIN_HIGH)\n#define LED_OFF (PORT_PIN_LOW)\n\nstatic tris_port_t *portb_ptr=(tris_port_ptr_t)REG_PORTB_ADDR;\nstatic tris_port_t *trisb_ptr=(tris_port_ptr_t)REG_TRISB_ADDR;\n    \nstatic void switch_event_manager()\n{\n    switch(portb_ptr-&gt;SWITCH_PIN)\n        {\n            case PORT_PIN_LOW:\n                portb_ptr-&gt;RED_LED_PIN = LED_ON;\n                portb_ptr-&gt;YELLOW_LED_PIN = LED_OFF;\n                break;\n            case PORT_PIN_HIGH:\n                portb_ptr-&gt;RED_LED_PIN = LED_OFF;\n                portb_ptr-&gt;YELLOW_LED_PIN = LED_ON;    \n                break;\n            default:\n                break;        \n        }\n}\n\nstatic void initialize_switch_and_leds()\n{\n    trisb_ptr-&gt;port = TRIS_PORT_INPUT;\n    trisb_ptr-&gt;SWITCH_PIN = TRIS_PIN_INPUT;\n    trisb_ptr-&gt;RED_LED_PIN = TRIS_PIN_OUTPUT;\n    trisb_ptr-&gt;YELLOW_LED_PIN = TRIS_PIN_OUTPUT;\n    \n    portb_ptr-&gt;port = PORT_ALL_LOW;\n    \n    switch_event_manager();\n}\n\nstatic void initialize_switch_interrupt()\n{\n    intcon_reg_t *intcon_reg_ptr= (intcon_reg_ptr_t)REG_INTCON_ADDR;\n    option_reg_t *option_reg_ptr = (option_reg_ptr_t)REG_OPTION_ADDR;\n    \n    register_rb0_int_callback(switch_event_manager);\n    \n    option_reg_ptr-&gt;bits.INTEDG = INT_EDGE_RISING;\n        \n    intcon_reg_ptr-&gt;bits.INTF = INT_FLAG_CLEAR;\n    intcon_reg_ptr-&gt;bits.INTE = INT_ENABLE;\n    intcon_reg_ptr-&gt;bits.GIE = INT_ENABLE;     \n}\n\nvoid main() {\n\n    initialize_switch_and_leds();\n    initialize_switch_interrupt();\n      \n    while(1);\n}\n<\/pre>\n\nKodda, vadetti\u011fimiz t\u00fcm de\u011fi\u015fiklikleri yapm\u0131\u015f olduk. En en en en en \u00f6nemli yer, kullan\u0131c\u0131n\u0131n yani main dosyas\u0131n\u0131n kesme fonksiyonunu hi\u00e7 bir \u015fekilde g\u00f6rmeden kesme i\u015flemlerini haber almas\u0131. Bunun i\u00e7in SDK geli\u015ftiricisi olarak \u00e7\u0131kard\u0131\u011f\u0131m\u0131z fonksiyonu kullanc\u0131 a\u015fa\u011f\u0131daki \u015fekilde\u00a0\u00e7a\u011f\u0131rm\u0131\u015f oldu:\n\n<pre class=\"lang:c decode:true \"> register_rb0_int_callback(switch_event_manager);<\/pre>\n\nBu fonksiyonun implementasyonu da tam anlam\u0131yla ibretlik. Maksimum 5 kaynak RB0\/INT kesmesine abone olabiliyor. Bu geni\u015fletilebilirlik a\u00e7\u0131s\u0131ndan \u00e7ok \u00e7ok \u00f6nemli. Biz switch kodunu yar\u0131n \u00f6b\u00fcrg\u00fcn \"switch geldi\u011finde bir de d\u00fcd\u00fck \u00e7als\u0131n\" isteriyle geni\u015fletmek istedi\u011fimizde d\u00fcd\u00fc\u011f\u00fc \u00e7alacak fonksiyonu da register edecersek o d\u00fcd\u00fck \u00e7al\u0131nacakt\u0131r ve bizim \u00f6nceki i\u015flerimiz asla bundan etkilenmeyecektir. Bu olaya l\u00fctfen \u00e7ok dikkat ediniz. Listeye kaydolmu\u015f fonksiyonlar\u0131n yani callback'lerin \u00e7a\u011f\u0131r\u0131ld\u0131\u011f\u0131 sat\u0131r ise a\u015fa\u011f\u0131daki sat\u0131r.\n\n<pre class=\"lang:c decode:true  \">rb0_int_callback_list[cb_index]();<\/pre>\n\n\u015eimdilik bu kadar :) Bu g\u00fcn epey fantastik mevzulara de\u011findik. PIC deyip ge\u00e7memek gerek, bu basit alet i\u00e7in bile ileri d\u00fczey tasar\u0131m yapmak m\u00fcmk\u00fcn. Nitekim daha da ilerleyece\u011fiz.\u00a0Yaz\u0131lar devam edecek.\n\nYaz\u0131lar\u0131 be\u011fendiyseniz, faydalanabilecek tan\u0131d\u0131klar\u0131n\u0131zla payla\u015fmay\u0131 unutmay\u0131n\u0131z.\n\n[su_button url=\"http:\/\/ozenozkaya.com\/blog\/?p=422\" style=\"3d\"\u00a0icon=\"icon: arrow-circle-o-left\"]\u00d6nceki Sayfa[\/su_button] \u00a0[su_button url=\"http:\/\/ozenozkaya.com\/blog\/?p=457\" style=\"3d\" icon=\"icon: arrow-circle-right\"]Sonraki Sayfa[\/su_button]\n\n&nbsp;","_tr_post_name":"pic-programlama-6-kesmeler-interrupts","_tr_post_excerpt":"","_tr_post_title":"PIC Programlama \u2013 6 \u2013 Kesmeler (Interrupts)","_en_post_content":"","_en_post_name":"","_en_post_excerpt":"","_en_post_title":"","edit_language":"tr","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"enabled":false},"version":2}},"categories":[2,3],"tags":[],"class_list":["post-432","post","type-post","status-publish","format-standard","hentry","category-elektronik","category-gomulu-sistemler"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p5gWM6-6Y","jetpack-related-posts":[],"_links":{"self":[{"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/432","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=432"}],"version-history":[{"count":0,"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/432\/revisions"}],"wp:attachment":[{"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=432"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=432"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=432"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}