Bölüm-8 Capture/Compare/PWM Modülleri

Capture/Compare/PWM Modülü

CCP (Capture/Compare/PWM) modülü, mikrodenetleyicileri klasik dijital sistemlerden ayıran en önemli özelliklerden biridir. Kimi mikrodenetleyicilerde bu modülden bir adet bulunurken bazılarında iki adet bulunur. İki adet CCP modülüne sahip mikrodenetleyicilerde bu modüller CCP1 ve CCP2 olarak adlandırılırlar. Genel olarak birbirleriyle aynı özelliklere sahip olmakla birlikte, iki adet CCP modülüne sahip mikrodenetleyicilerde CCP1 modülü güçlendirilmiş (enhanced) CCP özelliğine sahiptir ve ayırt etmek için ECCP olarak adlandırılır.

CCP modülleriyle birlikte kullanılan birtakım kaydediciler vardır. Bu kaydediciler benzer özelliklere sahip olduklarından belge içinde zaman zaman CCPRx ya da CCPx olarak adlandırılacaklardır. Burada, ‘x’ kodu ilgili CCP modülünün numarasına karşılık gelmektedir. Bu başlık altında öncelikle tek bir CCP modülüne sahip olan PIC16F628A için temel özellikler açıklanacak olup, ardından iki adet CCP modülüne sahip PIC16F887 üzerinden daha ayrıntılı bir açıklama uygulama örnekleriyle yapılacaktır.

8-bitlik mikrodenetleyicilerde CCP modülü 16-bitlik yakalama (capture) kaydedicisine, 16-bitlik karşılaştırma (compare) kaydedicisine ve bir PWM master/slave görev çevrimi (duty cycle) kaydedicisine sahiptir. Tablo 8.1’de CCP modülünün farklı modları için kullanılan zamanlayıcılar gösterilmiştir.

Tablo 8.1 CCP modülünün modları için kullanılan zamanlayıcılar
CCP Modülü Zamanlayıcı Kaynağı
Capture ModuTimer1
Compare ModuTimer1
PWM ModuTimer2

CCP modülü ilgili mikrodenetleyicide kaç adetse sayı numarasıyla kodlanır. PIC16F628A’da bir adet olduğundan CCP1, PIC16F887 ve PIC18F4550’de iki adet olduğundan CCP1 ve CCP2 olarak adlandırılırlar.

CCP1 modülü her biri 8-bitlik CCPR1L ve CCPR1H kaydedicilerinden oluşan CCPR1 kaydedicisine sahiptir. CCP1CON kaydedicisi CCP1 modülünün nasıl kullanılacağını ayarlar.

CCP1CON KAYDEDİCİSİ (ADRES: 17h – PIC16F628A)

bit 7-6 Kullanılmıyor: ‘0’ olarak okunur.
bit 5-4 CCP1X:CCP1Y: PWM modunda en düşük değerlikli 2 bittir.
Yakalama (Capture) Modu: Kullanılmaz
Karşılaştırma (Compare) Modu: Kullanılmaz
PWM Mode: Bu bitler PWM görev çevriminin iki LSB bitini oluşturur. Diğer 8 bit CCPRxL kaydedicisinde yer alır.
bit 3-0 CCP1M3:CCP1M0: CCPx Modu tercih bitleridir.
0000 = Capture/Compare/PWM kapalıdır (CCP1 modülünü resetler).
0100 = Her düşen kenarda yakalama modudur.
0101 = Her yükselen kenarda yakalama modudur.
0110 = Her 4’üncü yükselen kenarda yakalama modudur.
0111 = Her 16’ıncı yükselen kenarda yakalama modudur.
1000 = Eşleşme durumunda çıkışın lojik-1 olmasını sağlayan karşılaştırma modudur (CCP1IF bayrağı set edilir).
1001 = Eşleşme durumunda çıkışın lojik-0 olmasını sağlayan karşılaştırma modudur (CCP1IF bayrağı set edilir).
1010 = Eşleşme durumunda yazılımsal olarak kesme üreten karşılaştırma modudur (CCP1IF bayrağı set edilir, CCP1 çıkışı etkilenmez).
1011 = Özel olay tetiklemesi gerçekleştiren karşılaştırma modudur (CCP1IF bayrağı set edilir; CCP1 TMR1’i resetler).
11xx = PWM modudur.

Yakalama (Capture) Modu

Yakalama modunda, CCPR1H:CCPR1L kaydedicileri, RB3/CCP1 pininde bir olay meydana geldiğinde TMR1 kaydedicisinin 16-bitlik değerini yakalar. Diğer bir ifadeyle TMR1 kaydedicisinin o anki değeri CCP1R kaydedicisine yazılır. Olayın ne olduğu şu şekilde ifade edilir:

  • Her düşen ↓ kenar
  • Her yükselen ↑ kenar
  • Her 4’üncü yükselen kenar
  • Her 16’ıncı yükselen kenar

Hangi olaya göre yakalama işlminin gerçekleşeceği CCP1CON kaydedicisinin CCP1M3:CCP1M0 bitleri ayarlanarak yapılır. Yakalama modu aktfi kılındığında otomatik olarak CCP1IF kesme bayrağı (PIR1 kaydedicisinin 2’inci biti) kurulur. Yakalama eylemi gerçekleştiğinde bu bayrağın yazılım içinde temizlenmesi gerekir. Yeni bir yakalama eylemi gerçekleştiğinde CCP1R kaydedicisinin önceki değeri kaybolur. Dolayısıyla bu işleme dayalı uygulamalar tasarlanırken, yakalama anında CCP1R kaydedicisine yazılan değer program içinde bir başka değişkene aktarılmalıdır.

Yakalama modunun kullanımı için şu adımlara dikkat edilmelidir:

  • RB3/CCP1 pini “TRISB3_bit=1;” mikroC komutuyla giriş olarak ayarlanmalıdır
  • CCPxCON kaydedicisi ile istenilen yakalama modu ayarlanmalıdır.
  • Çevresel aygıt kesmesi olan Timer1 kesmesi (TMR1IE) aktif yapılmalıdır.
  • Timer1 modülü zamanlayıcı (timer) modunda ya da senkronize sayıcı (counter) modunda çalışmalıdır.
  • Timer1 modülünün asenkron sayıcı modunda çalıştırılması durumunda yakalama modu doğru çalışmayabilir.

Şekil 8.1’de bu modun donanımsal çalışma ilkesi gösterilmiştir.

DİKKAT: Yakalama modu değiştirildiğinde, yanlış bir yakalama kesmesi üretilebilir. Yanlış kesmelerden sakınmak için kullanıcı CCP1IE (PIE1<2>) bitini ve CCP1IF(PIR1<2>) bitini temizlemelidir.

Şekil 8.1 Yakalama modunun çalışma diyagramı

Uyku modunda çalışma sırasında, Timer1 modülü işlemci frekansıyla senkronize edilmiş olmasından dolayı TMR1H-TMR1L kaydedicilerinin içeriği sabit kalmaktadır. Bu durumda CCPRxH-CCPRxL kaydedicilerinin de içeriği güncellenmemiş olacaktır. Ancak CCP kesmesinin aktif olması durumunda cihaz uyku modundan çıkar. Diğer bir ifadeyle uyku modunda CCP pini durum değişimi izlemeye devam eder. Kısacası uyku modunda, CCP pini ilave bir harici kesme girişi olarak davranmış olur.

CCP modülünün yakalama modunun çalışma ilkesini anlamak için şu şekilde bir senaryo yapabiliriz: Bunun için görsel donanım olarak 2 satır 16 sütun karakter LCD kullanabiliriz. LCD ekranda aynı anda o anki Timer1 kaydedicisinin değerini, CCP1 girişine bağlı bir butona basıldığında da butona basılma anındaki Timer1 kaydedicisinin değerini ve Timer1’in önölçekleme hızına bağlı olarak oluşan Timer1 kesme sayısını gösteren uygulama devresi şekil 8.2’de gösterilmiştir.

Şekil 8.2 Timer1 ile CCP1 yakalama modunun ilişkisini gösteren uygulama

Şekildeki uygulamada mikrodenetleyicinin CCP1 özellikli B3 pinine pull-down bağlantılı bir direnç üzerinden buton bağlanmıştır. Butonun diğer ayağıda 5V besleme bağlanmıştır. MCU’nun dâhili pull-up özelliği kapatılmış olup, CCP1 modülünün girişin yükselen kenarında tepki vermesi amaçlanmıştır. Timer1 modülünün önölçekleme değeri 1:8 olarak ayarlanmış olup TMR1H-TMR1L kaydedicilerinin sayma değeri 8 kat yavaşlatılmıştır. LCD ekranda aynı anda oluşan Timer1 kesme sayısı, Timer1’in o anki değeri ve butona basıldığı andaki Timer1 değeri görülmektedir. Uygulama devresinin mikroC kaynak kodu tablo 8.2’de gösterilmiştir.

Tablo 8.2 Timer1 ile yakalama modunun ilişkisini gösteren uygulamanın mikroC kodu

