16F877 ile led yakıp söndürme programı hatası yardım.

Başlatan proxrth, 27 Mart 2012, 23:41:57

proxrth

Merhaba üstadlar ccs c de yazmam gereken program ;
RA2 pinine bağlı butona 3 defa basıldığında RC5'e bağlı ledi yakan ,aynı butona 12.defa basıldığında ise aynı ledi söndüren ve bu işi sürekli olarak
yapan programı ccs c ile yazınız.
(4mhz,butona basılmadıgında lojik 0 , basıldıgında 1 geliyor, ledler lojik 1 de yanıyor.)


Buda benim yazdığım kodlar  fakat isisde simüle ederken RA2 ye bağlı butona bastığımda RC5 pini hiç tepki vermiyor  yardımcı olursanız sevinirim ;
#include <16f877.h>
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD


#use delay(clock=4000000)
#use fast_io(a)
#use fast_io(c)

unsigned int x=0;

  void main ()
   {  
      setup_psp(PSP_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);
      
      set_tris_a(0xFF);
      output_a(0x00);
      set_tris_c(0x00);
      output_c(0x00);
   
      while (1)
    {
      if(input(pin_a2))
      x++;
      if(x==3)
      {  output_high(pin_C5);
         delay_ms(500); }
         
        if(x==12)
         {
            output_low(pin_C5);
            delay_ms(500);
            x=0;
         }  
            
     }
   }


İsis şeması ;
[IMG]http://i39.tinypic.com/25syl91.jpg[/img]

shark27

bence burdaki hata pin_a2 ye bastığınızda program 1 kere bastığınıızı daha fazla basılmış gibi algılayacaktır.onun için

if(input(pin_a2))
while(input(pin_a2));
      x++;
bu şekilde eklerseniz 1 kere basıp bıraktığınızda butonu problem olmayacaktır.

shark27

bide yeni gördüm MCLR ucuna şaseye vermişsiniz o zaman pic daima reset atar +5v'a bağlayın...

Nedenler

shark27 doğru söylemiş while(input(pin_a2)); bu satırı eklediğinde buton basılı olduğu sürece bu satırda kalınacak ve aşağıdaki işlemlere geçilmeyecektir. Dolayısıyla "butona bas-çek" bir basım olarak kabul edilecektir. Senin yaptığında butona yarım saniye kadar basılı tutarsan yarım saniye boyunca x değişkenini sürekli arttıracak ve bıraktığında x değişkeni hangi sayıda kaldıysa o sayı üzerinden işlem yapacaktır.

Bir diğer husus ise gecikmeler. Ledin yanıp sönmesi herhangi bir gecikmeye bağlı olmadığı için delayları kullanmana gerek yok. İşlemci delay_ms(500); satırını işlerken butona basarsan da bastığını görmeyecektir zaten.

proxrth

Alıntı yapılan: shark27 - 28 Mart 2012, 07:35:41
bence burdaki hata pin_a2 ye bastığınızda program 1 kere bastığınıızı daha fazla basılmış gibi algılayacaktır.onun için

if(input(pin_a2))
while(input(pin_a2));
      x++;
bu şekilde eklerseniz 1 kere basıp bıraktığınızda butonu problem olmayacaktır.

Alıntı yapılan: Nedenler - 28 Mart 2012, 09:11:56
shark27 doğru söylemiş while(input(pin_a2)); bu satırı eklediğinde buton basılı olduğu sürece bu satırda kalınacak ve aşağıdaki işlemlere geçilmeyecektir. Dolayısıyla "butona bas-çek" bir basım olarak kabul edilecektir. Senin yaptığında butona yarım saniye kadar basılı tutarsan yarım saniye boyunca x değişkenini sürekli arttıracak ve bıraktığında x değişkeni hangi sayıda kaldıysa o sayı üzerinden işlem yapacaktır.

Bir diğer husus ise gecikmeler. Ledin yanıp sönmesi herhangi bir gecikmeye bağlı olmadığı için delayları kullanmana gerek yok. İşlemci delay_ms(500); satırını işlerken butona basarsan da bastığını görmeyecektir zaten.

Teşekkürler üstadlar yardımlarınız için.Çözdüm sorunu yardımlarınızla.Peki ama burada "while(input(pin_a2));" bu komutun işlevi tam olarak şu şekildemi?
Benim yazdığım kodlarda "while(input(pin_a2));" komutu yokken A2 butonuna basılı tutulduğu süre x değişkeni artıyordu while komutunu koyduktan sonra butona basılı tutulsa bile bunu x değişkeninde sadece 1 artış olarak algılıyor heralde ben burada yanlış yaptım.
Sanırım şimdi mantığını anladım programın.
Tekrardan ilgileriniz için teşekkürlerimi sunarım.

Nedenler

Aynen öyle.

While(x) { .... }

While komutu x değişkeni değeri sıfırdan farklı olduğu sürece parantez içerisindeki işlemleri yapar. Eğer parantez içindeki işlemler tek satır ise paranteze gerek yoktur. Yani While(x) a=b; yapabilirsin. Bu if, for gibi şart ve döngüler için de geçerlidir. Bu durumda işlemci şöyle davranır;

x sıfıra eşit mi ?
değil.  a=b; satırını icra et.
x sıfıra eşit mi ?
değil. a=b; satırını icra et.
x sıfıra eşit mi ?
değil. a=b; satırını icra et.
x sıfıra eşit mi ?
eşit.
bir sonraki satıra geç.

