Yazar arşivleri:

CCS-C ile PIC Programlama, İşlemci Kontrol Fonksiyonları

CCS-C Derleyici’sinde işlemci kontrol görevlerini yerine getirebilmek için aşağıdaki fonksiyonlar hazır olarak gelmektedir.

  • disable_interrupts()
  • enable_interrupts()
  • clear_interrupt()
  • interrupt_active()
  • jump_to_isr()
  • ext_int_edge()
  • goto_adress()
  • label_adress()
  • read_bank()
  • write_bank()
  • brownout_enable()
  • reset_cpu()
  • restart_cause()
  • sleep()
  • setup_oscillator()
  • getenv()

disable_interrupts()
enable_interrupts()
clear_interrup()
ext_int_edge()

Yukarıdaki fonksiyonları kesme kullanımıyla ilgili yayımladığım yazıda açıklamıştım. Yazı için buraya tıklayın

jump_to_isr()

PIC’lerde kesme vektörü belirli bir adreste bulunur (0×0004), bazı uygulamalarda farklı bir adrese kesme kodu yazma ihtiyacı olabilir, böyle bir durumda herhangi bir kesme oluştuğunda jump_to_isr() fonksiyonu adres bilgisiyle çağrıldığında kesme kodunun bulunduğu adrese atlanır.

#define ISR_ADDR 0x0FF
#define ISR_ADDR 0x3FF
#int_global
void global_isr() {
/* kesme oluştuğunda ISR_ADDR'ye git */
jump_to_isr(ISR_ADDR);
}

ext_int_edge()

Bu fonksiyon PIC’in harici kesme girişindeki sinyal değişiminin hangi durumda kesme oluşturacağını belirler. İki adet seçenek mevcuttur;
Low to High: Giriş sinyalinin yükselene kenarında, yani voltaj 0 eşik değerinden 1 eşik değerine çıktığı durumda kesme tetiklenir. 1 değerinden 0′a düştüğünde herhangi bir kesme tetiklenmez.
High to Low: Giriş sinyalinin düşen kenarında, yani voltaj 1 eşik değerinden 0′a düştüğü durumda kesme tetiklenir. 0 değerinden 1′e yükseldiğinde herhangi bir kesme tetiklenmez.

ext_int_edge(L_TO_H);
ext_int_edge(H_TO_L)

Bazı PIC’lerde 1′den fazla harici kesme bulunmaktadır, bu gibi durumlarda ikinci bir parametre ile hepsi ayrı ayrı ayarlanabilmektedir.

/* birinci harici kesme yükselen kenarda */
ext_int_edge(0, L_TO_H);
/* ikinci harici kesme düşen kenarda */
ext_int_edge(1, H_TO_L);

Harici kesmenin sinyalin hem yükselen hemde düşen kenarında oluşmasını istiyorsanız bunu siz elle yapmak zorundasınız. Harici kesmenin hangi kenarda oluşacağını OPTION registerinin 6. biti belirler. ext_int_edge() fonksiyonuda bu biti ayarlar. Datasheet’lerden OPTION Registerini inceleyebilirsiniz.

#byte OPTION_REG = 0x81
#bit INTEDGE = OPTION_REG.6
#int_ext
void external_isr()
{
if (INTEDGE)
INTEDGE = 0;
else
INTEDGE = 1;
/* kesmeye düşen kenarda girildiyse
yükselen kenara kur,
yükselende girildiyse düşene kur
*/
.
.
uygulama kodları
.
}

goto_address()

Kod içerisinde herhangi bir adrese atlama yapmak için kullanılır

goto_address(0x1f00);
/* program akışı 0x1f00 dan devam eder */

Kullanılırken dikkatli olunması gereken bu fonksiyon gerekli olmayan durumlarda kesinlikle kullanılmamalıdır.

label_address()

Kod içerisinde bulunan etiketlerin bulunduğu noktalardaki adres bilgisini veren bu fonksiyon normal durumlarda pek kullanılmaz, muhtemelen hiç kullanmayacağınız bu fonksiyonu daha iyi anlayabilmek için yardım dosyasındaki örneğe bakalım

start:
a = (b+c);
end:
printf(label_address(end)-label_address(start));

Yukarıdaki program parçasında a = (b+c) işleminin romda ne kadar kod alanı işgal ettiği belirleniyor ve yazdırılıyor.

read_bank(), write_bank()

Ram’den veri okuma işlemi yapmak için read_bank(), yazma işlemi için ise write_bank() fonksiyonları kullanılır. read_bank() Parametre olarak okunacak RAM bank numarasını ve offset değerini alır. write_bank() ise RAM bank numarasını, offseti ve yazılacak veriyi alır

write_bank(1,5,0x55);
/* 1 nolu Bank'ın 5 nolu offsetine 0x55 değerini yaz.*/
read_bank(1,5);
/* 1 nolu Bank'ın 5 nolu offsetindeki datayı oku. (0x55)*/

