PIC sürekli Kesmeye Giriyor.

Başlatan ByTEK, 04 Mayıs 2014, 21:28:01

ByTEK

Merhaba Arkadaşlar.

pc kontrollü 4 adet çift taraflı saat yaptım. PIC tarafında jalv2 pc tarafında delphi kullandım. Sistem çalışıyor fakat arada sıkıntı yaşıyorum. Büyük ihtimal donanımsal olduğunu düşünmekteyim.  Sorun şu;

PC ile 4 adet saat arasında max485 üzerinden seri veri göndererek saatleri ayarlıyorum. Bu işlem için algoritma olarak uart kesmesini aktif ettim ve veri geldiğinde gelen veriyi şu ise şunu ayarla gibi yazılım var. Fakat PIC sürekli birşeyler almaya çalışıyor ve kesmeye gidiyor. Bunu şöyle anladım. kesmeye girdiğinde ne geldiğine bakmadan şunu yap dedim. enerji verdiğinde sürekli kesmeye gittiğini anladım. Bu sisteme saatte sorun olarak yansıyor. Mesela dakika ilerlemiyor saat adeta donuyor. Anladığım kadarıyla hatta gürültü alıyor ve kesmeye girince ne olduğuna bakıyor. böylece saat okurken kesmeye gittiği için gerekli zaman geçikmelerinden fazla zaman geçiyor ve işleyişi bozuyor. PC den birşey gönderidğimde saati sorunsuz ayarlıyorum. Boşta iken ise PIC sürekli birşeyler geldiğini görüp kesmeye girip girip çıkıyor. kesmeyi pasif yapınca saat hiç donmadan devam ediyor.

Devre şeması aşağıdaki gibi. PC tarafında max232 ve max485 var. birde 120 ohm direnç var. client taraflarında max485 ve 120 ohm dirençler var. 4 adet client var. acaba donanımda atladığım eksik nedir.? nasıl çözebilirim. ?


z

Kesme rutininde interruptin donanimda set ettigi flagi soft olarak sildiginden eminmisin?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

ByTEK

#2
Alıntı yapılan: z - 04 Mayıs 2014, 21:29:35
Kesme rutininde interruptin donanimda set ettigi flagi soft olarak sildiginden eminmisin?

kodlardan göründüğü gibi evet sıfırlıyorum. Donanımsal olduğunu düşünüyorum. ?

procedure veri_geldi is
  pragma interrupt
    var byte gelen_veri
    var byte sira,bas[2];

    if PIR1_RCIF then
       if serial_hw_read(gelen_veri)then

         if gelen_veri == "P" then   -- Saati Kapat Komutu
           Saat_Durum = False
           data_eeprom_write(0,0)
         end if
  
         if gelen_veri == "E" then   -- Saati Aç Komutu
           Saat_Durum = True
           data_eeprom_write(0,1)
         end if
         
         if gelen_Veri == "J" then    -- Saat Formatı 12 Saat
           data_eeprom_write(1,12)
           ds1302_saat_format(12)
         end if
         
         if gelen_Veri == "K" then    -- Saat Formatı 24 Saat
           data_eeprom_write(1,24)
           ds1302_saat_format(24)
         end if
         
         if gelen_Veri == "S" then    -- Saat Kısmını Ayarlar
           sira = 0
           repeat
             if serial_hw_read(gelen_veri) then
                bas[sira] = gelen_veri
                sira = sira + 1
             end if
            until gelen_Veri == "G"
            ds1302_durum(0)
            saat_yaz(strtoint(bas[0],bas[1]))
            ds1302_durum(1)
         end if

         if gelen_Veri == "D" then    -- Dakika Kısmını Ayarlar
           sira = 0
           repeat
             if serial_hw_read(gelen_veri) then
                bas[sira] = gelen_veri
                sira = sira + 1
             end if
            until gelen_Veri == "G"
             ds1302_durum(0)
              dakika_yaz(strtoint(bas[0],bas[1]))
             ds1302_durum(1)
         end if
         
           if gelen_Veri == "L" then    -- Dakika Kısmını Ayarlar
           sira = 0
           repeat
             if serial_hw_read(gelen_veri) then
                bas[sira] = gelen_veri
                sira = sira + 1
             end if
            until gelen_Veri == "G"
             ds1302_durum(0)
              saniye_yaz(strtoint(bas[0],bas[1]))
             ds1302_durum(1)
         end if

      PIR1_RCIF = low
   end if
end if
end procedure

ete

RCIF registeri direk ulaşılıp RCIF=0 şeklinde sıfırlanabilen bir register değildir. O nedenle o şekilde sıfırlasanız bile sıfırlanmaz. Zaten programın kesmeden kurtulmaması sıfırlanmadığını gösteriyor. Sıfırlanması için RCREG registerini boşaltmanız gerekir. Yani RCREG içeriğini bir başka değişkene aktarmalısınız (TEMP=RECREG) Alakası yok gibi gözüküyor ama gayet mantıklı.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

