Merhabalar, geçen yazıda RB0/INT kesmesini bahane ederek kesmeler hakkında bir takım feyizli işler yapmıştık. Bu yazımızda da kesmelere olan sevgimizi ve ilgimizi pekiştirerek, ilginç bir başka örnek yapacağız ve yeni ibretlerle karşılaşacağız. PIC mikrodenetleyicilerde de bir taş üstüne bir taş daha koyalım diyerekten bu günkü örneğimizi PORTB değişme kesmesi üzerinden gerçekleyeceğiz.
Bundan seneler önce, gömülü sistemlerdeki ilk dönemlerimde; keypad (tuş takımı) sürmekten nefret ederdim çünkü mikrodenetleyicilerde kullanımı hem zordu hem de inanılmaz derecede verimsiz idi. Tuş takımının pinlerini matris gibi düşünürsek, sütünları ikili düzende her seferinde bir pin 1’de diğerleri 0’da olacak şekilde, 1 olan pini bir kaydırarak sürerdik ve o esnada da satır pinlerini input olarak ayarlayıp değerini okuyup hangi pine basıldığını anlamaya çalışırdık. Bu olay son derece can sıkıcı bir olaydı ama neyse ki bu can sıkıcı durumu uzunca bir süredir unutmuştum. Ta ki bu yazıyı kafamda planlayana kadar. Bu yazı, bu çirkin yönteme bir tepki olabilirdi, olacak da.
Bir donanımı sürmek için yazılan kodun kesmeler yerine polling (sürekli değer okuma/yazma yani bir nevi deneme yanılma) ile sürülmesi gerek performans açısından gerek güç tüketimi açısından kötü bir durum. Öte yandan tuş takımı sürülmesini anlatan resmi dökümanlar bile en iyi çözüm olarak kesme/polling hibrit kodlar veriyorlar. Bu da oldukça verimsiz bir duruma tekabül ediyor. Daha önce tuş takımı süren arkadaşlar eminim anlayacaklardır. Tuştakımı sürme işinin sadece kesme ile yapılabilmesi güzel olurdu. Öyleyse sadece kesmeyle yapalım 🙂 Arada PORTB değişme kesmesini de anlatmış olacağız.
Gördüğünüz üzere b portunun 4-7 arası pinleri pull down yaparak satır girişlerine bağladık. Yine 0-3 arası pinlerle keypadin sütun pinlerini süreceğiz. Pull down amaçlı koyduğumuz dirençler bize çok yardımcı olacak 😉 Şimdi gelelim kodlara. Öncelikle güncellediğimiz kütüphanelerimiz aşağıdaki gibi:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
/* * File: pic16f84a_lib.h * Author: ozenozkaya * * Created on 20 Temmuz 2015 Pazartesi, 00:05 */ #ifndef PIC16F84A_LIB_H #define PIC16F84A_LIB_H #ifdef __cplusplus extern "C" { #endif #include <stdint.h> #define F_OSC (1000000UL) #define REG_TRISB_ADDR (0x86) #define REG_TRISB (*( volatile unsigned char*)REG_TRISB_ADDR) #define REG_TRISA_ADDR (0x85) #define REG_TRISA (*( volatile unsigned char*)REG_TRISA_ADDR) #define TRIS_PIN_OUTPUT (0) #define TRIS_PIN_INPUT (1) #define TRIS_PORT_OUTPUT (0) #define TRIS_PORT_INPUT (0xFF) #define REG_PORTB_ADDR (0x06) #define REG_PORTB (*( volatile unsigned char*)REG_PORTB_ADDR) #define REG_PORTA_ADDR (0x05) #define REG_PORTA (*( volatile unsigned char*)REG_PORTA_ADDR) #define PORT_PIN_LOW (0) #define PORT_PIN_HIGH (1) #define PORT_ALL_LOW (0) #define PORT_ALL_HIGH (0xFF) #define REG_INTCON_ADDR (0x0B) #define REG_INTCON (*( volatile unsigned char*)REG_INTCON_ADDR) #define INT_ENABLE (1) #define INT_DISABLE (0) #define INT_FLAG_CLEAR (0) #define REG_OPTION_ADDR (0x81) #define REG_OPTION (*( volatile unsigned char*)REG_OPTION_ADDR) #define INT_EDGE_FALLING (0) #define INT_EDGE_RISING (1) #define MAX_INT_CALLBACK_NUM (2) typedef struct { //one bit is stored in one BYTE uint8_t pin0:1; uint8_t pin1:1; uint8_t pin2:1; uint8_t pin3:1; uint8_t pin4:1; uint8_t pin5:1; uint8_t pin6:1; uint8_t pin7:1; }_tris_port_pin_t, *_tris_port_pin_ptr_t; typedef struct { uint8_t RBIF:1; uint8_t INTF:1; uint8_t T0IF:1; uint8_t RBIE:1; uint8_t INTE:1; uint8_t T0IE:1; uint8_t EEIE:1; uint8_t GIE:1; }_intcon_reg_t,*_intcon_reg_ptr_t; typedef struct { uint8_t PS:3; uint8_t PSA:1; uint8_t T0SE:1; uint8_t T0CS:1; uint8_t INTEDG:1; uint8_t RBPU:1; }_option_reg_t,*_option_reg_ptr_t; typedef union { _tris_port_pin_t pins; uint8_t port; }tris_port_t,*tris_port_ptr_t; typedef union { _option_reg_t bits; uint8_t value; }option_reg_t, *option_reg_ptr_t; typedef union { _intcon_reg_t bits; uint8_t value; }intcon_reg_t, *intcon_reg_ptr_t; typedef void (*rb0_int_callback_t)(); typedef void (*portb_int_callback_t)(); int8_t register_rb0_int_callback(rb0_int_callback_t new_cb); int8_t unregister_rb0_int_callback(rb0_int_callback_t cb_to_unreg); int8_t register_portb_int_callback(portb_int_callback_t new_cb); int8_t unregister_portb_int_callback(portb_int_callback_t cb_to_unreg); #ifdef __cplusplus } #endif #endif /* PIC16F84A_LIB_H */ |
Ve yukarıdaki header dosyasına ilişkin kaynak kodu aşağıda:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
#include "pic16f84a_lib.h" #define BIT_TOGGLE(x) (x^=1) #ifndef NULL #define NULL ((void*)0) #endif rb0_int_callback_t rb0_int_callback_list[MAX_INT_CALLBACK_NUM]; portb_int_callback_t portb_int_callback_list[MAX_INT_CALLBACK_NUM]; static void interrupt global_isr_handler() { intcon_reg_t *intcon_reg_ptr= (intcon_reg_ptr_t)REG_INTCON_ADDR; option_reg_t *option_reg_ptr = (option_reg_ptr_t)REG_OPTION_ADDR; uint32_t cb_index=0; if(intcon_reg_ptr->bits.INTF) { for(cb_index=0;cb_index<MAX_INT_CALLBACK_NUM; cb_index++) { if(NULL != rb0_int_callback_list[cb_index]) { rb0_int_callback_list[cb_index](); } } BIT_TOGGLE(option_reg_ptr->bits.INTEDG); intcon_reg_ptr->bits.INTF=INT_FLAG_CLEAR; } if(intcon_reg_ptr->bits.RBIF) { for(cb_index=0;cb_index<MAX_INT_CALLBACK_NUM; cb_index++) { if(NULL != portb_int_callback_list[cb_index]) { portb_int_callback_list[cb_index](); } } BIT_TOGGLE(option_reg_ptr->bits.INTEDG); intcon_reg_ptr->bits.RBIF=INT_FLAG_CLEAR; } } int8_t register_rb0_int_callback(rb0_int_callback_t new_cb) { uint32_t cb_index=0; if(NULL != new_cb) { for(cb_index=0;cb_index<MAX_INT_CALLBACK_NUM; cb_index++) { if(NULL == rb0_int_callback_list[cb_index]) { rb0_int_callback_list[cb_index]=new_cb; } } if(MAX_INT_CALLBACK_NUM == cb_index) { return -2; //All callbacks are already registered } } else { return -1; // Callback is NULL } return 0; } int8_t unregister_rb0_int_callback(rb0_int_callback_t cb_to_unreg) { uint32_t cb_index=0; if(NULL != cb_to_unreg) { for(cb_index=0;cb_index<MAX_INT_CALLBACK_NUM; cb_index++) { if(cb_to_unreg == rb0_int_callback_list[cb_index]) { rb0_int_callback_list[cb_index]=NULL; } } } else { return -1; // Callback is NULL } return 0; } int8_t register_portb_int_callback(portb_int_callback_t new_cb) { uint32_t cb_index=0; if(NULL != new_cb) { for(cb_index=0;cb_index<MAX_INT_CALLBACK_NUM; cb_index++) { if(NULL == portb_int_callback_list[cb_index]) { portb_int_callback_list[cb_index]=new_cb; } } if(MAX_INT_CALLBACK_NUM == cb_index) { return -2; //All callbacks are already registered } } else { return -1; // Callback is NULL } return 0; } int8_t unregister_portb_int_callback(portb_int_callback_t cb_to_unreg) { uint32_t cb_index=0; if(NULL != cb_to_unreg) { for(cb_index=0;cb_index<MAX_INT_CALLBACK_NUM; cb_index++) { if(cb_to_unreg == portb_int_callback_list[cb_index]) { portb_int_callback_list[cb_index]=NULL; } } } else { return -1; // Callback is NULL } return 0; } |
Gördüğünüz gibi TRISA ve PORTA kütüklerini de modelledik ve ayrıca kütüphaneyi PORTB kesmesini de destekleyecek hale getirdik. Şimdi gelelim main fonksiyonunun bulunduğu main.c’ye 🙂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
/* * File: main.c * Author: ozenozkaya * * Created on 20 Temmuz 2015 Sali, 23:47 */ #include "pic16f84a_lib.h" #define KEYPAD_DRIVE0_PIN pins.pin0 #define KEYPAD_DRIVE1_PIN pins.pin1 #define KEYPAD_DRIVE2_PIN pins.pin2 #define KEYPAD_SCAN0_PIN pins.pin4 #define KEYPAD_SCAN1_PIN pins.pin5 #define KEYPAD_SCAN2_PIN pins.pin6 #define KEYPAD_SCAN3_PIN pins.pin7 static void keypad_event_manager() { tris_port_t *portb_ptr=(tris_port_ptr_t)REG_PORTB_ADDR; tris_port_t *porta_ptr=(tris_port_ptr_t)REG_PORTA_ADDR; uint8_t cnt=0; portb_ptr->port |=0x01; for(cnt=0;cnt<3;cnt++) { portb_ptr->port &= 0xF8; portb_ptr->port |= (1 << cnt); switch((portb_ptr->port&0xF0)>>4) { case 1: porta_ptr->port=0x01+cnt; break; case 2: porta_ptr->port=0x04+cnt; break; case 4: porta_ptr->port=0x07+cnt; break; case 8: switch(cnt) { case 0: porta_ptr->port=0x0A; break; case 1: porta_ptr->port=0x00; break; case 2: porta_ptr->port=0x0B; break; } break; default: break; } } portb_ptr->KEYPAD_DRIVE0_PIN = PORT_PIN_HIGH; portb_ptr->KEYPAD_DRIVE1_PIN = PORT_PIN_HIGH; portb_ptr->KEYPAD_DRIVE2_PIN = PORT_PIN_HIGH; } static void initialize_keypad_and_leds() { tris_port_t *portb_ptr=(tris_port_ptr_t)REG_PORTB_ADDR; tris_port_t *trisb_ptr=(tris_port_ptr_t)REG_TRISB_ADDR; tris_port_t *porta_ptr=(tris_port_ptr_t)REG_PORTA_ADDR; tris_port_t *trisa_ptr=(tris_port_ptr_t)REG_TRISA_ADDR; trisb_ptr->port = TRIS_PORT_INPUT; trisb_ptr->KEYPAD_SCAN0_PIN = TRIS_PIN_INPUT; trisb_ptr->KEYPAD_SCAN1_PIN = TRIS_PIN_INPUT; trisb_ptr->KEYPAD_SCAN2_PIN = TRIS_PIN_INPUT; trisb_ptr->KEYPAD_SCAN3_PIN = TRIS_PIN_INPUT; trisb_ptr->KEYPAD_DRIVE0_PIN = TRIS_PIN_OUTPUT; trisb_ptr->KEYPAD_DRIVE1_PIN = TRIS_PIN_OUTPUT; trisb_ptr->KEYPAD_DRIVE2_PIN = TRIS_PIN_OUTPUT; portb_ptr->port = PORT_ALL_LOW; portb_ptr->KEYPAD_DRIVE0_PIN = PORT_PIN_HIGH; portb_ptr->KEYPAD_DRIVE1_PIN = PORT_PIN_HIGH; portb_ptr->KEYPAD_DRIVE2_PIN = PORT_PIN_HIGH; trisa_ptr->port = TRIS_PORT_OUTPUT; porta_ptr->port = PORT_ALL_LOW; } static void initialize_keypad_event() { intcon_reg_t *intcon_reg_ptr= (intcon_reg_ptr_t)REG_INTCON_ADDR; option_reg_t *option_reg_ptr = (option_reg_ptr_t)REG_OPTION_ADDR; register_portb_int_callback(keypad_event_manager); option_reg_ptr->bits.INTEDG = INT_EDGE_RISING; intcon_reg_ptr->bits.RBIF= INT_FLAG_CLEAR; intcon_reg_ptr->bits.RBIE = INT_ENABLE; intcon_reg_ptr->bits.GIE = INT_ENABLE; } void main() { initialize_keypad_and_leds(); initialize_keypad_event(); while(1); } |
Gördüğünüz gibi gerekli pin ayarlamalarını yaptıktan sonra, kesmeyi aşağıdaki gibi aktive ettik:
1 |
intcon_reg_ptr->bits.RBIE = INT_ENABLE; |
Ardından, yazdığımız kütüphaneye eklediğimiz callback registration (fonksiyon bildirimi kaydı) mekanizmasını kullanarak kesme geldiğinde, haberdar olmak için initialize_keypad_event fonksiyonunu implement ettik. Buna göre PORTB’nin 4-7 arası pinlerinde gerilimsel bir değişme olduğunda haberdar olacağız. Yükselen kenarı ilk konfigurasyon olarak almamızın sebebi ise, keypad satır pinlerimizi donanımsal olarak pull-down’a yani lojik sıfıra çekmiş olmamız. Pull-down ne demek bilmiyorsanız buradan öğrenebilirsiniz.
Bu durumda kodumuz tamamen kesme ile çalışacak şekilde tamamlanmış oldu ve başarıyla da çalışıyor. Ancak yine içimize sinmeyen bazı noktalar var. Bunlardan birincisi şu aşağıdaki satır.
1 |
portb_ptr->port &= 0xF8; |
Bu satırın amacı, B portunun ilk 3 pinini 0 değerine çekmek ama bunu yaparken diğerlerini değiştirmemek. Aslında bu satır daha anlaşılır şekilde aşağıdaki gibi de implement edilebilirdi.
1 2 3 |
portb_ptr->KEYPAD_DRIVE0_PIN = PORT_PIN_LOW; portb_ptr->KEYPAD_DRIVE1_PIN = PORT_PIN_LOW; portb_ptr->KEYPAD_DRIVE2_PIN = PORT_PIN_LOW; |
Peki neden yukarıdaki gibi yazmadık? Çok daha anlaşılır olurdu oysa ki. İşte burada cevap “performans”. Tek satır olan kod eğer diğerinden daha kısa sürede işletiliyorsa, o zaman zaman kaybetmemek için anlaşılırlıktan feda edilebilir, ki burada yapılan da o 🙂 Ancak bu durumda bile anlaşılırlığı kaybetmemek mümkün. Nasıl mı? Comment yani yorum satırları ekleyerek. Bu vesileyle bir kez daha yorum satırlarının ne denli önemli olduğuna değinmekte fayda var. Kodu iyileştirmek için aklımda bazı hinlikler var ama önce kodun bellek kullanımına bakalım.
Yukarıdaki kodun bellek kullanımı aşağıdaki gibi:
1 2 3 4 5 6 7 |
Memory Summary: Program space used 264h ( 612) of 400h words ( 59.8%) Data space used 25h ( 37) of 44h bytes ( 54.4%) EEPROM space used 0h ( 0) of 40h bytes ( 0.0%) Data stack space used 0h ( 0) of 1Fh bytes ( 0.0%) Configuration bits used 0h ( 0) of 1h word ( 0.0%) ID Location space used 0h ( 0) of 4h bytes ( 0.0%) |
Şimdi iyileştirme yaptığımız main.c dosyamıza bakalım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
/** * @file main.c * @author Özen Özkaya * @date 31 July 2015 * @brief File containing example of keypad interfacing by using PORTB * interrupt of PIC16F84A. Keypad is attached to B port pins of PIC and a * 7-SEG display is attached to A port pins of PIC. Application displays the * last pressed number of keypad on 7-SEG led display. * * This file is freely published and distributed in my blog. * @see http://ozenozkaya.com/blog/ */ #include "pic16f84a_lib.h" #define KEYPAD_DRIVE0_PIN pins.pin0 #define KEYPAD_DRIVE1_PIN pins.pin1 #define KEYPAD_DRIVE2_PIN pins.pin2 #define KEYPAD_SCAN0_PIN pins.pin4 #define KEYPAD_SCAN1_PIN pins.pin5 #define KEYPAD_SCAN2_PIN pins.pin6 #define KEYPAD_SCAN3_PIN pins.pin7 #define KEYPAD_DIRECTION_REG ((tris_port_ptr_t)REG_TRISB_ADDR) #define KEYPAD_PORT_REG ((tris_port_ptr_t)REG_PORTB_ADDR) #define SEVEN_SEG_DIRECTION_REG ((tris_port_ptr_t)REG_TRISA_ADDR) #define SEVEN_SEG_PORT_REG ((tris_port_ptr_t)REG_PORTA_ADDR) /** * @brief keypad_event_manager function is an interrupt callback function. * * We register this function for PORTB change interrupt event. Normally, * keypad drive & scan is done here. When user is pressed to any key in * keypad, interrupt occurs and this callback is called by our library. * Then here we scan & drive keypad pins to detect the pressed button. * @see http://ozenozkaya.com/blog * @note Please share if you like :) * @warning Do not forget to register this function with: . * @code * register_portb_int_callback(keypad_event_manager); * @endcode */ static void keypad_event_manager() { uint8_t cnt=0; KEYPAD_PORT_REG->KEYPAD_SCAN0_PIN =PORT_PIN_HIGH; for(cnt=0;cnt<3;cnt++) { KEYPAD_PORT_REG->port &= 0xF8; /*Here we are shifting the drive pin. Possible values: 1 0 0 0 1 0 0 0 1 By the way we scan each row*/ KEYPAD_PORT_REG->port |= (1 << cnt); switch((KEYPAD_PORT_REG->port&0xF0)>>4) { case 1: SEVEN_SEG_PORT_REG->port=0x01+cnt; break; case 2: SEVEN_SEG_PORT_REG->port=0x04+cnt; break; case 4: SEVEN_SEG_PORT_REG->port=0x07+cnt; break; case 8: switch(cnt) { case 0: SEVEN_SEG_PORT_REG->port=0x0A; break; case 1: SEVEN_SEG_PORT_REG->port=0x00; break; case 2: SEVEN_SEG_PORT_REG->port=0x0B; break; } break; default: break; } } KEYPAD_PORT_REG->KEYPAD_DRIVE0_PIN = PORT_PIN_HIGH; KEYPAD_PORT_REG->KEYPAD_DRIVE1_PIN = PORT_PIN_HIGH; KEYPAD_PORT_REG->KEYPAD_DRIVE2_PIN = PORT_PIN_HIGH; } static void initialize_keypad_and_leds() { KEYPAD_DIRECTION_REG->port = TRIS_PORT_INPUT; KEYPAD_DIRECTION_REG->KEYPAD_SCAN0_PIN = TRIS_PIN_INPUT; KEYPAD_DIRECTION_REG->KEYPAD_SCAN1_PIN = TRIS_PIN_INPUT; KEYPAD_DIRECTION_REG->KEYPAD_SCAN2_PIN = TRIS_PIN_INPUT; KEYPAD_DIRECTION_REG->KEYPAD_SCAN3_PIN = TRIS_PIN_INPUT; KEYPAD_DIRECTION_REG->KEYPAD_DRIVE0_PIN = TRIS_PIN_OUTPUT; KEYPAD_DIRECTION_REG->KEYPAD_DRIVE1_PIN = TRIS_PIN_OUTPUT; KEYPAD_DIRECTION_REG->KEYPAD_DRIVE2_PIN = TRIS_PIN_OUTPUT; KEYPAD_PORT_REG->port = PORT_ALL_LOW; KEYPAD_PORT_REG->KEYPAD_DRIVE0_PIN = PORT_PIN_HIGH; KEYPAD_PORT_REG->KEYPAD_DRIVE1_PIN = PORT_PIN_HIGH; KEYPAD_PORT_REG->KEYPAD_DRIVE2_PIN = PORT_PIN_HIGH; SEVEN_SEG_DIRECTION_REG->port = TRIS_PORT_OUTPUT; SEVEN_SEG_PORT_REG->port = PORT_ALL_LOW; } static void initialize_keypad_event() { register_portb_int_callback(keypad_event_manager); ((option_reg_ptr_t)REG_OPTION_ADDR)->bits.INTEDG = INT_EDGE_RISING; ((intcon_reg_ptr_t)REG_INTCON_ADDR)->bits.RBIF= INT_FLAG_CLEAR; ((intcon_reg_ptr_t)REG_INTCON_ADDR)->bits.RBIE = INT_ENABLE; ((intcon_reg_ptr_t)REG_INTCON_ADDR)->bits.GIE = INT_ENABLE; } void main() { initialize_keypad_and_leds(); initialize_keypad_event(); while(1); } |
Yapılan değişiklikleri kısaca sıralarsak:
- Register erişimi için değişken kullanımını ortadan kaldırdık. Ve bu iş için hiç değişken kullanmadık!
- Bellek bayram etti (mi acaba, göreceğiz 🙂 ama etti)
- Kodun anlaşılabilirliğini çeşitli define ve yorum satırları ile boost ettik.
- Doxygen stili dökümantasyon yaparak (hepsini yapmasak da 😉 ) o işi de kodun üzerinde aradan çıkardık.
Ve güncellenmiş main kodumuzun olduğu uygulamanın bellek kullanımı:
1 2 3 4 5 6 7 |
Memory Summary: Program space used 1B8h ( 440) of 400h words ( 43.0%) Data space used 1Dh ( 29) of 44h bytes ( 42.6%) EEPROM space used 0h ( 0) of 40h bytes ( 0.0%) Data stack space used 0h ( 0) of 27h bytes ( 0.0%) Configuration bits used 0h ( 0) of 1h word ( 0.0%) ID Location space used 0h ( 0) of 4h bytes ( 0.0%) |
Gördüğünüz üzere program alanı kullanımını 612’den 440 worde (1 word=2 byte) düşürdük. Ayrıca veri alanı kullanımını da 37 byte’dan 29 byte’a düşürdük 🙂 İşte bu elle tutulur bir optimizasyon.
Keypad’i de tertemiz, kesme kullanarak sürmüş olduk. Arada PORTB değişme kesmesi nasıl kullanılır onu da hallettik. Sayısız ibretlere de değindiğimizden bu günlük bu kadar diyoruz 🙂
Yazıları beğendiyseniz, faydalanabilecek tanıdıklarınızla paylaşmayı unutmayınız.
Önceki Sayfa Sonraki Sayfa