char msj01[] = "TIMER1= ";
char msj02[6];
char msj03[6];
char msj04[6];
unsigned int timer1, ccp1, sayac;
sbit LCD_RS at RB0_bit; //LCD bağlantıları ayarlanıyor
sbit LCD_EN at RB1_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_RS_Direction at TRISB0_bit;
sbit LCD_EN_Direction at TRISB1_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
void ayarlar(){
 TRISA=0;
 PORTA=0;
 Lcd_Init(); // Lcd_Init PORTB LCD için hazırlandı
 TRISB2_bit=0;
 TRISB3_bit=1;
 PORTB=0;
 CMCON=0x07; // Karşılaştırıcı modülleri dijitale ayarlandı
 OPTION_REG = 0B10000000; //dâhili pull-up'lar aktif değil
 INTCON.GIE = 1; // Evrensel kesme aktif yapılıyor
 INTCON.PEIE=1; // Çevresel aygıt kesmesi aktif yapılıyor
 PIE1.TMR1IE=1; //Timer1 kesmesi aktif
 T1CON = 0B00110001;//Timer1 MCU osilatörü ile eşleştirilerek aktif 
 // yapılıyor prescaler 1:8
 CCP1CON = 0B00000101; // Her yükselen kenarda yakalama modudur
 Delay_us(50);
 TMR1H=0X00;
 TMR1L=0X00;
}
void main() {
 ayarlar();
 Lcd_out(1,1,msj01);
 while(1){
  timer1=((TMR1H << 8) + TMR1L);
  WordtoStr(timer1,msj02);//2byte'lık bilgi string mesaja çevriliyor
  Lcd_out(1,9,msj02);
  WordtoStr(sayac,msj03);//2byte'lık bilgi string mesaja çevriliyor
  Lcd_out(2,1,msj03);
  WordtoStr(ccp1,msj04);//2byte'lık bilgi string mesaja çevriliyor
  Lcd_out(2,9,msj04);
  delay_ms(100);
 }
}
void interrupt()
{
 if(CCP1IF_bit){ //CCP1IF kesmesi mi?
  ccp1 = ((CCPR1H << 8) + CCPR1L);
  CCP1IF_bit=0; //CCP kesmesi yeni kesme için sıfırlanıyor
  Delay_us(50);
 }
 if(TMR1IF_bit){
  sayac++; //Timer1 kesme hızını izlemek için kullanılan değişken
  T1CON.TMR1ON=0;
  Delay_us(50);
  TMR1H=0;
  TMR1L=0;
  T1CON.TMR1ON=1;
  TMR1IF_bit=0; //Timer1 kesmesi yeniden sayması için sıfırlanıyor
 }
}
	

NOT: Program içinde yakalama modu değiştirilmek istendiğinde CCP1CON kaydedicisi sıfırlanmalı (Ör: CCP1CON = 0;) ve ardından yeni değer yüklenmelidir:

Karşılaştırma (Compare) Modu

Karşılaştırma modunda sürekli olarak CCPR1 kaydedicisinin içeriğiyle TMR1 kaydedicisinin içeriği karşılaştırılır. Eşleşme olduğunda, RB3/CCP1 pini;

  • Lojik-1 olur.
  • Lojik-0 olur.
  • Durum değiştirmez.

Bu durumlar yakalama modunda olduğu gibi, CCP1CON kaydedicisinin CCP1M3:CCP1M0 bitlerinin ayarlanmasıyla elde edilir.

Şekil 8.3 Karşılaştırma modunun çalışma diyagramı

Bu modda RB3 pini çıkış olarak ayarlanmalıdır. CCP1CON kaydedicisinin resetlenmesi ya da yeniden kurulması RB3/CCP1 karşılaştırma tutma (latch) değerinin varsayılan sıfır seviyesine çekilmesine neden olur. Yakalama modunda olduğu gibi, karşılaştırma modunda da Timer1 modülü zamanlayıcı ya da senkron sayıcı modunda çalıştırılmalıdır.

Karşılaştırma modunun anlaşılması için şu şekilde bir uygulama senaryosu geliştirilmiştir: Timer1 modülü sayıcı (counter) modunda çalışacak şekilde ayarlanmıştır. Dışarıdan RB6/T1CKI girişine bir saat darbesi üreteci bağlanarak, darbenin her yükselen kenarında TMR1 kaydedicisinin değerinin artması istenmektedir. Darbe üreteci yerine, bir üretim bandından geçen ürünleri saymak için kullanılan kapasitif algılayıcı gibi bir algılayıcı da bağlanabilir. Ardından TMR1 kaydedicisinin değeri, program içinde belli bir değere kurulan CCPR1 kaydedicisinin değerine ulaştığında ışıklı ikaz verecektir. İkaz durumu harici kesme girişine bağlı çift yönlü ve çift kontaklı bir anahtar ile durdurulmaktadır. Anahtar eski konumuna getirildiğinde sayma işlemi tekrar başlamaktadır.

Şekil 8.4’te bu uygulamayı gerçekleştirecek prensip devre şeması gösterilmiştir. PROTEUS-ISIS® programında harici darbe üreteci olarak “Generator Mode” araçlarından “PULSE” aracı kullanılmıştır. Frekans olarak 1Hz ayarlanmış ve CCPR1 10 değeriyle yüklenmiştir. TMR1 kaydedicisinin değeri 10 değerine ulaştığında RB3/CCP1 pini lojik-1 olur. Artan Timer1 değerini izlemek için 2x16 LCD ekran kullanılmıştır.

Şekil 8.4 Timer1 ile CCP1 karşılaştırma modunun ilişkisini gösteren uygulama

Tablo 8.3 Timer1 ile karşılaştırma modunun ilişkisini gösteren uygulamanın mikroC kodu

char msj01[] = "TIMER1= ";
char msj02[6];
unsigned int timer1, ccp1, sayac;
sbit LCD_RS at RA7_bit; //LCD bağlantıları ayarlanıyor
sbit LCD_EN at RA6_bit;
sbit LCD_D4 at RA0_bit;
sbit LCD_D5 at RA1_bit;
sbit LCD_D6 at RA2_bit;
sbit LCD_D7 at RA3_bit;
sbit LCD_RS_Direction at TRISA7_bit;
sbit LCD_EN_Direction at TRISA6_bit;
sbit LCD_D4_Direction at TRISA0_bit;
sbit LCD_D5_Direction at TRISA1_bit;
sbit LCD_D6_Direction at TRISA2_bit;
sbit LCD_D7_Direction at TRISA3_bit;
void ayarlar(){
 TRISA=0;
 PORTA=0;
 TRISB=0X01; //B0 pini giriş
 PORTB=0;
 Lcd_Init();
 CMCON=0x07; // Karşılaştırıcı modülleri dijitale ayarlandı
 OPTION_REG = 0; // Dâhili pull-up'lar pasif
 INTCON.GIE = 1; // Evrensel kesme aktif yapılıyor
 INTCON.INTE = 1; // Harici kesme aktif yapılıyor
 T1CON = 0B00000010;// Timer1 sayıcı moduna ayarlanıyor, prescaler 1:1
 CCP1CON = 0B00001000; // CCP1'i lojik-1 yapan karşılaştırma modu
 Delay_us(50);
 CCPR1H=0x00;
 CCPR1L=0X0A; //CCPR1 kaydedicileri toplamda 10 değerine ayarlanıyor
 TMR1H=0X00;
 TMR1L=0X00;
 T1CON.TMR1ON=1;//Timer1 çalıştırılıyor
}
void main() {
 ayarlar();
 Lcd_out(1,1,msj01);
 while(1){
  timer1=((TMR1H << 8) + TMR1L);
  WordtoStr(timer1,msj02);//2byte'lık bilgi string mesaja çevriliyor
  Lcd_cmd(_LCD_CURSOR_OFF);
  Lcd_out(1,9,msj02);
 }
}
void interrupt()
{
 if(CCP1IF_bit){ //CCP1IF kesmesi mi?
  TMR1H=0X00;
  TMR1L=0X00;
  CCP1IF_bit=0; //CCP kesmesi yeni kesme için sıfırlanıyor
  Delay_us(50);
 }
 if(INTF_bit){
  CCP1CON=0;
  Delay_us(50);
  CCP1CON=0B00001000;//resetleme sonrası CCP1 tekrar kuruluyor
  CCPR1H=0x00;
  CCPR1L=0X0A;
  INTF_bit=0;
 }
}


NOT: CCP1 çıkışı tutma (latch) özelliklidir ve resetlenmedikçe ya da yeni değer yüklenmedikçe son durumunu korumaya devam eder. Bu nedenle harici kesme tetiklemesiyle birlikte RB3/CCP1 hattının lojik 0 olması istendiğinden CCP1 modülü sıfırlanmaktadır. Özel olay tetiklemesi gerçekleştiren karşılaştırma modunda (CCP1CON=0b00001011) CCP1, TMR1 kaydedici çiftini resetler. Böylece CCPR1 kaydedicisi, Timer1 için 16-bitlik programlanabilir periyot kaydedicisi olarak kullanılmış olur.

PWM Modu

