27 Haziran 2015 Cumartesi

SDCC ile RB4~RB7 Kesme(Interrupt) Uygulaması (16F877A) –Ders09




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

#include <pic14regs.h>

typedef unsigned short int uint16_t;

//sigorta tanımlarımızı yapıyoruz.
__code uint16_t __at _CONFIG __configword =
     _PWRTE_OFF &&
     _CP_OFF &&
     _FOSC_XT &&
     _WDT_OFF &&
     _BOREN_OFF &&
     _LVP_OFF ;


void main(void) // Ana fonksiyon alanı
{
    TRISB = 0xF0; // RB4..RB7 giriş, diğerleri çıkış
    PORTB = 0x00; // PORTB sıfırlanıyor
    TRISD = 0x00; // PORTD tamamı çıkış
    PORTD = 0x00; // PORTD sıfırlanıyor

    RBIF = 0; // RB4..RB7 kesme bayrağı temizleniyor.
    RBIE = 1; // RB4..RB7 kesme izni veriliyor.
    GIE = 1; // Genel kesme izni veriliyor

    for(;;); // İşlemci sonsuz döngüde bekletiliyor
}


static void Kesme(void) __interrupt 0 //Kesme fonksiyonu
{
    if(RBIF) //RB4..RB7 kesme oluşmuşmu?
    {
       if(RB4) //ilk butona basıldımı?
           PORTD = 0x01; //ilk ledi yak
       else
       if (RB5) //ikinci butona basıldımı?
           PORTD = 0x02; //ikinci ledi yak
       else
       if (RB6) //üçüncü butona basıldımı?
          PORTD = 0x04; //üçüncü ledi yak
       else
       if (RB7) //dördüncü butona basıldımı?
          PORTD = 0x08; //dördüncü ledi yak

       PORTB = PORTB;//son değişikliklerin algılanması için PORTB yi bir daha oku
       RBIF = 0; //Tekrar kesme alınabilmesi için kesme bayrağı temizleniyor.
   }
}


Bu dersimizde pic mikrodenetleyicilerin B4 ile B7 arası bacaklarındaki kesme nasıl yapılır onu göreceğiz. Billindiği üzere 16F877A mikrodenetleyicisinin kesmelerinden biridir b4~b7 kesmesi. Eğer bu kesme aktif edilirse B4 ile B7 arasındaki portlardan gelecek olan lojik sinyal değişimi algılandığı anda mikrodenetleyici elindeki işi bırakıp bu kesmenin gerçeklendiği fonksiyonu işletecektir. İşte biz bu kesmeyi SDCC derleyicisi ile kodda da gördüğünüz üzere gayet basit bir şekilde gerçekleştirdik.

Kodumuza göz atacak olursak; Öncelikle PORTB ye ait RB4 ~ RB7 portlarını giriş olarak TRISB=0xF0 ifadesi ile sağladık. Daha sonra PORTD yi de PORTD=0x00 ifadesi ile tamamen ledlerimiz için çıkış olarak ayarladık. RBIF=0 ile RB4~RB7 ile ilgili kesme bayrağını temizledik. RBIE=1 ile RB4~RB7 kesmesine izin veriyoruz. Sonrasında programı sonsuz döngüye sokarız. Program sonsuz döngüde esasında bir iş yapmaz. Daha doğrusu iş yapacak kodları biz kesme fonksiyonun içine gömdüğümüz için bütün işimiz bu fonksiyonun içinde olacaktır.

