TİMER0 ile butna basılı kalma süresi hesaplama YARDIM

Başlatan Denizccan, 27 Kasım 2014, 17:17:25

Denizccan

Merhaba arkadaşlar,

Şuan bir proje için zaman hesabı yapmam lazım dı. Örnek olarak küçük bir deneme yapayım istemiştim ama olmadı.
İsteğim ise A0 pinine bağlı butona basıldığında TIMER0 devreye girsin sayac adlı değişkeni 1'er 1'er arttırsın ve A0 butonu 0 olduğunda TIMER0 devre dışı kalsın. TIMER0 ayarıma göre A0 butonu basılı ise her 0.065536 sn de bir kesme oluşuyor ve  sayac adlı değişkenim 1 artıyor. A0 butonundan elimizi çektiğimizde sayac değişkenini 0.065536 ile çarptığımızda A0 butonuna kaç saniye basılı kaldığını hesaplayıp ekrana yazdırmak istiyorum ama çalışmadı sorun nerede yardımcı olabilirseniz sevinirim.

PIC olarak 16f877a ve 4 Mhz lik osilatör kullanıyorum kodları ve isis şemasını ekledim.

isis ve kodlar   http://dosya.co/r63wwgxskogt/buton_zamanı.rar.html

#FUSES NOWDT, XT, NOPUT, PROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG   
 #use delay(clock=4000000)   
 #define use_portb_lcd true  
 #include <lcd.c> 
 #use fast_io(a)
 #int_timer0
 int16 sayac=0, mesafe=0 ;     // Defining variables   
 
 void timer0_kesme ()
 {
 set_timer0(0);
 sayac++;
 }
 
 void main()   
 { 
 set_tris_a(0b00000001);
 output_a(0b00000000);
 setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256);
 set_timer0(0);
 lcd_init();                
 delay_ms(50);  
            
 while(1)   
 {  
 
 
 if(input(pin_a0)==1)
 {
 enable_interrupts(INT_timer0);
 enable_interrupts(GLOBAL);
 }
 disable_interrupts(INT_timer0);
 disable_interrupts(GLOBAL);
 mesafe=sayac*0.655536;
 lcd_gotoxy(1,1);  
 printf(lcd_putc, "\fZaman : %Lu sn",mesafe); // Display the time
 delay_ms(1000);
 
 
 
 }   
 } 




Salih

Şöyle denermisin.
#FUSES NOWDT, XT, NOPUT, PROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG   
 #use delay(clock=4000000)   
 #define use_portb_lcd true  
 #include <lcd.c> 
 #use fast_io(a)

 int16 sayac=0, mesafe=0 ;     // Defining variables   
  #int_timer0
 void timer0_kesme ()
 { 
 }
 
 void main()   
 { 
 set_tris_a(0b00000001);
 output_a(0b00000000);
 setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256);
 set_timer0(0);
 lcd_init();                
 delay_ms(50);  
            
 while(1)   
 {  
 
 
 if(input(pin_a0))
 {
set_timer0(0);
 enable_interrupts(INT_timer0);
 enable_interrupts(GLOBAL);
while (input(pin_A0));
 }
 disable_interrupts(INT_timer0);
 disable_interrupts(GLOBAL);
 mesafe=get_timer0()*0.655536;
 lcd_gotoxy(1,1);  
 printf(lcd_putc, "\fZaman : %Lu sn",mesafe); // Display the time
 delay_ms(1000); 
 }   
 } 

cripple

butona basınca interrupta girmesi yerine interrupt ın içinde butona basılıp basılmadığını denetlersen daha verimli olabilir diye düşünüyorum
void timer0_kesme ()
 {
    if(input(pin_a0)==1)
     {
       set_timer0(0);
       sayac++;
      }
 }
void main()   
 { 
set_timer0(0);
 enable_interrupts(INT_timer0);
 enable_interrupts(GLOBAL);

 while(TRUE)
   {

      if(input(PIN_A3))
      {
       //yapmak istediğin işlemler
       }
    }
}


gibi  kolay gesin..

Denizccan

Salih

Söylediğin şekilde denedim başlangıç olarak butona basılı değilken zamanı saymaya başlıyor. Ama ölçtüğü değerlerde yanlışlık var mesela direk 43 ten başlıyor zamana .Halbuki saymaması lazım çünkü if dışında
disable_interrupts(INT_timer0);
disable_interrupts(GLOBAL);
bu kodları belirtiyoruz ama yinede sayma işlemi yapıyor.

Benim denediğim şekilde hiç saymıyordu şuan sayma işlemini yapmaya başladı bi ilerleme var . Teşekkür ederim cvp verdiğin için

Denizccan

cripple