MikroC IDE ortamında, seçilen mikrodenetleyicilere özgü olarak kullanılabilen çok sayıda kütüphane olduğu daha önceden belirtilmişti. Bu kütüphanelerden biri de PWM kütüphanesidir. Ancak, Timer2 kaydedicisinin doğru şekilde ayarlanmasıyla kütüphane kullanmadan PWM sinyali üretmek mümkündür. Bunun için Capture/Compare/PWM (CCP) modülünün kontrol edilmesi gerekmektedir. Pek çok PIC mikrodenetleyicisinde bu modülden bir ya da iki adet bulunur. PIC16F628A’da CCP modülünden bir adet vardır ve CCP1 olarak adlandırılır. CCP1 modülünü kontrol eden iki önemli kaydedici vardır. Bunlardan birisi Analog İşlemler bölümünde ayrıntılı olarak açıklanan CCP1CON kaydedicisi, diğeri de CCPR1L kaydedicisidir.

Darbe genişliği modülasyonu (PWM) modunda, ilgili CCP modülü CCPx pininden 10-bit çözünürlüğüne kadar PWM çıkış üretir. CCPx pini veri tutma (data latch) devresine bağlıdır ve o an için tutulan bilginin çıkışa aktarılması için ilgili TRIS komutuyla yönlendirilmesi gerekir. Şekil 8.5’te PWM işleyişinin basitleştirilmiş blok diyagramı gösterilmiştir.

Şekil 8.5 Basitleştirilmiş PWM blok diyagramı

PWM modunda CCPRxH salt okunur kaydedici olarak davranır. 8-bit TMR2 kaydedicisi, 10 bitlik zaman tabanını oluşturmak için 2 bit dâhili sistem saati (FOSC) veya önölçekleyicinin 2 biti ile birleştirilir. PWM çıkışı Şekil 8.6’da gösterildiği gibi bir periyoda ve çıkışın yüksekte kaldığı bir zamana sahiptir.

Şekil 8.6 CCP PWM çıkışı

PWM Periyodu

Mikrodenetleyicinin PWM modunda çalışması için CCP1CON kaydedicisi ayarlanır. PWM periyodunun hesaplanması için Denklem 8.1’den yararlanılır. Ardından üretilecek PWM sinyalinin görev çevrim oranı CCPR1L kaydedicisine ve varsa diğer bitlere değer yazılmasıyla elde edilir.

PWM periyodu= [(PR2)+1] x 4 x TOSC x TMR2 prescaler değeri Denklem 8.1

Örnek uygulamada PWM sinyalinin 1kHz istendiği varsayılsın. Mikrodenetleyicinin dâhili 4 MHz frekansı kullanıldığında ve PR2 = 249, TMR2 önölçekleyicisi = 1:4 olarak ayarlandığında:

PWM periyodu=[249+1] x 4 x 1/4.000.000 x 4= 1.000/1.000.000=1/1000=1msn=1kHz olur.

PWM Görev Çevrimi

8-bitlik PIC mikrodenetleyicilerinde CCP modülü PR2 kaydedicisinin aldığı değere bağlı olarak en fazla 10-bit çözünürlüğe sahiptir. Dolayısıyla gerçekte 0-255 değil, 0-1023 aralığında bir hassasiyetle görev çevrimi ayarlanır. CCP1CON kaydedicisinin 5 ve 4 numaralı bitleri görev çevrimi değerinin düşük değerlikli bitleri olarak tahsis edilmiştir. Bu iki bit düşük değerlikli olduklarından etkileri azdır ve genellikle kullanılmaz. Bu nedenle genellikle yalnızca CCPR1L kaydedicisine yazılacak 8-bitlik (0-255) değerle PWM duty cycle değeri ayarlanmış olur.

PIC16F887 mikrodenetleyicisinin CCP1 ve CCP2 modülü için darbe genişliği ve görev çevrim oranları sırasıyla Denklem 8.2 ve Denklem 8.3 ile hesaplanır.

Darbe genişliği= CCPRxL:CCPxCON<5:4>x TOSC x TMR2 prescalerDenklem 8.2

Örneğin CCPR1L kaydedicisi 255 (FFh) değeriyle ve CCP1CON<5:4> bitleri 0 değeriyle yüklendiğinde 10 bitlik 1111111100b = 1020 değeri elde edilir. T2CON kaydedicisinin önölçekleme değeri 1:16 ve mikrodenetleyici çekirdek frekansı 8 MHz ise, bu durumda en yüksek darbe genişliği,

= 1020 x 1/8.000.000 x 16 = 0,00204 = 2,04ms olarak elde edilir.

Denklem 8.3

Örneğin CCPR1L kaydedicisi 128 (80h) değeriyle ve CCP1CON<5:4> bitleri 0 değeriyle yüklendiğinde 10 bitlik 1000000000b = 512 değeri elde edilir. T2CON kaydedicisinin önölçekleme değeri 1:16 ve PR2 kaydedicisi değeri 255 ise, bu durumda görev çevrim oranı,

PWM görev çevrim oranı= 512/(4(255+1))=512/1024=0,5=%50 olarak elde edilir.

PWM Çözünürlüğü

Çözünürlük tanımlı bir periyot için mevcut görev çevrimlerinin sayısını belirtir. Örneğin, 10-bit çözünürlük 1024 farklı görev çevrimi üretirken, 8-bit çözünürlük 256 farklı görev çevrimi üretir. PR2 kaydedicisine 255 (FFh) yüklendiğinde en yüksek PWM çözünürlüğü 10 olarak elde edilir. Çözünürlük Denklem 8.4’te gösterildiği gibi PR2 kaydedicisinin bir fonksiyonudur.

Denklem 8.4

Tablo 8.4’te ve 8.5’te sırasıyla 20 MHz ve 8 MHz FOSC değerlerine ve PR2 kaydedicisinin aldığı değerlere göre elde edilen PWM frekansları hesap tablosu verilmiştir. Yapacağınız uygulamalarda bu tablolardan yararlanabilirsiniz.

Tablo 8.4 Örnek PWM frekansları ve çözünürlükleri (20 MHz)
PWM Frekansı1,22 kHz4,88 kHz19,53 kHz78,12 kHz156,3 kHz208,3 kHz
Timer önölçekleyicisi (1, 4, 16)1641111
PR2 değeri0xFF0xFF0xFF0x3F0x1F0x17
Maksimum çözünürlük (bit)101010876,6


Tablo 8.5 Örnek PWM frekansları ve çözünürlükleri (8 MHz)
PWM Frekansı1,22 kHz4,90 kHz19,61 kHz76,92 kHz153,85 kHz200 kHz
Timer önölçekleyicisi (1, 4, 16)1641111
PR2 değeri0x650x650x650x190x0C0x09
Maksimum çözünürlük (bit)888655

PWM İşleyişinin Ayarlanması

Timer2 modülünün PWM üreteci olarak ayarlanması için sırasıyla aşağıdaki adımlar uygulanmalıdır:

  • PR2 kaydedicisine 0-255 arası bir değer yazarak PWM periyodu ayarlanır. (Not: Alt ve üst sınır değerlerin yazılması tavsiye edilmez.)
  • CCPR1L ve CCP1CON<5:4> pinlerine değer yazılarak PWM görev çevrimi (duty cycle) değeri ayarlanır. (Not: 10-bitlik çözünürlüğe sahip olmakla birlikte en küçük değerlikli-LSB bitleri olan CCP1CON<5:4> bitleri kullanılmamıştır.)
  • CCP1’e karşılık gelen pin (PIC16F628A için RB3 pini) ilgili TRIS komutuyla çıkış olarak ayarlanır.
  • T2CON kaydedicisiyle Timer2 modülü aktif yapılır ve önölçekleme değeri ayarlanır.
  • CCP1 modülü PWM işlemi için ayarlanır. (Not: CCP1CON kaydedicisinde CCP1M3 ve CCP1M2 bitleri lojik-1 yapıldığında PWM moduna geçilir.)

Şekil 8.7’de 1kHz’lik PWM sinyaliyle bir LED’in sürülmesini gerçekleştiren uygulama devresi gösterilmiştir.

Şekil 8.7 Timer2 modülü yardımıyla elde edilen PWM sinyali uygulaması

Tablo 8.6 Timer2 modülü yardımıyla elde edilen PWM sinyali uygulamasının mikroC kodu

unsigned short current_duty, baslat, saniye;
unsigned int sayac;
void main(){
     CMCON = 0X07;  //Karşılaştırıcılar kapatılıyor.
     OPTION_REG = 0B00000000;//ön ölçekleyici 1:1
     TRISA = 0;
     TRISB = 0X01;
     PORTA = 0;
     PORTB = 0;
     PR2 = 249;
     CCPR1L = 0;
     T2CON = 0B00000001; //Postscaler 1:1, prescaler 1:4, Timer2 off
     CCP1CON = 0; //PWM modu
     INTCON.GIE=1;
     INTCON.INTE=1;
     TMR0=156;
     Delay_ms(10);
     TMR2=0;
     T2CON.TMR2ON = 1;
     CCP1CON = 0B00001100;
     while(1){
        do{
         current_duty++;
         CCPR1L = current_duty;
         delay_ms(50);
        }while(current_duty<255 && baslat);
        do{
         current_duty--;
         CCPR1L = current_duty;
         delay_ms(50);
        }while(current_duty>0 && !baslat);
     }
}
void interrupt(){
 if(INTCON.INTF){
   baslat = ~baslat;
   INTCON.INTF=0;
 }
}


