16F877 için Timer 1 ve Int_RB Kullanımı

Başlatan oguzmania, 09 Haziran 2008, 12:58:52

oguzmania

Öncelikle selamlar anahatlarıyla yapmak istediğimi anlatacak olursam;

Elimde 4 adet birbirinin aynısı mikrofonlu ses dedektör devreleri var.Bu dedektörlerin yerleri birbirinden farklı , bu dedektörlerin çıkışında da karşılaştırıcı olarak çalışan Op-Amp bulunmakta.Kısacası eğer dedektör sesi algılarsa Op-Amp çıkışında +5V , algılamazsa ise 0V verecek.

Benim çıkarttığım sesin konumu her dedektöre farklı uzaklıkta olacağı için ses de dedektörlere farklı zamanlarda ulaşacaktır.İşte ben bu özellikten hareketle çıkarttığım sesin konumunu bulmaya çalışıyorum.

Bu 4 adet Op-Amp çıkışını ben Int_RB kesmesini kullanmak amacıyla RB4,RB5,RB6 ve RB7'ye bağlayacağım.Yani ses yokken 0V oluyorken ses çıkınca +5V'tan dolayı bir kesme oluşturulmasını istiyorum.Benim amacım oluşan kesmelerin arasındaki zaman farklarını tespit etmek.

Buraya kadar kafama takılan 2 sorun var;
Soru 1:Pratik uygulamalar için Op-Amp'ın çıkışını doğrudan RB pinlerine mi bağlamalıyım yoksa araya bir direnç koyup öyle mi bağlamalıyım , eğer öyleyse ne kadarlık bir direnç uygun düşer?
Soru 2:Ben interruptın oluşması için yalnızca 0V'tan 5V'a olan yükseltilmeleri kullanmak istiyorum.Bunu yapabilmem için programın altında interruptları belirlediğimiz bölümde;

enable_interrupts(INT_RB);
ext_int_edge(L_TO_H);

komutlarını kullanmam yeterli mi?

Şimdi kafama takılan asıl probleme gelecek olursam;

Kullandığımız bu dedektörleri şöyle tanımlayalım;

1.detector:RB4
2.detector:RB5
3.detector:RB6
4.detector:RB7

Zamanlayıcı işlemi için Timer 1'i kullanıyorum ve de bu işlem için 32 KHz'lik sayıcı kullanıyorum.Timer 1'le ilgili gerekli ayarlamaları da yaptım ve 30 usn ile 30 msn arasındaki değerleri ölçmek istiyorum.Bunun için de Timer 1'i 64536-65536 arasında kullanacağım.

Şimdi farz edelim ses önce 1. , sonra 2. , sonra 3. en son olarak da 4. dedektöre ulaşacak;
Time1 --> Detector 1
Time2 --> Detector 2
Time3 --> Detector 3
Time4 --> Detector 4

Benim yapmak istediğim;
Ses 1. dedektöre gelince zamanlayıcı başlayacak.Yani Time1=64536 olacak olacak daha sonra ses 2. dedektöre ulaşınca Timer 1'in o anki değeri Time2 değeri olacak , bu arada Timer 1 saymaya devam ederken bu sefer 3. dedektör aktif olacak o anki değer de Timer3'e atanacak aynı durum 4. dedektör için de geçerli olacak.

Bu bölümü sanırım yazılımla şöyle anlatabiliriz;
if (input(pin_b4))
set_timer1(64536);
time1=get_timer1()

if (input(pin_b5))
time2=get_timer1()

if (input(pin_b6))
time3=get_timer1()

if (input(pin_b7))
time4=get_timer1()


Benim durumum için Timer 1'in 65536'yı aşması olanaksız o yüzden Int_timer1'i kullanmaya gerek görmüyorum.

Soru 3:Int_RB kesmesini doğru kullanabilmek için bir bayrağı temizlemek ya da Port B'yi sıfırlamak gerekiyordu sanırım , bu işlemi nasıl yapabiliriz?