Söylediğin şekilde değiştirdim kodları yapmak istediğin işlem diye belirttiğin  bölümüde lcd ye yazması gerektirdiğini belirttim ama sayma işlemi yapmıyor değer hep 0 olarak gösteriyor.

#FUSES NOWDT, XT, NOPUT, PROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG   
 #use delay(clock=4000000)   
 #define use_portb_lcd true  
 #include <lcd.c> 
 #use fast_io(a)

 int16 sayac=0, mesafe=0 ; 
 
  #int_timer0
  void timer0_kesme ()
 {
    if(input(pin_a0)==1)
     {
       set_timer0(0);
       sayac++;
      }
 }
void main()   
 { 
 set_timer0(0);
 enable_interrupts(INT_timer0);
 enable_interrupts(GLOBAL);

 while(TRUE)
   {
 lcd_init();                
 delay_ms(50); 
 mesafe=sayac*0.655536;
 lcd_gotoxy(1,1);  
 printf(lcd_putc, "\fZaman : %Lu sn",mesafe); // DISPLAY the time
 delay_ms(100); 
     
    }
}

sadogan

if(input(pin_a0)==1)
 {
 enable_interrupts(INT_timer0);
 enable_interrupts(GLOBAL);
 }
 disable_interrupts(INT_timer0); ---> bura
 disable_interrupts(GLOBAL);     ---> bura
 mesafe=sayac*0.655536;
 lcd_gotoxy(1,1);  
 printf(lcd_putc, "\fZaman : %Lu sn",mesafe); // Display the time
 delay_ms(1000);

Hata butona basılınca 'if' içerigini yaptıktan sonra hemen ardından interrupt ları kapatıyorsun ve 1sn bekliyorsun
butona basılı oldugu sürece  interrupt ları kapatmaman gerekiyor. if  bir şartlı döndü deyildir.
söyle yapabilirsin
if(input(pin_a0)==1)
 {
 enable_interrupts(INT_timer0);
 enable_interrupts(GLOBAL);
 }
else
{
 disable_interrupts(INT_timer0); 
 disable_interrupts(GLOBAL);     
 mesafe=(float)sayac*0.655536;
 lcd_gotoxy(1,1);  
 printf(lcd_putc, "\fZaman : %Lu sn",mesafe); // Display the time
}
 delay_ms(10);


Denizccan

sadogan

Cvp verdiğin için teşekkür ederim.Söylediğin gibi değiştirdim kodu ama olmadı zaman hala 0 gözüküyor bir değişme olmuyor.
#FUSES NOWDT, XT, NOPUT, PROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG   
 #use delay(clock=4000000)   
 #define use_portb_lcd true  
 #include <lcd.c> 
 #use fast_io(a)

 int16 sayac=0  ; 
 float mesafe=0;
  #int_timer0
  void timer0_kesme ()
 {
       set_timer0(0);
       sayac++;
 }

void main()   
 { 
 set_tris_a(0b00000001);
 output_a(0x00);
 set_timer0(0);
  lcd_init();
  delay_ms(50);
 while(1)
 {
 if(input(pin_a0)==1)
 {
 enable_interrupts(INT_timer0);
 enable_interrupts(GLOBAL);
 }
else
{
 disable_interrupts(INT_timer0); 
 disable_interrupts(GLOBAL);     
 mesafe=sayac*0.655536;
                
 lcd_gotoxy(1,1);  
 printf(lcd_putc, "\fZaman : %f sn",mesafe); 
}
 delay_ms(10);
 
} 
}

ibocakir

Hocam 1 saniyenin 1 saniye olması çok önemli değilse intereupta bile girmene gerek kalmaz.

tekrar:

if (buton = 0)
{

sayac = sayac +1;
delay(1000);
GoTo tekrar
while (buton = 0)
{
}

}

Şeklinde yapabilirsin.
CCS'nin instructionlarına pek hakim değilim hatam varsa kusura bakma.

Denizccan

#8
sadogan

senin dediğin gibi değişmeyi bir kere daha yaptım şuan netice güzel butona basılınca saniye kısmını veriyor.Board üzerinde devreyi denedim netice çok güzel. Birde şunu sorcaktım eğer ikinci basışımda yine ölçmek istersem sayaç değişkenini nerede 0 lamam gerekir ?

