avatar_Burak

Operatör problemi

Başlatan Burak, 01 Nisan 2014, 19:22:30

Burak

Hocam Merhaba ;

RPM ölçüyorum ve ekteki programda tek problem oluşturan kısım */ ve * operatörlerinin oluşturduğu problem .  Program bu haliyle çalışıyor . Ama kırmızı ile gördüğünüz kod parçasındaki çarpma operatörünü * ile değiştirince ekranda yanlış bir sonuç görüyorum .

Sebebi nedir acaba ? Nihayetinde */ sonucun orta 16 bitini yani 256'ya bölünmüşünü veriyor . Bana sonucun tam kendisi lazım ki bunu bir sonraki satırdaki time'a 32 bit bölünce istediğimi elde edeyim . Neden çalışması gereken * operatörü yerine */ doğru çalışıyor ?

[NOT : TIME , RPM word değişkenleridir . Time değeri ekranda doğru görüntülebilmektedir . Örneğin 18912 gibi bir sayı görüntülenebiliyor . O konularda , TMR1 ile ilgili sıkıntı yok.]

Teşekkürler .



'------
DISABLE

intblock:

TMR1=0
INTF=0     'RB0/INT FLG

while INTF=0
@ NOP
wend

time=TMR1
rpm=6000*/10000
rpm=div32 time


INTF=0     'FLG

resume

enable
'------
Ω Gens Una Sumus Ω

ete

İki word değişkeni çarpılırken çarpım sonucu şayet word değişken kapasitesini aşıyor ise sonuç hatalı çıkar.
Bu gibi durumlarda 32 bit çarpma yapmak gerekir. Bununda en güzel yolu */ operatörünü kullanmaktır.
Bu operatörle yapılan işlem sonucunda sonuç 32 bit çıkar ama ortadaki 16 bitlik kısım alınır. Bu ise sonucun 256 ya bölünmüş hali demektir.
Örnekle açıklamak gerekir ise
(1475 * 2365)/275 =12685 olarak hesaplanır.
Bu işlemi normal çarpma komutu ile yaparsanız sonuç yanlış çıkacaktır. Zira 1475 x 2365 = 34.905.875 sayısına eşittir ve değeri 32 bit dir. Basic de 32 bit işlem sonuçları  ara hafızada saklanır. Dolayısıyla bu işlemi şöyle yaparsak sonuç doğru bulunur.
TEMP (word) =1475 * 2365
temp=div32 275

aynı işlemi
TEMP=1475*/2365
Temp=Div32 275
şeklinde yapıncada aynı sonucu alırız. Her ne kadar */ operatörü bize 256 ya bölünmüş sonucu versede ardından gelen DIV32 komutu işlemin 256 ya bölünmemiş halini kullandırır.

Ete







Burak

Peki o zaman aynı şekilde işlemi ( * ) operatörü ile yaptığım zamanda doğru görüntülemem gerekmiyo muydu sonucu ?
Ω Gens Una Sumus Ω

ete

Çarpımı normal yapıp bölmeyide normal yaparsan sonuç yanlış olur. Ama çarpımı normal bölmeyi div32 olarak yaparsan sonuç doğru olur. Fark burada.
Tekrarlıyorum. Çarpım aonucu 16 bit den büyük olaa bile ara hafızada tutuluyor sonuç. Bu sonucu kullanmak için div32 ile bölmek gerekir. Normal bölme yaparsan sonuç tekrar 16 bit oluncaya kadar çevrilir ve sonra bölme yapılır.

Ete

Burak

Hocam işte

time=TMR1
rpm=6000*10000
rpm=div32 time


deyince sonuç doğru çıkmıyor ... (Sizin dediklerinize göre çıkması gerek)

time=TMR1
rpm=6000*/10000
rpm=div32 time


şeklinde çarpınca doğru çıkıyor sonuç ...
Ω Gens Una Sumus Ω

ete

#5
Sonucun yanlış çıkmasının sebebi değişken kullanmamış olmandır.
6000 değerini bir değişkene ver (SAY=6000) ve işlemi
RPM=SAY*10000
RMP=DIV32 TIME