Kesme isimli fonksiyonumuz özetle; RB4,RB5,RB6 ve RB7 portlarının lojik durumunu kontrol ediyor. Eğer bu portlarda butona basılma durumu yani lojik 1 oluştuysa ilgili PORTD ye bağlanmış ledleri yakacak şekilde bir kod göndeririz. Örneğin ikinci butona basıldıysa PORTD ye bağlı ikinci ledi yakacak olan 0x02 kodunu gönderir. Bu ikilik sistemde 00000010 değerine karşılık geldiği için 1 e denk gelen led yanacak, diğerleri sönecektir. Diğer bir kod ise karşılaştırmaların sonuda bulunan PORTB=PORTB ataması. Bu işlem esnasında başka bir değişiklik olduysa şayet bunu PORTB yi kendisine atayarak hatalı durumun önüne geçiyoruz. Bu portun kendine atamayla ilgili sıkıntıları gidermek için PIC18FXXX serisinde ayrıca birde LAT port yazmacı geliştirilmiştir. Buda yine ileriki derslerde yeri gelince açıklamacaktır. Bu kodda dikkat edilecek olursa RBIF ile kesmenin aktif olup olmadığını kontrol ediyoruz. Bu RBIF kesme bayrağı RB4~RB7 kesmesinin durumunu bildiren bayraktır. Önceki dersimizde INT/RB0 kesmesinin aktif olup olmadığını INTF dış kesme bayrağını kontrol ederek öğreniyorduk. Demekki her kesmenin kendine özgü bir kontrol bayrağı var. Kodlama yaparken bunlara dikkat edersek hiçbir sıkıntı yaşamayız. Başka bir derste görüşmek üzeere hoşçakalın.


duralikiraz.blogspot.com
27 Haziran 2015

Muvaffakiyet Allahtandır”

24 Haziran 2015 Çarşamba

SDCC ile Harici INT/B0 Kesme(Interrupt) Uygulaması (16F877A) –Ders08


Pic microdenetleyicilerinin diğer bir yüzü sayılabilecek tarafıda kesmelerdir. Misal 16F877A da 14 adet kesme özelliği vardır. Kısaca kesmelerin (interruptların) faydasından bahsedecek olursak; mikrodenetleyicimizin birden fazla işi aynı anda kontrol edebilmesine olanak sağlar. Yani mikrodenetleyici programımız main fonksiyonu içinde normal işlerini yaparken bizde bir kesme kontrolü ile misal B4 ile B7 portlarına bağlı butonlara basılıp basılmadığının kontrolünü yapabiliriz. Ya da Timer0 sayacımız taşma yapmışmı gibi kontrolleri ana programın üstüne yük etmeden kontrol edebiliriz. Kesmelerle ilgili daha detaylı bilgiyi internetteki diğer kaynaklarda ve pic kitaplarında bulabilirsiniz. Burada pratik uygulamalar önceliğimiz olacaktır.

Bu dersimizde Harici INT/B0 kesmesiyle ilgili bir örnek yapacağız.













 







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

#include <pic14regs.h>

typedef unsigned short int uint16_t;

//sigorta tanımlarımızı yapıyoruz.
__code uint16_t __at _CONFIG __configword =
       _PWRTE_OFF &&
       _CP_OFF &&
       _FOSC_XT &&
       _WDT_OFF &&
       _BOREN_OFF &&
       _LVP_OFF ;


char i; //Kesme için bir değişken

void main(void) // Ana fonksiyon alanı
{

    TRISB = 0x01; // RB0/INT giriş, diğerleri çıkış
    PORTB = 0x00; // PORTB sıfırlanıyor

    INTF = 0; //RB0/INT kesme bayrağı temizleniyor
    INTEDG = 1; //Yükselen kenarda kesme oluşacak
    INTE = 1; //RB0/INT izni veriliyor
    GIE = 1; //Genel kesme izni veriliyor

    for(;;); // İşlemci sonsuz döngüde bekletiliyor
}


static void Kesme(void) __interrupt 0 //Kesme fonksiyonu
{
   if(INTF) //Dış kesme oluşmuşmu?
   {
      i++; //Her bir kesmede değişken bir artırılıyor
      if(i==1) //değişken 1 ise
         RB1=1; //Led yansın
      else //değilse
      if(i==2) //değişken 2 ise
      {
         RB1=0; //led sönsün
         i=0; //i sıfırlansın
      }
      INTF=0; //Tekrar dış kesme alınabilmesi için kesme bayrağı temizleniyor
   }
}


