switch cAse sorunu

Başlatan crnelektronik, 01 Ağustos 2012, 11:44:25

crnelektronik

iyi günler arkdaşlar programlamada yeniyim bu konuda yardimci olursaniz sevinirim

 
 switch(giris)
   {
   
     
     case 0b00000001:
     output_high(pin_a0);
     break;
     
     case 0b00000010:
     output_high(pin_a1);
     break;
     
     case 0b00000011:
     output_high(pin_a2);
     break;
     
     case 0b00000100:
     output_high(pin_a3);
     break;
     
     case 0b00000101:
     output_high(pin_a4);
     break;
     
     case 0b00000110:
     output_high(pin_a5);
     break;
     
     case 0b00000111:
     output_high(pin_a6);
     break;
     
     case 0b00001000:
     output_high(pin_a7);
     break;
     
     case 0b00001001:
     output_high(pin_a7);
     break;
     
     default:
     output_a(0x00);
     break;
   }
   
olay şu şekilde olmasi gerekiyor case girişteki bilgileri okuyup ona göre ilgili pini high  yapmasi gerekiyor ve yapiyor da fakat iki farkli case degişkeni ayni anda devreye girince program sapitiyor bunu önlemek için ne yapmam gerekiyor
aşagida ccs c dosyasini yükledim

yazici67

#1
İki farklı case değişkenin devreye girmesi derken neyi kasdediyorsun? Eğer gösterdikleri değerler farklıysa aynı anda devreye girmeleri imkansız...


Binary ve Gray fonksiyonlarında while(1) {..} kullanmışsın yani program o noktaya geldiği zaman kesme yakalanmadığı sürece döngüden çıkamayacak. Programda herhangi bir kesme yakalama rutini de göremedim bu demek oluyor ki program ilk binary() çağrısında while bloğunda kalıyor. Program hiçbir şekilde sonraki adıma geçemiyor.

crnelektronik

#2
 switch(giris)
   {
   
     
  1   case 0b00000001:       *
     output_high(pin_a0);
     break;
     
  2  case 0b00000010:
     output_high(pin_a1);
     break;
     
  3   case 0b00000011:      *
     output_high(pin_a2);
     break;
     
  4  case 0b00000100:
     output_high(pin_a3);
     break;
     
  5   case 0b00000101:     *
     output_high(pin_a4);
     break;
     
    1, 3, 5 inci case lerin ilk bit leri ayni oldugu için  A0 ,A2 ,A4  pinleri high oluyor
örnegin girişe 0b00000001 bilgisi gelince a0 high oluyor
            girişe 0b00000011 bilgisi gelince a2 high oluyor
bu bilgiler ayri ayri gelince sorunsuz ilgili pin high oluyor ama ikisi ayni anda gelince hem a0 hem a2 high oluyor bunu nasil engelleyebilirim hocam 

birgramda void binary de kullandigim while döngüsüne girince sürekli orda kalsin istiyorum zaten yani kesmeye ihtiyacim yok tek sorunum girişteki data bilgisi ayni anda geldince 3- 4 pin birden high oluyor

yazici67

Giriş bilgisini nasıl veriyorsun? Butonla mı? Switch-Case yapısı bit bit eşleştirmez.Yani 0b00000011 geldiğinde sadece 3 nolu rutin işler. Emin olmak için sayıların onluk karşılıklarını kullanabilirsin.Bu yazdığın durum derleyicide bir hata olmadıkça mümkün değil.Devre şemanı gönderebilir misin?

crnelektronik

elkedim giriş buton ile yapiliyor lojik de olabilir
sanki programin akış diyagraminda bi hata yaptim gibi

yazici67

Gördüğüm kadarıyla bir hata yok.Sadece söylediğim while döngüsü var.Butonların basma-çekme sırasındaki oluşacak titreşimleri filtreledin mi? Birde yazılımda o içinde sürekli kaldığın while döngüsüne (binary fonksiyonundaki) 20-30 ms lik bir gecikme koy.

crnelektronik

gecikmeyi deneyim programi pratikde denemedim ama isis de denemedim onda bu şekilde hata olabilir mi ?

yazici67

Ama isiste de denemedim derken denedim mi demek istedin? Bu durum hata değil normal zaten.ISIS ve dolayısıyla PROSPICE en ince ayrıntısına kadar simüle ediyor.Butonların çıkışına 10 nF lık kondansatörlerle toprağa bağla.Büyük ölçüde filtreleyecektir....

crnelektronik

evet hocam isis de denedim diyecektim buton arkı ile similasyonda karşilaşmamak için girişleri logicstate ile yaptim  1 olunca 5volt 0 olunca 0 volt veriyor

yazici67

Tamam doğru tam lojik durumları veriyorsun peki sonuç nasıl?

crnelektronik

ayni şekilde saçmaliyor case 0b00000001 bilgisi gelince a0 ledi yaniyor ama
                                  case 0b00000011 bilgisi gelince sadece a2 ledi yanmasi gerekirken hem a0 hem a2 ledi yaniyor

yazici67

#11
--------------
Hmm devrede verilen uyarıları önceden söyleseydin çözüm bulurduk.Şimdi kodu düzenliyorum...
Dosyalar :Deneme

crnelektronik

tmm hocam nerde hata yaptiğimi merak ediyorum programlaya başladiğimdan beri kendimi bulmaca çözüyormuş gibi hissediyorum bir de bazi noktalarda takılmasam cok güzel olacak ama o da zamanla düzelir inş

crnelektronik

 giris = input_c();
      giris &= 0x0F;  hocam programda anlamadim neden giriş değişkenini  önce and leyip sonra eşit 0xff dediniz ?
bir de hocam void gray ile binary ayni işlemleri yapiyor benim amacım örneğin gray kodu seçtik gray kod listesindeki girişe göre a portu çıkış verecek

yazici67

giris &= 0x0F aslında giris = giris & 0x0F demek.Yani sadece alt 4 biti al demek. case kısımlarına ben dikkat etmedim.Oraları önceki programındaki gibi düzeltebilirsin.Kodda aslında belirgin bir sorun yok.Soruna neden olan ayrı ayrı portc ve portb adresleri tanımlaman.Ayrıca adreslerde yanlıştı.PortB ve C nin adreslerini datasheetlerden incele.input_c() fonksiyonundan sonra tekrar yalnızca okunabilir adrese veri yazmaya kalkıştığın için program ISIS te uyarı veriyordu.Gerçek hayatta ise büyük ihtimalle reset atacaktı... Kısaca bir iki basit hatalı koddan dolayı çalışmıyordu.Koda bu haliyle kendi istediğin yerlere müdaheleler yaparak düzenleyebilirsin :)