Bu fonksiyonlar full ram erişiminin olmadığı durumlarda kullanılabilirler. Daha önce #device önişlemci direktifini anlatırken pointer uzunluğu ile ilgili bir ayardan bahsetmiştik. Pointer uzunluğu arttırıldığında RAM’e full erişilebiliyor ama üretilen program koduda ona göre artıyor. ROM alanının daha verimli kullanılması ihtiyacı oluştuğunda pointer büyüklüğü küçültülerek erişilmesi zor olan bölgelere bu fonksiyonlarla ulaşılabilir. Açıkçası ben bu zaman kadar pek kullanma ihtiyacı duymadım.

brownout_enable()

Brownout mekanızması besleme voltajındaki oynamalara karşı PIC’i korumak için tasarlanmıştır. Bazı çiplerde sadece belirli voltajlarda bazılarında ise bir kaç voltaj seviyesi olarak tanımlanabilmektedir. Eğer çipin çalışma voltajı +5v ve Brownout voltajı da +4.2V ise, çipin besleme voltajı 4.2V’un altına düştüğünde çip resetlenir.

Brownout mekanizmasının devrede olup olmayacağı bir çok PIC’te konfigürasyon bitleri programlanırken belirlenir (#FUSE ayarları). Bazı PIC’lerde ise Brownout yönetimi software kontrollü olarak yapılabilmektedir. brownout_enable() fonksiyonu sadece bu çipler için geçerlidir.

brownout_enable(TRUE); /* Brownout devrede */
brownout_enable(FALSE); /* Brownout devre dışı */

reset_cpu()

PIC’e yazılımsal reset atmak için kullanılan bu fonksiyonun herhangi bir parametresi veya geri dönüş değeri yoktur

reset_cpu(); /* PIC resetlenir */

restart_cause()

Bu fonksiyon işlemcinin son olarak nasıl başladığını belirleyebilmek için kullanılır. İşlemci normal power-up ile açılmış olabilir, watchdog reset ile başlatılmış olabilir, Uyku modundayken MCLR reset yapılmış olabilir. Bazı PIC’lerde bu kaynakların sayısı daha fazladır. İncelemek isterseniz kullandığınız PIC ile ilgili h dosyasına bakabilirsiniz.
Fonksiyon çağrıldığında geri dönüş değeri olarak bir sayı döndürür ve bunun değerine göre sonucu yorumlarız.

if(restart_cause() != WDT_TIMEOUT)
{
initialize_registers();
}

Programımızda watchdog kullanmış olalım ve watchdog reset geldiğinde programımızdaki değişkenlerin o anki değerlerinin korunmasını isteyelim. Normalde programın en başında kullandığımız değişkenlere ilk değer ataması yaparız, eğer çip resetlenirse program en başa geleceğinden bu atamalar tekrar yapılmış olur, işte bu durumun önüne geçmek için restart_cause() fonksiyonunu yukarıdaki örnekte olduğu gibi kullanabiliriz. Programın başında PIC’in nasıl resetlendiğine bakarak değişkenlere atama yapılıp yapılmayacağını belirleriz.

Sleep()

PIC’i sleep (uyku) moduna geçirmek için kullanılır asm kod karşılığı SLEEP’tir. PIC’ler uyku modunda 0.5- 2uA gibi oldukça düşük akım çekerler bu yüzden pille çalıştırılan uygulamalarda sıklıkla uyku modu kullanılmaktadır.
Sleep ile uyku moduna geçirilen PIC denetleyicisi gerekli durumlar oluştuğunda uyku modundan çıkar. Bu durumlara örnek olarak PORTB Durum değiştirme, watchdog taşmasını verebiliriz.

Sleep modu ayrı bir konu olarak ele alınacağım için ayrıntılı olarak anlatmıyorum.

Setup_oscillator()

bu fonksiyon bazı pic modellerinde dahili RC osilatör ile ilgili ayarlamalar yapar. İlgili PIC’in h dosyasına bakarak ne tür ayarlamalar yapılabileceğini görebilirisiniz. Run time (çalışma zamanında) osilaötün hızını değiştirirseniz #use_delay ile üretilen sürelerin hatalı olacağını unutmayın.

getenv

Bu fonksiyon ile derleyici ve çalışılan PIC ile ilgili bazı özellikler ve bilgiler öğrenilebilmektedir. Aşağıdaki kullanım örneklerine bakarak daha iyi anlayacağınızı düşünüyorum
Programımızda PORTB’yi tanımlamak isteyelim bu durumda PIC’in datasheet’ine bakıp PORTB’nin 0×06 adresinde olduğunu öğreniriz ve şu şekilde tanımlama yaparız.

#byte PORTB = 0x06

Peki adres bilgisi olmadan PORTB’yi tanımlamak istersek ne yaparız? elbette getenv() kullanırız

#byte B_PORTU = getenv(SFR:PORTB)
/* yine aynı şekilde */
#byte INTCON_REG =getenv(SFR:INTCON)
#bit GLOBAL_INT_ENABLE=getenv(BIT:GIE)
if(getenv(SPI))   /* Kullanılan PIC’te SPI  var mı? */

getenv () kullanılarak öğrenilebilecek diğer şeyler için derleyici yardım dosyasına bakabilirsiniz.

CCS-C ile PIC Programlama, PIC Interrupts (Kesmeler)

Giriş

Bildiğiniz gibi bundan önceki yazımızda Timer’lar konusuna giriş yapmıştık. Bu konuya biraz ara verip kesmeler konusuna geçiş yapacağız. Timer’lar da dahil olmak üzere ilerde anlatacağımız donanımlarda kesmeler konusuna mecburen girmemiz gerekiyordu, bu yüzden hepsinden önce anlatıp diğer konularda da yeri geldikçe kesmelerle ilgili örenekler vermeye deva edeceğiz.

Kesmeler (Interrupts) konusu yeni başlayanlar için zor veya karmaşık gibi görünse de (benim için de öyleydi ilk başladığım zamanlar), CCS-C’de kullanımı oldukça basittir gözünüz korkmasın, CCS-C’nin pratikliğini sonuna kadar kullanacağız :)

