4 Tane 7 Segmente virgullu sayı goruntuleme

Başlatan M_B, 09 Mayıs 2008, 19:13:37

M_B

Herkese merhaba
4 tane 7 segmentli dısplayde 12,25 veya 3,54  5,5 veya 4,07 rakamlarını
gostermek ıstıyorum. burda takıldıgım yer virgul kısmını nasıl yapacagım.
( İslemın sonucunun virgullu cıktıgında virgulun konumunu bulmak )
(Tabi oncelikle Float olarak tanımalayacagım. bunu biliyorum. )
Bu konuda fıkrı olan arkadaslardan yardım bekliyorum.  

Tesekkurler
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

Adnankaplan

İki dsplay arasına bir adet led baglayarak yapabilirsin display saat uygulamalarında oldugu gibi...

arslan74

Merhaba,

Önce kullanacağın değişkeni beliremelsin. Eğer float sayı kullanırsan bu sayının tamamını 4 dijite sığmaz. Sayının sadece bir kısmı gözükür. Bu sayını led display de göstermeden önce, bir LCD ekranda göstermeyi dene. Eğer onu başarırsan gerisi kolay. Ondan sonra daha iyi yardımcı olabilirim. şimdi bir şeyler yazsamda anlamassın.


Selamlar

M_B

Merhaba hocam;
benım burda asıl yapmak ıstedıgım sey su
sizin hi-Tech c konu anlatımındaki 10 bolumdeki kısmı ben LCD değilde 4 tane 7 segmentli led te gostermek istiyorum. ( 3,74880 değilde 3,74 gibi gostermek ıstıyorum ) bolum 10 dakı dersınıze ıyıce calıstım ama bır turlu Led displayde gosterme fonksıyonunu bulamdım. ( virgullu olarak )

Burda nasıl bır mantık yol izlemem gerekiyor.
Tesekkurler

Not: Ekrana Virgul nokta koymada sorunum yok. pozisyonunu bulmada sorunum var
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

arslan74

Alıntı yapılan: "M_B"Merhaba hocam;
benım burda asıl yapmak ıstedıgım sey su
sizin hi-Tech c konu anlatımındaki 10 bolumdeki kısmı ben LCD değilde 4 tane 7 segmentli led te gostermek istiyorum. ( 3,74880 değilde 3,74 gibi gostermek ıstıyorum ) bolum 10 dakı dersınıze ıyıce calıstım ama bır turlu Led displayde gosterme fonksıyonunu bulamdım. ( virgullu olarak )

Burda nasıl bır mantık yol izlemem gerekiyor.
Tesekkurler

Not: Ekrana Virgul nokta koymada sorunum yok. pozisyonunu bulmada sorunum var

Merhaba,

Elde ettin bu sayıyı ekrana göndermeden önce nasıl sakliyorsun?

Eğer benim anlatiğim konuyu iyi incelemişseniz. float türünü lcd ekrana göstermeden önce, sprintf fonksiyonu ile onu bir yazı dizisine dönüştüryorum.

Bu yazı dizisinin içinde virgül zaten var. Dizinin içini dolaraşark yerini kolayca bulabilirsin.

Senin tek yapman gerken işlem sadece yazı dizisini senin istediğin formata dönüştüren basid bir fonksiyon yapmak olacak. Aradığın bütün bilgiler yazı dizisinin içinde mevcud.

Selamlar

M_B

Merhaba Hocam;
yardımlarınız ve bilginiz icin teşekkür ederım.
Hocam bir kac yerde takıldım oncelıklık sprinft kullandıgım zaman PIC12F675 kod sıgmıyor. sıgdıramadım. bır de donusumlerde sanırsam hatam var.
Yazdıgım program asagıdadır.  Nerelerde duzetlme yapmalıyım.
Not: Compliler ederken mlapta ayarlardan long+integer+float secenegını secıyorum.

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


#define DATA GPIO0
#define CLK  GPIO1
#define ENB  GPIO2

//Dahili osilator,MCLR direnci yok
// __CONFIG(MCLRDIS&WDTDIS&PWRTEN&INTIO);