ADC Uygulamalı PWM İle DC Motor Kumandası

Şekil 8.8’da ADC modülüne sahip PIC16F887 ile yapılmış bir DC motor kontrol uygulaması gösterilmiştir. Uygulamada iki adet LDR kaynağından alınan ışık değerleri ADC modülü ile çözümlenip elde edilen fark nispetince DC motora ileri-geri kumanda yaptırılmaktadır. Motorlar ışık farkına bağlı olarak üretilen PWM değeri şiddetinde sürülmektedir.

PIC16F887 mikrodenetleyicisi bünyesinde, biri güçlendirilmiş olmak üzere iki adet CCP modülü bulundurur. CCP2 modülü, PIC16F628A’nın CCP1 modülüyle aynı özelliklere sahiptir ve bu uygulamada CCP2 modülü kullanılmıştır.

DC motor, yeterli akım ihtiyacının karşılanması için L298N çift kanallı tam köprü sürücüsü üzerinden sürülmüştür (Bkz. Ek-I3). Motora ileri-geri yön verebilmek için motor sürücüsünün IN1 ve IN2 girişleri kullanılmıştır. CCP2 üzerinden uygulanan PWM sinyali ile motor sürücüsünün ENA (enable-etkinleştirme) girişi kumanda edilerek motorun değişen şiddette sürülmesi sağlanmıştır.

Dikkat etmeniz gereken en önemli husus PWM sürerken T2CON kaydedicisinin açılmasıdır. CCP modülü PWM moduna ayarlandığında sistem Timer2 modülünün TMR2IF bitini izlemeye başlar. Timer2 kesmesini program başında kapatmanız gerekir. Ancak kesmeyi kapatmanıza karşın PWM modunun ayarlanmış olmasından dolayı TMR2IF bayrağı sistem tarafından aktif edilir. PWM frekans süresi bu bayrağın aktiflik süresiyle oluşturulur. TMR2IF bayrağı kesmesine göre işlem yapılacaksa, CCPR1L ya da CCPR2L duty_cycle kaydedicilerine değer aktarımı öncesinde bayrağın resetlenmesi gerekir. Bu işlemi şu şekilde yapabilirsiniz;

while(!PIR1.TMR2IF)
PIR1.TMR2IF=0;

Bu küçük yapıda PIR1 kaydedicisinin TMR2IF bayrağı 1 olana kadar döngü işletilmektedir. 1 olduğunda döngüden çıkılır. Bayrak resetlenir ve sonraki işlemler yapılır.

Şekil 8.8 PIC16F887 ile DC motorun ileri-geri yönde PWM modunda sürülmesi

Uygulamada T2CON kaydedicisi 1:16 önölçekleme değeriyle yüklenmiştir. Saat frekansı 8 MHz olduğundan PWM frekansı 500Hz olarak elde edilir.

Tablo 8.7 PIC16F887 ile DC motorun ileri-geri yönde PWM modunda sürülmesi mikroC kodu

#define MAKS_PWM 255
#define MIN_PWM 0
#define LED PORTE.RE0
#define KONTROL PORTD.RD0
#define KONTROL2 PORTD.RD1
unsigned short duty_cycle;
unsigned char maks_darbe=0;
unsigned char darbe_zirvesi=0;
unsigned char zirve_degeri = 0;
unsigned int i;
unsigned short ldr_sol;
unsigned short ldr_sag;
int ldr_fark;
void ayar(){
 TRISA = 0X03; //LDR bağlantıları giriş yapıldı
 PORTA = 0;
 TRISB = 0X00;
 PORTB = 0;
 TRISC = 0X00;
 PORTC = 0;
 TRISD = 0X00;
 PORTD = 0;
 TRISE = 0X00;
 PORTE = 0;
 OPTION_REG = 0; // 1:2 ön ölçekleme değeri
 /* Port girişlerinin davranışı belirleniyor ve analog kanal ayarları yapılıyor */
 ANSEL = 0b00000011; //AN1 ve AN0 kanalı analog, diğerleri dijital yapıldı.
 ANSELH = 0;
 ADCON1 = 0;
 CCP1CON = 0; //PWM kapalı
 CCP2CON = 0;
 TMR2 = 0;
 PR2=249;
 CCPR2L = MIN_PWM;
 INTCON = 0;
 Delay_ms(50);
 PIE1 = 0;
 PIR1 = 0;
 T2CON = 0B00000010; //Prescaler 1:16
 Delay_ms(10);
 T2CON.TMR2ON = 1;
 KONTROL = 0;
 KONTROL2 = 0;
}
void kontrol(){
 for(i=0;i<10;i++){
  LED = ~LED;
  Delay_ms(50);
 }
 LED=0;
}
void main(){
 ayar();
 kontrol();
 while(1) {
    /* ADC burada okunuyor */
  ADCON0=0B11000001; // ADC portunun AN0 kanalı seçiliyor. A/D işlemi çalıştırıılıyor
  Delay_us(50); /* ADC modülünün dönüştürmeye hazır hale gelmesi için kasıtlı be ekleme yapılıyor */
  GO_DONE_bit=1;
  while(GO_DONE_bit) continue;// ldr_sol dönüştürme işleminin bitmesi bekleniyorr
  ldr_sol=ADRESH; // 8 bitlik MSB okunuyor, ADRESL'deki 2 bitlik LSB önemsennmiyor
  ADCON0=0B11000101; // ADC portunun AN1 kanalı seçiliyor. A/D işlemi çalıştırıılıyor
  Delay_us(50); /* ADC modülünün dönüştürmeye hazır hale gelmesi için kasıtlı bekleme yapılıyor */
  GO_DONE_bit=1;
  while(GO_DONE_bit) continue; // ldr_sag dönüştürme işleminin bitmesi bekleniyyor
  ldr_sag=ADRESH; // 8 bitlik MSB okunuyor, ADRESL'deki 2 bitlik LSB önemsenmmiyor
   /* Fark hesaplanıyor */
  ldr_fark=ldr_sol - ldr_sag;
  if (ldr_fark > 0) {
      /* while(!PIR1.TMR2IF)
     PIR1.TMR2IF=0;*/
   CCP2CON = 0B00001100;
   duty_cycle = ldr_fark;
   CCPR2L = duty_cycle;
   KONTROL = 1;
   KONTROL2 = 0;
   delay_ms(5);
  }
  else if(ldr_fark < 0){
     /* while(!PIR1.TMR2IF) 
     PIR1.TMR2IF=0; */
   CCP2CON = 0B00001100;
   duty_cycle = (-1)*ldr_fark;
   CCPR2L = duty_cycle;
   KONTROL = 0;
   KONTROL2 = 1;
   delay_ms(5);
  }
  else{
   CCP2CON = 0;
   KONTROL = 0;
   KONTROL2 = 0;
  }
 }
}


Güçlendirilmiş (Enhanced) ECCP Modülü

CCP modülü ile PWM üretimi daha önceden anlatıldığı için (Bkz. 8.1.3) bu başlık altında güçlendirilmiş PWM üretimi ve bunun için gerekli olan kaydedici ayarlarından bahsedilecektir. Güçlendirilmiş CCP modülü ve PWM modu birden fazla CCP modülü bulunan PIC mikrodenetleyicilerinin sahip olduğu bir özelliktir. Bu başlık altında PIC16F887 mikrodenetleyicisinin güçlendirilmiş CCP modülü ve PWM modu anlatılacaktır. PIC16F887 CCP1 ve CCP2 olarak iki adet Capture/Compare/PWM modülüne sahiptir. Çok küçük bir farkla PIC16F628A’nın CCP1 modülü, PIC16F887’nin CCP2 modülüne eşdeğerdir.

CCP1 modülü bu MCU'larda gelişmiş (Enhanced) CCP modülüdür ve PWM özelliğini kullanmak bir miktar daha ayrıntılıdır. Bu modülün 3 farklı çalıştırma tekniği bulunur:

  1. Yalnızca P1A pininin klasik PWM çıkışı olarak kullanıldığı mod (P1B, P1C ve P1D normal dijital I/O).
  2. Yarım köprü (Half-Bridge) modu (P1A ve P1B birbirinin eşleniği modüleli çıkış üretir, P1C ve P1D normal dijital I/O).
  3. Tam köprü (Full-Bridge) modu. Bu mod en karmaşık olan moddur. İleri ve geri yön motor kumandası için çok uygundur. P1A, P1B, P1C ve P1D pinlerinin dördü de kullanılır. CCP1CON kaydedicisinin CCP1M bitlerinin durumu ‘1100’ iken P1M bitleri ‘01’ yapıldığında ileri yön, ‘11’ yapıldığında geri yön sürme işlemi yapılabilir.