crnelektronik

tamam hocam swich case konusunu anladim şimdi bu devreye ben bir de sayici eklemek istiyorum
3 buton olacak. yukari say  aşagi say, pals butonu
yukari say girişine sinyal geldiginde ve bir pals verildiginde 8inci led yaniyorsa o sönecek 7. led yanacak ayni şekilde aşaği say da öyle olacak,
böyle bir program yazmak için timer mi kullanmam gerekiyor?

yazici67

Çalışma mantığını tam anlayamadım biraz daha net açıklarsan programı yazarız...
Eğer butonları sadece PORTB4-7 veya PORTB0 ile kullansaydın Timer\'a gerek kalmazdı.Sadece EXT_INT ile yapardık.Ama butonlar başka tarafta olduğu için Timer\'la kontrol edebiliriz.Timer 0 kesmesini proje oluştururken ayarlayabilirsin...

crnelektronik

hocam butonun port c de veya B de olmasi çok önemli degil port b ye alabiliriz
ama benim ögrenmem acisindan her ikisini de yapsak daha iyi olur
programın senaryosu : arttır azalt ve pals diye 3 adet buton olacak
ve 8 adet çikişta ledler,
örneğin RA0 da ki led yanıyor, arttir butonuna basılı iken pals butonuna bir kez basip çektiğimizde RA1  de ki led yanacak bu şekilde Ra7 ye kadar arttir a high geldigi sürece her pals butonuna basilıp çekildiginde bir sonra ki led yanacak
sonra
azalt butonu high iken pals butonuna basilip çekildigi zaman 8. led yaniyorsa 7. led yanacak,

bir de hocam ccs c ile programlamayi en iyi nasil ögrenebilirim hiç temelim yok serdar çicek hocanin kitabina baka baka birşeyler yapmaya çalişiyorum ama bi yerde tıkaniyorum böyle?

yazici67

#18
Aslında bu iş kitaptan öğrenilmez kitapta sadece oradaki örneklerle kalırsın.Kendi kendine öğreneceksin bol bol ingilizce dökümanları yalayıp yutacaksın ki en az bir iki sene alacak.



Soruna gelince en iyisi Timer kullanmak.CCS C de proje oluştururken gerekli ayarları yap Timers dan Timer 0 veya Timer 1 i aktif et / ayarla.Sonra interrupts sekmesinde Timer 0 / Timer 1 Overflow sekmesini seç.Proje oluşturunca zaten direkt ayarlı c dosyası önüne geliyor.Eğer istersen bunları elle de yapabilirsin öğrenmek için.Sadece zaman harcamış olursun.
Sorumuza dönünce en iyisi LED diyebyte fiziksel adres ataması yapmak.Kısacası

