{"id":457,"date":"2015-07-31T18:54:36","date_gmt":"2015-07-31T15:54:36","guid":{"rendered":"http:\/\/ozenozkaya.com\/blog\/?p=457"},"modified":"2015-07-31T18:54:36","modified_gmt":"2015-07-31T15:54:36","slug":"pic-programlama-7-kesmeler-interrupts-2","status":"publish","type":"post","link":"http:\/\/ozenozkaya.com\/blog\/?p=457","title":{"rendered":"PIC Programlama \u2013 7 \u2013 Kesmeler (Interrupts) 2"},"content":{"rendered":"<p>Merhabalar, ge\u00e7en yaz\u0131da RB0\/INT kesmesini bahane ederek kesmeler hakk\u0131nda bir tak\u0131m feyizli i\u015fler yapm\u0131\u015ft\u0131k. Bu yaz\u0131m\u0131zda da kesmelere olan sevgimizi ve ilgimizi peki\u015ftirerek, ilgin\u00e7 bir ba\u015fka \u00f6rnek yapaca\u011f\u0131z ve yeni ibretlerle kar\u015f\u0131la\u015faca\u011f\u0131z. PIC mikrodenetleyicilerde de bir ta\u015f \u00fcst\u00fcne bir ta\u015f daha koyal\u0131m diyerekten bu g\u00fcnk\u00fc \u00f6rne\u011fimizi PORTB de\u011fi\u015fme kesmesi \u00fczerinden ger\u00e7ekleyece\u011fiz.<\/p>\n<p>Bundan seneler \u00f6nce, g\u00f6m\u00fcl\u00fc sistemlerdeki ilk d\u00f6nemlerimde; keypad (tu\u015f tak\u0131m\u0131) s\u00fcrmekten nefret ederdim \u00e7\u00fcnk\u00fc mikrodenetleyicilerde kullan\u0131m\u0131 hem zordu hem de inan\u0131lmaz derecede verimsiz\u00a0idi. Tu\u015f tak\u0131m\u0131n\u0131n pinlerini matris gibi d\u00fc\u015f\u00fcn\u00fcrsek, s\u00fct\u00fcnlar\u0131 ikili d\u00fczende her seferinde bir pin 1&#8217;de di\u011ferleri 0&#8217;da olacak \u015fekilde, 1 olan pini bir kayd\u0131rarak s\u00fcrerdik ve o esnada da sat\u0131r pinlerini input olarak ayarlay\u0131p de\u011ferini okuyup hangi pine bas\u0131ld\u0131\u011f\u0131n\u0131 anlamaya \u00e7al\u0131\u015f\u0131rd\u0131k. Bu olay son derece can s\u0131k\u0131c\u0131 bir olayd\u0131 ama neyse ki bu can s\u0131k\u0131c\u0131 durumu uzunca bir s\u00fcredir unutmu\u015ftum. Ta ki bu yaz\u0131y\u0131 kafamda planlayana kadar. Bu yaz\u0131, bu \u00e7irkin y\u00f6nteme bir tepki olabilirdi, olacak da.<\/p>\n<p>Bir donan\u0131m\u0131 s\u00fcrmek i\u00e7in yaz\u0131lan kodun kesmeler yerine polling (s\u00fcrekli de\u011fer okuma\/yazma yani bir nevi deneme yan\u0131lma) ile s\u00fcr\u00fclmesi gerek performans a\u00e7\u0131s\u0131ndan gerek g\u00fc\u00e7 t\u00fcketimi a\u00e7\u0131s\u0131ndan k\u00f6t\u00fc\u00a0bir durum. \u00d6te yandan tu\u015f tak\u0131m\u0131 s\u00fcr\u00fclmesini anlatan <a href=\"http:\/\/ww1.microchip.com\/downloads\/en\/AppNotes\/01081a.pdf\" target=\"_blank\">resmi d\u00f6k\u00fcmanlar<\/a> bile en iyi \u00e7\u00f6z\u00fcm olarak kesme\/polling hibrit kodlar veriyorlar. Bu da olduk\u00e7a verimsiz bir duruma tekab\u00fcl ediyor. Daha \u00f6nce tu\u015f tak\u0131m\u0131 s\u00fcren arkada\u015flar eminim anlayacaklard\u0131r.\u00a0Tu\u015ftak\u0131m\u0131 s\u00fcrme i\u015finin sadece kesme ile yap\u0131labilmesi g\u00fczel olurdu. \u00d6yleyse sadece kesmeyle yapal\u0131m \ud83d\ude42 Arada PORTB de\u011fi\u015fme kesmesini de anlatm\u0131\u015f olaca\u011f\u0131z.<\/p>\n<p><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-459\" src=\"https:\/\/i0.wp.com\/ozenozkaya.com\/blog\/wp-content\/uploads\/keypad.png?resize=640%2C538\" alt=\"keypad\" width=\"640\" height=\"538\" \/><\/p>\n<p>G\u00f6rd\u00fc\u011f\u00fcn\u00fcz \u00fczere b portunun 4-7 aras\u0131 pinleri pull down yaparak sat\u0131r giri\u015flerine ba\u011flad\u0131k. Yine 0-3 aras\u0131 pinlerle keypadin s\u00fctun pinlerini s\u00fcrece\u011fiz. Pull down ama\u00e7l\u0131 koydu\u011fumuz diren\u00e7ler bize \u00e7ok yard\u0131mc\u0131 olacak \ud83d\ude09 \u015eimdi gelelim kodlara. \u00d6ncelikle g\u00fcncelledi\u011fimiz k\u00fct\u00fcphanelerimiz a\u015fa\u011f\u0131daki gibi:<\/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\n#define REG_TRISA_ADDR (0x85)\n#define REG_TRISA (*( volatile unsigned char*)REG_TRISA_ADDR)\n    \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    \n#define REG_PORTA_ADDR (0x05)\n#define REG_PORTA (*( volatile unsigned char*)REG_PORTA_ADDR)\n    \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\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 (2)\n\ntypedef struct \n{\n    \/\/one bit is stored in one BYTE\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)();\ntypedef void (*portb_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\nint8_t register_portb_int_callback(portb_int_callback_t new_cb);\nint8_t unregister_portb_int_callback(portb_int_callback_t cb_to_unreg);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif \/* PIC16F84A_LIB_H *\/\n<\/pre>\n<p>Ve yukar\u0131daki header dosyas\u0131na ili\u015fkin kaynak kodu a\u015fa\u011f\u0131da:<\/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];\nportb_int_callback_t portb_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    if(intcon_reg_ptr-&gt;bits.RBIF)\n    {\n        for(cb_index=0;cb_index&lt;MAX_INT_CALLBACK_NUM; cb_index++)\n        {\n            if(NULL != portb_int_callback_list[cb_index])\n            {\n                portb_int_callback_list[cb_index]();\n            }\n        }\n        BIT_TOGGLE(option_reg_ptr-&gt;bits.INTEDG);\n        intcon_reg_ptr-&gt;bits.RBIF=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\nint8_t register_portb_int_callback(portb_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 == portb_int_callback_list[cb_index])\n            {\n                portb_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\n\n\nint8_t unregister_portb_int_callback(portb_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 == portb_int_callback_list[cb_index])\n            {\n                portb_int_callback_list[cb_index]=NULL;\n            }\n        }\n    }\n    else\n    {\n        return -1; \/\/ Callback is NULL\n    }\n    return 0;\n}\n\n<\/pre>\n<p>G\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi TRISA ve PORTA k\u00fct\u00fcklerini de modelledik ve ayr\u0131ca k\u00fct\u00fcphaneyi PORTB kesmesini de destekleyecek hale getirdik. \u015eimdi gelelim main fonksiyonunun bulundu\u011fu main.c&#8217;ye \ud83d\ude42<\/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 KEYPAD_DRIVE0_PIN pins.pin0\n#define KEYPAD_DRIVE1_PIN pins.pin1\n#define KEYPAD_DRIVE2_PIN pins.pin2\n\n#define KEYPAD_SCAN0_PIN pins.pin4\n#define KEYPAD_SCAN1_PIN pins.pin5\n#define KEYPAD_SCAN2_PIN pins.pin6\n#define KEYPAD_SCAN3_PIN pins.pin7\n    \nstatic void keypad_event_manager()\n{\n    tris_port_t *portb_ptr=(tris_port_ptr_t)REG_PORTB_ADDR;\n    tris_port_t *porta_ptr=(tris_port_ptr_t)REG_PORTA_ADDR;\n    uint8_t cnt=0;\n\n    portb_ptr-&gt;port |=0x01;\n    for(cnt=0;cnt&lt;3;cnt++)\n    {\n        portb_ptr-&gt;port &amp;= 0xF8;  \n        portb_ptr-&gt;port |= (1 &lt;&lt; cnt);\n        \n        switch((portb_ptr-&gt;port&amp;0xF0)&gt;&gt;4)\n        {\n            case 1:\n                porta_ptr-&gt;port=0x01+cnt;\n                break;\n            case 2:\n                porta_ptr-&gt;port=0x04+cnt;\n                break;\n            case 4:\n                porta_ptr-&gt;port=0x07+cnt;\n                break;\n            case 8:\n                switch(cnt)\n                {\n                    case 0:\n                        porta_ptr-&gt;port=0x0A;\n                        break;\n                    case 1:\n                        porta_ptr-&gt;port=0x00;\n                        break;\n                    case 2:\n                        porta_ptr-&gt;port=0x0B;\n                        break;\n                }\n                break;\n            default:\n                break;\n\n        } \n    }\n    \n    portb_ptr-&gt;KEYPAD_DRIVE0_PIN = PORT_PIN_HIGH;\n    portb_ptr-&gt;KEYPAD_DRIVE1_PIN = PORT_PIN_HIGH;\n    portb_ptr-&gt;KEYPAD_DRIVE2_PIN = PORT_PIN_HIGH;\n            \n}\n\nstatic void initialize_keypad_and_leds()\n{\n    tris_port_t *portb_ptr=(tris_port_ptr_t)REG_PORTB_ADDR;\n    tris_port_t *trisb_ptr=(tris_port_ptr_t)REG_TRISB_ADDR;\n    tris_port_t *porta_ptr=(tris_port_ptr_t)REG_PORTA_ADDR;\n    tris_port_t *trisa_ptr=(tris_port_ptr_t)REG_TRISA_ADDR;\n    \n    trisb_ptr-&gt;port = TRIS_PORT_INPUT;\n    trisb_ptr-&gt;KEYPAD_SCAN0_PIN = TRIS_PIN_INPUT;\n    trisb_ptr-&gt;KEYPAD_SCAN1_PIN = TRIS_PIN_INPUT;\n    trisb_ptr-&gt;KEYPAD_SCAN2_PIN = TRIS_PIN_INPUT;\n    trisb_ptr-&gt;KEYPAD_SCAN3_PIN = TRIS_PIN_INPUT;\n    trisb_ptr-&gt;KEYPAD_DRIVE0_PIN = TRIS_PIN_OUTPUT;\n    trisb_ptr-&gt;KEYPAD_DRIVE1_PIN = TRIS_PIN_OUTPUT;\n    trisb_ptr-&gt;KEYPAD_DRIVE2_PIN = TRIS_PIN_OUTPUT;\n    \n    portb_ptr-&gt;port = PORT_ALL_LOW;\n    portb_ptr-&gt;KEYPAD_DRIVE0_PIN = PORT_PIN_HIGH;\n    portb_ptr-&gt;KEYPAD_DRIVE1_PIN = PORT_PIN_HIGH;\n    portb_ptr-&gt;KEYPAD_DRIVE2_PIN = PORT_PIN_HIGH;\n    \n    trisa_ptr-&gt;port = TRIS_PORT_OUTPUT;\n    porta_ptr-&gt;port = PORT_ALL_LOW;\n   \n}\n\nstatic void initialize_keypad_event()\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_portb_int_callback(keypad_event_manager);\n    \n    option_reg_ptr-&gt;bits.INTEDG = INT_EDGE_RISING;\n        \n    intcon_reg_ptr-&gt;bits.RBIF= INT_FLAG_CLEAR;\n    intcon_reg_ptr-&gt;bits.RBIE = INT_ENABLE;\n    intcon_reg_ptr-&gt;bits.GIE = INT_ENABLE;     \n}\n\nvoid main() {\n\n    initialize_keypad_and_leds();\n    initialize_keypad_event();\n      \n    while(1);\n}\n<\/pre>\n<p>G\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi gerekli pin ayarlamalar\u0131n\u0131 yapt\u0131ktan sonra, kesmeyi a\u015fa\u011f\u0131daki gibi aktive ettik:<\/p>\n<pre class=\"lang:c decode:true \">intcon_reg_ptr-&gt;bits.RBIE = INT_ENABLE;<\/pre>\n<p>Ard\u0131ndan, yazd\u0131\u011f\u0131m\u0131z k\u00fct\u00fcphaneye ekledi\u011fimiz callback registration (fonksiyon bildirimi kayd\u0131) mekanizmas\u0131n\u0131 kullanarak kesme geldi\u011finde, haberdar olmak i\u00e7in initialize_keypad_event fonksiyonunu implement ettik. Buna g\u00f6re PORTB&#8217;nin 4-7 aras\u0131 pinlerinde gerilimsel bir de\u011fi\u015fme oldu\u011funda haberdar olaca\u011f\u0131z. Y\u00fckselen kenar\u0131 ilk konfigurasyon olarak almam\u0131z\u0131n sebebi ise, keypad sat\u0131r pinlerimizi donan\u0131msal olarak pull-down&#8217;a yani lojik s\u0131f\u0131ra \u00e7ekmi\u015f olmam\u0131z. Pull-down ne demek bilmiyorsan\u0131z <a href=\"http:\/\/ozenozkaya.com\/blog\/?p=136\" target=\"_blank\">buradan <\/a>\u00f6\u011frenebilirsiniz.<\/p>\n<p>Bu durumda kodumuz tamamen kesme ile \u00e7al\u0131\u015facak \u015fekilde tamamlanm\u0131\u015f oldu ve ba\u015far\u0131yla da \u00e7al\u0131\u015f\u0131yor. Ancak yine i\u00e7imize sinmeyen baz\u0131 noktalar var. Bunlardan birincisi \u015fu a\u015fa\u011f\u0131daki sat\u0131r.<\/p>\n<pre class=\"lang:c decode:true\">portb_ptr-&gt;port &amp;= 0xF8;<\/pre>\n<p>Bu sat\u0131r\u0131n amac\u0131, B portunun ilk 3 pinini 0 de\u011ferine \u00e7ekmek ama bunu yaparken di\u011ferlerini de\u011fi\u015ftirmemek. Asl\u0131nda bu sat\u0131r daha anla\u015f\u0131l\u0131r \u015fekilde a\u015fa\u011f\u0131daki gibi de implement edilebilirdi.<\/p>\n<pre class=\"lang:default decode:true \">portb_ptr-&gt;KEYPAD_DRIVE0_PIN = PORT_PIN_LOW;\nportb_ptr-&gt;KEYPAD_DRIVE1_PIN = PORT_PIN_LOW;\nportb_ptr-&gt;KEYPAD_DRIVE2_PIN = PORT_PIN_LOW;<\/pre>\n<p>Peki neden yukar\u0131daki gibi yazmad\u0131k? \u00c7ok daha anla\u015f\u0131l\u0131r olurdu oysa ki. \u0130\u015fte burada cevap &#8220;performans&#8221;. Tek sat\u0131r olan kod e\u011fer di\u011ferinden daha k\u0131sa s\u00fcrede i\u015fletiliyorsa, o zaman zaman kaybetmemek i\u00e7in anla\u015f\u0131l\u0131rl\u0131ktan feda edilebilir, ki burada yap\u0131lan da o \ud83d\ude42 Ancak bu durumda bile anla\u015f\u0131l\u0131rl\u0131\u011f\u0131 kaybetmemek m\u00fcmk\u00fcn. Nas\u0131l m\u0131? Comment yani yorum sat\u0131rlar\u0131 ekleyerek. Bu vesileyle bir kez daha yorum sat\u0131rlar\u0131n\u0131n ne denli \u00f6nemli oldu\u011funa de\u011finmekte fayda var. Kodu iyile\u015ftirmek i\u00e7in akl\u0131mda baz\u0131 hinlikler var ama \u00f6nce kodun bellek kullan\u0131m\u0131na bakal\u0131m.<\/p>\n<p>Yukar\u0131daki kodun bellek kullan\u0131m\u0131 a\u015fa\u011f\u0131daki gibi:<\/p>\n<pre class=\"lang:default decode:true \">Memory Summary:\n    Program space        used   264h (   612) of   400h words   ( 59.8%)\n    Data space           used    25h (    37) of    44h bytes   ( 54.4%)\n    EEPROM space         used     0h (     0) of    40h bytes   (  0.0%)\n    Data stack space     used     0h (     0) of    1Fh bytes   (  0.0%)\n    Configuration bits   used     0h (     0) of     1h word    (  0.0%)\n    ID Location space    used     0h (     0) of     4h bytes   (  0.0%)<\/pre>\n<p>\u015eimdi iyile\u015ftirme yapt\u0131\u011f\u0131m\u0131z main.c dosyam\u0131za bakal\u0131m.<\/p>\n<pre class=\"lang:c decode:true \" title=\"main.c\">\/**\n * @file main.c\n * @author \u00d6zen \u00d6zkaya\n * @date 31 July 2015\n * @brief File containing example of keypad interfacing by using PORTB \n * interrupt of PIC16F84A. Keypad is attached to B port pins of PIC and a \n * 7-SEG display is attached to A port pins of PIC. Application displays the\n * last pressed number of keypad on 7-SEG led display. \n *\n * This file is freely published and distributed in my blog.\n * @see http:\/\/ozenozkaya.com\/blog\/\n *\/\n\n#include \"pic16f84a_lib.h\"\n\n#define KEYPAD_DRIVE0_PIN pins.pin0\n#define KEYPAD_DRIVE1_PIN pins.pin1\n#define KEYPAD_DRIVE2_PIN pins.pin2\n\n#define KEYPAD_SCAN0_PIN pins.pin4\n#define KEYPAD_SCAN1_PIN pins.pin5\n#define KEYPAD_SCAN2_PIN pins.pin6\n#define KEYPAD_SCAN3_PIN pins.pin7\n\n#define KEYPAD_DIRECTION_REG    ((tris_port_ptr_t)REG_TRISB_ADDR)\n#define KEYPAD_PORT_REG         ((tris_port_ptr_t)REG_PORTB_ADDR)\n\n#define SEVEN_SEG_DIRECTION_REG    ((tris_port_ptr_t)REG_TRISA_ADDR)\n#define SEVEN_SEG_PORT_REG         ((tris_port_ptr_t)REG_PORTA_ADDR)\n \n\n\/**\n * @brief keypad_event_manager function is an interrupt callback function.\n *\n * We register this function for PORTB change interrupt event. Normally,\n * keypad drive &amp; scan is done here. When user is pressed to any key in\n * keypad, interrupt occurs and this callback is called by our library.\n * Then here we scan &amp; drive keypad pins to detect the pressed button.\n * @see http:\/\/ozenozkaya.com\/blog\n * @note Please share if you like :)\n * @warning Do not forget to register this function with: .\n * @code\n * register_portb_int_callback(keypad_event_manager);\n * @endcode\n *\/\nstatic void keypad_event_manager()\n{\n    uint8_t cnt=0;\n\n    KEYPAD_PORT_REG-&gt;KEYPAD_SCAN0_PIN =PORT_PIN_HIGH;\n    for(cnt=0;cnt&lt;3;cnt++)\n    {\n        KEYPAD_PORT_REG-&gt;port &amp;= 0xF8;  \n        \/*Here we are shifting the drive pin. Possible values:\n         1 0 0\n         0 1 0\n         0 0 1\n         By the way we scan each row*\/\n        KEYPAD_PORT_REG-&gt;port |= (1 &lt;&lt; cnt);\n        \n        switch((KEYPAD_PORT_REG-&gt;port&amp;0xF0)&gt;&gt;4)\n        {\n            case 1:\n                SEVEN_SEG_PORT_REG-&gt;port=0x01+cnt;\n                break;\n            case 2:\n                SEVEN_SEG_PORT_REG-&gt;port=0x04+cnt;\n                break;\n            case 4:\n                SEVEN_SEG_PORT_REG-&gt;port=0x07+cnt;\n                break;\n            case 8:\n                switch(cnt)\n                {\n                    case 0:\n                        SEVEN_SEG_PORT_REG-&gt;port=0x0A;\n                        break;\n                    case 1:\n                        SEVEN_SEG_PORT_REG-&gt;port=0x00;\n                        break;\n                    case 2:\n                        SEVEN_SEG_PORT_REG-&gt;port=0x0B;\n                        break;\n                }\n                break;\n            default:\n                break;\n\n        } \n    }\n    \n    KEYPAD_PORT_REG-&gt;KEYPAD_DRIVE0_PIN = PORT_PIN_HIGH;\n    KEYPAD_PORT_REG-&gt;KEYPAD_DRIVE1_PIN = PORT_PIN_HIGH;\n    KEYPAD_PORT_REG-&gt;KEYPAD_DRIVE2_PIN = PORT_PIN_HIGH;\n            \n}\n\nstatic void initialize_keypad_and_leds()\n{   \n    KEYPAD_DIRECTION_REG-&gt;port = TRIS_PORT_INPUT;\n    KEYPAD_DIRECTION_REG-&gt;KEYPAD_SCAN0_PIN = TRIS_PIN_INPUT;\n    KEYPAD_DIRECTION_REG-&gt;KEYPAD_SCAN1_PIN = TRIS_PIN_INPUT;\n    KEYPAD_DIRECTION_REG-&gt;KEYPAD_SCAN2_PIN = TRIS_PIN_INPUT;\n    KEYPAD_DIRECTION_REG-&gt;KEYPAD_SCAN3_PIN = TRIS_PIN_INPUT;\n    KEYPAD_DIRECTION_REG-&gt;KEYPAD_DRIVE0_PIN = TRIS_PIN_OUTPUT;\n    KEYPAD_DIRECTION_REG-&gt;KEYPAD_DRIVE1_PIN = TRIS_PIN_OUTPUT;\n    KEYPAD_DIRECTION_REG-&gt;KEYPAD_DRIVE2_PIN = TRIS_PIN_OUTPUT;\n    \n    \n    KEYPAD_PORT_REG-&gt;port = PORT_ALL_LOW;\n    KEYPAD_PORT_REG-&gt;KEYPAD_DRIVE0_PIN = PORT_PIN_HIGH;\n    KEYPAD_PORT_REG-&gt;KEYPAD_DRIVE1_PIN = PORT_PIN_HIGH;\n    KEYPAD_PORT_REG-&gt;KEYPAD_DRIVE2_PIN = PORT_PIN_HIGH;\n    \n    SEVEN_SEG_DIRECTION_REG-&gt;port = TRIS_PORT_OUTPUT;\n    SEVEN_SEG_PORT_REG-&gt;port = PORT_ALL_LOW;\n   \n}\n\nstatic void initialize_keypad_event()\n{    \n    register_portb_int_callback(keypad_event_manager);\n    \n    ((option_reg_ptr_t)REG_OPTION_ADDR)-&gt;bits.INTEDG = INT_EDGE_RISING;\n        \n    ((intcon_reg_ptr_t)REG_INTCON_ADDR)-&gt;bits.RBIF= INT_FLAG_CLEAR;\n    ((intcon_reg_ptr_t)REG_INTCON_ADDR)-&gt;bits.RBIE = INT_ENABLE;\n    ((intcon_reg_ptr_t)REG_INTCON_ADDR)-&gt;bits.GIE = INT_ENABLE;     \n}\n\nvoid main() {\n\n    initialize_keypad_and_leds();\n    initialize_keypad_event();\n      \n    while(1);\n}<\/pre>\n<p>Yap\u0131lan de\u011fi\u015fiklikleri k\u0131saca s\u0131ralarsak:<\/p>\n<ul>\n<li>Register eri\u015fimi i\u00e7in de\u011fi\u015fken kullan\u0131m\u0131n\u0131 ortadan kald\u0131rd\u0131k.\u00a0Ve bu i\u015f i\u00e7in hi\u00e7 de\u011fi\u015fken kullanmad\u0131k!<\/li>\n<li>Bellek bayram etti (mi acaba, g\u00f6rece\u011fiz \ud83d\ude42 ama etti)<\/li>\n<li>Kodun anla\u015f\u0131labilirli\u011fini \u00e7e\u015fitli define ve yorum sat\u0131rlar\u0131 ile boost ettik.<\/li>\n<li>Doxygen stili d\u00f6k\u00fcmantasyon yaparak (hepsini yapmasak da \ud83d\ude09 ) o i\u015fi de kodun \u00fczerinde aradan \u00e7\u0131kard\u0131k.<\/li>\n<\/ul>\n<p>Ve g\u00fcncellenmi\u015f main kodumuzun oldu\u011fu uygulaman\u0131n bellek kullan\u0131m\u0131:<\/p>\n<pre class=\"lang:default decode:true \">Memory Summary:\n    Program space        used   1B8h (   440) of   400h words   ( 43.0%)\n    Data space           used    1Dh (    29) of    44h bytes   ( 42.6%)\n    EEPROM space         used     0h (     0) of    40h bytes   (  0.0%)\n    Data stack space     used     0h (     0) of    27h bytes   (  0.0%)\n    Configuration bits   used     0h (     0) of     1h word    (  0.0%)\n    ID Location space    used     0h (     0) of     4h bytes   (  0.0%)<\/pre>\n<p>&nbsp;<\/p>\n<p>G\u00f6rd\u00fc\u011f\u00fcn\u00fcz \u00fczere program alan\u0131 kullan\u0131m\u0131n\u0131 612&#8217;den 440 worde (1 word=2 byte) d\u00fc\u015f\u00fcrd\u00fck. Ayr\u0131ca veri alan\u0131 kullan\u0131m\u0131n\u0131 da 37 byte&#8217;dan 29 byte&#8217;a d\u00fc\u015f\u00fcrd\u00fck \ud83d\ude42 \u0130\u015fte bu elle tutulur bir optimizasyon.<\/p>\n<p>Keypad&#8217;i de tertemiz, kesme kullanarak s\u00fcrm\u00fc\u015f olduk. Arada PORTB de\u011fi\u015fme kesmesi nas\u0131l kullan\u0131l\u0131r onu da hallettik. Say\u0131s\u0131z ibretlere de de\u011findi\u011fimizden bu g\u00fcnl\u00fck bu kadar diyoruz \ud83d\ude42<\/p>\n<p>&nbsp;<\/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=432\" 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=470\" 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","protected":false},"excerpt":{"rendered":"<p>Merhabalar, ge\u00e7en yaz\u0131da RB0\/INT kesmesini bahane ederek kesmeler hakk\u0131nda bir tak\u0131m feyizli i\u015fler yapm\u0131\u015ft\u0131k. Bu yaz\u0131m\u0131zda da kesmelere olan sevgimizi ve ilgimizi peki\u015ftirerek, ilgin\u00e7 bir ba\u015fka \u00f6rnek yapaca\u011f\u0131z ve yeni ibretlerle kar\u015f\u0131la\u015faca\u011f\u0131z. PIC mikrodenetleyicilerde de bir ta\u015f \u00fcst\u00fcne bir ta\u015f daha koyal\u0131m diyerekten bu g\u00fcnk\u00fc \u00f6rne\u011fimizi PORTB de\u011fi\u015fme kesmesi \u00fczerinden ger\u00e7ekleyece\u011fiz. Bundan seneler \u00f6nce, g\u00f6m\u00fcl\u00fc <a class=\"read-more\" href=\"http:\/\/ozenozkaya.com\/blog\/?p=457\">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":"Merhabalar, ge\u00e7en yaz\u0131da RB0\/INT kesmesini bahane ederek kesmeler hakk\u0131nda bir tak\u0131m feyizli i\u015fler yapm\u0131\u015ft\u0131k. Bu yaz\u0131m\u0131zda da kesmelere olan sevgimizi ve ilgimizi peki\u015ftirerek, ilgin\u00e7 bir ba\u015fka \u00f6rnek yapaca\u011f\u0131z ve yeni ibretlerle kar\u015f\u0131la\u015faca\u011f\u0131z. PIC mikrodenetleyicilerde de bir ta\u015f \u00fcst\u00fcne bir ta\u015f daha koyal\u0131m diyerekten bu g\u00fcnk\u00fc \u00f6rne\u011fimizi PORTB de\u011fi\u015fme kesmesi \u00fczerinden ger\u00e7ekleyece\u011fiz.\n\nBundan seneler \u00f6nce, g\u00f6m\u00fcl\u00fc sistemlerdeki ilk d\u00f6nemlerimde; keypad (tu\u015f tak\u0131m\u0131) s\u00fcrmekten nefret ederdim \u00e7\u00fcnk\u00fc mikrodenetleyicilerde kullan\u0131m\u0131 hem zordu hem de inan\u0131lmaz derecede verimsiz\u00a0idi. Tu\u015f tak\u0131m\u0131n\u0131n pinlerini matris gibi d\u00fc\u015f\u00fcn\u00fcrsek, s\u00fct\u00fcnlar\u0131 ikili d\u00fczende her seferinde bir pin 1'de di\u011ferleri 0'da olacak \u015fekilde, 1 olan pini bir kayd\u0131rarak s\u00fcrerdik ve o esnada da sat\u0131r pinlerini input olarak ayarlay\u0131p de\u011ferini okuyup hangi pine bas\u0131ld\u0131\u011f\u0131n\u0131 anlamaya \u00e7al\u0131\u015f\u0131rd\u0131k. Bu olay son derece can s\u0131k\u0131c\u0131 bir olayd\u0131 ama neyse ki bu can s\u0131k\u0131c\u0131 durumu uzunca bir s\u00fcredir unutmu\u015ftum. Ta ki bu yaz\u0131y\u0131 kafamda planlayana kadar. Bu yaz\u0131, bu \u00e7irkin y\u00f6nteme bir tepki olabilirdi, olacak da.\n\nBir donan\u0131m\u0131 s\u00fcrmek i\u00e7in yaz\u0131lan kodun kesmeler yerine polling (s\u00fcrekli de\u011fer okuma\/yazma yani bir nevi deneme yan\u0131lma) ile s\u00fcr\u00fclmesi gerek performans a\u00e7\u0131s\u0131ndan gerek g\u00fc\u00e7 t\u00fcketimi a\u00e7\u0131s\u0131ndan k\u00f6t\u00fc\u00a0bir durum. \u00d6te yandan tu\u015f tak\u0131m\u0131 s\u00fcr\u00fclmesini anlatan <a href=\"http:\/\/ww1.microchip.com\/downloads\/en\/AppNotes\/01081a.pdf\" target=\"_blank\">resmi d\u00f6k\u00fcmanlar<\/a> bile en iyi \u00e7\u00f6z\u00fcm olarak kesme\/polling hibrit kodlar veriyorlar. Bu da olduk\u00e7a verimsiz bir duruma tekab\u00fcl ediyor. Daha \u00f6nce tu\u015f tak\u0131m\u0131 s\u00fcren arkada\u015flar eminim anlayacaklard\u0131r.\u00a0Tu\u015ftak\u0131m\u0131 s\u00fcrme i\u015finin sadece kesme ile yap\u0131labilmesi g\u00fczel olurdu. \u00d6yleyse sadece kesmeyle yapal\u0131m :) Arada PORTB de\u011fi\u015fme kesmesini de anlatm\u0131\u015f olaca\u011f\u0131z.\n\n<img class=\"alignnone size-full wp-image-459\" src=\"http:\/\/ozenozkaya.com\/blog\/wp-content\/uploads\/keypad.png\" alt=\"keypad\" width=\"680\" height=\"572\" \/>\n\nG\u00f6rd\u00fc\u011f\u00fcn\u00fcz \u00fczere b portunun 4-7 aras\u0131 pinleri pull down yaparak sat\u0131r giri\u015flerine ba\u011flad\u0131k. Yine 0-3 aras\u0131 pinlerle keypadin s\u00fctun pinlerini s\u00fcrece\u011fiz. Pull down ama\u00e7l\u0131 koydu\u011fumuz diren\u00e7ler bize \u00e7ok yard\u0131mc\u0131 olacak ;) \u015eimdi gelelim kodlara. \u00d6ncelikle g\u00fcncelledi\u011fimiz k\u00fct\u00fcphanelerimiz a\u015fa\u011f\u0131daki gibi:\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\n#define REG_TRISA_ADDR (0x85)\n#define REG_TRISA (*( volatile unsigned char*)REG_TRISA_ADDR)\n    \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    \n#define REG_PORTA_ADDR (0x05)\n#define REG_PORTA (*( volatile unsigned char*)REG_PORTA_ADDR)\n    \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\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 (2)\n\ntypedef struct \n{\n    \/\/one bit is stored in one BYTE\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)();\ntypedef void (*portb_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\nint8_t register_portb_int_callback(portb_int_callback_t new_cb);\nint8_t unregister_portb_int_callback(portb_int_callback_t cb_to_unreg);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif \/* PIC16F84A_LIB_H *\/\n<\/pre>\n\nVe yukar\u0131daki header dosyas\u0131na ili\u015fkin kaynak kodu a\u015fa\u011f\u0131da:\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];\nportb_int_callback_t portb_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    if(intcon_reg_ptr-&gt;bits.RBIF)\n    {\n        for(cb_index=0;cb_index&lt;MAX_INT_CALLBACK_NUM; cb_index++)\n        {\n            if(NULL != portb_int_callback_list[cb_index])\n            {\n                portb_int_callback_list[cb_index]();\n            }\n        }\n        BIT_TOGGLE(option_reg_ptr-&gt;bits.INTEDG);\n        intcon_reg_ptr-&gt;bits.RBIF=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\nint8_t register_portb_int_callback(portb_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 == portb_int_callback_list[cb_index])\n            {\n                portb_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\n\n\nint8_t unregister_portb_int_callback(portb_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 == portb_int_callback_list[cb_index])\n            {\n                portb_int_callback_list[cb_index]=NULL;\n            }\n        }\n    }\n    else\n    {\n        return -1; \/\/ Callback is NULL\n    }\n    return 0;\n}\n\n<\/pre>\n\nG\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi TRISA ve PORTA k\u00fct\u00fcklerini de modelledik ve ayr\u0131ca k\u00fct\u00fcphaneyi PORTB kesmesini de destekleyecek hale getirdik. \u015eimdi gelelim main fonksiyonunun bulundu\u011fu main.c'ye :)\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 KEYPAD_DRIVE0_PIN pins.pin0\n#define KEYPAD_DRIVE1_PIN pins.pin1\n#define KEYPAD_DRIVE2_PIN pins.pin2\n\n#define KEYPAD_SCAN0_PIN pins.pin4\n#define KEYPAD_SCAN1_PIN pins.pin5\n#define KEYPAD_SCAN2_PIN pins.pin6\n#define KEYPAD_SCAN3_PIN pins.pin7\n    \nstatic void keypad_event_manager()\n{\n    tris_port_t *portb_ptr=(tris_port_ptr_t)REG_PORTB_ADDR;\n    tris_port_t *porta_ptr=(tris_port_ptr_t)REG_PORTA_ADDR;\n    uint8_t cnt=0;\n\n    portb_ptr-&gt;port |=0x01;\n    for(cnt=0;cnt&lt;3;cnt++)\n    {\n        portb_ptr-&gt;port &amp;= 0xF8;  \n        portb_ptr-&gt;port |= (1 &lt;&lt; cnt);\n        \n        switch((portb_ptr-&gt;port&amp;0xF0)&gt;&gt;4)\n        {\n            case 1:\n                porta_ptr-&gt;port=0x01+cnt;\n                break;\n            case 2:\n                porta_ptr-&gt;port=0x04+cnt;\n                break;\n            case 4:\n                porta_ptr-&gt;port=0x07+cnt;\n                break;\n            case 8:\n                switch(cnt)\n                {\n                    case 0:\n                        porta_ptr-&gt;port=0x0A;\n                        break;\n                    case 1:\n                        porta_ptr-&gt;port=0x00;\n                        break;\n                    case 2:\n                        porta_ptr-&gt;port=0x0B;\n                        break;\n                }\n                break;\n            default:\n                break;\n\n        } \n    }\n    \n    portb_ptr-&gt;KEYPAD_DRIVE0_PIN = PORT_PIN_HIGH;\n    portb_ptr-&gt;KEYPAD_DRIVE1_PIN = PORT_PIN_HIGH;\n    portb_ptr-&gt;KEYPAD_DRIVE2_PIN = PORT_PIN_HIGH;\n            \n}\n\nstatic void initialize_keypad_and_leds()\n{\n    tris_port_t *portb_ptr=(tris_port_ptr_t)REG_PORTB_ADDR;\n    tris_port_t *trisb_ptr=(tris_port_ptr_t)REG_TRISB_ADDR;\n    tris_port_t *porta_ptr=(tris_port_ptr_t)REG_PORTA_ADDR;\n    tris_port_t *trisa_ptr=(tris_port_ptr_t)REG_TRISA_ADDR;\n    \n    trisb_ptr-&gt;port = TRIS_PORT_INPUT;\n    trisb_ptr-&gt;KEYPAD_SCAN0_PIN = TRIS_PIN_INPUT;\n    trisb_ptr-&gt;KEYPAD_SCAN1_PIN = TRIS_PIN_INPUT;\n    trisb_ptr-&gt;KEYPAD_SCAN2_PIN = TRIS_PIN_INPUT;\n    trisb_ptr-&gt;KEYPAD_SCAN3_PIN = TRIS_PIN_INPUT;\n    trisb_ptr-&gt;KEYPAD_DRIVE0_PIN = TRIS_PIN_OUTPUT;\n    trisb_ptr-&gt;KEYPAD_DRIVE1_PIN = TRIS_PIN_OUTPUT;\n    trisb_ptr-&gt;KEYPAD_DRIVE2_PIN = TRIS_PIN_OUTPUT;\n    \n    portb_ptr-&gt;port = PORT_ALL_LOW;\n    portb_ptr-&gt;KEYPAD_DRIVE0_PIN = PORT_PIN_HIGH;\n    portb_ptr-&gt;KEYPAD_DRIVE1_PIN = PORT_PIN_HIGH;\n    portb_ptr-&gt;KEYPAD_DRIVE2_PIN = PORT_PIN_HIGH;\n    \n    trisa_ptr-&gt;port = TRIS_PORT_OUTPUT;\n    porta_ptr-&gt;port = PORT_ALL_LOW;\n   \n}\n\nstatic void initialize_keypad_event()\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_portb_int_callback(keypad_event_manager);\n    \n    option_reg_ptr-&gt;bits.INTEDG = INT_EDGE_RISING;\n        \n    intcon_reg_ptr-&gt;bits.RBIF= INT_FLAG_CLEAR;\n    intcon_reg_ptr-&gt;bits.RBIE = INT_ENABLE;\n    intcon_reg_ptr-&gt;bits.GIE = INT_ENABLE;     \n}\n\nvoid main() {\n\n    initialize_keypad_and_leds();\n    initialize_keypad_event();\n      \n    while(1);\n}\n<\/pre>\n\nG\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi gerekli pin ayarlamalar\u0131n\u0131 yapt\u0131ktan sonra, kesmeyi a\u015fa\u011f\u0131daki gibi aktive ettik:\n\n<pre class=\"lang:c decode:true \">intcon_reg_ptr-&gt;bits.RBIE = INT_ENABLE;<\/pre>\n\nArd\u0131ndan, yazd\u0131\u011f\u0131m\u0131z k\u00fct\u00fcphaneye ekledi\u011fimiz callback registration (fonksiyon bildirimi kayd\u0131) mekanizmas\u0131n\u0131 kullanarak kesme geldi\u011finde, haberdar olmak i\u00e7in initialize_keypad_event fonksiyonunu implement ettik. Buna g\u00f6re PORTB'nin 4-7 aras\u0131 pinlerinde gerilimsel bir de\u011fi\u015fme oldu\u011funda haberdar olaca\u011f\u0131z. Y\u00fckselen kenar\u0131 ilk konfigurasyon olarak almam\u0131z\u0131n sebebi ise, keypad sat\u0131r pinlerimizi donan\u0131msal olarak pull-down'a yani lojik s\u0131f\u0131ra \u00e7ekmi\u015f olmam\u0131z. Pull-down ne demek bilmiyorsan\u0131z <a href=\"http:\/\/ozenozkaya.com\/blog\/?p=136\" target=\"_blank\">buradan <\/a>\u00f6\u011frenebilirsiniz.\n\nBu durumda kodumuz tamamen kesme ile \u00e7al\u0131\u015facak \u015fekilde tamamlanm\u0131\u015f oldu ve ba\u015far\u0131yla da \u00e7al\u0131\u015f\u0131yor. Ancak yine i\u00e7imize sinmeyen baz\u0131 noktalar var. Bunlardan birincisi \u015fu a\u015fa\u011f\u0131daki sat\u0131r.\n\n<pre class=\"lang:c decode:true\">portb_ptr-&gt;port &amp;= 0xF8;<\/pre>\n\nBu sat\u0131r\u0131n amac\u0131, B portunun ilk 3 pinini 0 de\u011ferine \u00e7ekmek ama bunu yaparken di\u011ferlerini de\u011fi\u015ftirmemek. Asl\u0131nda bu sat\u0131r daha anla\u015f\u0131l\u0131r \u015fekilde a\u015fa\u011f\u0131daki gibi de implement edilebilirdi.\n\n<pre class=\"lang:default decode:true \">portb_ptr-&gt;KEYPAD_DRIVE0_PIN = PORT_PIN_LOW;\nportb_ptr-&gt;KEYPAD_DRIVE1_PIN = PORT_PIN_LOW;\nportb_ptr-&gt;KEYPAD_DRIVE2_PIN = PORT_PIN_LOW;<\/pre>\n\nPeki neden yukar\u0131daki gibi yazmad\u0131k? \u00c7ok daha anla\u015f\u0131l\u0131r olurdu oysa ki. \u0130\u015fte burada cevap \"performans\". Tek sat\u0131r olan kod e\u011fer di\u011ferinden daha k\u0131sa s\u00fcrede i\u015fletiliyorsa, o zaman zaman kaybetmemek i\u00e7in anla\u015f\u0131l\u0131rl\u0131ktan feda edilebilir, ki burada yap\u0131lan da o :) Ancak bu durumda bile anla\u015f\u0131l\u0131rl\u0131\u011f\u0131 kaybetmemek m\u00fcmk\u00fcn. Nas\u0131l m\u0131? Comment yani yorum sat\u0131rlar\u0131 ekleyerek. Bu vesileyle bir kez daha yorum sat\u0131rlar\u0131n\u0131n ne denli \u00f6nemli oldu\u011funa de\u011finmekte fayda var. Kodu iyile\u015ftirmek i\u00e7in akl\u0131mda baz\u0131 hinlikler var ama \u00f6nce kodun bellek kullan\u0131m\u0131na bakal\u0131m.\n\nYukar\u0131daki kodun bellek kullan\u0131m\u0131 a\u015fa\u011f\u0131daki gibi:\n\n<pre class=\"lang:default decode:true \">Memory Summary:\n    Program space        used   264h (   612) of   400h words   ( 59.8%)\n    Data space           used    25h (    37) of    44h bytes   ( 54.4%)\n    EEPROM space         used     0h (     0) of    40h bytes   (  0.0%)\n    Data stack space     used     0h (     0) of    1Fh bytes   (  0.0%)\n    Configuration bits   used     0h (     0) of     1h word    (  0.0%)\n    ID Location space    used     0h (     0) of     4h bytes   (  0.0%)<\/pre>\n\n\u015eimdi iyile\u015ftirme yapt\u0131\u011f\u0131m\u0131z main.c dosyam\u0131za bakal\u0131m.\n\n<pre class=\"lang:c decode:true \" title=\"main.c\">\/**\n * @file main.c\n * @author \u00d6zen \u00d6zkaya\n * @date 31 July 2015\n * @brief File containing example of keypad interfacing by using PORTB \n * interrupt of PIC16F84A. Keypad is attached to B port pins of PIC and a \n * 7-SEG display is attached to A port pins of PIC. Application displays the\n * last pressed number of keypad on 7-SEG led display. \n *\n * This file is freely published and distributed in my blog.\n * @see http:\/\/ozenozkaya.com\/blog\/\n *\/\n\n#include \"pic16f84a_lib.h\"\n\n#define KEYPAD_DRIVE0_PIN pins.pin0\n#define KEYPAD_DRIVE1_PIN pins.pin1\n#define KEYPAD_DRIVE2_PIN pins.pin2\n\n#define KEYPAD_SCAN0_PIN pins.pin4\n#define KEYPAD_SCAN1_PIN pins.pin5\n#define KEYPAD_SCAN2_PIN pins.pin6\n#define KEYPAD_SCAN3_PIN pins.pin7\n\n#define KEYPAD_DIRECTION_REG    ((tris_port_ptr_t)REG_TRISB_ADDR)\n#define KEYPAD_PORT_REG         ((tris_port_ptr_t)REG_PORTB_ADDR)\n\n#define SEVEN_SEG_DIRECTION_REG    ((tris_port_ptr_t)REG_TRISA_ADDR)\n#define SEVEN_SEG_PORT_REG         ((tris_port_ptr_t)REG_PORTA_ADDR)\n \n\n\/**\n * @brief keypad_event_manager function is an interrupt callback function.\n *\n * We register this function for PORTB change interrupt event. Normally,\n * keypad drive &amp; scan is done here. When user is pressed to any key in\n * keypad, interrupt occurs and this callback is called by our library.\n * Then here we scan &amp; drive keypad pins to detect the pressed button.\n * @see http:\/\/ozenozkaya.com\/blog\n * @note Please share if you like :)\n * @warning Do not forget to register this function with: .\n * @code\n * register_portb_int_callback(keypad_event_manager);\n * @endcode\n *\/\nstatic void keypad_event_manager()\n{\n    uint8_t cnt=0;\n\n    KEYPAD_PORT_REG-&gt;KEYPAD_SCAN0_PIN =PORT_PIN_HIGH;\n    for(cnt=0;cnt&lt;3;cnt++)\n    {\n        KEYPAD_PORT_REG-&gt;port &amp;= 0xF8;  \n        \/*Here we are shifting the drive pin. Possible values:\n         1 0 0\n         0 1 0\n         0 0 1\n         By the way we scan each row*\/\n        KEYPAD_PORT_REG-&gt;port |= (1 &lt;&lt; cnt);\n        \n        switch((KEYPAD_PORT_REG-&gt;port&amp;0xF0)&gt;&gt;4)\n        {\n            case 1:\n                SEVEN_SEG_PORT_REG-&gt;port=0x01+cnt;\n                break;\n            case 2:\n                SEVEN_SEG_PORT_REG-&gt;port=0x04+cnt;\n                break;\n            case 4:\n                SEVEN_SEG_PORT_REG-&gt;port=0x07+cnt;\n                break;\n            case 8:\n                switch(cnt)\n                {\n                    case 0:\n                        SEVEN_SEG_PORT_REG-&gt;port=0x0A;\n                        break;\n                    case 1:\n                        SEVEN_SEG_PORT_REG-&gt;port=0x00;\n                        break;\n                    case 2:\n                        SEVEN_SEG_PORT_REG-&gt;port=0x0B;\n                        break;\n                }\n                break;\n            default:\n                break;\n\n        } \n    }\n    \n    KEYPAD_PORT_REG-&gt;KEYPAD_DRIVE0_PIN = PORT_PIN_HIGH;\n    KEYPAD_PORT_REG-&gt;KEYPAD_DRIVE1_PIN = PORT_PIN_HIGH;\n    KEYPAD_PORT_REG-&gt;KEYPAD_DRIVE2_PIN = PORT_PIN_HIGH;\n            \n}\n\nstatic void initialize_keypad_and_leds()\n{   \n    KEYPAD_DIRECTION_REG-&gt;port = TRIS_PORT_INPUT;\n    KEYPAD_DIRECTION_REG-&gt;KEYPAD_SCAN0_PIN = TRIS_PIN_INPUT;\n    KEYPAD_DIRECTION_REG-&gt;KEYPAD_SCAN1_PIN = TRIS_PIN_INPUT;\n    KEYPAD_DIRECTION_REG-&gt;KEYPAD_SCAN2_PIN = TRIS_PIN_INPUT;\n    KEYPAD_DIRECTION_REG-&gt;KEYPAD_SCAN3_PIN = TRIS_PIN_INPUT;\n    KEYPAD_DIRECTION_REG-&gt;KEYPAD_DRIVE0_PIN = TRIS_PIN_OUTPUT;\n    KEYPAD_DIRECTION_REG-&gt;KEYPAD_DRIVE1_PIN = TRIS_PIN_OUTPUT;\n    KEYPAD_DIRECTION_REG-&gt;KEYPAD_DRIVE2_PIN = TRIS_PIN_OUTPUT;\n    \n    \n    KEYPAD_PORT_REG-&gt;port = PORT_ALL_LOW;\n    KEYPAD_PORT_REG-&gt;KEYPAD_DRIVE0_PIN = PORT_PIN_HIGH;\n    KEYPAD_PORT_REG-&gt;KEYPAD_DRIVE1_PIN = PORT_PIN_HIGH;\n    KEYPAD_PORT_REG-&gt;KEYPAD_DRIVE2_PIN = PORT_PIN_HIGH;\n    \n    SEVEN_SEG_DIRECTION_REG-&gt;port = TRIS_PORT_OUTPUT;\n    SEVEN_SEG_PORT_REG-&gt;port = PORT_ALL_LOW;\n   \n}\n\nstatic void initialize_keypad_event()\n{    \n    register_portb_int_callback(keypad_event_manager);\n    \n    ((option_reg_ptr_t)REG_OPTION_ADDR)-&gt;bits.INTEDG = INT_EDGE_RISING;\n        \n    ((intcon_reg_ptr_t)REG_INTCON_ADDR)-&gt;bits.RBIF= INT_FLAG_CLEAR;\n    ((intcon_reg_ptr_t)REG_INTCON_ADDR)-&gt;bits.RBIE = INT_ENABLE;\n    ((intcon_reg_ptr_t)REG_INTCON_ADDR)-&gt;bits.GIE = INT_ENABLE;     \n}\n\nvoid main() {\n\n    initialize_keypad_and_leds();\n    initialize_keypad_event();\n      \n    while(1);\n}<\/pre>\n\nYap\u0131lan de\u011fi\u015fiklikleri k\u0131saca s\u0131ralarsak:\n\n<ul>\n    <li>Register eri\u015fimi i\u00e7in de\u011fi\u015fken kullan\u0131m\u0131n\u0131 ortadan kald\u0131rd\u0131k.\u00a0Ve bu i\u015f i\u00e7in hi\u00e7 de\u011fi\u015fken kullanmad\u0131k!<\/li>\n    <li>Bellek bayram etti (mi acaba, g\u00f6rece\u011fiz :) ama etti)<\/li>\n    <li>Kodun anla\u015f\u0131labilirli\u011fini \u00e7e\u015fitli define ve yorum sat\u0131rlar\u0131 ile boost ettik.<\/li>\n    <li>Doxygen stili d\u00f6k\u00fcmantasyon yaparak (hepsini yapmasak da ;) ) o i\u015fi de kodun \u00fczerinde aradan \u00e7\u0131kard\u0131k.<\/li>\n<\/ul>\n\nVe g\u00fcncellenmi\u015f main kodumuzun oldu\u011fu uygulaman\u0131n bellek kullan\u0131m\u0131:\n\n<pre class=\"lang:default decode:true \">Memory Summary:\n    Program space        used   1B8h (   440) of   400h words   ( 43.0%)\n    Data space           used    1Dh (    29) of    44h bytes   ( 42.6%)\n    EEPROM space         used     0h (     0) of    40h bytes   (  0.0%)\n    Data stack space     used     0h (     0) of    27h bytes   (  0.0%)\n    Configuration bits   used     0h (     0) of     1h word    (  0.0%)\n    ID Location space    used     0h (     0) of     4h bytes   (  0.0%)<\/pre>\n\n&nbsp;\n\nG\u00f6rd\u00fc\u011f\u00fcn\u00fcz \u00fczere program alan\u0131 kullan\u0131m\u0131n\u0131 612'den 440 worde (1 word=2 byte) d\u00fc\u015f\u00fcrd\u00fck. Ayr\u0131ca veri alan\u0131 kullan\u0131m\u0131n\u0131 da 37 byte'dan 29 byte'a d\u00fc\u015f\u00fcrd\u00fck :) \u0130\u015fte bu elle tutulur bir optimizasyon.\n\nKeypad'i de tertemiz, kesme kullanarak s\u00fcrm\u00fc\u015f olduk. Arada PORTB de\u011fi\u015fme kesmesi nas\u0131l kullan\u0131l\u0131r onu da hallettik. Say\u0131s\u0131z ibretlere de de\u011findi\u011fimizden bu g\u00fcnl\u00fck bu kadar diyoruz :)\n\n&nbsp;\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=432\" style=\"3d\"\u00a0icon=\"icon: arrow-circle-o-left\"]\u00d6nceki Sayfa[\/su_button] \u00a0[su_button url=\"http:\/\/ozenozkaya.com\/blog\/?p=470\" style=\"3d\" icon=\"icon: arrow-circle-right\"]Sonraki Sayfa[\/su_button]","_tr_post_name":"pic-programlama-7-kesmeler-interrupts-2","_tr_post_excerpt":"","_tr_post_title":"PIC Programlama \u2013 7 \u2013 Kesmeler (Interrupts) 2","_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-457","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-7n","jetpack-related-posts":[],"_links":{"self":[{"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/457","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=457"}],"version-history":[{"count":0,"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/457\/revisions"}],"wp:attachment":[{"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=457"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=457"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=457"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}