PIC'de ROM yeterli değil

Başlatan musti463, 04 Ekim 2013, 01:19:52

DumrulBey

Alıntı yapılan: musti463 - 05 Ekim 2013, 12:56:54
Çok teşekkürler hocam vaktim var,elimde de CCS C ile PIC Programlama kitabı var Serdar Çiçek'in
Estağfirullah, henüz teşekkürü hak edecek bir yardımımız dokunmadı. Ama vaktinin olması ve de bir kitaba sahip olman güzel. Ancak o kitap sana programlamanın temelleri konusunda çok yardımcı olamayabilir. Bu konuda Ali Çehreli'nin ücretsiz çevrimiçi kitabından faydalanabilirsin.

Alıntı yapılan: musti463 - 05 Ekim 2013, 12:56:54
Koddaki if yapılarının içerisindeki sabitleri aşağıdaki resimdeki tablodan aldım.aynı blokları çok defa kullandığım için baya bir yer israfı yapmışım :) Yeni yöntemde aşağıdaki her sütundaki değerleri dizi içine attım.tek if kullanıp değerleri bu dizilerden çağırıyorum.
Bu da güzel ama sen de itiraf etmişsin ki bazı verileri dizide toparlamanın bellek kullanımına çok faydası olmayacağı ortada. Allegro'nun dediği gibi mümkün olduğunca float'dan kurtulmamız gerekiyor. Bakalım bunu becerebilecek miyiz... ::)

Şimdi...

En genel hatları ile ilk olarak halletmemiz gereken, malum tablonun ilgili sütunundaki hesaplamaları yapan if() bloğunda. Hesaplamadım ama sadece buradaki float karşılaştırmaları bile ciddi sistem kaynağı (sadece bellek değil, MIPS'den de çalar) harcayacaktır. Peki biz bundan kurtulabilir miyiz? Bence mümkün ama adım adım gidelim:
void main(){
  unsigned long int uzunluk = 129; // 129, 256, 383, 512, 770, 1023;
  float32 uzunluk_voltaj, uzunluk_islem;
  
  uzunluk_voltaj = 0.0048828125 * uzunluk;
  if(uzunluk_voltaj < 0) uzunluk_voltaj = 0;
  uzunluk_islem = uzunluk_voltaj * 5.87 + 10.8;
  
   if(uzunluk_islem >= 10.8 &&
     uzunluk_islem <= 14.5) {           
     
     // 0 < uzunluk < 130
   
  } else if(uzunluk_islem > 14.5 &&
            uzunluk_islem <= 18.15) { 
            
    // 129 < uzunluk < 257
  
  } else if(uzunluk_islem > 18.15 &&
            uzunluk_islem <= 21.8) {
    
    // 256 < uzunluk < 384
  
  } else if(uzunluk_islem > 21.8 &&
            uzunluk_islem <= 25.5) {
    
    // 383 < uzunluk < 513
  
  } else if(uzunluk_islem > 25.5 &&
            uzunluk_islem <= 32.85) {
    
    // 512 < uzunluk < 770
  
  } else if(uzunluk_islem > 32.85 &&
            uzunluk_islem <= 40.15) {
            
   // 769 < uzunluk < 1024
  
  }
}

Yukarıdaki kod, bahsettiğim if() bloğunun sadeleştirilmiş halidir. Her koşulda, 2 adet float değeri arasında olup olmadığı sorgulanmakta. Ancak dikkat ederseniz biz uzunluk_islem yerine ADC'den okunan uzunluk değeri ile de bu işi halledebilirdik. Böylece mikrodenetleyiciyi, komut setinde yer almayan float compare komutlarının eş değer tonlarca satır ile kanımca muhatap etmeyeceğiz. Biz bu kodu x86 PC'leri için derleseydik her sorgu bu kadar kısa olacaktı:
fld	float ptr -4[EBP]
		fcomp	qword ptr FLAT:.rodata[0A9h]
		fstsw	AX
		sahf
		jb	LA6
		fld	float ptr -4[EBP]
		fcomp	qword ptr FLAT:.rodata[0BFh]
		fstsw	AX
		sahf
		jp	LA6
		jbe	L142


Özetle aşağıdaki gibi yaparak kodlamaya devam etmeyi salık veriyorum. İçindeki if()'ler için ise switch case kullanılması iyi olacaktır. Çünkü bu kadar değerin tek tek sorgulanması gereksiz. Oysa bir seferde ilgili bölüme dallanabilir.
  if(uzunluk < 130) {
                                                // 129
  } else if(uzunluk > 129 && uzunluk < 256) {
                                                // 256
  } else if(uzunluk > 255 && uzunluk < 383) {
                                                // 383
  } else if(uzunluk > 382 && uzunluk < 512) {
                                                // 512
  } else if(uzunluk > 511 && uzunluk < 769) {
                                                // 769
  } else if(uzunluk > 768 && uzunluk < 1023) {
                                                // 1023
  }

Başarılar...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)

