CCS C PIC16F877A İÇİN DELAY FONKSİYONU KULLANMADAN GECİKME SAĞLAMA

Başlatan whitelion54, 06 Mayıs 2024, 11:00:03

whitelion54

Merhaba. Benim ccs c derleyicisi ile pic16f877a kullanarak bir lamba parlaklığını kontrol etme projesi yapmam gerekiyor. Ancak hocam delay fonksiyonlarını kullanmamı yasaklıyor. Mikroişlemci durmayacak, daima çalışır durumda olacak diyor. Direkt 0 vereceğini söylüyor. Ancak delay fonksiyonu kodumda parlaklığın miktarını resmen ayarladığım kısım. Delay fonksiyonu kullanmadan istediğim zaman istediğim miktarda gecikme nasıl sağlarım?

int1 ZC = 0;
int16 alpha;
 
#INT_EXT            // external interrupt ISR
void ext_isr(void)
{
  ZC = 1;
 
  // toggle external interrupt edge
  if(INTEDG) INTEDG = 0;
  else       INTEDG = 1;
 
}
 
void main()
{
  output_low(triac_gate);
  output_drive(triac_gate);
 
  setup_adc(ADC_CLOCK_INTERNAL);     // set ADC clock source
  setup_adc_ports(AN0);              // configure AN0 pin as analog
  set_adc_channel(0);                // select channel AN0
 
  clear_interrupt(INT_EXT);          // clear external interrupt flag bit
  enable_interrupts(GLOBAL);         // enable global interrupts
  enable_interrupts(INT_EXT);        // enable external interrupt
 
  delay_ms(500);
 
  while(TRUE)
  {
    alpha = ( 1023 - read_adc() ) * 10;
 
    if (alpha > 9500)
      alpha = 9500;
    else if (alpha < 200)
             alpha = 0;
 
    while(ZC == 0) ;    // wait for zero crossing event
 
    // send firing pulse after alpha
    delay_us(alpha);
    output_high(triac_gate);
    delay_us(200);
    output_low(triac_gate);
 
    ZC = 0;
 
  }
 
}

Burada delay_us(alpha); kısmı resmen parlaklığı ayarlıyor. Bunu delay fonksiyonu olmadan programı geciktirip output_high(triac_gate); kısmına istediğim zaman gelmesini sağlamalıyım. Yardımcı olursanız çok sevinirim. Şimdiden teşekkürler.

istinaf duvarı

Lambanın yandığını algılamak için devreden bir geri besleme alabilirsin. Geri besleme ile okuduğun değeri bir değişkene atarsın.

Sonra while(!değişken) şeklinde bir döngü açarsın.
Değişken değeri doğru(1) olduğu sürece program sürekli while'ın içini kontrol eder. Delay'daki gibi durmaz. While'ın içindeki ifade yanlış(0) olduğunda while'den çıkıp akışa devam eder.

whitelion54

Gecikme miktarını potansiyometre değerine göre ayarlıyoruz. Yani programın ne kadar bekleyeceğini kontrol ediyoruz. Elimizde bir süre olmalı yani. O süreyi delay kullanmadan sanırım timer kullanarak kontrol etmem lazım ama yapamadım. Örneğin delay_us(5000); ile parlaklığı yarım yapıyoruz. 4000 ile %40. Ama hoca delaysiz yapacaksın diyor.

ete

İşin mantığını anlatacağım.
Dimmer devresinde AC hattından alınan uç ile harici kesme kullanılarak sıfır noktası yakalanıyor ve yakalandığı anda program kesmeye girince parlaklığa karşılık gelen süre kadar beklenip (delay ile) sonra triac ateşleniyor. Sistem kısaca böyle çalışıyor.
Programda Delay Komutunun olduğu noktada Timer kesmesi aktive edilir ise ve timer kesmeye yakalandığında triac ateşlenir ise sistem delay kullanılıyormuş gibi çalışır. Burada asıl sorun timer'a verilecek değerin hesaplanmasıdır. Bu değer potansiyometreden alınacak bilgiye göre ayarlanacaktır. Bu konuda da temel prensip şöyle olur. Bu işte bir defa Timer-1 sayacı kullanılacak olup süre değeri 0 ile 9500us arasında değişkenlik gösterecek olup pot hesabı buna göre yapılmalıdır. Sonuç olarak SURE değişkeni pot okumasından 0-9500 aralığında bir değer üretecektir. Timer-1 e verilecek ön yükleme değeri için ONYUKLE=65535-SURE+8 şeklinde bir formül kullanılabilir.
Delay komutunun olduğu noktada ;
Timer-1 kesmesi aktif edilip PIR1.0 kesmesi sıfırlandıktan sonra TMR1H=ONYUKLE.BYTE1, TMR1L=ONYUKLE.BYT0 şeklinde değer verilmelidir. Bu komutlar C dilinde yok ise şöylede yapılabilir. TMR1H=ONYUKLE/256, TMR1L=ONYUKLE-(TMR1H*256)

Bu noktada öncelik TMR1 kesmesinde olacağı için gerekirse o noktada harici kesme iptal bile edilebilir. Sonra kesmeden çıkıp Timer-1 kesmesinin oluşması beklenmeli ve kesme oluşunca triac ateşlenerek TMR1 kesmesi pasif edilip harici kesme aktive edilmeli çünki bu aşamada gelecek olan kesme sıfır noktasına ait harici INT kesmesi olacaktır. Karmaşık gibi görünsede sıralı düşünüp konmutlarada hakimseniz kolaylıkla uygulanabilir.
 
Bu durumda anlaşılacağı üzere program iki farklı kesmeyi takip edecek şekilde düzenlenmeli.
İlki Harici INT kesmesi ve ikinciside TMR1 kesmesi. Bunların takibi genelde kesme bayrağından yapılır. C dilinde nasıl yapılıyor bilmiyorum.

Ete

Powered by EzPortal