z

#4
PIR1_RCIF = low yi bir alta almayi dene.

Evet Etenin dedigi gibi bu zaten read only bir flagmis.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

ByTEK

#5
peki dediğinizi deneyeceğim. Yarın donanım ile deneme imkanım olacak.

lib dosyasında o flag için aşağıdaki gibi tanımlama yapılmış.

var volatile bit    PIR1_RCIF                 at PIR1 : 5


daha önce bu şekilde kullandım ve kesmeyi kapatabiliyordum.

mesaj birleştirme:: 04 Mayıs 2014, 22:06:33

Alıntı yapılan: ete - 04 Mayıs 2014, 21:34:59
RCIF registeri direk ulaşılıp RCIF=0 şeklinde sıfırlanabilen bir register değildir. O nedenle o şekilde sıfırlasanız bile sıfırlanmaz. Zaten programın kesmeden kurtulmaması sıfırlanmadığını gösteriyor. Sıfırlanması için RCREG registerini boşaltmanız gerekir. Yani RCREG içeriğini bir başka değişkene aktarmalısınız (TEMP=RECREG) Alakası yok gibi gözüküyor ama gayet mantıklı.

Ete

Hocam algılayamadım. RCIF flagını sıfırlamak için TEMP = RCREG yaptıktan sonra RECREG = 0 mı demek gerek ? böylece seri port kesme flağını temizlemiş mi olacağız

z

#6
serial_hw_read(gelen_veri) zaten bu registeri  okuyor olmali.

Interrupttan cikmadan once RCIF bitinin silinip silinmedigine bak. Eger silinmisse sorun burada değildir.

Yalniz int rutini icinde o kadar cok islem varki bunlar tamamlanmadan seri porttan yeni bir data geliyormudur?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

ByTEK

pc den veriler 100ms aralıkla geliyor. Gelen komut neyse o işlem yapılıyor. ve kesmeden çıkıyor. Program devam ediyor. İşin ilginç yanı 4 taneden 2 tanesinde sorun yaşıyorum. herşey birebir aynı. acaba PIC ile ilgili bir sıkıntımı anlayamadım. Benim düşüncem max485 ile ilgili olduğunu düşünüyorum. değiştirdim. Sanki hattaki gürültüyü data sanıp PIC kesmeye giriyor gibime geliyor. ama ete hocamın dediklerini yarın deneyeceğim. Hocam bu işlemleri kesme içinde yapmazsam anlık güncelleme ve kayıt etmede sıkıntı yaşadım. çözümü böyle buldum.

Veli B.

RCIF flagı, receive buffer okunduğunda otomatikman temizlenir ve yeni data almak ve INT üretmek için hazır bekler. Siz buffer içeriğini okumadığınız sürece flag setli durur ve INT rutininden çıkmanızla beraber tekrar ınterrupt var diye INT rutinine geri dönersiniz.
Ete' nin bahsettiği olay bu. Başka bir değişkene datayı aktarmak için bufferı okursunuz ve bu esnada flag düşer.

RS485 ile haberleşirken yansımayı engellemek için bir bus hattında en uç noktalara 120 ohm gibi bir sonlandırma direnci takmanız gerekir. Her node 120 ohm içerirse Transceiverlar ve 4 adet 120 ohm paralel bağlı olacak ve hat direnci oldukça düşecektir. Bu kararsız çalışmalara sebep olur. BUS üzerinde, birbirine en uzak 2 noda bağlanacak şekilde, sadece 2 adet 120 ohm kullanın.
SCOP imkanınız var ise sinyalleri gözlemleyin, yok ise haberleşmeyi analiz etmek için pc ye data aktaracak bir node daha bağlayın ve bütün haberleşmeyi PC ortamına aktarıp, karşılaştırın.

ByTEK

Alıntı yapılan: katana - 05 Mayıs 2014, 03:22:12
RCIF flagı, receive buffer okunduğunda otomatikman temizlenir ve yeni data almak ve INT üretmek için hazır bekler. Siz buffer içeriğini okumadığınız sürece flag setli durur ve INT rutininden çıkmanızla beraber tekrar ınterrupt var diye INT rutinine geri dönersiniz.
Ete' nin bahsettiği olay bu. Başka bir değişkene datayı aktarmak için bufferı okursunuz ve bu esnada flag düşer.

RS485 ile haberleşirken yansımayı engellemek için bir bus hattında en uç noktalara 120 ohm gibi bir sonlandırma direnci takmanız gerekir. Her node 120 ohm içerirse Transceiverlar ve 4 adet 120 ohm paralel bağlı olacak ve hat direnci oldukça düşecektir. Bu kararsız çalışmalara sebep olur. BUS üzerinde, birbirine en uzak 2 noda bağlanacak şekilde, sadece 2 adet 120 ohm kullanın.
SCOP imkanınız var ise sinyalleri gözlemleyin, yok ise haberleşmeyi analiz etmek için pc ye data aktaracak bir node daha bağlayın ve bütün haberleşmeyi PC ortamına aktarıp, karşılaştırın.