Güçlendirilmiş PWM modundan bahsetmeden önce güçlendirilmiş Capture/Compare/PWM (ECCP) modülü ve onu kontrol etmek için kullanılan CCP1CON kaydedicisini açıklamak daha uygun olacaktır.

Güçlendirilmiş CCP1 modülü, kullanıcıya farklı olayları zamanlamasına ve kontrol etmesine olanak tanıyan bir çevresel aygıttır. Yakalama modunda, bir olayın oluş süresinin zamanlaması gerçekleştirilirken, karşılaştırma modunda ise önceden tanımlanmış bir süre aşımı gerçekleştiğinde harici bir olayın tetiklenmesi gerçekleştirilir. PWM modu ise (PWM hakkında ayrıntılı bilgi için 4.10’a bakınız) değişen frekansta ve görev çevrimi süresinde darbe genişliği modülasyonlu sinyal üretimini sağlar. Güçlendirilmiş CCP modülünün P1A(RC2), P1B(RD5), P1C(RD6) ve P1D(RD7) olarak isimlendirilen 4 adet pini bulunmaktadır. Bu pinlerin ne işe yaradıkları ayrıntılı olarak aşağıdaki gibi anlatılmıştır.

CCP1CON KAYDEDİCİSİ (ADRES: 17h – PIC16F887)

bit 7-6 P1M<1:0>: PWM çıkış konfigürasyon bitleridir.
Eğer CCP1M<3:2> = 00, 01, 10 ise:
XX = P1A/CCP1 yakalama/karşılaştırma girişi olarak kullanılırken; P1B, P1C ve P1D olağan I/O portu olarak kullanılır.

Eğer CCP1M<3:2> = 11 ise:
00 = Tek çıkış; P1A modüleli PWM çıkışı, P1B, P1C, P1D olağan I/O portu olarak kullanılır.
01 = İleri yön beslemeli tam-köprü çıkışı; P1D modüleli PWM çıkışı olarak kullanılırken, P1A sürekli aktif, P1B ve P1C ise sürekli pasiftir.
10 = Yarım-köprü çıkışı; P1A ve P1B ölü-bant kontrollü modüleli PWM çıkışı olarak kullanılırken, P1C ve P1D ise olağan I/O portudur.
11 = Geri yön beslemeli tam-köprü çıkışı; P1B modüleli PWM çıkışı olarak kullanılırken, P1C sürekli aktif, P1A ve P1D ise sürekli pasiftir.
bit 5-4 DC1B<1:0>: PWM görev çevrimi değerinin en düşük değerlikli 2 bittir.
Yakalama (Capture) Modu: Kullanılmaz
Karşılaştırma (Compare) Modu: Kullanılmaz
PWM Modu: Bu bitler PWM görev çevriminin iki LSB bitini oluşturur. Diğer 8 bit CCPR1L kaydedicisinde yer alır.
bit 3-0 CCP1M<3:0>: ECCP Modu tercih bitleridir.
0000 = Capture/Compare/PWM kapalıdır (ECCP modülünü resetler).
0001 = Kullanılmaz (rezerve edilmiştir).
0010 = Karşılaştırma modudur. Karşılaştırma her sağlandığında çıkışın durumu terslenir (CCP1IF bayrağı set edilir).
0011 = Kullanılmaz (rezerve edilmiştir).
0100 = Her düşen kenarda yakalama modudur.
0101 = Her yükselen kenarda yakalama modudur.
0110 = Her 4’üncü yükselen kenarda yakalama modudur.
0111 = Her 16’ıncı yükselen kenarda yakalama modudur.
1000 = Eşleşme durumunda çıkışın lojik-1 olmasını sağlayan karşılaştırma modudur (CCP1IF bayrağı set edilir).
1001 = Eşleşme durumunda çıkışın lojik-0 olmasını sağlayan karşılaştırma modudur (CCP1IF bayrağı set edilir).
1010 = Eşleşme durumunda yazılımsal olarak kesme üreten karşılaştırma modudur (CCP1IF bayrağı set edilir, CCP1 çıkışı etkilenmez).
1011 = Özel olay tetiklemesi gerçekleştiren karşılaştırma modudur (CCP1IF bayrağı set edilir; CCP1 TMR1’i ve TMR2’yi resetler).
1100 = PWM modudur. P1A, P1C ve P1B, P1D aktif yüksektir.
1101 = PWM modudur. P1A, P1C aktif yüksektir ve P1B, P1D aktif düşüktür.
1110 = PWM modudur. P1A, P1C aktif düşüktür ve P1B, P1D aktif yüksektir.
1111 = PWM modudur. P1A, P1C ve P1B, P1D aktif düşüktür.

Tablo 8.5’te ECCP modülünün farklı modları için kullanılan zamanlayıcılar gösterilmiştir.

Tablo 8.8 CCP modülünün modları için kullanılan zamanlayıcılar
ECCP ModülüZamanlayıcı Kaynağı
Capture ModuTimer1
Compare ModuTimer1
PWM ModuTimer2

Şekil 8.9’da güçlendirilmiş PWM çıkış dalga ilişkileri gösterilmiştir. PWM ilk etkinleştirildiğinde tamamlanmamış bir dalga formunun üretilmesini engellemek için, ECCP modülü bir PWM sinyali üretmeden önce yeni bir PWM periyodu başlayana kadar bekler.

Şekil 8.9 Güçlendirilmiş PWM çıkış dalga ilişkileri

NOT: Her bir PWM çıkışı TRIS komutuyla uygun şekilde ayarlanmalıdır. CCPxCON kaydedicisinin temizlenmesi tüm PWM çıkış pinlerinin serbest kalmasını sağlayacaktır. ECCP tarafından kullanılmayan herhangi bir pin normal dijital I/O uygulamaları için kullanılabilir.

Yarım Köprü Modu

Yarım köprü modunda, push-pull yüklerin sürülmesi için iki pin kullanılır. PWM çıkış sinyali CCPx/P1A pininden alınırken PWM sinyalinin eşleniği P1B pininden alınır (Bkz. Şekil 8.10).

Şekil 8.10 Yarım-köprü PWM'in dalga şekli

Bu mod Şekil 8.11’de gösterildiği gibi yarım-köprü uygulamalarında ya da tam-köprü uygulamalarında kullanılabilir. Birinci uygulamada iki ayrı DC kaynak üzerinden yük kontrolü yapılmaktadır. Kullanılan MOSFET ya da transistörlerin her ikisi de aynı kutupludur. Örnekte iki adet N-tipi MOSFET kullanılmıştır. P1A girişi aktif yüksekken P1A çıkışına bağlı MOSFET iletim geçer ve kendisine bağlı kaynak üzerinden bir yönde yükü bir yönde çalıştırır. Bu esnada P1B çıkışı ters polarizeli olduğundan diğer devre kesimdedir. P1B aktif yüksek durumuna geçince bu sefer P1B çıkışına bağlı MOSFET iletime geçer ve bir önceki akımın ters yönünde akım geçişi başlar.

İkinci uygulamada ise her bir durumda iki MOSFET iletimdedir. Bu uygulamada dört adet anahtarlama elemanı (MOSFET ya da güç transistörü) kullanılırken tek bir DC kaynak kullanılmaktadır. Böylece her iki uygulamada da ileri ve geri yön motor kumandası gerçekleştirilebilir.

Yarım köprü modunda, yarım-köprü cihazlarının hepsinin aynı anda aynı yönde iletime geçme tehlikesi vardır. Böyle bir durumda çok kısa süreliğine de olsa, kumanda edilecek motor gibi bir cihazın her iki yöne de hareket etmeye çalışması istenmeyen arızalara yol açacaktır. Bu olaya neden olan akıma “shoot-through” akımı denir. Böyle bir riskin ortadan kaldırılması için programlanabilir ölü-bant gecikmesi eklenmiştir. PWM1CON kaydedicisinin PDC<6:0> bitleri kullanılarak, çıkış aktif yüksek konuma geçmeden önce işletilecek komut sayısı tanımlanabilir. Bir bakıma bu kaydedici sayesinde yapay bir gecikme üretilmektedir.

Şekil 8.11 Yarım-köprü uygulamalarına örnek

PWM1CON KAYDEDİCİSİ (ADRES: 9Bh – PIC16F887)

bit 7 PRSEN: PWM yeniden etkinleştirme bitidir.
1 = Otomatik kapanma üzerine, ECCPASE biti, kapatma olayı giderildikten sonra otomatik olarak temizlenir; PWM otomatik olarak yeniden başlatılır.
0 = Otomatik kapanma üzerine, ECCPASE biti PWM’in yeniden başlatılması için temizlenmelidir.
bit 6-0 PDC<6:0>: PWM gecikmesi sayma bitleridir.
PDCn = FOSC/4 (4*TOSC) süresiyle bitlerin değeri çarpılır ve PWM çıkışının aktif olması anına kadar geçecek bekleme süresi elde edilir. Örneğin tüm bitler ‘1111111’ ise 127 çarpan değeri elde edilir. FOSC = 4 MHz ise bir komut çevrimi 1us’dir. Bu durumda 127 x 1us = 127us’lik bir ölü-bant gecikme süresi elde edilir.

