CCS-C ile PIC Programlama, Önişlemci Direktifleri – 3

Önişlemci direktifleri konusuna devam ediyoruz, biliyorum biraz can sıkıcı bu konular ama size güzel bir temel oluşturacağını düşünüyorum.

YAZI İÇERİĞİ

#org
#reserve
#rom
#int_xxx
#int_global
#int_default
#priority
#fuse
#use delay
#use fast_io
#use standart_io
#use fixed_io
#use rs232
#use i2c
#use spi
#use rtos

#org

Bu direktif istenilen bir fonksiyonun veya sabit tanımlamanın ROM(Program Memory)da ilgili adrese yerleştirilmesini sağlar. Aşağıdaki örnekleri anlamanız #org için yeterli olacaktır.

#org 0x1e00,0x1fff
void BenimFonksiyon()
{
}
// BenimFonksiyon() isimli fonksiyon ROM'da 0x1e00 adresinden başlayacak
#ORG 0x1E00
DigerFonksiyon(){
}
// DigerFonksiyon() isimli fonksiyon ROM'da 0x1e00 - 0x1fff adresleri arasında olacak
#ORG 0x800, 0x820 {} //800-820 arasında hiçbir şey olmayacak
#ORG 0x1C00, 0x1C0F
CHAR CONST KIMLIK[10}= {"123456789"};
// KIMLIK ADLI SABIT DIZI 0x1C00 adresinden başlayacak

#reserve

Bu direktif RAM’de istenilen adres veya adres bölgesinin reserve edilmesini yani derleyici tarafından kullanımının engellenmesini sağlar. Kullanımı şu şekildedir

#reserve adres    // tek adresi reserve etme
#reserve adres,adres,adres  // birden fazla adresi reserve etme
#reserve adres:adres // bir adres aralığını reserve etme

Önemli Not: #reserve direktifi mutlaka #device direktifinden sonra gelmelidir.

#reserve 0x50          // 0x50 RAM adresini derleyici kullanmayacak
#reserve 0x41,0x46  // 0x41 ve 0x46 RAM adreslerini derleyici kullanmayacak
#reserve 0x40:0x50 // 0x40-0x50 RAM adres aralığını derleyici kullanmayacak.

#rom

Bu direktif ile .HEX dosyasına data girebilme imkanına sahip olabiliyorsunuz. Derleyici yardım dosyasının dediğine göre bu sayede dahili eeprom programlaması yapılabilirmiş. Kullanım şekli aşağıdaki gibidir.

#rom adress = {list} // elemanlar 16 bit olarak (word) yazılır
#rom int8 adress = {list} elemanlar 8 bit olarak yazılır (byte)

Örnek

#rom 0x2100 = {1,2,3,4,5}

#int_xxx, #int_default, #int_global

Programınızda PIC denetleyicisinin interrupt’larından (Kesme) birini veya bir kaçını kullandığınızda bu interrupt için servis verecek fonksiyonu da yazmanız gerekir. PIC’te interrupt vektörü 0×04 adresidir, CCS-C de interrupt kullandığınızda derleyici bu vektöre (0×04) yerleşecek kodu otomatik olarak ayarlar. Diyelimki programınızda TIMER0 kesmesi kullanacaksınız, bu durumda TIMER0 için interrupt Servise Routine (ISR) yani kesme hizmet fonksiyonu yazmanız gerekecektir. Aşağıda örneğini veriyorum

#INT_TIMER0     // TIMER0 Kesmesi kullanılacak
timer0_isr()        // kesmenin fonksiyonu bu
{
işletilecek kodlar    // buradaki kodlar işletilecek
....
...
}

PIC’in interrupt mekanizmasına ilerki yazılarda ayrıntılı olarak değineceğiz.
CCS-C de kullanılabilecek kesmelerin listesine yardım dosyalarından veya program içerisindeki View->Valid İnterrupts yolunu takip ederek seçtiğiniz çipte hangi interruptları kullanabileceğinizi görebilirsiniz.

char ch;
#int_rda
void pc_den_veri_al()
{
ch = getc();
}

Bu örenekte de RS232 Receive Data Available (Veri alındı ve okunmak için hazır) kesmesinin kullanım örneği görülüyor.

#int_global direktifine gelecek olursak, bu direktifi kullanarak PIC’in kesme vektörüne yazılacak kodu siz belirleyebilirsiniz. Kullanırken dikkatli olmak gerekir zira derleyici Context Saving olayına girmez bu işi size bırakır. Bu konuya da başka bir yazıda değineceğiz.

#int_global
void interrupt_dispatcher()
{
..
..
..
}

#int_default direktifi ise PIC’in bir kesme oluşturduğu ama hiç bir kesme bayrağının set edilmediği veya bir kesme bayrağının set edilip kesme’nin tetiklenmediği durumlar için kullanılır. (CCS-C’nin yalancısıyım :) )

#priority