Ete hocamın dediği gibi RECREG başka bir değişkene aktardım. sonuç değişmedi. Z hocamının dediği gibi flag silme işlemini bir alt end if aldım. gene sonuç değişmedi.

Sizin dediğiniz gibi her clienta 120 ohm seri direnç vardı. Fakat 4 taneden sadece 1 ve bazen 2 tanesi problem çıkartıyordu. şuanda elimde en çok problem çıkartan ve pc bağlantısı için gerekli 485 ve max 232 devresi var yani, toplam 2 tane 120 ohm var. PIC i değiştirdim. normalde 16F628-04 kullanmıştım aynı kodu derleyip 16F628A atıp koşturudğumda salak PIC ds18b20 yi okuyamıyor. geri kalanı normal çalışıyor.  En iyisi 16F628-04 bulup onu değiştirmek sanırım.

FEHMİ_ASM

     Hocam tx de kullanıyorsanız txıe iznini sadece usarttan veri göndereceğinizde verin. Txen ve trmt bitlerini de inceleyin.
   
     Özellikle kesmeden olduğu düşünülen hataları bulmak için en etkili ve doğru yöntem kuşkusuz adım adım debug yapmak. Interrupt rutininizde, gönderme - alma kesmesi (bayrakları) ve hata bayraklarını birkaç pine ayrı ayrı yönlendirerek gözlemleyin. Bu işlemi hatanın olabileceğini zannettiğiniz her bayrağı adeta ablukaya alarak yaparsanız işlemcide kesme fonksiyonlarında bir hata olup olmadığını, varsa nerede olduğunu bulabilirsiniz.

ByTEK

Sorunu henüz çözemedim. kesmeyi kapatınca saat normal işliyor. sıkıntı yok gibi. fakat hattan anlamsız parazitler alıyorum ve pic doğal oalrak sürekli kesmeye girip çıkıyor. sanırım 3 adet buton koyup ayarı onlar üstünden yapacağım.

hasankara

#12
gürültü ne kadar etkili olabilir ki söylediğiniz anlamsız geliyor bana çünkü belirlenen baud değerine bağlı olarak 8 adet bit geldiği zaman veri almış kabul edilip ona göre flag set ediliyor. yada bilgisayar sizin kontrolünüz dışında karakter gönderiyor olabilir mi? saat bilgisayardan bağımsız iken çalışmasını sürdürüyorsa bu şekilde pc bağlantısı yapmadığınızda olağan dışı karakter geldi diyecek mi diye gözlemleyin.

gerçekten de sorun dediğin gibi gürültüden kaynaklanıyorsa hattın gidiş yönüne göre alçak geçiren filtre koyup çıkışı da opamp ile istediğimiz eşik gerilimiyle karşılaştırabiliriz.



örnek olarak zihnimizde simüle edelim. işaretlediğim haberleşme kanalında öyle bir gürültü olsun ki filtre ettiğimizde sinyalin alt seviyesi 1, üst seviyesi 3 volt olsun. karar eşiğini bu ikisinin tam ortasına getirmek mantıklı bir hareket olabilmekte. bunun anlamı şemada bağladığım pot un orta uç gerilimini tam 2 volt a getirmek demek oluyor. bu şekilde opamp 2 voltun altında çıkışa 0 V,  üstünde ise 5 V verecek.

filtreden dolayı biraz faz farkı oluşacak ve Vpp düşecektir. 9600 baud için örnek kullanılabilecek değerleri girdim. bunun için bu filtre de yaklaşık olarak 5/RC formülünden yararlanarak faz farkını, 1/2*pi*f*c ile de kondansatörün göstereceği direnç hesaplanabilir. görüldüğü gibi direnç ve kondansatörün değerleri sonuca 1. dereceden ters bir orantısı oluyor.  9600 baud için verdiğim R ve C değerlerini ideal kabul edersek, frekansı 4800 bauda çekmek istediğimizde ideal değerler için kondansatörü 2 e katlayıp, direnci 2 e bölerek tekrar ideal değerler elde etmiş oluruz. yani aynı faz farkı değeri elde edilebilir. pratik hesap için bir metod gibi düşünülebilinir.

ByTEK

şöyle bir durum var. MAX485 lerin A - B uçlarını boşa aldığımda saate bir program attım kesmeye girince ekrana -- -- çıkacak şekilde ayarladım. elle dokununca boştaki uçlara pic hemen kesmeye giriyor. elimi çekince düzeliyor. Çok garip geldi. Kesin sorun bu diyorum kendimce..

bayelektronik

485 entegrelerini genelde b ucunu pull-down a ucunuda pull-up a çekerek kullanırım sizde deneyebilirsiniz.