15 Haziran 2015 Pazartesi

SDCC ile Butona Basıldığında Ledi Yakma (PIC16F877A) – Ders04



Bir önceki dersimizde basit şekilde led nasıl yakılır ve pic14, pic16 serisine mensup mikrodenetleyicilerin sigorta ayarlarının yapılmasındaki farkı anlamaya çalıştık. Aslında tek kelimelik bir farkmış :) Dikkat ettiyseniz derslerimizde bir tek işlemci üzerinden anlatımı yapmak yerine neredeyse her derste farklı bir işlemci ile örnek yapıyoruz. Esasında bu şekilde yapmak bayağı bir zorluyor insanı. Kitap yazarlarının neden tek mikrodenetleyiciye bağlı kitap yazdıklarını şimdi daha iyi anlıyorum. Benim farklı mikrodenetleyicileri seçmemin sebebi zaten bilinen led yak söndür, butona bas zıplasın örneklerini hemen hemen tüm kitaplarda birbirinin kopyası niteliğinde bulabiliyorsunuz. Bunları birde benim tekrarlamamda bir anlam yok. Bize bilinmeyen farklılıklar lazım. Sdcc ile ilgili Türkçe bilgi azlığından dolayı bende elimden geldiğince öğrenilmesi gereken farklılıklara dikkat çekip, yazı yazarken bir taraftanda kendime de öğretmek.

Bu dersimizde piyasanın en çok üzerine belki yazılıp çizilmiş mikrodenetleyicisi olan PIC16F877A yı kullanıp buton led yakma uygulaması yapacağız. Şunu artı bilgi olarak paylaşmak istiyorum; microchip firması PIC16F877 yerine PIC16887 yi önermekte. Bazı yerlerde iyileştirme yaptıklarından da bahsediğini duydum. Herneyse buda aklınızda bulunsun. Hem daha da ucuz.

Devre şemamızı ve mikrodenetleyici kodumuzu aşağıda vererek işe başlayalım.




























// Copyright (C) 2015 Durali Kiraz
// PIC16F877A için hazırlandı.

#define NO_BIT_DEFINES
#include <pic14regs.h> //Mikrodenetleyici Ayar adreslerini ve seçenekleri içerir
//#include <stdint.h> //uint16_t tanımı için gerekliydi. Şimdi ise tipi kendimiz tanımladık.

typedef unsigned short int uint16_t;

//sigorta tanımlarımızı yapıyoruz.
__code uint16_t __at _CONFIG __configword =
_FOSC_XT &&
_WDT_OFF &&
_BOREN_OFF && //Brown Out Reset (BOR) Disable
_LVP_OFF;

#define LED_PORT PORTBbits.RB0
#define BUTON PORTAbits.RA0
#define TRIS_A0 TRISAbits.TRISA0
#define TRIS_B0 TRISBbits.TRISB0


void main(void)
{
   ADCON1 = 0x07; //PortA yi dijital olarak yönlendirdik.
   TRIS_A0 = 1; //A0 giriş olarak seçildi.
   TRIS_B0 = 0; //B0 çıkış olarak seçildi.

   LED_PORT = 0; // LED sönük
   BUTON = 0; // Buton pasif
  
   while(1)
   {
      LED_PORT = BUTON;
   }

}


Bu koddaki birinci değişiklik tek bir adet uint16_t tipi için <stdint.h> başlık dosyasını koda ekleyip gereksiz bir kod şişkinliği yapıyorduk. Bunun yerine bu tipi bu ana kodun içinde tanımlayıp bizim için çok önemli olan microdenetleyici program hafızasından tasarruf etmiş olduk. Mikrodenetleyici programı yaparken bu hususa dikkat edilmediği takdirde daha yüksek hafızalı ve daha pahalı olan entegrelere para yatırmış olursunuz. Buda istenmeyen bir durumdur.