#byte PORTA = 0x05
#byte PORTB = 0x06
#byte PORTC = 0x07
#byte PORTE = 0x09

#byte TRISA = 0x85
#byte TRISB = 0x86
#byte TRISC = 0x87
#byte TRISE = 0x89
Bunları nerden buluyoruz dersen Datasheet\'lerde hepsi var.Buda bir kesit:




Buda Datasheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/41291F.pdf
İstediğin devreyi yapmak kolay.Mesela yukarıya arttırmayı göstereyim:
// .h dosyası içinde
#byte PORTA = 0x05
$byte PORTB = 0x06
#byte PORTC = 0x07
#byte PORTE = 0x09

#byte TRISA = 0x85
#byte TRISB = 0x86
#byte TRISC = 0x87
#byte TRISE = 0x89

#define BTN_UP  0b00001000  // Yukarı butonunu hatırlamıyorum rastgele RC.4 dedim
...

// int main() içinde
TRISC = 0xFF;
TRISB = 0x00;
..
PORTB = 0x00;
..

//... Kesme kodları içinde
if((PORTC & BTN_UP) && ( PORTB != 0b10000000))
{
    PORTB = PORTB << 1;      // Tüm bitleri bir sola kaydır.Aynı zamanda sayı değeri 2 ile çarpılmış olur
}
Birde ipucu vereyim: 2 ve üssü ile çarpma işlemlerini kaydırma ile yap.Kaydırma işlemi aritmetik çarpmadan 2-3 kat hızlı gerçekleşir...C de ipuçları önemlidir...
Bir ipucuda isis için: PIC e programın HEX dosyasını değilde COFF dosyasını göster .COFF dosyası hata ayıklama bilgisinide içerir.Programını C kodlarıyla birlikte adım adım işletebilirsin.Pause butonunu kullan.
Verdiğim örneği tekrarlayarak diğer fonksiyonlarıda ekleyebilrsin...

crnelektronik

verdiginiz bilgiler için teşekkürler hocam bu 882 ile yaptiğim devreyi 628 ile yaptim ama isiste sayısı sürekli yükselen hata veriyor \" indirect write of 0x00 to address 0x0000 is itself indirect write \" sorun nerde olabilir hocam programda mi  hata yapiyorum yine
 

yazici67

#20
Bu seferki kodlarda baya hata var.WORD cinsinden 8 elemanlı deger adında dizi oluşturmuşsun.Dizinin elemanlarını değiştiriyorsun ama entegreye deger adresini, otomatik olarak 0 indeksli elemanı yoluyorsun.Tam olarak ne yapmak istediğini anlayamadım.Önceki projene benzetimle kodu toparlıyorum... Yukarı aşağı saymaları kullanmamışsın onları ne yapacaksın?

crnelektronik

yukari aşagi saydiri da kullanacam hocam önce sheft register ile bi çalişayim diye ugraştim
progamin ana fikri  8 adet  led i sirasiyla yakacam ve söndürecem fakat girişteki bilgilerimi degiştirebilecem
örneğin kod seçimini binary e aldigimda o alt pgramdaki değişkenlere göre 8 led sirasiyla yanacak
yada kod seçimini sayiciya aldiğim zaman girişteki 3 pini kullanarak gelen dataya göre ledler sirasiyla yanacak ve sönecek
 bu şekilde 4 adet alt program oluşturacam binary, gray, sayıcı, yediseg diye
mesela kodseçiminde yediseg seçtiğim zaman girişe 0xF9 bilgisi gelince 1. led yanacak hocam

yazici67

Shift Register kullanımı basit. DS pinine veriye ait Bitleri sırasıyla yolluyorsun.Her bit bitte bir adet clock palsını  SHCP pinine yolluyorsun.En sonda Shift Register\'a aktarılan bilgiyi STCP pinine bir clock palsı yollayarak çıkışlara aktarıyorsun... Projende kullandığından farklı bir örnek
#define SW_DATA  PIN_A1
#define SW_SHIFT PIN_A0
#define SW_STORE PIN_A2