şeklinde yap doğru çıkacaktır.

Ete

Burak

Örneğin Time = 19827  , 1dk= 60 * 10^6 us bunuda her ihtimale karşı 6000 * 10000 şeklinde yazarsak sonuç aşağıdaki kod ile

time=TMR1
rpm=6000*/10000
rpm=div32 time


3026 çıkıyor ama ben buradan 11 sonucunu elde etmeyi umuyorum çünkü */ operatörü sonucu 256'ya bölüyor .

time=TMR1
rpm=6000*10000
rpm=div32 time

şekliyle doğru çıkmıyor..  Saçma sapan değerler çıkıyor ekranda rpm'yi yazdırırken , halbuki aynı ekranda time değeri doğru okunuyor .. ..
Ω Gens Una Sumus Ω

Burak

Hocam başka bir forumdan cevap geldi .İki sabitin çarpması pbp optimizasyon kuralları gereği derleme süresince yapılmaktaymış yani , iki sabitin 32 bit çarpımı run-time süresince değil compile time süresince yapılmaktaymış (* operatörü ile yaptığımızda) .. Ama */ operatörü runtime süresince yapıldığından sistem değişkenleri div32 kodu işletilmeden önce hesaplanıp  , yükleniyormuş ve bir sonraki rpm=div32 time kodunda kullanılabiliyor .. Yani 32bit değişkenler elde edilene kadar runtime süresince mcu'yu meşgul ediyor . 32 bit sonucun tamamı elde edilince bir sonraki koda geçiyor ..  ama * operatörü bir derleme süresince bu sayıyı hesaplıyor ve hiçbirzaman sistem değişkenlerine 32 bitlik sonuç yüklenemiyormuş ..
Ω Gens Una Sumus Ω

Burak

Sizede teşekkürler ilgilendiğiniz için .
Ω Gens Una Sumus Ω

ete

Sen önce işlemini gerçek hesap makinası ile yapsanda dorğu sonucu orada görsen ve asıl senin yaptığın hesabın yanlış olduğunu anlasan olmazmı!!!

Sen zannediyorsunki işlemci sonucu 256 ya bölüyor. Hayır bölmüyor. Anlatmaya çalışıyorum ama anlamamakta ısrar ediyorsun. Daha açık anlatayım.
İşlemci açısında şu işlemlerin farkı yok.
RPM= 6000 */10000   ile
RPM=6000 * 10000
Her iki işlem sonucu 32 bit olarak ara hafızada saklanıyor. Yani işlem sonucu= 60000000 şeklinde saklanıyor.
Bu işlemden sonra DIV 32 TIME komutunu kullanır isen bu ara sonuç Time değerine bölünüp sonuç sana veriliyor.
Ama DIV32 komutunu orada kullanmaz  ve rpm=rpm/time  yazarsan bu işlem önce rpm değerinin 256 ya bölünmüş hali alınıp sonra timne değerine bölünerek yapıldığını söylüyorum. Dolayısıyla işlemde bir hata yok.
Hesap makinası ile yaparsan ,
rpm=6000*10000/19827=3026 olarak sonuç alırsınki buda işlemcinin doğru hesap yaptığını gösterir.

Ete

Burak

Tamam hocam her iki operant da sonucu sistem değişkenlerine 32 bit olarak yerleştiriyor ama ardından gelen komuta göre bunu işliyor ve bizim belirlediğimiz bir başka değişkene (veya aynı) atıyor bunu şimdi anladım , ama sizin dediğinize göre ;

time=TMR1
rpm=6000*10000
rpm=div32 time

şeklinde kod uyguladığımızda ekranda rpm değerinin doğru görüntülenmesi gerek ama görüntülenmiyor hiçbir zaman , bir kere bile ..

Ancak ve ancak */ operandı kullanıldığında sonuç ekrana yansıyor .. Sebebininde 2 önceki postumdaki gibi olduğu söyleniyor .
Eğer o sebep yanlış ise doğrusunu herzaman olduğu gibi sizlerden öğrenmek isteriz .
Ω Gens Una Sumus Ω

Powered by EzPortal