while(x); yaptığında sadece while(x) şartı sağlandığında hiç bir işlem yapma ama şartı kontrol etmeye devam et diyorsun.

Bu durumda butona bastın;

if(input(pin_a2))           //pin_a2 deki butona basıldı mı?
while(input(pin_a2));   //butona basılı olduğu sürece bu satırda kal
      x++;                       //buton bırakıldığı anda x'i bir arttır.

Senikinde ise şöyle çalışıyordu.

if(input(pin_a2))           //pin_a2 deki butona basıldı mı?
      x++;                       //basıldıysa bir arttır.

program milisaniyelerle ifade edilecek bir zaman diliminde tüm işlemlerini bitirip tekrar aynı satıra geliyordu ve butona hala basılı olduğu için tekrar arttırıyordu.

proxrth

Alıntı yapılan: Nedenler - 28 Mart 2012, 11:13:49
Aynen öyle.

While(x) { .... }

While komutu x değişkeni değeri sıfırdan farklı olduğu sürece parantez içerisindeki işlemleri yapar. Eğer parantez içindeki işlemler tek satır ise paranteze gerek yoktur. Yani While(x) a=b; yapabilirsin. Bu if, for gibi şart ve döngüler için de geçerlidir. Bu durumda işlemci şöyle davranır;

x sıfıra eşit mi ?
değil.  a=b; satırını icra et.
x sıfıra eşit mi ?
değil. a=b; satırını icra et.
x sıfıra eşit mi ?
değil. a=b; satırını icra et.
x sıfıra eşit mi ?
eşit.
bir sonraki satıra geç.

while(x); yaptığında sadece while(x) şartı sağlandığında hiç bir işlem yapma ama şartı kontrol etmeye devam et diyorsun.

Bu durumda butona bastın;

if(input(pin_a2))           //pin_a2 deki butona basıldı mı?
while(input(pin_a2));   //butona basılı olduğu sürece bu satırda kal
      x++;                       //buton bırakıldığı anda x'i bir arttır.

Senikinde ise şöyle çalışıyordu.

if(input(pin_a2))           //pin_a2 deki butona basıldı mı?
      x++;                       //basıldıysa bir arttır.

program milisaniyelerle ifade edilecek bir zaman diliminde tüm işlemlerini bitirip tekrar aynı satıra geliyordu ve butona hala basılı olduğu için tekrar arttırıyordu.

Daha iyi anlamış oldum açıklamanız sayesinde çok teşekkürler üstadım.

ziyaretci

!_SON DURUM_AŞAĞIDA_!

#include <16f877.h>
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay(clock=4000000)

int x2=0;  // x2 adında değişken atanıyor.0 a eşitleniyor.

//_______________ Bir artırma alt programı______________//
   void artir()                                                                                                                    
{                                                                                                                                     
  while(input(pin_a2));  //butona basılı kaldığı sürece bu satırda kal                              
   x2++;                 //buton bırakıldığında x2 değerini bir artır.                                        
}                                                                                                                                     


//____İşlevin sürekli tekrar etmesi için gereken alt program_____//
void azalt()                                                                                                 
{                                                                                                                 
 while(input(pin_a2));   //butona basılı kaldığı sürece bu satırda kal         
 x2-=15;                //buton bırakıldığında x2 değerini 15 azalt                   
}                                                                                                                


//_______Ana program_____//
void main ()
   {  
      setup_psp(PSP_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);
      
   
   set_tris_a(0xff);  //port A tümüye giriş olarak atanıyor
 
 
  for(;;)              //sonsuz döngü 
  {
   if(input(pin_a2))     //butona her basıldığında 
    artir();          // "artir" alt programı işleve girsin.
   
       if(x2==3)      //x2 değeri 3 olunca 
        {
         output_high(pin_c5); //port C deki 6. pin e lojik-1 ver.
        }
     
           if(x2==15)   // x2 değeri 15 olunca
          {
           output_low(pin_c5);  //port C deki 6. pin e lojik-0 ver.
           }
    
        if(x2==16)   // x2 değeri 16 olunca
       {
        azalt();   //"azalt" alt programı devreye girsin.
       }       //İSTENİLEN İŞLEVİN SÜREKLİ OLARAK TEKRARLANMASI 
             //İÇİN GEREKEN DEYİM SONU
    }   //sonsuz döngü sonu.
 }    // Ana program sonu.

balhan146

Tek yapman gereken proğrama while(input(pin_a2)); komutunu eklemen.Çünki gerçekte sen bu devreyi yaptığında butona bastığın andaki oluşan arktan dolayı pic bunu butona 1 defa basmış olarak algılamaz.Eyerki ben bunu yazılıma ekleyemem diyorsan o zamanda donanımda butona parelel bir tane kondastör bağla ve orda oluşan arkı sönümlendir.

proxrth

Alıntı yapılan: balhan146 - 28 Mart 2012, 15:30:20
Tek yapman gereken proğrama while(input(pin_a2)); komutunu eklemen.Çünki gerçekte sen bu devreyi yaptığında butona bastığın andaki oluşan arktan dolayı pic bunu butona 1 defa basmış olarak algılamaz.Eyerki ben bunu yazılıma ekleyemem diyorsan o zamanda donanımda butona parelel bir tane kondastör bağla ve orda oluşan arkı sönümlendir.
Yok yazılıma ekledim bir sorun yok , fakat bu butona paralel kondansatör bağlantısını ilk sizden duydum Serdar Çiçek hocanın kitabındada dikkatimi çekmedi böyle bir yöntem.