Öncelikle SDCC derleyicisi için sadece bir adet kesme fonksiyonu tanımlanır. Bütün kesme olayları bu fonksiyon içinde kontrol edilir. Biz bu programda sadece INTF kesme bayrağını yani “dış kesme” olup olmadığını kontrol ediyoruz. Eğer B4 ve B7 arasındaki pinlere bağlı butonları da kontrol etseydik bu kesmeler için “RBIF” kesme bayrağını kontrol ederdik. Peki hem harici(dış) kesme hemde B4~B7 kesmelerini kontrol eden kodu nasıl yazardık? Cevabı aşağıdaki gibi olurdu.

 
static void Kesme(void) __interrupt 0 //Kesme fonksiyonu
{
   if(INTF) //Dış kesme oluşmuşmu?
   {
      :
      :

      INTF = 0; //Tekrar dış kesme alınabilmesi için kesme bayrağı temizleniyor
   }

   if(RBIF) //B4 ve B7 pinlerinde kesme oluşmuşmu?
   {
      :
      :

      RBIF = 0; //Tekrar dış kesme alınabilmesi için kesme bayrağı temizleniyor
   }
}

 
Tabi buradaki kesme kontrol bloğu PIC16F877A da 14 adet olabilirdi. Kesme fonksiyonundaki “__interrupt 0” ifadesi olmak zorunda olan bir ifadedir. Bu ifadedeki 0 yerine 1 ve 2 gibi sayılarda olabilir. 1 sayısı yüksek önceliği, 2 sayısı düşük önceliği ifade eder. Ancak 0 kullanılması önerilir, şayet ileri seviye bilginiz yoksa. Bu fonksiyonun ismini “Kesme” olarak isimlendirdim. İsterseniz daha başka bir isimde verebilirsiniz.

Bu harici kesmeyi çalıştırabilmek için main fonksiyonunda bazı hazırlıklar yapmamız gerekmekte.

INTF = 0;

ile kesme bayrağımız ilk olarak sıfırlanır. Bu kesme bayrağı INTCON register'ı içinde bulunur.

INTEDG = 1;

satırı ile kesmeyi yükselen kenardamı yada düşen kenardamı kontrol edeceğimize karar veriyoruz. 0 düşen kenarı, 1 ise yükselen kenarı aktif eder. Bu kodda da yükselen kenarı aktif ettik. Bu kesme bayrağı OPTION register'ında bulunur.

INTE = 1;

ile dış kesmeye izin verip vermeyeceğimiz belirliyoruz. 1 değeri izin verdiğimizi gösterir. Bu kesme bayrağı INTCON register'ında bulunur.

GIE = 1;

ile tüm aktif edilmiş kesmelere izin veriyoruz yada vermiyoruz. Burada 1 değeri tüm kesmelere izin verdiğimizi gösterir. Yine bu kesme bayrağıda INTCON register'ı içinde bulunur.


Tahmin edeceğiniz üzere bu kesme registerları ve bayrakları ile değişik birçok ayar yapabilirsiniz. Bu sizin ihtiyaç duyduğunuz programlama ile yapmak istediklerinizi ayarlamanızla alakalı olacaktır. Temel olarak bu örnek üzerinde anlatacaklarımız şimdilik bukadar. Bir sonraki derste görüşmek üzere hoşçakalın.


duralikiraz.blogspot.com
25 Haziran 2015


Muvaffakiyet Allahtandır”



22 Haziran 2015 Pazartesi

SDCC ile İki Rakamlı 7 Segment Display Uygulaması 00-99 Sayıcı (16F877A) –Ders07



















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

#include <pic14regs.h>

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 &&
      _LVP_OFF ;

// Bu ms_bekle 168877a 4 Mhz frekansı için ayarlanmış bir fonksiyondur
void ms_bekle(uint16_t milisaniye)
{
   uint16_t i,j;
   for (i = 0; i < milisaniye; i++)
   {
     // Döngüde optimizasyon için bu asm komutu eklenmiştir.
     for (j=0; j < 46; j++)
       __asm nop __endasm;
   }
}

                                      // .gfedcba Görünen
const unsigned char segment[]={ 0x3F, // 00111111 0
                                0x06, // 00000110 1
                                0x5B, // 01011011 2
                                0x4F, // 01001111 3
                                0x66, // 01100110 4
                                0x6D, // 01101101 5
                                0x7C, // 01111100 6
                                0x07, // 00000111 7
                                0x7F, // 01111111 8
                                0x6F // 01101111 9
                          };