// Global degiskenler
float sonuc;
signed int  deger;
unsigned char outstring[4];

//-------- A/D donusum alt programi------
void donusum_yap(void)
{
	ADCON0=0x8F; // A/D donusumu baslat
	while(GODONE!=0); // Donusumun bitmesini bekle
	deger=256*ADRESH+ADRESL;
	sonuc=deger*(5./1023); 
   
}
//--------- veri gonderme kısmı ------------------------
void gonder(unsigned char veri) 
{
  int i;
    for(i = 0; i<4; i++) 
	{  
    		if((veri & 0x08 ) == 0x08 )
     			DATA =1;
    		else
      			DATA =0;
   				veri<<=1;
   				CLK =0;
				DelayUs(20);
   				CLK =1;
  	}
}  


//----------ANA PROGRAM-----------------
main(void)
{
	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

	for(;;){
		donusum_yap();
    	sprintf(outstring," %d",sonuc);
		
				ENB = 0;
		    	gonder(outstring[0]);	// point digit 4 
				gonder(outstring[1]);	// 1 digit	 Right 4 digit
				gonder(outstring[2]);	// 2 digit   Right 3 digit
				gonder(outstring[3]);	// 3 digit	 Right 2 digit
				gonder(outstring[4]);	// 4 digit	 Right 1 digit	
				DelayMs(10);
				ENB = 1; 
			    DelayMs(1000); 

		}
}// Program sonu
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

arslan74

Alıntı yapılan: "M_B"Merhaba Hocam;
yardımlarınız ve bilginiz icin teşekkür ederım.
Hocam bir kac yerde takıldım oncelıklık sprinft kullandıgım zaman PIC12F675 kod sıgmıyor. sıgdıramadım. bır de donusumlerde sanırsam hatam var.
Yazdıgım program asagıdadır.  Nerelerde duzetlme yapmalıyım.
Not: Compliler ederken mlapta ayarlardan long+integer+float secenegını secıyorum.

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


#define DATA GPIO0
#define CLK  GPIO1
#define ENB  GPIO2

//Dahili osilator,MCLR direnci yok
// __CONFIG(MCLRDIS&WDTDIS&PWRTEN&INTIO);

// Global degiskenler
float sonuc;
signed int  deger;
unsigned char outstring[4];

//-------- A/D donusum alt programi------
void donusum_yap(void)
{
	ADCON0=0x8F; // A/D donusumu baslat
	while(GODONE!=0); // Donusumun bitmesini bekle
	deger=256*ADRESH+ADRESL;
	sonuc=deger*(5./1023); 
   
}
//--------- veri gonderme kısmı ------------------------
void gonder(unsigned char veri) 
{
  int i;
    for(i = 0; i<4; i++) 
	{  
    		if((veri & 0x08 ) == 0x08 )
     			DATA =1;
    		else
      			DATA =0;
   				veri<<=1;
   				CLK =0;
				DelayUs(20);
   				CLK =1;
  	}
}  


//----------ANA PROGRAM-----------------
main(void)
{
	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

	for(;;){
		donusum_yap();
    	sprintf(outstring," %d",sonuc);
		
				ENB = 0;
		    	gonder(outstring[0]);	// point digit 4 
				gonder(outstring[1]);	// 1 digit	 Right 4 digit
				gonder(outstring[2]);	// 2 digit   Right 3 digit
				gonder(outstring[3]);	// 3 digit	 Right 2 digit
				gonder(outstring[4]);	// 4 digit	 Right 1 digit	
				DelayMs(10);
				ENB = 1; 
			    DelayMs(1000); 

		}
}// Program sonu

Merhaba,