Bu direktif kesmelerin aynı anda oluşmaları durumunda öncelikli olarak hangisinin servis edileceğini belirlemek için kullanılır

#priority rtcc,timer1 // rtcc ve timer1 kesmesi aynı anda gelirse
// ilk olarak rtcc servis edilecek

#fuse, #use_delay

Bu iki direktifi daha önce anlatmıştım http://www.teknobakis.com/2008/07/21/ccs-c-dersleri-bit-ve-byte-islemleri-dahili-fonksiyonlari/ buradan bakabilirsiniz

#use fast_io, #use standart_io, #use fixed_io

Bu direktiflere de şu yazıda değinmiştim http://www.teknobakis.com/ccs-c-ile-pic-programlama-dahili-giris-cikis-komutlari-ile-pic-portlarinin-kullanimi/

#use rs232, #use i2C, #use spi

RS232 haberleşmesi kullanacaksanız bu direktif ile haberleşme hızı, bit sayısı, kullanılacak PIC Port’ları gibi ayarları yapmanız gerekiyor. Aynı durum i2c ve spi haberleşmesi için de geçerli.

Tüm bu haberleşme protokollerine birer yazı ayıracağım için burada ayrıntılarına girmiyorum.

#use rtos

Bu direktif derleyicinin RTOS (Real Time Operating System – Gerçek Zamanlı İşletim Sistemi) desteği kullanılmak istediğinde bazı ayarlamaları yapmak için kullanılır. RTOS konusuna daha sonra değinmeyi düşünüyorum

Ona sonra değin buna sonra değin derken kalan kısmını 2 yazı olarak planladığım Önişlemci Direktifleri Konusunu 1 yazı harcayarak bitirmiş bulunuyorum. Sıradaki konuyu henüz düşünmedim ama bu konudan daha eğlenceli olacağına emin olabilirsiniz :)