void sayi_goster(char i) // Sayı göstermeye yarayan fonksiyon
{
    PORTC = 0x02;          //PORTC'de 2 değeri gönderiliyor 10
    PORTB = segment[i/10]; //i'nin 10'a bölümü gösteriliyor
    ms_bekle(10);          //10ms bekleniyor
    PORTC = 0x01;          //PORTC'de 1 değeri gönderiliyor 01
    PORTB = segment[i%10]; //i'nin 10'a bölümünden kalanı gösteriliyor
    ms_bekle(10);          //10ms bekleniyor
}


void main(void)
{
   int i = 0; // Herhangi bir değişken tanımlanıyor
   ADCON1 = 0x07; // PORTA dijital yapılıyor
   TRISA = 0x03; // PORTA'nın ilk iki pini giriş
   TRISB = 0x00; // PORTB çıkış olarak yönlendiriliyor
   TRISC = 0x00; // PORTC çıkış yapılıyor
   PORTA = 0x00; // PORTA'nin tüm çıkışları sıfırlanıyor
   PORTB = 0x00; // PORTB'nin tüm çıkışları sıfırlanıyor
   PORTC = 0x00; // PORTC'nin tüm çıkışları sıfırlanıyor
   for(;;) // Sonsuz döngüye giriliyor
   {
      if(RA0==0) // RA0'pini 0 mı?
      {
         while(!RA0); // Buton bırakıldı mı diye bakılıyor
         i++; // Değişken artırılıyor
         if(i>99) // Eğer değişken 99'dan büyükse 0 oluyor
              i=0;
      }
      else
      if(RA1==0) // RA1'pini 0 mı?
      {
          while(!RA1); // Buton bırakıldı mı diye bakılıyor
          i--; // Değişken azaltılıyor
          if(i<0) // Eğer değişken 0'dan küçükse 99 oluyor
               i=99;
      }
     
      sayi_goster(i); // O anki sayı gösteriliyor
   }
}


Bir önceki dersimizde tek haneli 7 segment display için 0-9 arası bir sayıcı devresini oluşturmuştuk. Bu dersimizde ise 00-99 arası sayabilen bir sayıcı oluşturacağız. Eğer istenirse iki tane tek 7 segment display yanyana konularak da 00-99 sayıcı devresi yapılabilir. Ancak yapışık haldeki iki haneli 7 segment display i programlamakla arasında pek bir fark olmayacaktır. Bu iki haneli olan displayde abcdefg uçları ortaktır. Kicad programının kılıflarında ayrı ayrı gözükmüş ama aslında birleşiktir. Burdaki kılıf şeklinde bile olsa pic portlarını her halükarda ortak kullanırlar. Yani 1. display hanesinin a girişi ile 2. display hanesinin a girişi birleşip Port B0 a bağlanır. O yüzden kafanız karışmasın.

Bu displaydeki dikkat edeceğimiz hususlardan biride display hanelerinin aktiflenme portlarıdır. Port C0 ve Port C1 e bağlanan portlar aktifleme işlemini yapar. Bilindiği üzere biz bu display hanelerine veri göndereceğimiz zaman hane seçimine göre C0 veya C1 portlarından birini aktifleriz. Bu şekilde aktif olan (Lojik 1) display hanesine veri yazılabilir. İlk haneden sonra diğer haneye yazabilmek için bu haneyi aktif (lojik 1), diğer haneleri ise pasif (lojik 0) yapmamız gerekir. Ayrıca bir haneden diğerine geçiştede belirli bir süre aralığı bekleme yapmamız gerekmekte. Buradaki devrede denemelerimizde 10 ms ile isiste kararlı çalıştığı görüldü.

Bu kodla ilgili bir diğer dikkat edilecek husus ise Butona basılmanın algılanması ile birlikte Buton bırakılana kadar döngüde tutulma durumudur. Buda bize butona basıştaki arttırma yada azaltmanın birer birer yapılmasının kontrollü bir şekilde sağlar. Bu bir programlama tekniğidir. Projelerinizde tam buton kontrolünü sağlayabilir.