musti463

@DumrulBey çok teşekürler dediklerinizi uygulayacağım
Mustafa Emir SADE

Burak B

#32
Benden de bir ipucu

Aşağıdaki kod 216 byte yer kaplıyor.
   yuk_islem=(yuk_voltaj-2.385)*19.12045889;
   yuk_gosterge=(yuk_voltaj-2.385)*19.12045889;

Yukarıdaki gibi tekrarlayan hesaplamaları aşağıda verdiğim örnekteki gibi #define makroları ile tanımlarsan.

Aşağıdaki kod 122 Byte yer kaplıyor.
#define YUK_HESAPLA(x) (x-2.385F)*19.12045889
...
...
yuk_gosterge = yuk_islem = YUK_HESAPLA(yuk_voltaj);


Tekrarlayan her satır için %50-60'a yakın bir alan kazancın olur.  Yanlış saymadıysam senin kodunda bunun gibi 4 tekrar var.
Kaba bir hesapla 4*216=864byte neredeyse 1K yer tutan kodun 4*122=488Byte kadar bir boyut optimizasyonuna uğruyor. Bu kısımlar daha da optimize edilebilir.
Ayrıca float kullandığın için tüm sabitlerini tablolara taşımalısın. Böylece derleyicinin bunları tekrarlamasını önlemiş olursun. Mesela bu işlem benim verdiğim örneğe uygulanırsa o kod daha da optimize bir hal alabilir.

Ayrıca böyle bir MCU için bu tip bir kodlama fazla lüks. Eğer kayan nokta kullanacaksan Cortex-M3(M4)' lere yönelmelisin. Yok ben bunda kalacam diyorsan @mufit_sözen hocamın bahsettiği fixed point sayıları incele. Fixed point integer demek değildir. Sadece nokta oynamaz. Noktanın nerde duracağını bilin yeter.



"... a healthy dose of paranoia leads to better systems." Jack Ganssle

musti463

@ByteMaster teşekkürler hocam
Mustafa Emir SADE

salihonur

#34
Alıntı yapılan: yldzelektronik - 04 Ekim 2013, 14:10:30
   uzunluk_islem=uzunluk_voltaj*5.87+10.8;//////////formüllerde kullanılacak
   uzunluk_gosterge=uzunluk_voltaj*5.87+10.8;//////////grafik ekranda kullanılacak

bunlar ilk bakışta göze çarpanlar.

Bir de, sadece matematik işleminin gerçekleştirilip  başka kullanılmayan float değişkenler var. Bunlar için bir tane global float değişken tanımlayıp, ilgili kısımda işlemden önce sıfırlayıp, işlemi gerçekleştirmek gerek.

Aynı işlemi birden fazla yapmak yerine adım adım yürütmeli.

Diyelim ki;

satis fiyati=alis fiyatı*kar*kdv*otv*gumrük gibi işlem yapacak, kdvsiz, ötvsiz gümrüksüz ayrı ayrı işlemleri ekrana yazdıracaksınız:

alis = 100;
satis = alis * 1.2;    //%20 kar
printf("Satis fiyati %g", satis);
satis = satis* 1.18;
printf("Kdv dahil satis fiyati %g", satis);
satis = satis* 1.27;    //ÖTV salladım %27
printf("OTV dahil satis fiyati %g", satis);
satis = satis* 1.2;
printf("Gumruk dahil satis fiyati %g", satis);



Eğer yuvarlama da yapacaksanız, mesela satış fiyatım hiçbir zaman 255'den yukarı çıkmayacaksa

yuvarlanmis_8bit = (int)satis;

eğer 65535'i geçmeyecekse

yuvarlanmis_16bit = (int16)satis;

gibi yapmak oldukça optimize eder.