Şimdi gelelim en can alıcı noktaya;

Sorun 4:Benim uygulamamda dedektörlerin hangi sırayla Lojik 1 olacağını bilmiyorum , örneğin yukarıdaki durumda sırasıyla 1-2-3-4 aktif olurken , uygulamada 2-3-1-4 , 4-3-2-1 vs. gibi 16 farklı durum gerçekleşebilir.Ben bununla nasıl başa çıkabilirim bilmem gereken sabitler Time1, Time2, Time3 ve Time4 bu değerleri doğru olarak nasıl elde edebilirim.

Sanırım biraz uzun oldu , umarım aklımdan geçenleri sizlere doğru olarak aktarabilmişimdir.Kurduğum mantıkla ilgili aklınıza takılan sorun ve çözüm yöntemlerinizi dinlemek isterim.

Zaman ayırdığınız için teşekkürler , cevabınızı bekliyor olacağım , saygılarımla...

picusta

öncelikle bu isin teorisini hakkinda biraz fikir edinmen gerekir.
Bunun için asagidaki linki inceledin mi?
http://picproje.org/index.php/topic,12241&postdays=0&postorder=asc&start=0

Madem sen pratikte bu isi tamamen lojik olarak (1-0) çözeceksin, sana op-amp yaramaz, bir schmitt-triger karsilastiricisi daha uygun.

Hatirladigim kadari ile RB interrupt'unu teyit etmek için porta okuma ve yazma yapmak gerekir zannedersem.

oguzmania

Alıntı yapılan: "picusta"öncelikle bu isin teorisini hakkinda biraz fikir edinmen gerekir.
Bunun için asagidaki linki inceledin mi?
http://picproje.org/index.php/topic,12241&postdays=0&postorder=asc&start=0

Madem sen pratikte bu isi tamamen lojik olarak (1-0) çözeceksin, sana op-amp yaramaz, bir schmitt-triger karsilastiricisi daha uygun.

Hatirladigim kadari ile RB interrupt'unu teyit etmek için porta okuma ve yazma yapmak gerekir zannedersem.

Cevap için teşekkürler , hatta projeyle uğraşan arkadaşla da iletişim kurmuştum O'nun yöntemini incelediğimde çok daha komplike olduğunu hatta proje için yurtdışından özel mikrofonlar getirtildiğini duymuştum.(Tübitak destekli bir projeydi sanırım)

Benimki onunkine nazaran biraz daha basit ve de 2 boyutlu ölçümleri içeren bir uygulama olacak.

RB interruptı için yapılabilcek işlemi CCS üzerinde nasıl yapabiliriz , bir örnek verebilir misin acaba?

Bu arada benim işimi görebilecek (4 farklı girişle çalışabilecek) tavsiye edebileceğiniz bir Schmitt-Trigger entegresi var mıdır?

aliveli

interrupt ile kasma bence
bu işi adc ile daha rahat yapabilirsin bu sayede gelen sinyali illa lojik 1'e çıkarman gerekmez devrede mic den gelen sinyali analog girişe bağla ve aynı şekilde analog girişlere pulldown direnci bağla süreklide gelen sinyalleri oku. eğer sinyal gelirse 0 volttan yüksek bir değer okuman gerekir
örneğin

set_adc_channel( 0 );
mic1=read_adc();
if(mic1>1)
{set_timer1(64536);}

set_adc_channel( 1 );
mic2=read_adc();
if(mic2>1)
{time2=get_timer1();}
.
.
.
sıralama için karşılaştırma yapabilir yada bu değerleri diziye doldurup karşılaştırma yapabilirsin

picusta