Tam Köprü Modu

Tam köprü modunda, tüm dört pin de çıkış olarak kullanılır. N-tipi MOSFET’ler kullanılarak yapılmış bir tam-köprü bağlantısı örneği Şekil 8.12’de gösterilmiştir.

İleri modda CCP1/P1A pini aktif duruma çekilirken, P1D modüleli çıkıştır. P1B ve P1C ise pasif durumdadır. Geri modda P1C aktif duruma çekilirken, P1B modüleli çıkıştır. P1A ve P1D ise pasif duruma çekilir.

P1A, P1B, P1C ve P1D çıkışları PORT veri tutucularıyla çoktan seçme işlemine tabi tutulur. İlgili TRIS bitleri P1A, P1B, P1C ve P1D’yi çıkış yapmak için temizlenmelidir.

Şekil 8.12 Tam-köprü uygulamasına örnek

Şekil 8.13’te tam-köprü modunun pratikte nasıl kullanıldığını gösteren bir devre uygulaması verilmiştir. Uygulamada anahtarlama elemanı olarak BDX53 güç transistörleri kullanılmıştır. Şekil 8.8’de klasik PWM tekniğiyle yapılmış uygulamanın tam-köprü moduna uyarlanmış halidir. Tablo 8.9’da uygulamanın kaynak kodu gösterilmiş olup CCP1CON kaydedicisinin ileri ve geri yön için nasıl ayarlandığına dikkat ediniz.

Tam-köprü modu uygulamasında ileri ve geri yön geçişleri sırasında, yarım-köprü moduna benzer şekilde modüleli çıkışlar olan P1D ve P1B sinyalleri belli bir gecikmenin ardından aktif duruma gelir. Bu gecikme 4 Timer2 sayma değeri kadardır. Böylece kontrol edilen yükün aynı anda her iki yön için de aktif olmasının önüne geçilir.

Şekil 8.13 Tam-köprü modunda güçlendirilmiş PWM modülü uygulaması

Tablo 8.9 Tam köprü modunda güçlendirilmiş PWM modülü uygulaması mikroC kodu

#define MAKS_PWM 255
#define MIN_PWM 0
#define LED PORTE.RE0
unsigned short duty_cycle;
unsigned char maks_darbe=0;
unsigned char darbe_zirvesi=0;
unsigned char zirve_degeri = 0;
unsigned int i;
unsigned short ldr_sol;
unsigned short ldr_sag;
int ldr_fark;
void ayar(){
 TRISA = 0X03;
 PORTA = 0;
 TRISB = 0X00;
 PORTB = 0;
 TRISC = 0X00;
 PORTC = 0;
 TRISD = 0X00;
 PORTD = 0;
 TRISE = 0X00;
 PORTE = 0;
 OPTION_REG = 0; // 1:2 ön ölçekleme değeri
   /* Port girişlerinin davranışı belirleniyor ve 
   analog kanal ayarları yapılıyor */
 ANSEL = 0b00000011; //AN1 ve AN0 kanalı analog, diğerleri dijital yapıldı.
 ANSELH = 0;
 ADCON1 = 0;
 CCP1CON = 0; //PWM kapalı
 TMR2 = 0;
 PR2=249;
 CCP1CON = 0B01001100; //Full-bridge ileri mod
 CCPR1L = MIN_PWM;
 INTCON = 0;
 Delay_ms(50);
 PIE1 = 0;
 PIR1 = 0;
 T2CON = 0B00000011;
 OSCCON = 0X70; //Konfigürasyon ayarlı ve dâhili 8MHz
 Delay_ms(10);
 T2CON.TMR2ON = 1;
}
void kontrol(){
 for(i=0;i<10;i++){
  LED = ~LED;
  Delay_ms(50);
 }
 LED=0;
}
void main(){
 ayar();
 kontrol();
 while(1) {
  /* ADC burada okunuyor */
  ADCON0=0B11000001; /* ADC portunun AN0 kanalı seçiliyor.
  		A/D işlemi çalıştırılıyor */
  Delay_us(50); /* ADC modülünün dönüştürmeye hazır hale
  		gelmesi için kasıtlı bekleme yapılıyor */
  GO_DONE_bit=1;
  while(GO_DONE_bit) continue;// ldr_sol dönüştürme işleminin bitmesi bekleniyor
  ldr_sol=ADRESH; // 8 bitlik MSB okunuyor, ADRESL'deki 2 bitlik LSB önemsenmiyor
  ADCON0=0B11000101; // ADC portunun AN1 kanalı seçiliyor. A/D işlemi çalıştırılıyor
  Delay_us(50); /* ADC modülünün dönüştürmeye hazır hale
  			gelmesi için kasıtlı bekleme yapılıyor */
  GO_DONE_bit=1;
  while(GO_DONE_bit) continue; // ldr_sag dönüştürme işleminin bitmesi bekleniyor
  ldr_sag=ADRESH; // 8 bitlik MSB okunuyor, ADRESL'deki 2 bitlik LSB önemsenmiyor
   /* Fark hesaplanıyor */
  ldr_fark=ldr_sol - ldr_sag;
  if (ldr_fark > 0) {
    /* while(!PIR1.TMR2IF)
   PIR1.TMR2IF=0; */
   CCP1CON = 0B11001100; //Geri yön beslemeli tam-köprü çıkış, P1B PWM çıkışı
   duty_cycle = ldr_fark;
   CCPR1L = duty_cycle;
   delay_ms(5);
  }
  else if(ldr_fark < 0){
    /* while(!PIR1.TMR2IF)
    PIR1.TMR2IF=0; */
   CCP1CON = 0B01001100;//İleri yön beslemeli tam-köprü çıkış, P1D PWM çıkışı
   duty_cycle = (-1)*ldr_fark;
   CCPR1L = duty_cycle;
   delay_ms(5);
  }
  else{
   CCP1CON = 0;
  }
 }
}


Kaynak kodunun uygulaması yapıldığında iki LDR arasında fark olduğu sürece motora sürekli olarak PWM sinyalinin verildiği görülecektir. Eğer güneş takip sistemi gibi bir uygulama yapılacaksa farkın sabit olması durumunda hareketin de durması gerekir. Söz konusu uygulama kullanılarak güneş takip sistemi tasarlamak için zamana bağlı fark değişim oranının hesaplanması ve eğer değişim yoksa PWM sinyalinin durdurulması gerekir. Diğer bir ifadeyle belli bir zaman aralığı için sol ve sağ LDR kaynaklarının ışık farklarının türevi hesaplanmalıdır. Bir sistemde, bir başka değişkene bağlı bir değişkenin durumundaki değişim sabitse türev sabittir. Eğer ışık farkına ‘V’ dersek ve zamanı da ‘t’ ile gösterirsek, zamana bağlı ışık farkının türevi aşağıdaki gibi gösterilir.

dV/dt=(V2-V1)/(t2-t1 )=sabit ise PWM çıkışları sıfırlanmalıdır.

Zaman aralığı ölçümleri için 16-bitlik Timer1 kaydedicisinden yararlanılabilir. Belli aralıklarla sürekli olarak iki fark değeri karşılaştırılır, eğer fark aynıysa motorun hareket ettirilmesine gerek yoktur. Tablo 8.10’da gösterilen uygulamadan Timer1 başlangıç değeri 536 ile yüklenmiş ve önölçekleyici 1:8 değerine kurulmuştur. Dolayısıyla 8 MHz’lik işlemci frekansında 260 msn’lik sürelerle kesme üretilmektedir. Motora hareket verecek fark değeri oluştuğu sürece motor 260ms süresince hareket ettirilmektedir.

Tablo 8.10 Işık farkının türevine göre tepki veren güneş takip sistemi mikroC kaynak kodu