CCS-C ile PIC Programlama, PIC Timer Modülleri ve Kullanımı – 1

Uzunca bir süre siteye yazı ekleyemediğim için konuları takip eden arkadaşlardan özür diliyorum.  Son yazıyı ekleyeli epey zaman geçmiş :) Site için daha fazla zaman ayırmak istiyorum ama bir türlü rayına oturtamadım işte :)

Sıradaki konumuz başlıktan da anlaşıldığı gibi Timer’ler ve CCS-C ile Timer’ların kullanımı. Bu konuyu 3 bölüm olarak ele almayı düşünüyorum.

  • Yeni başlyanalar için timer’lar ve özellikleri
  • CCS-C Timer fonksiyonları
  • Timer kod örnekleri

Daha önceki yazılarımda da bahsettiğim gibi, PIC programlama öğrenilirken yazılım simulasyonundan çok donanımları bizzat deneyerek tecrübe etmek daha sağlam temeller oluşturacaktır öğrenen kişide. Bunun için de iki seçenek var; Birincisi her defasında donanımları board üzerine kurmak, İkincisi ise bir geliştirme kiti kullanmak. İkinci yöntem yani geliştirme kiti kullanmak size hem zamandan hemde emekten kazandıracaktır. Sürekli board üzerine devre kurup kaldırmak oldukça zahmetli ve çok zaman alan bir iştir.

CCS-C ile PIC Programlama, Portlar Led Buton ve Röle Kullanımı

Her ne kadar daha önceki yazılarımızda kısmen anlatmış olsakda PORT’lar ve kullanımı konusunu daha ayrıntılı olarak bu yazımıda ele alacağız.

PORTLAR

Portlar PIC denetleyicilerinde giriş/çıkış işlemleri için kullanılan yapılardır. Örneğin bir anahtarın açık/kapalı durumunu belirlemek, LED yakmak, Röle açıp kapamak, veya bir LCD ekranı sürmek için PORT’ları kullanırız. Her PIC modelinde farklı sayıda port bulunur ve bu portlar farklı büyüklüklerde olabilir. Büyüklükten kastımız PORT’un kaç bit olduğudur.

Kullandığınız denetleyicinin teknik dökümanına bakarak kaç porta sahip olduğunu öğrenebilirisiniz. Portlar A,B,C….F gibi harflerle isimlendirilir, PORTA, PORTB, PORTC gibi. Aşağıdaki resim 16f628A Denetleyicisinin pin bağlantılarını göstermektedir.

Resimde de görüldüğü gibi PIC 16F628A Denetleyicisi PORTA, ve PORTB olmak üzere iki adet porta sahiptir. PORTB RB0…..RB7 olmak üzere 8 Bit, PORTA ise RA0….RA5 olmak üzere 6 Bit’tir.

CCS-C ile PIC Programlama, PIC’lerin Temel Donanımsal Bağlantıları

Kısa bir süre ara verdiğim ccs-c ile pic programlama yazılarına kaldığım yerden devam ediyorum. Son olarak önişlemci direktifleri konusunu işleyerek sıkıcı bölümlerden kurtulmuştuk. :) Bu yazımızda ise biraz donanım konularına gireceğiz.

Her ne kadar ISIS gibi programlarla simule edilerek PIC programlama öğrenilebilse de devre gerçeklendiğinde acemiler için bır takım sıkıntılar oluşabilmektedir. Bu nedenle bu işe yeni başlayan arkadaşlara tavsiyem gerçek malzemelerle bread-boar’a kurarak veya bir geliştirme kartı kullanarak çalışmaları.