CCS'in makro fonksyonalarindan anlamam.
Fakat bence bu isi RB interrupt'u yerine capture pinini de kullanabilirsin (Or kapisi ekleyerek).
Normal kullanimda ve hersey yolunda giderse interrupt 4 kez çagrilacak.Timer'in degerini her seferinde MX_DETECTOR uzunlugunda olan bir tabloya ata.
Bunun için her interrupt'ta IdxSensor degiskenini artiracaksin.
Ayni uzunlukta bir de pin tablosu olsun, böylece pin sirasini da saklamis olursun.
4 sinyal de geldiginde ana döngüye haber veren bir flag gönderirsin, o da bu iki tabloya (Zaman ve pin) bakarak  hesabi yapar ve lcd'de gösterir. (veya timeout durumu: hata log + hersey reset).

oguzmania

Alıntı yapılan: "picusta"CCS'in makro fonksyonalarindan anlamam.
Fakat bence bu isi RB interrupt'u yerine capture pinini de kullanabilirsin (Or kapisi ekleyerek).
Normal kullanimda ve hersey yolunda giderse interrupt 4 kez çagrilacak.Timer'in degerini her seferinde MX_DETECTOR uzunlugunda olan bir tabloya ata.
Bunun için her interrupt'ta IdxSensor degiskenini artiracaksin.
Ayni uzunlukta bir de pin tablosu olsun, böylece pin sirasini da saklamis olursun.
4 sinyal de geldiginde ana döngüye haber veren bir flag gönderirsin, o da bu iki tabloya (Zaman ve pin) bakarak  hesabi yapar ve lcd'de gösterir. (veya timeout durumu: hata log + hersey reset).

Tekrar selamlar acaba anlattığın yöntemi biraz daha detaylandırabilir misin acaba?
Programlamada yeni olduğum için kavramları anlamakta biraz zorluk yaşıyorum  :oops:

İlginiz ve cevaplarınız için çok teşekkürler...

picusta

// CONSTANT
typedef enum
{
DETECTOR_A,
DETECTOR_B,
DETECTOR_C,
DETECTOR_D,
MX_DETECTOR,
}ENU_DETECTOR;

// Struct
typedef struct
{
int Pin;          // Hangi Pin?
int Time;         // Ne zamanda
}STR_DETECTOR;

// Global
STR_DETECTOR  Detector[MX_DETECTOR];   // Detector bilgileri
int IdxDet;                            // Kaçinci detector
bool DetBitisFlag;

// Ana program
void main(void)
{
int ii;     // Döngü degiskeni
// init
 /*...*/
DetBitisFlag = false;
IdxDet =0;

while(1)
   {
   /*
   Diger isleri yap
   */  
   if (DetBitisFlag)
      {
      // ölçüm bitti, hesabini yap LCD'ye yaz 
      for (ii = 0; ii < MX_DETECTOR; ii++)
         {
         /* Tabloyu tarayarak zamani ve mesafeyi hesapla */
         Mesafe[ii] = f(Detector[ii].Pin, Detector[ii].Time);
         /* vs..*/
         }
      /*...*/
      // Bir sonraki ölçüm için sifirliyoruz
      IdxDet = 0;
      DetBitisFlag = false;
      }
   }
}

ENU_DETECTOR  MapPort  (BYTE  Port)
{
ENU_DETECTOR   Donus;
/*...*/
switch (PortB&Mask)
   {
   case XX:
   Donus = DETECTOR_A;
   break;
   case YY:
   Donus = DETECTOR_B;
   break;
   /*  vs...*/
   .
   .
   }
return Donus;
}

void ISR(void)
{
if (DetInterrupt)
   {
   if (!DetBitisFlag)
      {
      Detector[IdxDet].Time = GetCaptureTime();
       // PortB'yi Oku, hangi Pinden geldigini kaydet
      Detector[IdxDet].Pin = MapPort(PortB)
      IdxDet++;
      // ölçümler biti ise bitis flagini set ediyoruz
      if (IdxDet == MX_DETECTOR)
         DetBitisFlag = true;
      }
   }
/*
.
.
*/
}

Kodu iyice incele, mantigi anlamaya çalis. Buradaki kavramlari ögrenirsen C'de sirtin yere gelmez.