#FUSES NOWDT, XT, NOPUT, PROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG   
 #use delay(clock=4000000)   
 #define use_portb_lcd true  
 #include <lcd.c> 
 #use fast_io(a)

 int16 sayac=0 ;
 float mesafe=0 ;     
  #int_timer0
 void timer0_kesme ()
 { 
 set_timer0(0);
 sayac++;
 }
 
 void main()   
 { 
 set_tris_a(0b00000001);
 output_a(0b00000000);
 setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256);
 set_timer0(0);
 lcd_init();                
 delay_ms(50);  
            
 while(1)   
 {  
 
 
 if(input(pin_a0))
 {
 set_timer0(0);
 enable_interrupts(INT_timer0);
 enable_interrupts(GLOBAL);
while (input(pin_A0));
 }  
 else
{
 disable_interrupts(INT_timer0); 
 disable_interrupts(GLOBAL);     
 mesafe=(float)sayac*0.065536;
 lcd_gotoxy(1,1);  
 printf(lcd_putc, "\fZaman : %f sn",mesafe); // Display the time
}
 delay_ms(10);
 }
 }

cripple

void timer0_kesme ()
 {
 if(input(pin_a0))
 set_timer0(0);
 sayac++;
 }
 
 void main()   
 { 
   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);            
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256);
   set_tris_a(0b00000001);
   
   output_a(0b00000000);
   set_timer0(0);
   enable_interrupts(INT_timer0);
   enable_interrupts(GLOBAL);
   lcd_init();                
   delay_ms(50);  
            
 while(1)   
 {  
 
 
     if(input(pin_a0))
      {  
         while(input(pin_a0))// buton bırakılana kadar bekle eğer bekleme yapmazsan sayac değişkeni değer almadan(0 iken) lcd de görüntü verecek 
         mesafe=sayac*0.655536;
         lcd_gotoxy(1,1);  
         printf(lcd_putc, "\fZaman : %Lu sn",mesafe); // Display the time
         delay_ms(1000);
         sayac=0;// sıfırlama yapılmazsa üzerine sayar
      }
 }   
 } 

bu kodları bir denermisin

Salih

Aşağıdaki kodları denedim çalışıyor.
Yalnız benim CCS C versiyonunda (5.010) Printf den sonra kesmeler iptal oluyor Ona göre yazdım.
#Include  <16F877.h>
#Fuses XT
#Use Delay(clock=4000000)
#include <Lcd.c>

int16 sayac=0;
float sure=0.0;

#int_Timer0
void Kesme()
{
      sayac++;
} 
void main()
{
   setup_psp(PSP_DISABLED);
   Setup_spi(SPI_SS_DISABLED);
   Setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T1_DISABLED,0,1);   
   Setup_adc_ports(NO_ANALOGS);
   Setup_adc(ADC_OFF);
   Setup_CCP1(CCP_OFF);
   Setup_CCP2(CCP_OFF);  
   Lcd_init();
   delay_ms(10);
   Printf(Lcd_Putc,"\fSur=%fsn",sure);
   Set_timer0(0);   
   Enable_interrupts(INT_Timer0);
   Enable_interrupts(GLOBAL);
   While(True)   
   {
      if (input(Pin_A0))
      {
         sayac=0;
         while(input(Pin_A0));
         sure=sayac*0.065543;
         Printf(Lcd_Putc,"\fSur=%fsn",sure);
         Enable_interrupts(INT_Timer0);
         Enable_interrupts(GLOBAL);
      }
      delay_ms(50);
   }
} 

karbal656

Timer kullanmadan yapılmış hali:
#FUSES NOWDT, XT, NOPUT, PROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG   
 #use delay(clock=4000000)   
 #define use_portb_lcd true  
 #include <lcd.c> 
 #use fast_io(a)

 int16 sayac=0, mesafe=0 ; 
 
 
void main()   
 { 
 set_tris_a(0x01);
lcd_init();   
 while(TRUE)
   {
 if(input(pin_A0))           
 {
 mesafe=0;
 do
 {
 ++mesafe;
 delay_ms(10);            // milisaniye. 1000ms=1saniye
 }while(input(pin_A0));  //butona basılı olduğu sürece say
 }
 lcd_gotoxy(1,1);  
 printf(lcd_putc, "\fZaman : %Lu sn",mesafe); // DISPLAY the time
 delay_ms(100); 
     
    }
}

selimkoc

Başlama durdurma özelliğine sahip TMR1 veya TMR2 kullanarak yapabilirsin.

Algoritma şöyle olabilir;
  Butana basıldığında (T1CON.TMR1ON=1;// TMR1'i başlat)
  Buton bırakldığında (T1CON.TMR1ON=0;// TMR1'i durdur)
  TMR değerini oku. Peryot değeriyle çarp. Varsa kesme ekle (16-bit olduğundan max 65535 olacaktır 0'a dönüşte kesme oluşur.-kesme sayısı*65535)
  TMR içeriğini kesme sayısını sıfırla

TMR0 ile Basıldığında içerik sıfırlanır ve kesme adeti sıfırlanır. Bırakıldığında aynı işlemler uygulanabilir.