#define MAKS_PWM 255
#define MIN_PWM 0
#define LED PORTE.RE0
unsigned short duty_cycle;
signed short carpan;
unsigned char maks_darbe=0;
unsigned char darbe_zirvesi=0;
unsigned char zirve_degeri = 0;
unsigned int i;
unsigned short ldr_sol;
unsigned short ldr_sag;
unsigned short ldr_fark, fark, ilk_fark, son_fark;
void ayar(){
 TRISA = 0X03;
 PORTA = 0;
 TRISB = 0X00;
 PORTB = 0;
 TRISC = 0X00;
 PORTC = 0;
 TRISD = 0X00;
 PORTD = 0;
 TRISE = 0X00;
 PORTE = 0;
  /* Port girişlerinin davranışı belirleniyor ve
  analog kanal ayarları yapılıyor */
 ANSEL = 0b00000011; /*AN1 ve AN0 kanalı analog,
 				diğerleri dijital yapıldı.*/
 ANSELH = 0;
 ADCON1 = 0;
 CCP1CON = 0; //PWM kapalı
 T1CON = 0B00000000;
 T2CON = 0B00000011;
 TMR1L = 24;
 TMR1H = 2;// 00000010 00011000 = 536
 TMR2 = 0;
 PR2=249;
 CCP1CON = 0B01001100; //Full-bridge ileri mod
 CCPR1L = MIN_PWM;
 Delay_ms(50);
 INTCON.GIE=1;
 INTCON.PEIE=1; //Çevresel kesme açılıyor
 PIE1.TMR1IE=1; //Timer1 kesmesi açılıyor
 PIR1.TMR1IF=0;
 OSCCON = 0X70; //Konfigürasyon ayarlı ve dâhili 8MHz
 Delay_ms(10);
 T1CON.TMR1ON = 1;
 T2CON.TMR2ON = 1;
}
void kontrol(){
 for(i=0;i<10;i++){
  LED = ~LED;
  Delay_ms(50);
 }
 LED=0;
}
void main(){
 ayar();
 kontrol();
 while(1) {
   /* ADC burada okunuyor */
  ADCON0=0B11000001; /* ADC portunun AN0 kanalı seçiliyor.
  		A/D işlemi çalıştırılıyor*/
  Delay_us(50);
  GO_DONE_bit=1;
  while(GO_DONE_bit) continue;// ldr_sol dönüştürme işleminin bitmesi bekleniyor
  ldr_sol=ADRESH; // 8 bitlik MSB okunuyor, ADRESL'deki 2 bitlik LSB önemsenmiyor
  ADCON0=0B11000101; /* ADC portunun AN1 kanalı seçiliyor.
  		A/D işlemi çalıştırılıyor */
  Delay_us(50);
  GO_DONE_bit=1;
  while(GO_DONE_bit) continue; // ldr_sag dönüştürme işleminin bitmesi bekleniyor
  ldr_sag=ADRESH; // 8 bitlik MSB okunuyor, ADRESL'deki 2 bitlik LSB önemsenmiyor
    /* Fark hesaplanıyor */
  if(ldr_fark > 0){
   son_fark = ldr_fark;
   fark = (son_fark - ilk_fark);
   ilk_fark = fark;
    if(fark > 0){
     CCP1CON = 0B11001100; /*Geri yön beslemeli 
	 			tam-köprü çıkış, P1B PWM çıkışı */
     carpan = 1;
    }
   else if(fark < 0){
    CCP1CON = 0B10001100;
    carpan = -1;
   }
   else{
    CCP1CON = 0;
   }
   duty_cycle = carpan * fark;
   CCPR1L = duty_cycle;
   delay_ms(5);
  }
  if(ldr_fark < 0){
   son_fark = (-1)*ldr_fark;
   fark = (son_fark - ilk_fark);
   ilk_fark = fark;
    if(fark > 0){
     CCP1CON = 0B10001100; /*İleri yön beslemeli 
	 		tam-köprü çıkış, P1B PWM çıkışı */
     carpan = 1;
    }
   else if(fark < 0){
    CCP1CON = 0B11001100;
    carpan = -1;
   }
   else{
    CCP1CON = 0;
   }
   duty_cycle = carpan * fark;
   CCPR1L = duty_cycle;
   delay_ms(5);
  }
  else{
   CCP1CON = 0;
  }
 }
}
void interrupt(){
 if(PIR1.TMR1IF){
  ldr_fark=ldr_sol - ldr_sag;  
  TMR1L = 24;
  TMR1H = 2;// 00000010 00011000 = 536
  PIR1.TMR1IF=0;
 }
}


DİKKAT: Bilgisayar performansınıza bağlı olarak simülasyon istenilen sonucu veremeyebilir. Etkili sonucu görmek için gerçek uygulamasının kurulması ve performans analizinin gerçek bir ortama göre yapılması daha uygun olacaktır.

PWM Otomatik Kapanma ve Açılma Modu

PWM modu, harici bir kapatma olayı olduğunda PWM çıkışlarını devre dışı bırakan otomatik kapanma Auto-Shutdown) moduna sahiptir. Otomatik kapanma moduyla PWM pinleri önceden tanımlanmış duruma getirilirler. Bu mod, PWM’in uygulamaya zarar vermesini engellemede kullanılır.

Otomatik kapatma kaynakları olarak ECCPAS kaydedicisinin ECCPAS<2:0> bitleri kullanılır. Bir kapatma olayı aşağıdaki durumlardan biri gerçekleştiğinde oluşur:

  • Harici kesme girişi ‘INT’ pininde lojik-0 oluşması durumunda
  • C1 karşılaştırıcısının durum değişiminde
  • C2 karşılaştırıcısının durum değişiminde
  • Yazılım içinde ECCPASE bitini kurarak

Kapanma durumu ECCPASE (Auto-Shutdown Event Status) bitiyle izlenebilir. Eğer bit lojik-0 ise, PWM normal olarak işliyordur. Eğer bit lojik-1 ise, PWM çıkışları kapalı durumdadır. Bir kapanma olayı meydana geldiğinde iki olay olur:

  • ECCPASE biti lojik-1 değerine kurulur.
  • ECCPASE biti, yazılım içinde sıfırlanana ya da otomatik yeniden başlatma işletilene kadar kurulu kalır.

Etkinleştirilen PWM pinleri kapalı durumlarına asenkron olarak alınır. PWM çıkış pinleri [P1A/P1C] ve [P1B/P1D] gruplarına ayrılır. Her pinin durumu PSSAC ve PSSBD bitleriyle belirlenir. Her pin çifti aşağıdaki üç durumdan birine alınır:

  • Lojik-1 seviyesi
  • Lojik-0 seviyesi
  • Tri-state (yüksek empedans – çıkışın devre bağlantısının kesilmesi) durumu

ECCPAS KAYDEDİCİSİ (ADRES: 9Ch – PIC16F887)

bit 7 ECCPASE: ECCP otomatik kapanma olay izleme ve müdahale durum bitidir.
1 = Bir otomatik kapatma meydana geldi; ECCP çıkışları kapalı durumda
0 = ECCP çıkışları çalışıyor.
bit 6-4 ECCPAS<2:0>: ECCP otomatik kapanma için kaynak seçim bitleridir.
000 = Otomatik kapanma özelliği kapalı
001 = C1 karşılaştırıcısı çıkış değişimi
010 = C2 karşılaştırıcısı çıkış değişimi
Not: Eğer C2SYNC biti etkinleştirilirse kapanma süresi Timer1 ile geciktirilebilir.
011 = C1 ya da C2 karşılaştırıcısı çıkış değişimi
100 = INT pininde düşük voltaj (VIL) durumunun oluşması
101 = INT pininde düşük voltaj (VIL) durumunun oluşması ya da C1 çıkış değişimi
110 = INT pininde düşük voltaj (VIL) durumunun oluşması ya da C2 çıkış değişimi111 = INT pininde düşük voltaj ya da C1 ya da C2 karşılaştırıcılarında çıkış değişimi
bit 3-2 PSSACn: P1A ve P1C pinleri kapanma durum kontrol bitleridir.
00 = P1A ve P1C pinleri lojik-0’a çekilir.
01 = P1A ve P1C pinleri lojik-1’e çekilir.
Not: Şekil 8.12’deki devrenin çalışma ilkesine dikkat edilecek olursa, P1A ve P1C pinlerinin her ikisinin de aynı lojik seviyeye çekilmesi durumunda, kumanda edilen yük kutupları arasında potansiyel fark oluşmayacağından yük durdurulmuş olur. ECCPAS kaydedicisi sayesinde ek bir kullanıcı müdahalesine gerek kalmadan doğrudan kaydedici üzerinden durdurma işlemi gerçekleşmiş olur.
1x = P1A ve P1C pinleri tri-state durumuna alınır. Tri-state durumu, pinlerin dış ortam ile bağlarının kesilmesi demektir. Böylece ilgili pinlerde yüksek empedans gözükür.
bit 1-0 PSSBDn: P1B ve P1D pinleri kapanma durum kontrol bitleridir.
00 = P1B ve P1D pinleri lojik-0’a çekilir.
01 = P1B ve P1D pinleri lojik-1’e çekilir.
1x = P1B ve P1D pinleri tri-state durumuna alınır.

NOT:
1: Otomatik kapanma durumu kenar tetiklemeli değil seviye temelli bir sinyaldir. Durum değişimine neden olan lojik seviye devam ettiği sürece otomatik kapanma olayı devam edecektir.
2: Otomatik kapanma durumu devam ettiği sürece ECCPASE bitine yazma işlemi gerçekleştirilemez.
3: Otomatik kapanma durumu ortadan kalktığı anda, PWM sinyali her zaman bir sonraki PWM periyodunun başlangıcından yeniden başlar.

Yukarıda ifade edilen adımlara göre, PWM1CON kaydedicisinin PRSEN bitinin lojik-0 olması durumunda, otomatik kapanma ve yazılımsal olarak yeniden başlatma sürecinin sinyalizasyon örneği Şekil 8.14’te gösterilmiştir.

Şekil 8.14 PRSEN bitinin lojik-0 olması durumunda otomatik kapanma sinyalizasyonu