VOID Serial_Write(int8 n)
{
   int8 bit_count = 0;
   
   output_low (SW_DATA|SW_SHIFT|SW_STORE);
   
   while (bit_count < 8)
   {
      ((n >> bit_count) & 1) ? output_high (SW_DATA) : output_low (SW_DATA);
      output_high (SW_SHIFT);
      delay_us (10);
      output_low (SW_SHIFT);
      delay_us (10);
      bit_count++;
   }

   
   output_high (SW_STORE);
   delay_us (10);
   output_low (SW_STORE);
   delay_us (10);
   
   output_low (SW_DATA|SW_SHIFT|SW_STORE);
}
kullanabilirsin.Projede deger dizisini kullanmanın amacını çözemedim... Programın toparladığım hali ekte...

crnelektronik

hocam aradan biraz zaman geçti ama bu sheft register li projeyi sonlandiramadim ekldedign program tam istedigim gibi fakat pratikte çalişmadi 74hc595 in vcc gnd verdim 10. bacaga +5v 13. bacaga gnd verdim
pic in beslemesini de verdim fakat çalişmadi sanki sigorta ayarlarinda sorun var gibi etegrenin arka tarafina parmağimi yaklaştirinca led yaniyor sanki program biraz ilerliyor sonra öyle kaliyor gibi

yazici67

O zaman osilatör problemi vardır. Kurduğun devrenin yakından resmini çekebilir misin?

crnelektronik

devreyi breadbord üzerinde yaptim çalişmasini denemek için sadece isisde ki gibi tek ledi yakmak için baglanti yaptim, 628a nin dahili osilatorünü kullandim
Resim #1:



 Resim #2:


yazici67

Dokunduğun kısımda B portunun pinleri var. PIC\'in OSC uçlarına kendini topraklayarak dokun.
HC595 e giden kablolarada birer adet LED bağla. Büyük ihtimalle statik bir olay.

kuylus

   Sayın yazıcı67

   Birde ipucu vereyim: 2 ve üssü ile çarpma işlemlerini kaydırma ile yap.Kaydırma işlemi aritmetik çarpmadan 2-3 kat hızlı gerçekleşir.

Konusuna  detaylı bir örnek verebilirmisin?

Örneğin aşağıdaki kodları siz yazmışsınız burada çarpma  nasıl yapılmıştır? daha detaylı bir örnek vermeniz mümkünmü?
//... Kesme kodları içinde
if((PORTC & BTN_UP) && ( PORTB != 0b10000000))
{
    PORTB = PORTB << 1;      // Tüm bitleri bir sola kaydır.Aynı zamanda sayı değeri 2 ile çarpılmış olur
}

Teşekkürler.

RaMu

Ölülere soru sormayın :)
Konuya son mesaj 2012 de yazılmış.

Yinede cevabı vereyim ama
bu gibi durumlar için yeni konu açmanız daha doğru olur.

Kısaca mcu işlemleri 2 lik tabanda yapar,
2lik tabanda bir sayıyı bir defa sola kaydırırsanız
doğal olarak iki katını almış olursunuz,
sağa kaydırsaydık 2 ye bölmüş olacaktık.


Mcu da işlemler ikilik tabanda yapılır,
8 bitlik bir değişkenin olsun, adı ahmet olur portb olur,
ahmet = 3;
dediğinde
ahmet in 8 bitlik alanında
0b 0000 0011
yazılır,

ahmet i bir sola kaydır dediğinde bu bitler
bir defa sola kaydırılır,
yeni ahmet
0b 0000 0110
olur (kaydırırken sonuna sıfır geleceğini garanti etmeliyiz, kendide edebilir
kullanılan dil derleyici komut vs. ye göre değiebilen bir durumdur detaya girmek istemiyorum)
bu sayıya bakarsak 0b 0000 0110 sayısı onluk tabanda 6 ya karşılk gelir,
3 sayısını bir sola kaydırdık 6 oldu,
bu aslında apaçık ortada,
misal onluk tabandaki bir sayıyı birdefa sola kaydırsan sayı on katı olur
örneğin (onluk tabanda) 15 sayısını bir sola kaydır 150 olur,
mcuda işlemler 2lik taban üzerinden yapıldığından ötürü
sayıyı bir sola kaydırırsan 2 katını almış olursun,
kaç defa sola kaydırırsan o kadar defa tekrarlayarak 2 katını almış olursun.

ahmet << 1  ;   << sola kaydır demek,   1 ise bir defa demek oluyor.

Hızlı Yanıt

Not: Bu konu bir moderatör tarafından onaylanmadan görüntülenmeyecektir.

Adı:
E-Posta:
Doğrulama:
Lütfen bu kutuyu boş bırakın:
IRFP250 Nedir:
kısayollar: göndermek için alt+s veya önizleme yapmak için alt+p'ye basın