12F675 ile analog digital convertor

Başlatan aliyilmaz, 04 Ocak 2009, 15:42:52

aliyilmaz

Merhaba arkadaşlar gaz sensörü projesi için convertor yapmam gerekiyor. İstenen şey tam olarak şöyledir, bir direncin üstündeki voltaj belli bir değeri aşınca çıkışın 1 olması diğer durumlarda 0 olması isteniyor. Kodları aşağıdaki gibi yazdım cof dosyası oluşuyor ama proteusta simüle edince çalışmadı.Hata nerde acaba yardımlarınız için şimdiden teşekkür ederim...

#include<pic.h>
#include<stdio.h>
#define output GPIO0
float oran=5.0/1023.0;
float deger,volt,yuksek,dusuk;

__CONFIG(MCLRDIS&WDTDIS&PWRTEN&INTIO);

void donusum_yap(void)
{ADCON0=0x8F;
while((ADCON0&4)!=0);
yuksek=ADRESH;
dusuk=ADRESL;
deger=256.0*yuksek+dusuk;

volt=deger*oran;
  if(volt>=620)
   output=1;
   else
     output=0;
}
main(void)
{
CMCON=0x07;
TRISIO=0x01;
ADCON0=0x8F;
ANSEL=0x38;
GPIO=0;

for(;;)
{donusum_yap();}

}

Tagli

ADCON1 ayarlarını göremedim kodunda. Burda analog ve dijital kanalların seçimi ve sonucun ADRESH ve ADRESL'ye yerleşim şekli ayarlanır. Başlangıç ayarında sonuç sola dayalıdır, programın senin yazdığın şekliyle çalışabilmesi için sağa dayalı olması gerekiyor. ADCON1'in 7. bitine bak, 1 olması gerekiyor.

ADCON0 ayarlarının doğruluğundan emin misin? Bu ayarları bir kez yapıp fonksiyon içinde sadece go/done bitini ayarlayıp kontrol etmek daha mantıklı. Sen bu ayarları fonksiyon içinde yaptırmışsın. Gerçi zararlı bir etkisi olmayabilir, emin değilim ama yine de hatalı bir yaklaşım.

Her A/D dönüşümünden önce "acquisition time" denen bir süre kadar beklemek gerekir. Kodunda bu beklemeyi göremedim. Bu süre hakkında ayrıntılı bilgiyi datasheet'te bulabilirsin.

Düzeltme: Kodunda yazdığın "ANSEL = .." ifadesini yeni görüyorum. Eğer bu ADCON1 ayarıysa yukarda yazdığım ilgili bölümü görmezden gelebilirsin.
Gökçe Tağlıoğlu

aliyilmaz

12F675 entegresinde ANSEL ve ADCON0 kaydedicileri ile çevirme işlemi yapılıyor.ADCON1 kaydedicisi bu entegrede yoktur.Convert işleminin sonucunun nereye dayalı yazılacağıda ADCON0 IN 7. bitine bağlı olarak yapılıyor.
Bekleme için kodun sonuna aşağıdaki döngüyü ve delay dosyalarını ekledim.Ama yine proteusta çalışmadı.
for(;;)
{donusum_yap();
 for(j=0;j<4;j++)DelayMs(200);
}
}

ADCON0 ayarlarını denemek için aşağıdaki gibi acemice bi kod yazdım ama buda çalışmadı.Acaba burda ne gibi bi hata yapmış olabilirim. Yapmak istediğim şey 2.5 sn aralıklarla godone bitini 1 yapıp if komutuyla çıkış almaktır.

#include<pic.h>
#include<stdio.h>
#include"delay.h"

#define output GPIO0
unsigned char j;

main(void){
for(;;)
{
for(j=0;j<10;j++)DelayMs(250);
ADCON0=0x8F;
TRISIO=0x00;
CMCON=0x07;
 if(GODONE!=1)
     output=1;
  else
      output=0;

}
}

Acaba proteusla ilgili bir sorun olabilirmi veya kodumda bir hata mı var?
Teşekkür ederim..

Tagli