Sayigoster isimli fonksiyonumuzda dikkat çeken bir husus ise bir sayının onlar hanesinin alınması işleminin sayının 10 a bölümü ile çıkan bölüm sonucunun olmasıdır. Yani bölmenin bölüm sonucu onlar hanesidir. Aynı şekilde bir sayının 10 bölümünden kalan değer ise birler hanesini verir. Yine buda bir pratik programlama tekniğidir. Diğer kısımlari önceki derslerde tekrarladığımız için yinelemeye gerek görülmemiştir. Bir sonraki derste görüşmek üzere hoşçakalın.


duralikiraz.blogspot.com
23 Haziran 2015


Muvaffakiyet Allahtandır.”

20 Haziran 2015 Cumartesi

SDCC ile 7 Segment Display Uygulaması ve 0-9 Sayıcı (16F877A) –Ders06











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

#include <pic14regs.h>

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 &&
      _LVP_OFF ;

// Bu ms_bekle 168877a 4 Mhz frekansı için ayarlanmış bir fonksiyondur
void ms_bekle(uint16_t milisaniye)
{
   uint16_t i,j;
   for (i = 0; i < milisaniye; i++)
   {
    // Döngüde optimizasyon için bu asm komutu eklenmiştir.
     for (j=0; j < 46; j++)
       __asm nop __endasm;
   }
}


                                      // .gfedcba Görünen 
const unsigned char segment[]={ 
                                0x3F, // 00111111 0
                                0x06, // 00000110 1
                                0x5B, // 01011011 2
                                0x4F, // 01001111 3
                                0x66, // 01100110 4
                                0x6D, // 01101101 5
                                0x7C, // 01111100 6
                                0x07, // 00000111 7
                                0x7F, // 01111111 8
                                0x6F // 01101111 9
                             };

void main(void) // Ana fonksiyon alanı
{
   char i = 0; // Herhangi bir değişken tanımlanıyor
   TRISB = 0x00;// PORTB çıkış olarak yönlendiriliyor
   PORTB = 0x00;// PORTB'nin tüm çıkışları sıfırlanıyor

   for(;;) // Sonsuz döngüye giriliyor
   {
      PORTB = segment[i]; // Seven segment değerleri alınıyor
      i++;                // i bir artırılıyor
      ms_bekle(1000);     // 1000ms bekleniyor
      if(i>9)             // Eğer sayı 9'dan büyük ise 0'a dön
         i=0; // Değişken 0 yapılıyor
   }
}



Bu dersimizde elektroniğin en önemli çıktı araçlarından 7 segment display ile 0~9 arası basit bir sayıcı (counter) yapmaya çalışacağız. 7Segment display; kısaca üzerinde 7 adet led'i bulunan elektronik bir parça. Çalışma şekli olarak ortak katot ve ortak anot olmak üzere iki çeşittir. Tabi bunların da alt çeşitlerinin olduğunu bilmek gerekiyor. Yazılımla bu 7 segmente ait ledlerden hangisinin yanıp hangisinin söneceğine karar veriyoruz. Olayın hepsi bu. Tabi bunun yanında ikili,üçlü hatta 4 lü segment display lerde kullanılmakta. Onlarla igili örneğimizi başka bir ders yada dersler olarak değerlendireceğiz.




Bu devredeki uygulayacağımız mantık bellirli zaman aralıklarında (1000ms) sırayla ilgili ledlerini yakıyoruz. Böylece sayı sayma efektimiz oluşmuş oluyor. Kod'a bakacak olursak; daha önceki derslerimizde bahsettiğimiz sigorta tanımlarımız, pic16f877a 4 MHZ için senkronize ettiğimiz ms_bekle isimli bekleme fonksiyonumuz yer almakta. Daha sonra kod üzerinde açıklamaya çalıştığımız segment isimli bir sayısal dizi tipimiz var. Diziyi onaltılık (hexadecimal) olarak tanımladık. İstersek binary yada onluk tipinde de yazabilirdik, farkeden bir şey olmaz. Dizide her değerin yanında ikilik karşılıklarını açıklama olarak yazdığımız dikkatinizi çekmiştir. By ikilik sayı görüntüsündeki 1 ler yanacak olan ledleri, 0 lar ise sönük kalacak ledleri işaret eder. Yani herşey 1 ve 0 olayı. Biz yinede hangi sayının gönderilen değerlerle 7 segment displayde görüneceğini Görünen diye belirttik. Herhalde bu husus anlaşılmıştır.