CCS-C ile PIC Programlama, Önişlemci Direktifleri – 3 yazısı için 20 yorum yapıldı

  1. Kemal says:

    Eline sağlık kardeşim çok faydalı bilgiler veriyorsun
    Başarılar dilerim

  2. Hocam bu yazınız da gerçekten çok güzel olmuş.
    Bu sıkıcı, ezber gerektiren kısımdan kurtulduğumuza çok sevindim:).Yeni yazılarınızı bekliyoruz…
    Çalışmalarınızda başarılar.

  3. [...] 11- Derleyici Önişlemci Direktifleri – 3 [...]

  4. murat can says:

    mrb hocam….
    yazilariniz super. gercekten oldukca sade ve guzel bir dille anlatiyorsunuz. hocam sizden istedigim su interrupt olayina en yakin zamanda mumkunse girmeniz. cunku sizinde bildiginiz gibi oldukca ugrastirici bir konu.
    tesekkurler

  5. Emrah AYDIN says:

    @murat can
    Timer’lardan sonra sırada kesmelerin anlatımı var…

  6. [...] şurada daha önce anlatmış olduğumuz önişlemci direktfilerindeki #int_xxx kelimesi ile ilgili kısmı okuyun. Yazıyı okuduğunuza [...]

  7. turkone says:

    sitedeki arkadaslar bana 74165 veya 74597 ile giris cogullamada yardimci olabilirsmisiniz?

  8. Hasan says:

    Gayet güzel, bilgilerinizi paylaştığınız için saolun.
    http://www.elektrokampus.com da bizde bu tür şeyler yapmaya çalışıyoruz.

  9. Altan says:

    Hocam Allah razı olsun,C den gözüm korkuyordu. sayenizde bu işi öğrenebileceğimi anladım.Geçmişte biraz jal ile uğraşmış bazı projeler de geliştirmiştim.Örneğin aracım için LCD li yol bilgisayarı yapmıştım.Sizin bir kitabınız ya da sizin tarzınızda anlatım yapan bir kitap tavsiyeniz olursa çok memnun olacağım.
    Saygılarımla.

  10. Emrah AYDIN says:

    @Altan
    Piyasadaki kitapları inceleme fırsatım olmadı. Web üzerinde başka kaynakları da araştırabilirsin. Kolay gelsin

  11. yaren says:

    sa.Hocam yaklaşık 8ay önce sayenizde pwm’i yazılım olaraka gerçekleştirdim. şimdi bilgisayar kontrollü bir projem var ama derleyicide seri porta karakter gönderiminde hatalarla karşılaştım.
    char klavye[80]; diye bir değişken tanıttım ve bilgisayardan k harfi gönderince aşağıdaki işlem gerçekleşsin. Hocam burda bir hata yaşıyorum nasıl kullanmam lazım.
    if(klavye==”k”||klavye==”K”){
    output_high(pin_d1); }
    seri port ile iki adet step motor kontrol edeceğim. Yardımınıza ihtiyacım var.TEŞEKKÜRLER…

  12. Emrah AYDIN says:

    @Yaren

    char klavye;
    while(1)
    {

    while(kbhit());
    klavye = getc();
    if((klavye == ‘k’) || (klavye == ‘K’);
    {
    output_high(PIN_D1);
    }

    }

    RS-232 için donanımsal bağlantıları ve yazılımda da #use rs232 direktifini kullanmayı unutma

    char ch;
    ch = “c”; // yanlış…
    ch = ‘c’; // doğru…

    Kolay gelsin…

  13. sahin says:

    #include “16F877.h”
    #fuses HS,NOWDT,NOPROTECT,NOLVP
    #use delay (clock=4000000)
    #include
    #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
    char klavye;

    while(1)
    {

    while(kbhit());
    klavye = getc();
    if(klavye == ‘5’);
    {
    output_high(PIN_B1);
    }

    }

    hocam yukarıda program ile proteusta 5 rakamına bastıgımda port b1 deki ledin yanmasını istiyorum.Ancak yanmıyor.yardımcı olabilrimisiniz.Seri haberleşme ile asıl amacım C# da arayuz ile bunları kontrol etmek.Ancak oncelikle CCS C de seri haberleşme sorununu gidermee calısyorum.Yardımcı olursanız seviirim.
    saygılarımla…

  14. Emrah AYDIN says:

    herhangi bir hata ile karşılaştığında öncelikle doğru çalıştığını düşündüğün yerleri test etmelisin. Örneğin çip istediğini yapmıyorsa öncelikle çipin çalışıp çalışmadığını test edeceksin bunun içinde ilk açılışta

    output_high(PIN_B1);
    delay_ms(1000);
    output_low(PIN_B1);

    kodunu eklersen, program çalıştığında led’in 1 saniye yanıp sonra sönmesi gerekir ve böylece çipin çalışıp çalışmadığı anlşılır.

    Verdiğin kodda main fonksiyonu yok? bu kodu derleyememen lazım. Benim yukarıdaki örneğe uymaya çalıştıysan hatalı olur çünkü ben tam kodu vermedim

    4000000 clock frekansı için fuse ayarı HS yerine XT olmalı.

    Biraz daha uğraş çözemezsen ayrıntılı yardımcı olurum

  15. sahin says:

    void LedControl(unsigned int led)
    {
    output_b(0×00);
    output_b(1<=’1′) && (digit<='8'))
    {
    putc(digit);
    i=digit-'1';
    ledControl(i);
    }
    else
    {
    puts("gecersiz numara");

    }

    }

    }

  16. sahin says:

    hocam yukarıdaki program klavyeden 1 ile 8 arasında herhangi bir rakama basıldıgında ilgili ledi yakan porgram.Sorunu cozdum.Ben proteustaki uygulamada COMPIM bagladım once.COMPIM ozelliklerine de 9600,8,Com1 ve eslik biti olmayacak sekilde yapmaya calıstım.Olmadı.Daha sonra seri port yerine virtual terminal bagladım C6 ve C7 pinlerine bu sefer calıstı.Sanırım bilgisayarda simulasyon yaparken ve bilgisayar ile haberleştireceksek COMPIM baglamaya gerek yok.Onun yerine Virtual terminal baglamak gerekiyor.Ben bu sonucu cıkardım.Ancak emin değilim hocam.Bu devre insallah arkadslar için faydalı olur.Simdi ise C# ile bir arayuz programı yazmaya calısyorum.Formda 1 den 8 kadar buton olacak ve hangi butona basılırsa ilgili ledi yakacak.Suana kadar arayuz ile proteustaki simulasyon devremi haberleştiremedim.eger yaparsam C# seri haberleşme konusuna yeni baslayanlar için cok faydalı olacagına inanıyorum.

  17. sahin says:

    yukarıdaki programıı eksik gondermisim.dogru olanı asagıda olandır.

    void LedControl(unsigned int led)
    {
    output_b(0×00);
    output_b(1<=’1′) && (digit<='8'))
    {
    putc(digit);
    i=digit-'1';
    ledControl(i);
    }
    else
    {
    puts("gecersiz numara");}}}

  18. sahin says:

    #include “16F877.h”
    #fuses HS,NOWDT,NOPROTECT,NOLVP
    #use delay (clock=4000000)
    #include
    #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

    void LedControl(unsigned int led)
    {
    output_b(0×00);
    output_b(1<=’1′) && (digit<='8'))
    {
    putc(digit);
    i=digit-'1';
    ledControl(i);
    }
    else
    {
    puts("gecersiz numara");}}}

  19. sahin says:

    hocam ne yaptıysam programın tam halini gondermedim.CCS Cden kopyala yapıstır yapıyorum ancak gonder dediğimde programın bir kısmını ekranda gosteriyor.

  20. Emrah AYDIN says:

    mail yoluyla gönderebilirsin,gerçi şu sıralar çok vakit ayıramıyorum ama yine de bakarım. Eğer bilgisayarla devreyi haberleştireceksen gerçek devreyi yapıp kulllan en sağlıklı ve faydalı yöntem budur.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>