Öncelikle dikkatsizliğim için özür dilerim. PIC modelini mesajın içinde aramıştım ama dalgınlıktan olsa gerek modelin başlıkta ifade edildiğini unutmuşum mesajı okumaya başlayınca.

Alıntı yapılan: "12F675 Datasheet"After the analog input channel is selected (changed), this acquisition must be done before the conversion can be started.
Burdan anlaşıldığı üzere bu beklemeyi tüm ayarları yaptıktan sonra ve go/done bitini 1 yapıp işlemi başlatmadan önce yapman gerekiyor. Öncelikle ADCON0, ANSEL, CMCON ve TRISIO register'larının gerekli ayarlarını yap. Bunu yaparken ADCON0'daki go/done bitini 0 olarak bırak. Bu ayarlar programın başında yapılsın ve gerekmedikçe de bir daha dokunma (muhtemelen sadece kanal değiştirirken oynaman gerekecek), yani donusum_yap fonksiyonunun içinde bunlar yer almasın. Bu fonksiyonun içinde sırayla gerekli bekleme, sadece go/done bitinin 1 yapılması, go/done biti 0 olana kadar beklenmesi ve sonra da sonucun ADRESH ve ADRESL'den çekilmesi olmalı.
Gökçe Tağlıoğlu

M_B

Merhaba

donusum kısmını su sekilde yap .

void donusum_yap(void)
{
	ADCON0=0x8F;	 // A/D donusumu baslat
	while(GODONE!=0);	 // Donusumun bitmesini bekle
          yuksek=ADRESH; 
          dusuk=ADRESL; 
          deger=256.0*yuksek+dusuk; 
          volt=deger*oran; 
           if(volt>=620) 
          output=1; 
           else 
           output=0; 
}


main kısmınıda asagıdaki gibi ayarla
CMCON=0x07; 		// GPIO portlari sayisal I/O secildi
ANSEL=0x18; 		// AN3 analog giris secildi 
TRISIO=0x10;		// GP0,GP1,GP2 cikis
GPIO=0;  			// Baslangicta cikislar lojik 0  
ADCON0=0x8D; 		// A/D ayarlarini yap


bu sekılde dene işini gormesı lazım.
Kolay gelsın
M_B


Not: senın yazdıgın kodta dıkkatımı ceken nokta su oldu main kısmında
Neden ANSEL 0X38 yaptın ?
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

aliyilmaz

Yardımlarınız için çok teşekkür ederim kod en son aşağıdaki haliyle çalışır duruma geldi.
#include<pic.h>
#include<stdio.h>
#include"delay.h"

#define output GPIO0

float yuksek;
unsigned char j;

__CONFIG(MCLRDIS&WDTDIS&PWRTEN&INTIO);

void donusum_yap(void)
{ADCON0=0x0F;
while(GODONE!=0);
yuksek=ADRESH;

if(yuksek>=0b01111111)
output=1;
else
output=0;
}

main(void)
{
CMCON=0x07;
TRISIO=0x10;
ADCON0=0x0D;
ANSEL=0x78;
GPIO0=0;

for(;;)
{for(j=0;j<5;j++)DelayMs(200);
  donusum_yap();
 
}
}

Yalnız burada convert işlemi sonucu sola dayalı yazılmıştır ve sadece ADRESH değerine bakılmıştır.Bu yüzden sonuçlar çok hassas değildir. Ama bu proje için çok önemli değil bu.

ANSEL=0x78 olarak kaydedildi.Burada internal clock seçilmiştir.Ayrıca bu değer 0x38 olarakta kaydedilebilir.Çünkü ANSEL kaydedicisinin 6. biti data sheetinde x olarak geçmektedir.Bunun anlamı x yerine istediğimiz sayının yazılabilmesidir.

Bu kodu yazmadan önce dönüşüm işlemini M_B arkadaşımızın dediği gibi yaptım ama o şekilde çalışmadı.Sanırım 620 sayısını program bizim istediğimiz şekilde anlamıyor.Onun yerine yazacağımız sayıyı binary olarak yazdığımızda sorun kalmadı.
Tekrar teşekkür ederim ilgilenen arkadaşlara...