Ana kodumuza (main fonksiyonu) gelecek olursak; B portunun tüm pinleri çıkış olarak ayarlanmış, ardından başlangıç olarak 0x00 değeri gönderilmiştir. Sonrasında for ile sonsuz döngümüz başlamakta. Bu döngü içinde

PORTB = segment[i];

satırında segment isimli dizi değişkenin i ninci elemanı PORTB ye atanıyor. Bildiğiniz gibi diziler 0 başlangıç değerini indis olarak seçer. Yani sıfırıncı eleman ilk elemanıdır. Dolayısınla ilk olarak i=0 olduğu için segmentin sıfırıncı eleamanı (0x3F) PortB ye atanır. 0x3F gösterimde sıfırın gösterilmesini sağlar. Bu sebeple displayda 0 gözükür. Sonrasında

i++;

ile esasında “i = i+1” yapılır. Ve

ms_bekle(1000) ;

ile 1 saniye kadar bekleme yapılır.

if(i>9)
i=0;

satırı ile i eğer 9 a ulaşmışsa sıfırlanır. Yani döngü 10 kere dönüş yapar ve dizideki 10 elemanı sıra ile display'e gönderir. Bu döngü sonsuza kadar devam eder. Başka bir derste görüşmek üzere hoşçakalın.


duralikiraz.blogspot.com
20 Haziran 2015


Muvaffakiyet Allahtandır”



17 Haziran 2015 Çarşamba

SDCC ile Karaşimşek Uygulaması (16F877A) –Ders05




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

#include <pic14regs.h> //Mikrodenetleyici Ayar adreslerini ve seçenekleri içerir

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 &&
_LVP_OFF ;

// kalibrasyonsuz delay, sadece bir dizi döngü yinelemeleri için beklemeyi sağlar.
// Bu ms_bekle 168877a 4 Mhz frekansı için ayarlanmış bir fonksiyondur
void ms_bekle(uint16_t milisaniye)
{
  uint16_t i,j;
  for (i = 0; i < milisaniye; i++)
  {
    // Döngüde optimizasyon için bu asm komutu eklenmiştir.
    for (j=0; j < 46; j++)
     __asm nop __endasm;
  }
}



void main(void)
{
  unsigned char kaydirikci=1; // kaydirikci şeklinde bir sabit tanımlanıyor
  TRISB = 0x00; // PortB tamamen çıkış olarak ayarlandı.
  PORTB = 0x00; // PORTB'nin tüm çıkışları sıfırlanıyor

  for(;;) // Sonsuz döngüye giriliyor
  {
     PORTB = kaydirikci; // PORTB kaydirikci değişkenine eşitleniyor
     kaydirikci = kaydirikci << 1; // kaydirikci birimi bir sola kaydırılıyor
     ms_bekle(100); // 100ms bekleniyor

    if(kaydirikci == 0x80) // Eğer PORTB=0x80 olursa alt işlemlere geçiliyor
    {
      for(;;) // Tekrar sonsuz döngüye giriliyor
      {
        PORTB = kaydirikci; // PORTB led değişkenine eşitleniyor
        kaydirikci = kaydirikci >> 1; // kaydirikci birimi bir sağa kaydırılıyor
        ms_bekle(100); // 100ms bekleniyor
        if(kaydirikci == 0x01) // Eğer PORTB=0x01 olursa ikinci sonsuz döngüden
           break; // birinci sonsuz döngüye giriliyor
      }
    }
  }

}


Bu dersimizde nev'i şahsına münhasır Karaşimşek devresini yapamaya çalışacağız. Yukarıda açık devre çizimini ve kodu paylaştım Bu kodu derlemek için Konsolda;

sdcc --use-non-free -mpic14 -p16f877a Karasimsek.c

