DS1302 Dış kesme ve timer uygulama sorunu

Başlatan mechanicalengine, 19 Nisan 2014, 00:10:03

mechanicalengine

Merhaba arkadaşlar;

DS1302 kullandığımda iki çeşit kesmeyi çalıştıramıyorum.

DS1302 RTC yardımı ile lcd'yi de kullanarak her sabah saat sekizde b1 ledini aktive eden bir program yaptım ve bu ledi dış kesme yardımı ile iki saniye boyunca söndürüp aynı zamanda b2 ledini iki saniye boyunca yaktım. Kesme komutum aşağıdaki gibi.

void ext_kesmesi()
         {     
         output_low(pin_b2);
         output_high(pin_b1);
         delay_ms(2000);
         output_low(pin_b1);
         output_high(pin_b2);
         }


saat  sekizde b2 led'ini yaktığım kodu da aşağıdaki gibi yazım.

void main()
      {   
   lcd_init();  
   rtc_init();  
   rtc_set_datetime(29,03,14,7,8,00); 
      while(1)
      {
      setup_psp(PSP_DISABLED);
      setup_spi(SPI_SS_DISABLED);
      setup_timer_1(T1_DISABLED);     
      setup_timer_2(T2_DISABLED,0,1);
      setup_adc_ports(NO_ANALOGS);
      setup_adc(ADC_OFF);
      setup_CCP1(CCP_OFF);
      setup_CCP2(CCP_OFF);
      rtc_get_time(saat,dakika,saniye);       
      rtc_get_date(gun,ay,yil,haftanin_gunu); 
      printf(lcd_putc,"\fTARIH:%02d/%02d/20%02d ",gun,ay,yil); 
      printf(lcd_putc,"\n    >S:%02d:%02d:%02d",saat,dakika,saniye); 
      
      switch(haftanin_gunu)  
      {                      
         case 1: printf(lcd_putc,"\nPAZ"); break; 
         case 2: printf(lcd_putc,"\nPZT"); break; 
         case 3: printf(lcd_putc,"\nSAL"); break; 
         case 4: printf(lcd_putc,"\nCRS"); break; 
         case 5: printf(lcd_putc,"\nPER"); break; 
         case 6: printf(lcd_putc,"\nCUM"); break; 
         case 7: printf(lcd_putc,"\nCTS"); break; 
      }
         delay_ms(1000); 
if(saat==8&&dakika==00&&saniye==00)
               {
               set_tris_b(0b00000001);
               output[b]_b(0x00);
               output_high(pin_b2);
               ext_int_edge(H_TO_L);
               enable_interrupts(INT_EXT);
               enable_interrupts(GLOBAL);
               }


Buradaki ilk sorum kesme bittikten sonra sistem ana programa dönüp b2 ledini yakmıyor bu yüzden kesme programının sonunda ana programdaki b2 ledini tekrar yak demek zorunda kalıyorum. Bu sorunu nasıl giderebilirim? Kesme bittikten sonra ana programa nasıl dönebilirim? 

ikinci sorum;

5 kesme oluştuktan sonra kesmeleri iptal et ve b4 pininde bulunan ledi yak demek istiyorum fakat bunu timer1 ile yapmaya çalıştığımda program timer 1 kesmesini aktive etmedi.

Nasıl bir timer kullanmalıyım? Ya da 5 dış kesmeyi sayabileceğim bir yol var mıdır?

Kullandığım yöntem aşağıdaki gibi fakat işe yaramadı.
#int_timer1

 void timer1_kesme()
 {
   set_timer1(65531);
   kesme++;
   output_high(pin_b4);
}
  
       {set_tris_c(0x01);
          setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
          set_timer1(65531);
          ext_int_edge(H_TO_L);
          enable_interrupts(INT_timer1);
          enable_interrupts(INT_EXT);
          enable_interrupts(GLOBAL);}
       }



Yardımcı olabilirseniz çok sevinirim. Yardımlarınız için şimdiden çok teşekkürler.

Kabil ATICI

kesmeleri o kadar meşgul etmek yerine bayrak kullan. Kesme geldiğinde bayrağını 1 yaparsın  ana program çevriminde bu bayrağın 1 olup olmadığını kontrol edersin ve sonrada bayrağı 0 yaparsın. Bu arada bu bayrak dış kesme için ise istediğin gibi de atadığın bir sayacını saydırırsın.

ambar7

mechanicalengine

Yardımcı olduğunuz için çok teşekkür ederim. Özür dileyerek söylemeliyim ki bu işte yeniyim ve bayrak daha önceki prijelerimde kullanmadım.  Rica etsem bayrak kullanımıyla ilgili bir örnek veya bayrak kullanımına ait bir döküman önerme şansınız olabilir mi?

Kabil ATICI

Değişken tanımlamayı biliyorsun.
diyelim ki (değişken) bayrağımızın adı dis_kesme
ilk değeri de
dis_kesme=0;
olsun


void ext_kesmesi()
         {     
         dis_kesme=1;
         }

ana program döngüsünün içinde;

if (dis_kesme==1)
{
// kesme ile ne yacaksan..
dis_kesme=0;
}
ambar7

mechanicalengine

#4
Tavsiyeniz için tekrar çok teşekkürler. Söylediğiniz gibi yaptım ve dış kesmem çalışıyor. Tek sorunum kaldı o da dış kesmeyi saydırmayı başaramamam.

5 kesme meydana gelince kesmeleri iptal edip diğer ledleri söndürüp sadece b4 pinine bağlı ledi yakmak istiyorum, fakat ilk kesme meydana geldiğinde b4 pini yanıyor, diğer ledler sönüyor ve kesmeler devre dışı kalıyor bu yüzden 5 kesme saydıramıyorum sanırım. Aşağıdaki gibi yazdım fakat belirttiğim gibi çalışmadı. Bu sorunu nasıl aşabileceğim ve 5 kesmeyi nasıl saydırabileceğim konusunda bir tavsiyeniz olabilir mi?

Teşekkürler.

if(dis_kesme==1)
            {
            dis_kesme=dis_kesme++;
            if(dis_kesme==5)
            disable_interrupts(INT_EXT);
            disable_interrupts(GLOBAL);
            output_low(pin_b2);
            output_low(pin_b1);
            output_high(pin_b4);
            {
            dis_kesme=0;
            }}

JKramer

Parantezlere dikkat edin:

void ext_kesmesi()
{
    dis_kesme++;
}


if( dis_kesme == 5 )
{
    disable_interrupts( INT_EXT );
    disable_interrupts( GLOBAL );
    output_low( pin_b2 );
    output_low( pin_b1 );
    output_high( pin_b4 );
    dis_kesme = 0;
}

Kabil ATICI

#6
@mechanicalengine
Dikkat et. Burada biz "dis_kesme" bayrak olarak kullandık. Sayaç olarak değil. Eğer sayaç istiyorsan kendine "dis_kesme_say" gibi bir değişken oluşturmalısın.

Hatta programda karışıklık olmasını istemiyorsan, bayrak olarak kullandığın değişkeni örneğin
"dis_kesme_bay" şeklinde kullanabilirsin.

Değişkenlerini birbirine karıştırırsan programında içinden çıkılamayacak şekilde karışır...
ambar7

mechanicalengine

Tavsiyeleriniz için tekrar teşekkür ederim, dünden beri uğraşıyorum fakat kesmeleri saydırmayı bir türlü başaramıyorum.

yaptıklarımı aşağıda açıklamaya çalıştım;
önce;

int dis_kesme=0;
int dis_kesme_say=0;


şeklinde iki değişken tanımladım. Daha sonra bu değişkenleri kesme programının içerisinde belirttim.

void ext_kesmesi()
{
dis_kesme=1;
dis_kesme_say++;
}


ana program içerisinde

if(dis_kesme==1)        
       {
       output_low(pin_b2);
       output_high(pin_b1);
       delay_ms(2000);
       output_low(pin_b1);
       output_high(pin_b2);
       dis_kesme=0;
        }
       
if(dis_kesme_say==5);
         {
         disable_interrupts( INT_EXT );
         disable_interrupts( GLOBAL );
         output_low( pin_b2 );
         output_low( pin_b1 );
         output_high( pin_b3 );
         dis_kesme = 0;
         }


şeklinde belirttim. Program if(dis_kesme==5) koşulunu dikkate almadan direk sonuca gidip kesmeleri iptal edip sadece b3 pinini yakarak çalışmaya başlıyor.
if(dis_kesme_say==5) kısmını silersem programda kesmeler çalışıyor fakat bu kısmı eklediğimde program direk b3 pinini yakarak çalışmaya başlıyor ve kesmeler iptal oluyor, if komutları dikkate alınmıyor. Program if koşulunu bir şekilde atlayıp direk sadece komut içerisindeki b3 pinini yakarak çalışmaya başlıyor.  Bir yerde mantık hatası mı yapıyorum anlayamadım.

Kesmeleri saydırma ve if koşullarını nasıl hesaba kattırabileceğim konusunda yardımcı olabilirseniz çok sevinirim.

Şimdiden teşekkürler.


Kabil ATICI

#8
void ext_kesmesi()
{
dis_kesme=1;
}


if(dis_kesme==1)       
       {
       output_low(pin_b2);
       output_high(pin_b1);
       delay_ms(2000);  //>>olay burada
       output_low(pin_b1);
       output_high(pin_b2);
       dis_kesme=0;
       dis_kesme_say++;
        }
       
if(dis_kesme_say==5);
         {
         disable_interrupts( INT_EXT );
         disable_interrupts( GLOBAL );
         output_low( pin_b2 );
         output_low( pin_b1 );
         output_high( pin_b3 );
         dis_kesme_say = 0;
         }

senin yaptığın gibi yaparsan kesme        delay_ms(2000);  //>>olay burada  satırında iken
gelirse 2 kere sayar ve dis_kesme_say senin ölçüm sınırın dışına çıkar....

onun için yukarıdaki gibi yapabilirsin... Dışarıdan gelen kesme 1 saniye ise o delay yerine kod üzerinde bir düzenleme ile de işlemi yapabilirsin. Sadece biraz uğraştırır o kadar.

örneğin diyelim ki yak_son_say diye bir sayaç açtık

yak_son_say=0; ilk değeri

if(dis_kesme==1)       
       {
       dis_kesme=0;
       dis_kesme_say++;
       yak_son_say++;
if (yak_son_say==1)
{
       output_low(pin_b2);
       output_high(pin_b1);
}

if (yak_son_say==3)
{
       output_low(pin_b1);
       output_high(pin_b2);
       yak_son_say=0;
}
        }
ambar7

mechanicalengine

Merhaba;

Sanıyorum bir anlaşmazlık var, aşağıda da açıklamak istedim;

Devrede b1,b2 ve b3 ledleri bulunuyor. Bunlardan b2 ledi her gün saat 8'de yanıyor. Kesme verdiğim zaman b2 led'i sönüp b1 ledi'i 2 saniye süre ile yanıyor ve daha sonra b1 led'i sönüp b2 led'i yanmaya devam ediyor. Buraya kadar sorun yok.

Benim yapmaya çalıştığım yukarıdaki döngü veya kesme 5 defa meydana gelince her iki led'in  (b1,b2) yanmasını da devre dışı bırakıp b3 ledini yakmak.

ilk sorum;
Delay komutunu kallanmadan 2 saniye yanmayı nasıl kontrol edebilirim? sizin önerdiğiniz şekilde yaparsam ledlerin yanıp sönmesini kesmeye göre kontrol etmiş olmuyor muyum?

ikinci sorum;
Sayacı nasıl tanımlamam gerekiyor? int şeklinde mi tanımlamalıyım yoksa başka bir yöntem önerebilir misiniz?

Teşekkürler.