CCS-C ile PIC Programlama, ADC Fonksiyonları

Bu yazıda PIC Mikro Denetleyicilerinde bulunan ADC (Analog To Digital Converter) modüllerinin CCS-C derleyicisinde nasıl kullanıldığını anlatmaya çalışacağım. ADC modülü Analog sinyali Dijital bilgiye dönüştüren donanımdır. ADC girişine uygulanan analog sinyal bir More »

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() More »

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

Uzunca bir ara verdikten sonra ccs-c ile ilgili konu anlatımlarına devam ediyorum. En son Timer’lar konusunda kalmıştık, dolayısıyla bu yazıda Timer kullanımı ile ilgili bir kaç örneğe yer vereceğim. Denemelerimde sitenin sağında More »

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

Merhaba, uzunca bir aradan sonra tekrar birlikteyiz. CCS-C ile Pic programlama kategorisinde en son Timer’lar ve interrupt konularına değinmiştik, bu yazımızda da timer’lardan devam ediyoruz. Yazımızın amacı CCS-C derleyicisinde Timer modüllerinin nasıl More »

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

Giriş Kesme (Interrupt) Nedir Kesme Mekanizması Kesme kaynakları CCS-C’de kesmelerin kullanımı Kesmelerle ilgili fonksiyonlar Örnek Uygulama Kesmelerle alakalı register’lar Giriş Bildiğiniz gibi bundan önceki yazımızda Timer’lar konusuna giriş yapmıştık. Bu konuya biraz More »

CCS-C ile PIC Programlama, ADC Fonksiyonları

Bu yazıda PIC Mikro Denetleyicilerinde bulunan ADC (Analog To Digital Converter) modüllerinin CCS-C derleyicisinde nasıl kullanıldığını anlatmaya çalışacağım.

ADC modülü Analog sinyali Dijital bilgiye dönüştüren donanımdır. ADC girişine uygulanan analog sinyal bir referans voltajı ile karşılaştırılarak ADC çözünürlüğüne uygun sayısal değere çevrilir. Bir örnekleme yaparak konuyu daha iyi anlayalım.

ADC çözünürlüğümüz 10 Bit olsun, 10 bit ile üretilebilecek en büyük sayı 1023 değeridir.

ADC Referans voltajımız ise 5V olsun, bu durumda ADC girişine 2.5V luk bir sinyal uygularsak dönüştürme işlemi sonucunda 511 değeri okunacaktır.

ADC modülümüz de referans 5V olduğuna göre 0-5v arası gerilim, 0-1023 arası bir değer üretecektir

5 / 1023 = 0.0048875
2.5 / 0.0048875 = 511

CCS-C Derleyicisinde Pic mikro denetleyicilerinin ADC donanımlarını kullanabilmek için aşağıdaki fonksiyonlar hazır olarak gelmektedir.

setup_adc()
setup_adc_ports()
set_adc_channel()
read_adc()
adc_done()

Şimdi sırasıyla bu fonksiyonların ne işe yaradıklarını ve kullanım şekillerini izah edelim.

setup_adc()

Bu fonksiyon kullanılarak ADC modülünün ayarları yapılabilir. Aşağıda kullanım örneklerini görebilirsiniz.

setup_adc(ADC_OFF);   // ADC modülü kapalı
setup_adc(ADC_CLOCK_INTERNAL); // ADC için dahili clock kullanılacak
setup_adc(ADC_CLOCK_DIV_8); // Clock 8'e bölünerek kullanılacak

setup_adc_ports()

Bu fonksiyon kullanılarak ADC modülüne bağlı olan ADC kanallarına ait ayarlamalar yapılır. ADC modülüne sahip olan PIC Mikro denetleyicilerinde analog kanal olarak kullanılabilen PIN’ler dijital I/O olarak ta kullanılabilmektedir.

ADC modülünde referans  voltajı için iki seçenek mevcuttur. Birinci seçenek ADC’nin referans voltajı olarak çipe uygulanan besleme voltajını kullanmasıdır, bu durumda çipe uygulanan besleme voltajı ne ise ADC modülünün referans voltajı da aynı değer olur.

İkinci seçenek ise başka bir gerilim kaynağını ADC modülüne ait VREF+ ve VREF- Pinlerine uygulamak. Bu şekilde çalıştırabilmek için ADC modülü, vref voltajını harici kullanacak şekilde ayarlanmalıdır.

setup_adc_ports() fonksiyonu kullanılarak referans voltaj ayarlaması ve hangi portun analog hangi portun dijital kullanılacağı ayarlanabilir.

setup_adc_ports(NO_ANALOGS);
setup_adc_ports(ALL_ANALOGS);
setup_adc_ports(AN0_ANALOG);
setup_adc_ports(AN0_AN1_AN4_AN5_AN6_AN7_VREF_VREF);

set_adc_channel()

Analog modüle sahip pic mikro denetleyicilerinin bir çoğunda birden fazla analog kanal bulunmaktadır. Bu fonksiyon yardımıyla hangi kanaldan okuma yapılacağı belirtilir.

set_adc_chanel(1);
set_adc_chanel(2);