demeniz yeterli. Oluşan hex dosyasını gpsim yada Proteus-Isis gibi bir similasyon programında verdiğimiz açık devredeki gibi oluşturarak test edebilirsiniz. Bu derslerdeki devreler proteus isis üzerinde test'i tarafımdan yapılarak burada paylaşılmaktadır. Simulasyonda ledler arasındaki yanıp sönme ile oluşan ahengi sizde hissedebilirsiniz.
Kodumuza bakacak olursak bir önceki derste bahsedildiği gibi 16F877A ya mikrodenetleyicisinin 4 MHZ kristal ösilatör ile nispeten uyumlu bir ms_bekle fonksiyon tanımız var. Sigorta ayarlarımız keza yine bu mikrodenetleyici seçimine uygun. Kodumuzdaki can alıcı nokta iç içe olan “for” döngüleri. İlk for döngüsü ile 1 değeri atanmış kaydirikci isimli bir değişkenimizi PortB nin tamamına atamasını yapıyoruz. Bu değişken adı üstünde ikilik sistemde 1 değerini sağdan (yani b0 bitinden) sola (b7 bitine) doğru birer basamak kaydırma işlemlerini öncesinde yapacağımız, sonrasında da bu kaydırılmış değeri PORTB ye atayacağımız bir değişkendir. Zaten bir alt satırda

kaydirikci = kaydirikci << 1;
yapıldığı görülmekte. Buradaki “<<” ifade ANSI C dilinde sağdan sola doğru bitsel kaydırma operatörüdür. Yaptığı iş kısaca bir sayının ikilik değerinin sağ tarafına bir adet sıfır ekleyerek bir basamak kaydırmasını yapmaktır. Şöyleki;

00000001 sayısını
00000001 << 1 işlemine bir sefer tâbi tutarsak
00000010 sayısını elde ederiz.

Umarım farkı anlayabilmişsinizdir. Şimdi bu işlem bu ilk for döngümüz ile 00000001 sayısı 10000000 haline gelene kadar devam eder. 10000000 ikilik sayısının onaltılık sayı sistemindeki karşılığı 0x80 dir. Dolayısıyla 0x80 haline gelince ikinci for döngüsü başlayacaktır. Bu ikinci for döngüsüde diğer döngüde yaptığı gibi yine kaydirikci değişkenindeki sayımıza bitsel kaydırma işlemi yapacaktır. Fakat bu sefer kaydırmayi sağdan sola değil soldan sağa doğru yapacaktır. Bu işlemin şu şekilde

kaydirikci = kaydirikci >> 1;

yapıldığı görülmekte. Buradaki “>>” ifade ANSI C dilinde soldan sağa doğru bitsel kaydırma operatörüdür. Yaptığı iş kısaca bir sayının ikilik değerinin sol tarafına bir adet sıfır ekleyerek bir basamak sağa kaydırmasını yapmaktadır. Şöyleki;

10000000 sayısını
10000000 >> 1 işlemine bir sefer tâbi tutarsak
01000000 sayısını elde ederiz.

Bu ikinci for döngüsü de ikilik olarak 00000001 sayısına yani onaltılık sayı olarak 0x01 değerine ulaşıncaya kadar döngüyü devam ettirir. 0x01 değerine ulaştığında ise döngüyü “break” ifadesi ile durduruyoruz. Bunun sonucunda kodumuz tekrar ilk for döngüsünün başına gelir. Sonuçta bu iç içe iki döngü sonsuza kadar devam eder.

Şimdi bu bitsel kaydırmanın sonuçlarına toplu olarak bakarsak bütünü görmemiz daha kolay olabilir.

birinci döngünün çalışma sonuçları

00000001
00000010
00000100
00001000
00010000
00100000
01000000
10000000

ikinci döngünün çalışma sonuçları

10000000
01000000
00100000
00010000
00001000
00000100
00000010
00000001

Umarım bu görüntü mantığı anlamanızda yardımcı olmuştur. Efektimiz daha iyi olması için her kaydırma sonrası 100 milisaniye bekleme aralığı belirledik. Başka bir derste görüşmek üzere hoşçakalım.


duralikiraz.blogspot.com
17 Haziran 2015

Muvaffakiyet Allahtandır”