Öncelikleri sorunlarını tek tek çözelim. En başta kod sığmadığını söylemişsiniz. Onun en basid çözümü hazfızası daha yüksek olan PIC kullanmaktır. Hafızası yüksek bir PIC kullanırsanız bu sorunuzu halletmiş olursunuz. Örneğin 16f628,16f648, 16f876 gibi picler olabilir. Hatta 12f675 kılıfta 4k'lik PIC ler onuda kullanabilirsiniz.
Bu işlemden sonra kodunuzun düzgün çalışıb çalışmadığını incelersiniz. Düzgün çalışmayan bir yer var ise hep beraber inceleriz, sonrada çözmeye çalışırız. Hafızası yüksek PIC de bir programınız düzgün çalıştırdıktan sonra programda ne gibi düzeltmeler yaparak hafızasını azaltabiliriz kısmına daha sonra bakarız.

Selamlar

M_B

Merhaba Hocam;
Yardımlarınız dogruktusunda isi cozmeye basladım.
Sayenızde ilerleme kaydettım.
Kod sıgmadıgı ıcın dedıgınız gıbı Entegreyi degiştirdim ve sizin
10 bolumdeki uygulamanızı baz alarak degısıklık yaparak yenıden programı düzenledim.
Virgul kısmının nasıl bulunacagını ogrendım. Programın son halı
asagıda. ( Simulasyonda calısıyor. Entegre elımde olmadıgı ıcın henuz
gercekte deneyemedım. )
Sımdıki problemım bu ıse programı PIC12F675 e gore duzenleme yapmam gerekıyor.
Neden bu işlemciyi seciyorsunuz dersenız 1.si elimde var  degerlendirmek istiyorum
2.si mınımum malzeme ile yapmak. 4 dısplay olarakta elimde MC14499P ile yapılmış display katı var
onuda degerlendirmek istiyorum.
Duzenledıgım programda
unsigned int	adc_val;
        float	Volt;
  	adc_val = read_adc();
	Volt = ((5./1023)*adc_val)*7; 
	sprintf (outString," %lf V.", Volt ); kod blugunu  


baska nasıl yapabilirim. Bu işlem hafızada cok yer kaplıyor. Float olmasından dolayı
Bu konudaki fikriniz nedir. Nasıl bır yol mantık izlemem gerekiyor.

Tesekkurler


Not: Sonradan farkettim ki 12,25 ile 3,25 yazdırmam gerektigi zaman
virgulun konumu hep aynı yerde o yuzden MC14499P ye gidecek nokta kısmı hep sabit kalacak
ornegin
     gonder(2); // yazarak hep aynı yerde nokta cıkmasını saglıyor.
bu virgul olayı sayesınde bir seyler daha ogrendim.  Simdilik bu projemde virgul 
konumunu bilmem gerekmiyor.  

ama     sprintf (outString," %lf V.", Volt ); bu işlemiyapmak gerekiyor.
outString[] ={   } volt degerini yazdırmak ısımı goruyor.