PWM1CON kaydedicisinin PRSEN bitinin lojik-1 olması durumunda, otomatik başlatma işlemi otomatik kapanmaya neden olan olay ortadan kalktığı gibi işletilir. Bu işlemin sinyalizasyon süreci Şekil 8.15’te gösterilmiştir.

Şekil 8.15 PRSEN bitinin lojik-1 olması durumunda otomatik kapanma sinyalizasyonu

PWM Yönlendirme Modu (Steering Mode)

Yönlendirme modu CCP1CON kaydedicisinin CCP1M<3:2> bitleri ‘11’, P1M<1:0> bitleri ‘00’ olduğunda kullanılan bir özelliktir. Diğer bir ifadeyle, güçlendirilmiş PWM modülünün normal PWM moduna ayarlanmasıyla kullanılabilir. Bu çalışma modu, 4 PWM pininden istenilenin modüleli çıkış olmasını sağlar. Ayrıca, aynı PWM sinyali eş zamanlı olarak birden fazla pine yönlendirilebilir.

PSTRCON: DARBE YÖNLENDİRME KONTROL KAYDEDİCİSİ (ADRES: 9Dh – PIC16F887)

bit 7-5 Kullanılmıyor: Lojik-0 olarak okunur.
bit 4 STRSYNC: Yönlendirme senkronizasyon bitidir.
1 = Çıkış yönlendirme güncellemesi bir sonraki PWM periyodunda gerçekleşir.
0 = Çıkış yönlendirme güncellemesi komut çevrim sınırının başlangıcında meydana gelir.
bit 3 STRD: P1D pini için yönlendirmeyi etkinleştirme bitidir.
1 = PWM sinyali P1D pini üzerinden CCPxM<1:0> polarite kontrol bitleriyle sunulur.
0 = P1D pini normal dijital I/O pini olarak tahsis edilir.
bit 2 STRC: P1C pini için yönlendirmeyi etkinleştirme bitidir.
1 = PWM sinyali P1C pini üzerinden CCPxM<1:0> polarite kontrol bitleriyle sunulur.
0 = P1C pini normal dijital I/O pini olarak tahsis edilir.
bit 1 STRB: P1B pini için yönlendirmeyi etkinleştirme bitidir.
1 = PWM sinyali P1B pini üzerinden CCPxM<1:0> polarite kontrol bitleriyle sunulur.
0 = P1B pini normal dijital I/O pini olarak tahsis edilir.
bit 0 STRA: P1A pini için yönlendirmeyi etkinleştirme bitidir.
1 = PWM sinyali P1A pini üzerinden CCPxM<1:0> polarite kontrol bitleriyle sunulur.
0 = P1A pini normal dijital I/O pini olarak tahsis edilir.

Şekil 8.16’da yönlendirme modunun basitleştirilmiş blok diyagramı gösterilmiştir. Blok diyagram dikkatlice incelenecek olursa, standart PWM modundayken (P1M<1:0> = 00, CCP1M<3:2>= 11) STRA, STRB, STRC ve STRD bitlerinin lojik-1 yapılması durumunda XOR kapı çıkışı ilgili pinlere yönlendirilmektedir. Bu durumdayken ilgili XOR kapısına denk gelen CCPM1<1:0> biti lojik-0 yapıldığında, PWM sinyalinin lojik-1 olduğu anlarda çıkış lojik-1 olur, dolayısıyla sinyalin kendisi alınır. İlgili XOR kapısına denk gelen CCPM1<1:0> biti lojik-1 yapıldığında, PWM sinyalinin lojik-0 olduğu anlarda çıkış lojik-1 olur, dolayısıyla PWM sinyali terslenir.

Şekil 8.16 PWM yönlendirme modunun basitleştirilmiş blok diyagramı

Şekil 8.17’deki devrede PWM yönlendirme modunun işleyişini gösteren bir uygulama devresi görülmektedir. Uygulama devresinde dört farklı PWM çıkışı için farklı animasyon modları yapılmaktadır. Animasyon modlarından birinde yalnızca tek bir kanal aktif olurken, bir başka modda disko efekti oluşturacak şekilde kanallar sıralı olarak sürülmektedir. Son modda ise tüm kanallar aynı anda sürülmektedir (bu durumdayken RGB LED grubunu “beyaz ışık” modunda çalıştırabilirsiniz). “ARTTIR” ve “AZALT” isimli butonlarla ise CCPR1L görev çevrimi kaydedicisinin değeri 10-200 arasında ayarlanmaktadır.

Şekil 8.17 PWM yönlendirme modu uygulama devresi

Tablo 8.11’de gösterilen kaynak koduna dikkat edilirse harici kesme butonlarına uzun süreli basma durumunda da CCPR1L kaydedicisinin değerinin değişimi sağlanmaktadır. Bunun için 8 MHz dâhili çalışma frekansı dikkate alınarak Timer0 modülüyle 0,1 msn’lik gecikme süresi hesaplanmıştır. Ardından “buton_sure” adlı değişken ile 10 msn’lik bekleme işlemi gerçekleştirilmiştir. Böylece yalnızca kenar tetikleme ilkesine göre çalışan kesme girişlerine bağlamış olduğunuz butonlarla, sürekli basma durumunda da değer değişimi elde etmiş olursunuz.

Tablo 8.11 PWM yönlendirme modu uygulama devresi mikroC kodu

#define duty_artir PORTB.RB1
#define duty_azalt PORTB.RB2
unsigned int i, mod, buton_sure, duty_cycle=200;
void ayar(){
 TRISA = 0X00;
 PORTA = 0;
 TRISB = 0X07;//harici kesme ve RB1-RB2 girişi aktif
 PORTB = 0;
 TRISC = 0X00;
 PORTC = 0;
 TRISD = 0X00;
 PORTD = 0;
 TRISE = 0X00;
 PORTE = 0;
 OPTION_REG = 0; // 1:2 ön ölçekleme değeri
  /* Port girişlerinin davranışı belirleniyor
  ve analog kanal ayarları yapılıyor */
 ANSEL = 0; //tüm kanallar dijital yapıldı
 ANSELH = 0; //tüm kanallar dijital yapıldı
 ADCON1 = 0;
 CCP1CON = 0B00001100;; //ECCP1 standart PWM olarak açık
 CCP2CON = 0; //PWM2 kapalı
 TMR2 = 0;
 PR2=249;
 CCPR1L = duty_cycle;
 INTCON = 0;
 Delay_ms(50);
 PIE1 = 0;
 PIR1 = 0;
 T2CON = 0B00000001; //Prescaler 1:4 - 2kHz sinyal
 Delay_ms(10);
 T2CON.TMR2ON = 1;
 OSCCON=0X70; //Dâhili 8MHz frekans
 PSTRCON=0B00000001; //Başlangıçta P1A aktif PWM pini
 OPTION_REG=1; //dâhili pull-up'lar aktif ve prescaler 1:4
 WPUB=7;//Harici kesme girişi ve RB1 için dâhili weak pull-up aktif
 IOCB=6;//Durum değişimi aktif - 7 değeri yüklenirse harici kesme girişi
 INTCON.GIE=1; // port durum kesmesi gibi davranır!!!
 INTCON.TMR0IE=1;//Timer0 kesmesi aktif
 INTCON.INTE=1; //RB0 harici kesme aktif
 INTCON.RBIE=1; //Port durum değişim kesmesi aktif
 TMR0=206;
}
void mod0(){
 PSTRCON=0B00010001;
}
void mod1(){
 PSTRCON=0B00010010;
}
void mod2(){
 PSTRCON=0B00010100;
}
void mod3(){
 PSTRCON=0B00011000;
}
void mod4_disko(){
 PSTRCON = PSTRCON << 1;
 if(PSTRCON>8)PSTRCON=0B00000001;
  Delay_ms(100);
 }
void mod5_hepsi(){
 PSTRCON=0B00011111;
}
void main(){
 ayar();
 while(1) {
  if(duty_artir && duty_azalt) buton_sure=0;
  if(!duty_artir){
   if(buton_sure>100 && duty_cycle<200){
    duty_cycle++;
    CCPR1L=duty_cycle;
    buton_sure=0;
   }
  }
  if(!duty_azalt){
   if(buton_sure>100 && duty_cycle>10){
    duty_cycle--;
    CCPR1L=duty_cycle;
    buton_sure=0;
   }
  }
  switch (mod){
   case 0:mod0();break;
   case 1:mod1();break;
   case 2:mod2();break;
   case 3:mod3();break;
   case 4:mod4_disko();break;
   case 5:mod5_hepsi();break;
  }
 }
}
void interrupt(){
 if(INTCON.INTF){
  mod++;
  if(mod>5) mod=0;
  INTCON.INTF=0;
 }
 if(INTCON.RBIF){
  if(!duty_artir){
   if(duty_cycle<200) duty_cycle++;
  }
  if(!duty_azalt){
   if(duty_cycle>10) duty_cycle--;
  }
  CCPR1L=duty_cycle;
  INTCON.RBIF=0;
 }
 if(INTCON.TMR0IF){ // (256-206)*4/2.000.000 = 0.1msn elde ediliyor
  buton_sure++;
  TMR0=206;
  INTCON.TMR0IF=0;
 }
}