Kanal ayarlaması yapıldıktan sonra yanlış okuma yapmamak için kısa bir süre beklenmesi gerekmektedir. Bu yüzden bu fonksiyonun ardından ortalama 10us’lik bir gecikme kullanmak gerekmektedir.

read_adc()

Bu fonksiyon ayarlamaları yapılmış adc modülünden değer okuması yapmak için kullanılır. Bu fonksiyona aşağıdaki parametreler opsiyonel olarak verilebilmektedir.

ADC_START_AND_READ, (dönüştürme işlemini başlat sonucu oku, hiçbir parametre verilmezse bu geçerlidir)

ADC_START_ONLY (Dönüştürme işlemini başlat ve çık)

ADC_READ_ONLY (En son dönüştürme işlemini oku)

adc_done()

Bu fonksiyon kullanılarak başlamış olan bir ADC dönüştürme işleminin tamamlanıp tamamlanmadığı tespit edilebilir. Fonksiyon çağrıldığında dönüş değeri 1 ise dönüştürme işlemi tamamlanmış 0 ise dönüştürme işlemi devam etmektedir.

Örnek Program

Aşağıdaki örnek ugulamada PIC16f876 denetleyicisinin iki adet analog kanalından okuma yapılarak PORTB ve PORTC’ye bağlı ledler yakılıyor. Program başındaki #device ADC=8 ifadesi, adc_read() fonksiyonunun 8 bitlik değer döndürmesini sağlar.

#include <16F876.h>
#device ADC=8
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)

void main(void)
{
   int16 adc_value;
   /* adc modülü ayarlanıyor */
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_adc_ports(ALL_ANALOG);

   while(TRUE)
   {
      /* 1. ADC kanalını seç  ve değeri oku*/
      set_adc_channel(0);
      delay_us(10);
      adc_value = read_adc();

      /* okunan değere göre ilgili ledleri yak */
      output_bit(PIN_C0, (adc_value > 0));
      output_bit(PIN_C1, (adc_value > 32));
      output_bit(PIN_C2, (adc_value > 64));
      output_bit(PIN_C3, (adc_value > 96));
      output_bit(PIN_C4, (adc_value > 128));
      output_bit(PIN_C5, (adc_value > 160));
      output_bit(PIN_C6, (adc_value > 192));
      output_bit(PIN_C7, (adc_value > 224));

      /* 2. ADC kanalını seç  ve değeri oku*/
      set_adc_channel(1);
      delay_us(10);
      adc_value = read_adc();

      /* okunan değere göre ilgili ledleri yak */
      output_bit(PIN_B0, (adc_value > 0));
      output_bit(PIN_B1, (adc_value > 32));
      output_bit(PIN_B2, (adc_value > 64));
      output_bit(PIN_B3, (adc_value > 96));
      output_bit(PIN_B4, (adc_value > 128));
      output_bit(PIN_B5, (adc_value > 160));
      output_bit(PIN_B6, (adc_value > 192));
      output_bit(PIN_B7, (adc_value > 224));
    }
}
Be Sociable, Share!

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.

Be Sociable, Share!

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

Uzunca bir ara verdikten sonra ccs-c ile ilgili konu anlatımlarına devam ediyorum. En son Timer’lar konusunda kalmıştık, dolayısıyla bu yazıda Timer kullanımı ile ilgili bir kaç örneğe yer vereceğim.

Denemelerimde sitenin sağında reklamını gördüğünüz expkits firmasının PIC geliştirme devresini kullanıyorum.

Be Sociable, Share!

LM555 İle 1 Hz – 180 Khz Kare Dalga Üreteci

LM555 kullanılarak yapılan bu devre ile 1 Hz ila 180 KHz Arası kare dalga üretmek mümkün. Aşağıda projenin hazır devresini görebilirsiniz.

pulse_generator

ÖZELLİKLER

  • Çalışma voltajı 6-12V DC Max @ 40 mA
  • Devrenin çalıştığını gösteren led mevcuttur
  • İstenilen frekans aralığı devre üzerindeki jumperlar ile seçilebilir
  • 1Hz – 180 Khz arası darbe üretilebilir

AYARLAR

Be Sociable, Share!

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

Merhaba, uzunca bir aradan sonra tekrar birlikteyiz. CCS-C ile Pic programlama kategorisinde en son Timer’lar ve interrupt konularına değinmiştik, bu yazımızda da timer’lardan devam ediyoruz.

Yazımızın amacı CCS-C derleyicisinde Timer modüllerinin nasıl kullanılabileceğini göstermek. İlk konularda da söylediğimiz gibi CCS-C derleyicisinin hiçbir hazır fonksiyonunu kullanmak zorunda değilsiniz. Sadece datasheet’e bakarak PIC’in tüm donanımları için kod yazabilirsiniz. Yazı içerisinde hem hazır fonksiyonlar, hem de hazır fonksiyonlar olmadan bu işin nasıl yapılabileceğini anlatmaya çalışacağım. Örnek PIC denetleyicisi olarak PIC16F628A kullanacağım, elinizde datasheet’in olması faydalı olacaktır.

Be Sociable, Share!