Not2: Programın son hali ( Su an bunu kullanmayacam sadece bir seyleri iyice pekiştirmek icin
uzerınde calıstım.

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

#define DATA RB1
#define CLK  RB2
#define ENB  RB0

// Global degiskenler
	unsigned char outString[6];


// ************************************************
// 				ADC OKUMA ALT PROGRAMI
// ************************************************	
read_adc(void)
{
	unsigned int val;

	ADIF = 0; 	//Clear ADIF bit
	ADGO=1;		// initiate conversion on the selected channel
			
	while ( ADGO || !ADIF )
		continue;
		
	val = ADRESL;
	val += ((unsigned int)ADRESH * 256);
	return val;
}
// --------------------- PROGRAM SONU --------------------

//--------- veri gonderme kısmı ------------------------
void gonder(unsigned char veri) 
{
  unsigned char i;
    for(i = 0; i<4; i++) 
	{  
    		if((veri & 0x08 ) == 0x08 )
     			DATA =1;
    		else
      			DATA =0;
   				veri<<=1;
   				CLK =0;
				DelayUs(20);
   				CLK =1;
  	}
}  

// -------------------- ANA PROGRAM BASLANGICI -----------------
void main(void)
{

	TRISA = 0b00000001; // RA0 input
	TRISB = 0;
	/***********************************************************************
		ADC ön ayarları
	***********************************************************************/
		CHS2 = 0;
		CHS1 = 0;
		CHS0 = 0;
	
		ADCS1 = 1;
		ADCS0 = 1;
			
		ADFM = 1; 
		
		PCFG0 = 0;
		PCFG1 = 1;
		PCFG2 = 1;
		PCFG3 = 1;
		
		ADON = 1;

	/**********************************************************************/

	
while(1)
	{
	
	unsigned int	adc_val;
    float	Volt;

  	adc_val = read_adc();
	Volt = ((5./1023)*adc_val)*7; 
	sprintf (outString," %lf V.", Volt );
	
/ --------------------- VIRGULUN HANGI HANEDE OLDUGUNU BULUYOR ------------------				
	if(outString[2]=='.')
		{
		outString[0]=outString[2]; 
		outString[2]=outString[3];
		outString[3]=outString[4];
		outString[4]=outString[5];
		}


	if(outString[3]=='.')
		{
		outString[0]=outString[3];
		outString[3]=outString[4];
		outString[4]=outString[5];
		}

/ ------------------- VIRGUL KONUM BULMA SONU -------------------------------
				ENB = 0;
			  	gonder(2);	// point digit 4 MC14499P entegresınde nokta koymak ıcın
				gonder(outString[1]);	// 1 digit	 Right 4 digit
				gonder(outString[2]);	// 2 digit   Right 3 digit
				gonder(outString[3]);	// 3 digit	 Right 2 digit
				gonder(outString[4]);	// 4 digit	 Right 1 digit	
				DelayMs(10);
				ENB = 1; 
			    DelayMs(100); 
	}
} // PROGRAM SONU
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

arslan74

Adım adım gidelim.

Önce ADC cevimi verdiğim koda göre yap.

unsigned int adc_read (void){

	unsigned int i;
	
	ADIF = 0; 	//Clear ADIF bit
	ADGO=1;		// initiate conversion on the selected channel
			
	while ( ADGO || !ADIF )
		continue;
			
	DelayUs(100);
		
//	i =  ADRESL + (ADRESL<<8);	// return 8 MSB of the result
	p = (char*)(&i);
	*(p++) = ADRESL;
	*p = ADRESH;

	return i;

}


ve bu fonksiyonu kullan

unsigned int 
convert2mV(unsigned int adc){
	
	unsigned int val,temp;

//  U[mV] = ((5*adc - 5*adc/64) - 5*adc/128)
	temp = val = (5*adc);
	val -= temp >> 6;
	val -= temp >> 7;
		
	return	val;
}


sonra tekrar başka düzeltmeler yapacağız.

Selamlar

arslan74

Merhaba,

unsigned char outString[16];

sprintf (outString,"%f",Volt );


Şeklinde dene.

Birde sting uzunluğunu biraz uzun tutarsan, taşma hatalarına karşı tedbir almış olursun. Kullanmayacağın Fazladan V karterini string de yazdırmak, sana fazladan yer kayıb ettirecek.

Selamlar

M_B

Merhaba Hocam;

unsigned int 
convert2mV(unsigned int adc){ 
    
   unsigned int val,temp; 

//  U[mV] = ((5*adc - 5*adc/64) - 5*adc/128) 
   temp = val = (5*adc); 
   val -= temp >> 6; 
   val -= temp >> 7; 
       
   return   val; 
}

Hocam bu fonksiyonun nasıl calıstıgını ne yapmak ıstedıgını anladım.
Bu benım ısıme cok guzel yarayacak. Yardımlarınız sayesınde daha guzel ögrenıyorum.
Tekrar teşekkür ederım.
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

arslan74

Alıntı yapılan: "M_B"Merhaba Hocam;

unsigned int 
convert2mV(unsigned int adc){ 
    
   unsigned int val,temp; 

//  U[mV] = ((5*adc - 5*adc/64) - 5*adc/128) 
   temp = val = (5*adc); 
   val -= temp >> 6; 
   val -= temp >> 7; 
       
   return   val; 
}

Hocam bu fonksiyonun nasıl calıstıgını ne yapmak ıstedıgını anladım.
Bu benım ısıme cok guzel yarayacak. Yardımlarınız sayesınde daha guzel ögrenıyorum.
Tekrar teşekkür ederım.

Merhaba,

Fonksiyon adında anlaşılacağı gibi elde ettiğin ADC değerini MiliVolt (convert to miliVolt) değerine gönüştürür.

Örnek kullanımı söyle yapabilirsin.

unsigned int adc_val;

adc_val = convert2mV( read_adc() );


Selamlar

M_B

Merhaba Hocam;
Verdiginiz fonksiyonla ilgili bir  soru sormak istiyorum.
Bir turlu anlayamadım.
Mumkunse acıklayabilirmisiniz.
2-3 kere de gostericiler ( pointer ) konusu okudum

anlayamadım kod
p=(char *)(&i) ; 
*(p++) = ADRESL;
*P = ADRESH;

simdi hocam burda (&i) bu kısım i nin bulundugu adresi veriyor değilmi.
( & Adres alma isleci. ) (char *)(&i) komple oluncada  i yi mi veriyor char tipinde .
* ve & kullanılınca kendisi oluyor ( yanlıs anlamıs olabilirim )
p = i ;  gibi oldu.
2 gundur dusunuyorum kavrayamadım.

Tesekkurler


Not: Projem az kaldı calıstırınca calısan programı koyacam.
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

M_B

Merhaba Hocam;
Verdiginiz fonksiyonla ilgili bir  soru sormak istiyorum.
Bir turlu anlayamadım.
Mumkunse acıklayabilirmisiniz.
2-3 kere de gostericiler ( pointer ) konusu okudum

anlayamadım kod
p=(char *)(&i) ; 
*(p++) = ADRESL;
*P = ADRESH;

simdi hocam burda (&i) bu kısım i nin bulundugu adresi veriyor değilmi.
( & Adres alma isleci. ) (char *)(&i) komple oluncada  i yi mi veriyor char tipinde .
* ve & kullanılınca kendisi oluyor ( yanlıs anlamıs olabilirim )
p = i ;  gibi oldu.
2 gundur dusunuyorum kavrayamadım.

Tesekkurler


Not: Projem az kaldı calıstırınca calısan programı koyacam.
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

arslan74

Alıntı yapılan: "M_B"Merhaba Hocam;
Verdiginiz fonksiyonla ilgili bir  soru sormak istiyorum.
Bir turlu anlayamadım.
Mumkunse acıklayabilirmisiniz.
2-3 kere de gostericiler ( pointer ) konusu okudum

anlayamadım kod
p=(char *)(&i) ; 
*(p++) = ADRESL;
*P = ADRESH;

simdi hocam burda (&i) bu kısım i nin bulundugu adresi veriyor değilmi.
( & Adres alma isleci. ) (char *)(&i) komple oluncada  i yi mi veriyor char tipinde .
* ve & kullanılınca kendisi oluyor ( yanlıs anlamıs olabilirim )
p = i ;  gibi oldu.
2 gundur dusunuyorum kavrayamadım.

Tesekkurler


Not: Projem az kaldı calıstırınca calısan programı koyacam.

Merhaba,

Sana yaptığım olayı anlatayım.

i değişkeni unsigned int türünden ve 2 byte( 16 bit ) uzunluğundadır. elde ettiğimiz ADC değeri 10 bit değerindedir. Seninde bildiğin gibi kullandığın PIC 8 bitlik mimariye sahip bir işlemci o yüzden 10bitlik bir değeri tek bir registerde sakliyamiyor. ADC düşük değerini ilk 8biti (1byte) ADRESL da, son iki biti ADRESH tutulur. Benim yaptığım olay ise ADCnin düşük byte değerini i nin düşük değerine, ADC'nin yüksek byte değerini i nin yüksek byte'tına doğrudan atama şeklinde ile yapiyorum. Yani hiç matematiksel işlemlere girmeden yapiyorum. Hem hızlı oluyor, hemde daha az yer kapliyor.

Selamlar