Yine dikkatinizi çektiği üzere sigorta ayarlarımızı kullanacağımız 16F877A aygıtına göre şekillendirdim. Bu konuda pic16F877a.h isimli dosyanın içine (/usr/local/share/sdcc/non-free/include/pic14 dizininden bulabilirsiniz) bir göz atmam gerekti. Buradaki osilatör ve sigorta tanımlarına ve açıklamalarına bakarak bu tanımlamayı kendi ihtiyacıma göre yaptım. Diğer derslerde belirtmediğim _BOREN_OFF && //Brown Out Reset (BOR) Disable Sigorta ayarı kısaca giriş voltajı eşik değerin altına indiğinde mikrodenetleyici kendini resetlemesin anlamında bir ayardır. Voltaj eşik değeri genelde +5 volttur. Diğer bir sigorta ayarı olan _FOSC_XT ile XT tipinde harici bir kristal osilatör kullanacağımı derleyiciye bildirdim. Eğer yüksek hızlı misal 20 MHZ lik bir osilatör kullandıysam devrede bu ayar _FOSC_HS şeklinde olması gerekirdi. Dikkat ettiyseniz bir önceki derslerde hep dahili osilatörle çalışmıştık. PIC16F877A nın dahili osilatörü olmadığı için bu örnekteki harici osilatör kullanma örneği bizim farkı anlamamız açısından önemlidir. Burada benim vermiş olduğum sigorta ayarları tamamen bir örnektir arkadaşlar. Siz kendi ihtiyacınıza göre kendi sigorta parametrelerinizi && işaretlerinin yanına ekleyerek oluşturacaksınız. Yoksa burada yazılan hersatır kural değildir.

#define LED_PORT PORTBbits.RB0” şeklinde ifade tanımlarımızın nasıl yapıldığını ve ne amaçla yapıldığını daha önceki derslerde zannedersem bahsettim. İsterseniz LED_PORT gibi bir ifade yerine program içinde PORTBbits.RB0 tanımını doğrudan kullanarak program yazabilirsiniz. Genelde biz kod okunaklığını daha iyi yapmak adına yeni bir sembol tanımlayıcı ile yani LED_PORT gibi bir isimler kullanırız. Dediğim gibi isterseniz kullanmayabilirsiniz.

Main ana fonksiyonumuzda sırasıyla
  • ADCON1 = 0x07;ile PORTA nın dijital olacağını (anolog olamayacağını),
  • TRIS_A0 = 1; ile A0 ın giriş için kullanılacağını
  • TRIS_B0 = 0; ile B0 in çıkış için kullanılacağını
  • LED_PORT = 0; ile led_port a lojik sıfır sinyali atadığımızı
  • BUTON = 0; ile butonumuzun basılı olmadığını yine lojik sıfır ile atamasını yapıyoruz.

Daha sonrasında while(1) işlem bloğumuz başlamakta. İsterseniz bu ifadenin yerine for(;;) şeklinde bir blok başlatabilirsiniz. Sonuçta iki ifadede sizin için sonsuz döngüyü başlatacaktır. Bu bloğumuzun için de sadece bir satırlık LED_PORT = BUTON; ifadesi var. Bu ifade LED_PORT içine BUTON ile tanımlı ifadenin sayısal değerini atar. Yani BUTON 1 ise LED_PORT' a lojik 1 yani 5 voltu gönderir. Dolayısıyla led eğer buton 1 ise yani basılı ise yanar. Eğer buton 0 ise yani basılı değilse ledimiz sönük olacaktır. Bu sonsuz döngü içerisindeki kod bloğumuz sonsuza kadar butona basılımı? Değilmi? Sorgulamasını yapıp led imize sonuç gönderecektir. Zaten bu koddan amaçlanan bu.

Bir sonraki derslerde daha iyi örneklerle buluşmak üzere hoşçakalın.



duralikiraz.blogspot.com
16 Haziraz 2015

Muvaffakiyet Allahtandır”

Hiç yorum yok:

Yorum Gönder