Ö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 :)
Eline sağlık kardeşim çok faydalı bilgiler veriyorsun
Başarılar dilerim
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.
[...] 11- Derleyici Önişlemci Direktifleri – 3 [...]
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
@murat can
Timer’lardan sonra sırada kesmelerin anlatımı var…
[...] şurada daha önce anlatmış olduğumuz önişlemci direktfilerindeki #int_xxx kelimesi ile ilgili kısmı okuyun. Yazıyı okuduğunuza [...]
sitedeki arkadaslar bana 74165 veya 74597 ile giris cogullamada yardimci olabilirsmisiniz?
Gayet güzel, bilgilerinizi paylaştığınız için saolun.
http://www.elektrokampus.com da bizde bu tür şeyler yapmaya çalışıyoruz.
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.
@Altan
Piyasadaki kitapları inceleme fırsatım olmadı. Web üzerinde başka kaynakları da araştırabilirsin. Kolay gelsin
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…
@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…
#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…
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
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");
}
}
}
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.
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");}}}
#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");}}}
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.
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.