avatar_ete

Matematik Operatörlerin Kullanımı

Başlatan ete, 25 Aralık 2011, 14:12:28

ete

PBP matematiğinde gerek işlemlerdeki bit kısıtlaması ve gerekse negatif ve ondalıklı sayıların olmaması nedeni ile bazı operatörler geliştirilmiş ve işlemlerin biraz daha kolaylaştırılması sağlanmıştır. Burada en çok kullanılanlara bir göz atacağız.

*/ operatörü;
16 bit işlemlerde iki sayının çarpılması sonucu elde edilecek olan en azından 32 bitlik sayının Byte0 kısmının atılarak kalan  diğer bytelarının bir değişkene yerelştirilmesini sağlar. BUşekilde sayı 256 ya bölünmüş gibi olur.
Örnekle açıklayalım.
2300 * 4500 işleminde sonuç  10.350.000 sayısıdır. Bu işlemi */ operatörü ile yaparsanız;
2300*/4500 = 40.429 sayısını elde edersiniz. BU sayı 10.350.000 syısının 256 ya bölünmüş halidir (Tam sayı kısmı).
Aslında hex sayılar kullanırsanız sonucu daha mantıklı görebilirsiniz.
2300 * 4500= $9DEDB0
2300 */4500=$9DED  (B0 atılmış oldu)

** Operatörü:
Buda bir 32 bit çarpma işlemidir. Ancak sonuç dan yalnızca 2 adet high byte alınır. İlk iki byte göz ardı edilir.
Örnekle açıklayalım;
2300 * 4500 çarpım sonucu 10.350.000 idi. Aynı işlemi ** operatörü ile yaparsak;
2300 ** 4500 = 157
Aslında bu işlem 48 bitlik bir çarpmaya imkan tanır ve sonucun yalnızca üst iki byte'ını alır. HEX formatında daha kolay gözükür.
2300*4500=$9DEDB0
2300 ** 4500 = $9D   ($EDB0 atılmış oldu) bu ise sayının 65536 ya bölünmüş halini verir.

// operatörü (Mod alma işlemi);
Br sayının bir başka sayıya bölündükten sonra kalan değeri size verir ve matematikte buna modülüs yada mod alma işlemi denilmektedir.
4500//2300 =2200  4500 sayısını 2300 böldük. Kalan 2200 olarak bulunmuş oldu.

Shift Yani  Bit Kaydırma İşlemleri; Sola Kaydır için << işareti ve  sağa kaydır için  >> işareti kullanılır.
Bir sayıyı 1 bit sola kaydırırsanız o sayıyı 2 ile çarpmış olursunuz. %00000001 sayısı (desimal 1) << 1 şeklinde ki bir ifadenin sonucu %00000010 şeklinde olur ve değeri desimal olarak 2 dir. Bunuda bir bit sola kaydırırsak değeri %00000100 olacak idi.
Format  SAYI << kaydırılacak bit sayısı   Örnek 16 sayısını 3 bit sola kaydırlaım  16 << 3 şeklinde yazılır.

Aynı şekilde soldan sağa kaydıma işlemi ise  sayının 2'ye bölünmesi anlamına gelir.  %10000000 sayısını (desimal 128) 2 bit sağa kaydıralım  %10000000 >>2  işlemi sonucu %00100000 olarak bulunur ki buda 128 sayısının 2 defa 2 ye bölünmesi anlamına gelir. SOnuç 32 olarak bulunacaktır.

DCD Operatörü;
Decoded bit sayısı anlamına gelir. Bir sayının herhangi bir bitini set etmekte kullanılır.
Elimizde 37 şeklinde bir sayı olsun. Sayı ne olursa olsun bu sayının 6 nolu bitini set etmek istersek;
SAYI=SAYI+ DCD 6 şeklinde bir komut kullanmamız yeterlidir.
SAYI=DCD 2 eşitliği bize sayı değişkenine %00000100  değerini yerleştirir.

DIG operatörü : Desimal dijit operatörü diyede adlandırılır. Her hangi bir sayının desimal hanelerinin alınmasını sağlar.
DIG 0 birler hanesini,
DIG 1 onlar hanesini
DIG 2 yüzler hanesini alır ve gerekirse bunlar ayrı birer değişkene eşitlenirler.
SAYI 123 olsun
DIG 0 işlemi bize 3 sayısını, DIG 1 işlemi bize 2 sayısını ve DIG 2 işlemide bize 1 sayısını verecektir.

DIV32 operatörü;
PBP da çarpma işlemi aslında 32 bitlik bir işlemdir ama hiç bir zaman 32 bitlik sonuca ulaşamazsınız. Ama sonuç bir ara hafızada tutulur. İşlemin devamında bu elde edilen 32 bitlik sonucu bir başka sayıya bölmek isterseniz DIV32 komutunu kullanabilirsiniz.
C=2300 * 4500 işlem sonucu 10.350.000 dir ancak siz bunu bir değişkene yazamadağınız gibi sonuca ulaşma imkanınızda yoktur. Ancak sonuç bir ara hafızada tutulur. Şayet o işlmin devamında DIV32 1000 komutunu yazarsam sonuç bana 10.350 olarak gelecektir. Yapalım hemen;
C=A * B (2300 x 4500)
C=DIV32 1000
C=10350 olarak bulunur.

DIV32 komutu çarpma işleminden hemen sonrasında yer alan satırda verilmelidir. Arada başka işlemler yaparsanız çarpım sonucu otomatik olarak unutulacak yada bozulacaktır.


NCD Operatörü;
Zaman zaman kullandığım bir işlem dir. NCD Bir sayı içinde en yüksek değerlikli bit'i bulur.
Elimizde SAYI=%01001001 şeklinde bir sayı olsun
C=NCD SAYI  dersek sonuç 7 olarak gelecektir. Zira Sayı değişkeni değerinde en yüksek bit 7 nolu bit dir.
Bitler 1 den başlayıp 8 de biter. Dolayısıyla yukarıdaki değişkende en yüksek değerlikli bit 7 dir.
Bir sayının 7 biti 1 midir diye bakmak isterseniz, IF (NCD SAYI)=7 THEN SAYININ 7 ci biti 1 dir denilebilir.


REV operatörü;
Bu operatör sayının bitlerini yer değiştirir. Yanında yer alan parametre kadar bitin sıralamasını tamamen tersine çevirir. Elimizde SAYI=%11100001 şeklinde bir sayı olsun. Bunu SAYI=SAYI REV 8 şeklinde bir komut kullanır isek;
SAYI=%10000111 şeklinde döner. Dikkatli bakarsanız 1 nolu bir 8 nolu bit olur. 2 nolu bit 7 nolu bite, 3 nolu bit 6 nolu bite, 4 nolu bit ise 5 nolu bit ile yer değiştirir. Yer değiştirme sürerek diziliş 8-7-6-5-4-3-2-1 şeklinde değil 1-2-3-4-5-6-7-8 şeklinde olur.

Matematik operatörleri bu kadar. Birazda lojik operatörlere bakalım.
Basicde bit bazında lojik operatör kullanımı oldukça yaygındır. Sırası ile İnceleyelim;

Bir sayının içindan yalnızca istediğimiz bitleri çekip almak için o bitleri AND (&) işlemine tabi tutarız.
Örnek verelim PORTB nin ilk 4 bitinde 4 adet buton bağlı ve butonlar boşta HIGH da duruyor ve basılan buton LOW oluyor.
Yalnızca butonları bir komut ile okumak istersek
BASILAN=PORTB & %00001111  şeklinde bir komut kullanırız.
Hiç bir tuşa basılı değil ise BASILAN=%00001111 olarak okunacaktır.
PORTB.0 da bulunan tuş basılı ise BASILAN=PORTB & %00001111=%00001110 şeklinde bir değer alacaktır.
Şayet hem PortB.0 hemde PortB.1 aynı anda basılı ise BASILAN=%00001100 şeklinde bir değer alacaktır.

Bir sayının herhangi bir bitini set etmek istersek onu 1 ile OR işlemine tabi tutarız. SAYI=%00000000 olsun Bu sayının 4 nolu biti ile 6 nolu bitini set etmek isterse (diğer bitlere dokunmadan) SAYI=SAYI OR %01010000=%01010000 değerini alacaktır.  Or komutunun işaretli gösterim şekli ise | şeklindedir.

Bir sayının herhangi bir bit'ine konum değiştirmek istersek o biti 1 ile XOR işlemine tabi tutarız.
1 XOR 1=0
0 XOR 1=1 dir.
XOR işaret i ise ^ şeklindedir.   SAYI = SAYI ^2 şeklinde bir komut Sayı değişkenini 2 sayısı ile XOR işlemine tabi tutar. SAYI önceden sıfır ise son değeri 2 olacaktır. Çünki SAYI=%00000000 ^ %00000010=%00000010 şeklinde olacaktır.

Hepsi bu kadar.

Ete

Mucit23

Hocam Çok Teşekkür Ederim tamda istediğim gibi bir yazı paylaşmışsınız. Ellerinize Yüreğinize sağlık
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

F®T

ETE hocam elinize sağlık aslında bir ders serisine bunlarda örneklerle eklenirse daha güzel olur.iyi çalışmalar.
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

zoptrik

Yüreğinize sağlık hocam. Forum mükemmel bir kütüphane oldu şimdiden.
iyi forumlar...
DEHA; İMKANSIZDA MÜMKÜNÜ GÖREBİLMEK DEMEKTİR.GEMİLERİN KARADA DA YÜZEBİLECEĞİNİ SEZMEK, MEHMETLERDEN BIRINI "FATİH" YAPAR...!

ete

Basic de kullanılan ve adına operatör dedğimiz bu komutlardan bazıları gerçekten son derece faydalı ve sıklıkla kullanılıyorlar.
Bu nedenle onları yeniden ele almakta fayda görüyorum. Mesela  " */" operatörü. ADC ölçümlerinde sabit çarpan hesabını yapmakta sıklıkla kullandığımız bir operatör. Bir tanesini yeniden vereyimki bilgi kafanıza tam otursun.
Bir ADC ölçümü yapıyoruz. Ölçüm sonucumuz sonuçta 0-5V girişe karılık olarak 0-1023 olarak değişecektir.
Ölçtüğümüz değer bir Voltmetre sistemine adapte edileck olsun. ADC değeri 1023 olduğunda bana 30V luk bir değeri gösterecek olsun. Yani 0-1023 değer aralığı aslında 0-30V luk bir voltmetredeki gösterge aralığına tekabül edecektir.
0-1023 aralığı sıfır dahil 1024 kademe demek oluyor.  O halde birim gösterilecek volt başına okunan ADC değeri yada okunan her ADC değerinin Volt karılığı için 30V/1024 = 0,0293 gibi bir değer hesaplarız.
Bu durumda okunan değeri bu sayı ile çarparsak bize direk gösterilecek volt değerini vermesi gerekir.
Hemen bir deneme yapalım. ADC den 511 okuduk. Buna 1 ekleyelim 512 oldu. Bunu 0,0293 ile çarpalım 15,00 gibi bir sayı elde ederizki bu 15V anlamına gelecektir. Zaten 512 değeri ADC den okunacak değerin tam orta noktasıdır ve 2,5V karşılığına denk gelir.
Şimdi olaya Pic matematiği açısından bakarsak 0,0293 gibi bir sayıyı işlemlerde kullanamayız. O halde ne yapalım.
Mademki */ işlemi bana 256 ya bölünmüş değeri veriyor o halde ben 0,029 sayısını 256 ile çarparsam  ;
0,0293 x 256 = 7,5  gibi bir değer bulurum. Bunuda virgülden kurtarmak için 10 ile çarparım ve bulduğum değer 75 olur.
O halde ben çarpma işlemini yaparken  * yerine */ operatörünü kullanırsam sonucu 256 ya bölünmüş olarak elde ederim. Ama baştan zaten 256 ile çarptığım için eşitlik bozulmayacaktır. Yalnızca sonradan çarptığım 10 yüzünden sonucu bir kez 10 a bölmem gerekecek.
Şimdi aynı hesabı bu seferde 75 rakamı ile yapalım.
512 * 75 = 38.400 değerini bulduk. Bunu 512 */ 75 şeklinde yapsa idik bulacağımız sonuç 38400 rakamının 256 ya bölünmüş hali olacak idi yani 150 rakamını bulacaktım. Bunuda 10'a bölerek 15 rakamını elde edeceğim.
Gördüğünüz gibi son derece pratik ve kullanışlı bir komut. Bir çok sıkıntıdan kurtarıyor. Her şeyden önemlisi küçük çarpan rakamını (0,0293) büyük rakam haline getiriyor ve ekstra bir işlem yapmadan direk sonucu veriyor bize.

Buradan aklınıza şunu getirmelisiniz. Küçük ama sabit çarpan rakamlarını kullanırken normal çarpma yerine */ operatörünü kullanarak çarpma yapın işiniz kolaylaşsın.

Diyelimki bir sayıyı 0,018 ile çarpanız gerekiyor. Bunu iki şekilde yapmak mümkün. Sayıyı önce 1000 ile çarparız. 18 rakamını elde ederiz. Sonra o sayıyı 18 ile çarpıp sonucu 1000'e böleriz.
İkincisi ise 0,018 sayısını 256 ile çarparım. 4,608 sayısını elde ederim. Bu sayıyı 1000 ile çarpar 4608 sayısını elde ederim.
Çarpma işlemini */ ile yaparak  (SAYI */ 4608 )/1000 şeklinde sonucu bulurum. Biraz daha pratik ve hassas sonuç veren bir hesaplama şeklidir bu.

Ondalıklı sayı kullanamamaktan kaynaklanan problemlerde çarpan olarak kullandığımız sayıyı 10 veya katları ile çarparak büyüttüğümüzü biliyorsunuz. Mesela bir sayıyı 2,54 ile çarpmak yerine 2,54 x 100=254 ile çarpıp sonucu 100 e bölüyoruz. Bazen sabit çarpan epeyce büyük çıkabiliyor. Mesela 2,5432 şeklinde bir sayının bütün ondalık hanelerini kullanmanız gerekebilir.
Bu durumda 2,5432 x 10000 sayısı ile çarpılınca sonuç 25432 şeklinde bir sayı elde edilecektir. Bu sayıyı bir başka sayı ile çarparsanız mesela 3276 sonuç 16 bit sınırlarını aşacaktır. Halbuki siz sabit çarpanı 10000 gibi bir sayı ile çarptınız ve sonucuda aynı sayıya bölerek durumu eşitlemeniz gerekir. İşte burada da DIV32 komutu imdada yetişmektedir.
SAYI=25432 * 3276
SAYI=DIV32 10000
şeklinde iki komut ile sonucu 8.331 olarak bulacaksınız.
SAYI=DIV32 10000 şeklindeki komut sanki havada duruyormuş ve bir yere bağlı değilmiş gibi gözüksede aslında bir önceki satıra bağımlı durmaktadır. Yani SAYI=25432 * 3276=83.315.232 şeklindeki sonuç direk ulaşılamaz isede ara bir hafızada pic tarafından saklanmaktadır. Sonrasında yer alan DIV32 10000 komutu ise bu sayıyı alarak 10.000 rakamına bölmekte ve sonucu yine SAYI değişkenine yerleştirmektedir. Bu da sıklıkla başvurduğumuz bşr hesap şeklidir.

Diğer opratörler ile ilgili daha fazla örnek vermek isterim ancak komutları çok yerinde örneklerle açıklamak gerekir. Aklıma geldikçe yazacağım. Yada bunların kullanım şekilleri ile ilgili örnekler bulursanız buraya koyun açıklamasını yapmaya çalışayım.

Ete

Mucit23

#5
Bu konuyu ele almanız gerçekten beni çok sevindirdi.

Aklıma bir encoderli motordan devir ölçümü örneği geldi. Bende bir tane encoderli DC motor var. Devir hesaplaması için gereken formülleri yazalım. Encoderden gelen palsları Timer1 sayacı ile sayalım. 1Sn de bir timer bir değerinine bakalım
Bendeki motorun encoderi motor mili 1 tur döndüğünde 15 pals veriyordu.

Motorun dakikadaki maximun hızı 10000Rpm/dak olduğunu varsayalım. Encoderde 1 tur döndüğünde 15 pals verdiği için katsayımız 15 olacak.

Timer1 değerin 1 sn içinde gelen pals sayısı 2000 olsun. Biz bu değeri 15'e bölersek 133.3(133) değerini buluruz. Bu 1 sn deki devridir. bu değeri 60 ile çarparsak 133*60=7980 Rpm/dak olur.
Şöyle bir hesaplama daha yapalım daha hassas bir sonuç için neler yapılabilir diyeyim. Yukarıdaki örnekte motor devri 8000RPM olacak şekilde ayarlamıştım.  dakikada 8000 RPM devirle dönüyorsa 1 snde 8000/60=133,33333333333333333333333333333 değeri çıkar yani çok küsüratlı bir sayı. PBP tam sayıyı hesaplamaya kattığı için yukarıdaki örnekte 7980 buldum. Yani aşağı yukarı 20 devir şaşma yapacaktır.
Bu tür sonucu çok küsüratlı olan hesaplamalarda PBP nasıl davranıyor. Hesaplamalarda Sadece Tam sayıyı alıyor. Bu tür hesaplamalarda tam net sonuca ulaşabilirmiyiz. Bunu merak ediyorum
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

ete

Küsürat işini PBP ile alakası yok biliyorsun. Tamamen matematiksel bir olaydır o.
Ne kadar çok küsüratı devreye sokarsan o kadar hassas sonuç alırsın. 133,3 saysı ile işlem yapmak yerine sırası ile;
- 133,33
- 133,333
- 133,3333
şeklinde ondalık ksımı artırarak hesap sonucunun gerçeğe daha yakın çıkmasını sağlarsın.
Çünki gerçek sonuç 133,333333333333333333333 şeklinde küsürat alınıca ortaya çıkmaktadır.

Ete

est32

bi sayı küsüratlı mı çıktı,o zmaan tekrar bir hesaplama yapılabilir.Ben de bunu sıcaklık hesaplarken kendim keşfettim.
8000/60=133

133*60=7980
8000-7980=20

şimdi küsürata bakalım.Küsüratı büyütelim

20*100=2000
2000/60=33

virgülden sonraki iki haneyi görmüş olduk,eğer 1000 ile çarpmış olsaydım üç haneli sonuca ulaşacaktım.
işlem uzar gider

Mucit23

Alıntı yapılan: ete - 26 Aralık 2011, 14:23:44
Küsürat işini PBP ile alakası yok biliyorsun. Tamamen matematiksel bir olaydır o.
Ne kadar çok küsüratı devreye sokarsan o kadar hassas sonuç alırsın. 133,3 saysı ile işlem yapmak yerine sırası ile;
- 133,33
- 133,333
- 133,3333
şeklinde ondalık ksımı artırarak hesap sonucunun gerçeğe daha yakın çıkmasını sağlarsın.
Çünki gerçek sonuç 133,333333333333333333333 şeklinde küsürat alınıca ortaya çıkmaktadır.

Ete


hocam net sonucu almak için tüm sayıyı virgülden kurtarmak gerekiyor öyle değilmi .Fakat küsüratı bukadar çok olan bir sayıda böyle bir işlem nasıl yapılır bilmem ama 16bit bir sayının el verdiği bir sayıla mesela 10000 ile çarpabiliriz. Galiba sonuca en yakın böyle ulaşırız.
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

karbal656

Ete hocam, öncelikle verdiğiniz bilgiler için çok teşekür edrerim. ADC uygulamalarında kullanışlı bir kod paylaşmak istedim. Biraz açıklarsak: örneğin : üst limiti 50v olan bir ölçüm istiyoruz fomüldeki yere degerimizi girdikmi yeterli.
başka hesaplamalara gerek kalmadan haloluyor.
Protonda örnek kod:
ADIn 0, Adval
        Inc Adval         ' adval + 1    
        Adval = (Adval*/50) >> 2  '  (adval * 50)/1024

Başarılar

ooben

#10


DEFINE OSC 4
TRISA=%100001:PORTA=0:TRISB=%00000001:PORTB=0
TRISC=%00001110:PORTC=0
ADCON1=0
FRQ VAR WORD:FRQ=5000
SAK VAR BYTE:SAK=0
TUTH VAR WORD:TUTH=0

TUS VAR BYTE:TUS=0
BIRLER VAR BYTE:BIRLER=0
ONLAR VAR BYTE:ONLAR=0
YUZLER VAR BYTE:YUZLER=0
BINLER VAR BYTE:BINLER=0
ONBINLER VAR BYTE:ONBINLER=0

Y_CAP VAR WORD:Y_CAP=0
HESAP1 VAR WORD:HESAP1=0
Y_CAPONDA VAR WORD:Y_CAPONDA=0

PI_TAM VAR BYTE:PI_TAM=6
PI_ONDA VAR BYTE:PI_ONDA=28

CEVRE_TAM VAR WORD:C[color=red][/color]EVRE_TAM=0
CEVRE_ONDA VAR WORD:CEVRE_ONDA=0

HESAP2 VAR WORD:HESAP2=0
HESAP3 VAR WORD:HESAP3=0

HESAP4 VAR WORD:HESAP4=0

HESAP5 VAR WORD:HESAP5=0
HESAP6 VAR WORD:HESAP6=0
HESAP7 VAR WORD:HESAP7=0
HESAP8 VAR WORD:HESAP8=0
HESAP9 VAR WORD:HESAP9=0
HESAP10 VAR WORD:HESAP10=0
HESAP11 VAR WORD:HESAP11=0
HESAP20 VAR WORD:HESAP20=0
HESAP21 VAR WORD:HESAP21=0
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX



DEFINE LCD_DREG PORTB
DEFINE LCD_DBIT 4
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 2
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 1
DEFINE LCD_BITS 4
DEFINE LCD_LINES 2
PAUSE 500
LCDOUT $FE,1,"SELAM........
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

'XXXXXXXXXXXXXXXXXXXXX EKLENENLER
READ 0,Y_CAP.HIGHBYTE
READ 1,Y_CAP.LOWBYTE



'ON INTERRUPT GOTO ACIL_STOP
'OPTION_REG=%01000000
'INTCON=%10010000
'lcdout $fe,1
Q:
LCDOUT $FE,1,"KALIBRE ICIN #"
LCDOUT $FE,$C0,"IS BILGI ICIN *"
PAUSE 100
YU:
PORTC.7=1
IF PORTC.1=1 THEN GOTO LCDCIKIS
IF PORTC.3=1 THEN GOTO LCDAYAR
PORTC.7=0
GOTO YU


LCDAYAR:
BIRLER=Y_CAP DIG 0:ONLAR=Y_CAP DIG 1:YUZLER=Y_CAP DIG 2:BINLER=Y_CAP DIG 3:ONBINLER=Y_CAP DIG 4
LCDOUT $FE,1,"ycap=",DEC ONBINLER,DEC BINLER,DEC YUZLER,",",DEC ONLAR,DEC BIRLER
PAUSE 500
PORTC.7=0


PAUSE 500 
TUS_TARAMAI:
PORTC.4=1
IF PORTC.1=1 THEN TUS=1 : gosub LCDI
IF PORTC.2=1 THEN TUS=2 : GOSUB LCDI
IF PORTC.3=1 THEN TUS=3 : GOSUB LCDI
PORTC.4=0 : PORTC.5=1               
IF PORTC.1=1 THEN TUS=4 : GOSUB LCDI
IF PORTC.2=1 THEN TUS=5 : GOSUB LCDI
IF PORTC.3=1 THEN TUS=6 : GOSUB LCDI
PORTC.5=0 : PORTC.6=1
IF PORTC.1=1 THEN TUS=7 : GOSUB LCDI
IF PORTC.2=1 THEN TUS=8 : GOSUB LCDI
IF PORTC.3=1 THEN TUS=9 : GOSUB LCDI
PORTC.6=0 : PORTC.7=1
IF PORTC.1=1 THEN TUS=10 : GOSUB LCDSILI
IF PORTC.2=1 THEN TUS=0  : GOSUB LCDI
IF PORTC.3=1 THEN TUS=11 : GOSUB LCDONAYI
PORTC.7=0
GOTO TUS_TARAMAI

LCDI :
pause 50
ONBINLER=BINLER
BINLER=YUZLER
YUZLER=ONLAR
ONLAR=BIRLER
BIRLER=TUS
Y_CAP=ONBINLER*10000+BINLER*1000+YUZLER*100+ONLAR*10+BIRLER*1
LCDOUT $FE,1,"ycap=",DEC ONBINLER,DEC BINLER,DEC YUZLER,",",DEC ONLAR,DEC BIRLER
PAUSE 500
GOTO TUS_TARAMAI

LCDSILI:
Y_CAP=0
ONBINLER=0:BINLER=0:YUZLER=0:ONLAR=0:BIRLER=0:TUS=0
LCDOUT $FE,1,"ycap=",DEC ONBINLER,DEC BINLER,DEC YUZLER,",",DEC ONLAR,DEC BIRLER
PAUSE 500
GOTO TUS_TARAMAI

LCDONAYI:
Y_CAP=ONBINLER*10000+BINLER*1000+YUZLER*100+ONLAR*10+BIRLER*1
LCDOUT $FE,1,#Y_CAP," MM"
LCDOUT $FE,$C0,"ONAYLANDI"
PAUSE 1000
WRITE 0,Y_CAP.HIGHBYTE
WRITE 1,Y_CAP.LOWBYTE
LCDOUT $FE,1,#Y_CAP," YAZILDI"
PAUSE 1000
LCDOUT $FE,1 '..........................................................................
ONBINLER=0:BINLER=0:YUZLER=0:ONLAR=0:BIRLER=0:TUS=0



Y_CAPONDA=Y_CAP DIG 0 'capın 0.bitini
HESAP1=Y_CAP DIG 1 'capın 1. bitini Y_CAPONDA ya atıyoruz "34
HESAP1=HESAP1*10
Y_CAPONDA=Y_CAPONDA+HESAP1:HESAP1=0
Y_CAP=Y_CAP/100
A:
LCDOUT $FE,1,#Y_CAPONDA," YCAP ONDA"
LCDOUT $FE,$C0,#Y_CAP,"  YCAP"
PAUSE 1000


'BURAYA KADAR GİRİLEN DEĞERİ 111,11 Yİ -111 VE -11 OLARAK AYIRDIM 2 DEĞİŞKENE ATTIM
'YARICAP HAZIR FORMUL İÇİN Pİ=6.28 DİYECEĞİZ BUNU ICIN PI_TAM=7:PI_ONDA=28 DEDIK
HESAP1=0
'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
HESAP1=Y_CAP*PI_TAM          'YARICAP * PI TAM CARPIMI
'BU TAMAM
'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
B:
LCDOUT $FE,1,#HESAP1," HESAP1"
PAUSE 1000

'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ

HESAP2=Y_CAP*PI_ONDA/100  'TAM YARICAP İLE PI ONDANIN CARPIMI
HESAP3=Y_CAP*PI_ONDA//100 'TAM YARICAP İLE PI ONDANIN CARPIMINDAN KALAN
HESAP3=HESAP3*10
C:
LCDOUT $FE,1,#HESAP2," HESAP2"
LCDOUT $FE,$C0,#HESAP3,"  HESAP3"
PAUSE 1000
'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
'HESAP4=Y_CAPONDA*PI_TAM  'Y_CAP ONDASI İLE PI_TAM CARPIMI
HESAP4=Y_CAPONDA*PI_TAM/100
HESAP5=Y_CAPONDA*PI_TAM//100
HESAP5=HESAP5*10
D:
LCDOUT $FE,1,#HESAP4," HESAP4"
LCDOUT $FE,$C0,#HESAP5, "HESAP 5"
PAUSE 1000

'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
HESAP6=Y_CAPONDA*PI_ONDA/10000    'YARICAP ONDASI İLE PI ONDASI NIN CARPIMI
HESAP7=Y_CAPONDA*PI_ONDA//10000 'KALANI ALIYORUZ
HESAP7=HESAP7/10
E:
LCDOUT $FE,1,#HESAP6," HESAP6"
LCDOUT $FE,$C0,#HESAP7,"  HESAP7"
PAUSE 1000
'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
CEVRE_TAM=HESAP1+HESAP2
HESAP8=HESAP4+HESAP6

HESAP9=HESAP5+HESAP7




HESAP8=HESAP8/100
F:
LCDOUT $FE,1,#HESAP1,"+",#HESAP2,"=",#CEVRE_TAM,",",#HESAP3 '
LCDOUT $FE,$C0,#HESAP8,",",#HESAP9                           '
PAUSE 5000
HESAP11=CEVRE_TAM+HESAP8
HESAP10=HESAP3+HESAP9
LCDOUT $FE,1,#HESAP8,"+",#CEVRE_TAM,"=",#HESAP11
LCDOUT $FE,$C0,#HESAP3,"+",#HESAP9,"=",#HESAP10
PAUSE 5000

LCDOUT $FE,1,#HESAP11,",",#HESAP10
PAUSE 5000
GOTO F



'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

LCDCIKIS:

end


'yukardaki kod keypad ten girilen 0-655,35 arası sayıyı alarak dairenin çemberini hesaplamaktadır. formul ise r*2*3.14 "yarıçap*2*pi sayısı

yukarıdaki kodu max girilecek sayı 655,35 olarak tasarladım naçizane xxxxx,xxxxx te "yaniiki word " olabilir ama asıl soracagım  (ekte isis te var )
bi yerde hata yaptım ama sadece tahmin ediyorum çoğu zaman doğru sonuçlar almama rağmen neden bazen hata yapıyor. doğru hesaplamıyor yardımcı olurmusunuz
teşekkürler
ooben

Edit; Foruma kod eklerken kod eklentisi kullanın.

ete

Basicte iki türlü dallanma yada bir yerden başka bir yere atlama komutu vardır.
Birincisi GOTO XXX şeklinde kullanılır. Burada XXX gidilecek etiket adıdır. Gittiğniz yerdden dönüş yine goto ile olmalıdır.
İkinci komut ise GOSUB XXX dur. Bu komutta da gidilecek yer XXX etiketidir. Ancak bukumutu kullandığınız zaman oradan dönüşü mutlaka RETURN ile yapmanız gerekir. Gidilenyerden bir başka yere goto ile gidebilirsin ama bu seferde yeni yerden Return ile dönmen gerekir. Bunu yapmazda hep goto ile dönersen program bir yerde tıkanır. Çünki her gosub Stack (yığın) denilen hafızaya ayrıldığı yerin adresini yazar. Return görünce bu adresi oradan alır ve ayrıldığı yere geri döner. Stack da sıfırlanır. Çünki bir adres girdi bir adres çıkmış oldu. Ama sürekli gosub komutu verip de return vermez isen stack bir yerde dolar ve programda ipin ucunu kaçırır. Zira stacknyalnızca gosub için kullanılmaz. Hesaplamalarda da ara hafıza olarak kullanılır.

Senin kusurun bolca Gosub kullanıp hiç return kullanmamış olman. Programını incele ya gosubları kaldırbgoto yap yada gosub ile gittiğn yerden return ile dön.

Pek çok kişi iki komutun farkınıda bilmiyor. Bunuda açıklamak gerek. Bir programda formüle bağlı hesaplama olsun. Bu hesap programın değişik yerlerinde gerekiyor onu bir alt programa yerleştirip oraya sürekli gosub ile giderim ve return ile dönerim.
Programın 100 satırlı bir program olduğunu düşünürsek. Ve hesap işlemide 10 - 45 - 70 nolu satırlarda gerekiyor ise, 10 nolu satırda Gosub hesap yazıp hesap isimli etikete gidersem oradan Return ile dönersem program otomatikman 11 nolu satıra döner. Aynı işi goto ile yaparsam Goto hesap ilengidip oradan goto 11 demem gerekirdi. Ama bu seferde aynı hesap kısmını 45 de kullanınca hesap kısmında bu sefer goto 46 olması gerekirdi. Halbuki gosub hesap ile gidersem ve return ile dönersem program otomatikman 46 ya dönecektir. İşte iki komutun kullanım farkı budur.

Ete

pwm3434

ete hocam bu konuyla ilgili  bir  sorunum   var.

sisteme  gerekli  olan şu;  pot tarafından ihtiyaca  göre ham biligi serçilip ve ldr ham değer  bilgisi pot bilgisine  eşit  olduğu  zaman gerekli  komut  parametreleri aktif  olacak. buraya  kadar  yapabiliyorum sorun  yok  ustalar. varsayalım ki sistemin aktif olma  ldr ham değer bilisi 45 olsun vede sistemin  pasif olma  ldr ham  değer  bilgisi ise 50 olsun. ldr bilgisi sürekli değişiyor  kayma  yapıyor yani  42-43-44-45-46-47-48 bana gerekli olan  42 ile 49 arasında ki ldr ham  değer bilsi okunur  haldey iken  sisten  aktif  olsun 50 vede  yukarısı olduğu  zamanda  pasif  olsun
gerçek  komutları  ekleyeceğim.

aşağıdaki örnek  komutların  isteğim gibi  çalışması  için  hangi komut  değişikliği  yapılması  gerekli
ıf  ldr=potansıyometre  then   
ıf  ldr>=50  then   goto basla
gosub sec
portb=bılgı1
portc=bılgı2
endıf





ooben

gosub ların yerini goto aldı teşekür ederim programın bi kısmını sabah tekrar yaptım gece sanıyorum kafam karışmış buraya son halini koyuyorum .



DEFINE OSC 4
'@ device MCLR_OFF
TRISA=%100001:PORTA=0:TRISB=%00000001:PORTB=0
TRISC=%00001110:PORTC=0
ADCON1=0
FRQ VAR WORD:FRQ=5000
SAK VAR BYTE:SAK=0
TUTH VAR WORD:TUTH=0
'''''''''FRQ VAR WORD:FRQ=5000
'''''''''SAY VAR BYTE:SAY=0
''''''''''DENEME
'''''''''PORTA.3=1:PAUSE 1
'''''''''A:
'''''''''IF FRQ=1000 THEN V
'''''''''SAY=SAY+1
'''''''''IF SAY=10 THEN SAY=0:FRQ=FRQ-10
'''''''''V:
'''''''''HIGH PORTC.0:PAUSEUS FRQ
'''''''''LOW PORTC.0:PAUSEUS FRQ
'''''''''GOTO A
'DEGER VAR BIT:DEGER=0
'ISSAYISI VAR WORD:ISSAYISI=0
'KESI_MM VAR WORD:KESI_MM =65535
'ISADEDI VAR WORD:ISADEDI=0
'MMGIT VAR WORD:MMGIT=0
'UZUNLUK VAR WORD:UZUNLUK=0
'SAY VAR WORD:SAY=0
TUS VAR BYTE:TUS=0
BIRLER VAR BYTE:BIRLER=0
ONLAR VAR BYTE:ONLAR=0
YUZLER VAR BYTE:YUZLER=0
BINLER VAR BYTE:BINLER=0
ONBINLER VAR BYTE:ONBINLER=0

Y_CAP VAR WORD:Y_CAP=0
HESAP1 VAR WORD:HESAP1=0
Y_CAPONDA VAR WORD:Y_CAPONDA=0

PI_TAM VAR BYTE:PI_TAM=6
PI_ONDA VAR BYTE:PI_ONDA=28

CEVRE_TAM VAR WORD:CEVRE_TAM=0
CEVRE_ONDA VAR WORD:CEVRE_ONDA=0

HESAP2 VAR WORD:HESAP2=0
HESAP3 VAR WORD:HESAP3=0

HESAP4 VAR WORD:HESAP4=0

HESAP5 VAR WORD:HESAP5=0
HESAP6 VAR WORD:HESAP6=0
HESAP7 VAR WORD:HESAP7=0
HESAP8 VAR WORD:HESAP8=0
HESAP9 VAR WORD:HESAP9=0
HESAP10 VAR WORD:HESAP10=0
HESAP11 VAR WORD:HESAP11=0
HESAP20 VAR WORD:HESAP20=0
HESAP21 VAR WORD:HESAP21=0
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX



DEFINE LCD_DREG PORTB
DEFINE LCD_DBIT 4
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 2
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 1
DEFINE LCD_BITS 4
DEFINE LCD_LINES 2
PAUSE 500
LCDOUT $FE,1,"SELAM........":PAUSE 500 'FIMA ISMI EKRANDA GOZUKME ZAMANI
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

'XXXXXXXXXXXXXXXXXXXXX EKLENENLER
READ 0,Y_CAP.HIGHBYTE
READ 1,Y_CAP.LOWBYTE



'ON INTERRUPT GOTO ACIL_STOP
'OPTION_REG=%01000000
'INTCON=%10010000
'lcdout $fe,1
Q:
LCDOUT $FE,1,"KALIBRE ICIN #"
LCDOUT $FE,$C0,"IS BILGI ICIN *"
PAUSE 100
YU:
PORTC.7=1
IF PORTC.1=1 THEN GOTO LCDCIKIS
IF PORTC.3=1 THEN GOTO LCDAYAR
PORTC.7=0
GOTO YU


LCDAYAR:
BIRLER=Y_CAP DIG 0:ONLAR=Y_CAP DIG 1:YUZLER=Y_CAP DIG 2:BINLER=Y_CAP DIG 3:ONBINLER=Y_CAP DIG 4
LCDOUT $FE,1,"ycap=",DEC ONBINLER,DEC BINLER,DEC YUZLER,",",DEC ONLAR,DEC BIRLER
PAUSE 500
PORTC.7=0


PAUSE 500 
TUS_TARAMAI:
PORTC.4=1
IF PORTC.1=1 THEN TUS=1 : goto LCDI
IF PORTC.2=1 THEN TUS=2 : GOto LCDI
IF PORTC.3=1 THEN TUS=3 : GOto LCDI
PORTC.4=0 : PORTC.5=1               
IF PORTC.1=1 THEN TUS=4 : GOto LCDI
IF PORTC.2=1 THEN TUS=5 : GOto LCDI
IF PORTC.3=1 THEN TUS=6 : GOto LCDI
PORTC.5=0 : PORTC.6=1
IF PORTC.1=1 THEN TUS=7 : GOto LCDI
IF PORTC.2=1 THEN TUS=8 : GOto LCDI
IF PORTC.3=1 THEN TUS=9 : GOto LCDI
PORTC.6=0 : PORTC.7=1
IF PORTC.1=1 THEN TUS=10 : GOto LCDSILI
IF PORTC.2=1 THEN TUS=0  : GOto LCDI
IF PORTC.3=1 THEN TUS=11 : GOto LCDONAYI
PORTC.7=0
GOTO TUS_TARAMAI

LCDI :
pause 50
ONBINLER=BINLER
BINLER=YUZLER
YUZLER=ONLAR
ONLAR=BIRLER
BIRLER=TUS
Y_CAP=ONBINLER*10000+BINLER*1000+YUZLER*100+ONLAR*10+BIRLER*1
LCDOUT $FE,1,"ycap=",DEC ONBINLER,DEC BINLER,DEC YUZLER,",",DEC ONLAR,DEC BIRLER
PAUSE 500
GOTO TUS_TARAMAI

LCDSILI:
Y_CAP=0
ONBINLER=0:BINLER=0:YUZLER=0:ONLAR=0:BIRLER=0:TUS=0
LCDOUT $FE,1,"ycap=",DEC ONBINLER,DEC BINLER,DEC YUZLER,",",DEC ONLAR,DEC BIRLER
PAUSE 500
GOTO TUS_TARAMAI

LCDONAYI:
Y_CAP=ONBINLER*10000+BINLER*1000+YUZLER*100+ONLAR*10+BIRLER*1
LCDOUT $FE,1,#Y_CAP," MM"
LCDOUT $FE,$C0,"ONAYLANDI"
PAUSE 1000
WRITE 0,Y_CAP.HIGHBYTE
WRITE 1,Y_CAP.LOWBYTE
LCDOUT $FE,1,#Y_CAP," YAZILDI"
PAUSE 1000
LCDOUT $FE,1 '..........................................................................
ONBINLER=0:BINLER=0:YUZLER=0:ONLAR=0:BIRLER=0:TUS=0



Y_CAPONDA=Y_CAP DIG 0 'capın 0.bitini
HESAP1=Y_CAP DIG 1 'capın 1. bitini Y_CAPONDA ya atıyoruz "34
HESAP1=HESAP1*10
Y_CAPONDA=Y_CAPONDA+HESAP1:HESAP1=0
Y_CAP=Y_CAP/100
A:
LCDOUT $FE,1,#Y_CAPONDA," YCAP ONDA"
LCDOUT $FE,$C0,#Y_CAP,"  YCAP"
PAUSE 1000


'BURAYA KADAR GİRİLEN DEĞERİ 111,11 Yİ -111 VE -11 OLARAK AYIRDIM 2 DEĞİŞKENE ATTIM
'YARICAP HAZIR FORMUL İÇİN Pİ=6.28 DİYECEĞİZ BUNU ICIN PI_TAM=6:PI_ONDA=28 DEDIK
HESAP1=0
'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
HESAP1=Y_CAP*PI_TAM          'YARICAP * PI TAM CARPIMI
'BU TAMAM
'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
B:
LCDOUT $FE,1,#HESAP1," tyc-pıtam"'" HESAP1"
PAUSE 1000

'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ

HESAP2=Y_CAP*PI_ONDA/100  'TAM YARICAP İLE PI ONDANIN CARPIMI
HESAP3=Y_CAP*PI_ONDA//100 'TAM YARICAP İLE PI ONDANIN CARPIMINDAN KALAN
HESAP3=HESAP3*10     '10 ile çarpıp tam sayı halıne getırmısım
C:
LCDOUT $FE,1,#HESAP2,"tyc-pion"'" HESAP2"
LCDOUT $FE,$C0,#HESAP3,"  tyc-pion kal"
PAUSE 1000
'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
'HESAP4=Y_CAPONDA*PI_TAM  'Y_CAP ONDASI İLE PI_TAM CARPIMI
HESAP4=Y_CAPONDA*PI_TAM/100
HESAP5=Y_CAPONDA*PI_TAM//100
HESAP5=HESAP5*10
D:
LCDOUT $FE,1,#HESAP4,"c.on*pitam"' HESAP4"
LCDOUT $FE,$C0,#HESAP5,"c.on*pitam kal"' "HESAP 5"
PAUSE 1000

'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
HESAP6=Y_CAPONDA*PI_ONDA/10000    'YARICAP ONDASI İLE PI ONDASI NIN CARPIMI
HESAP7=Y_CAPONDA*PI_ONDA//10000 'KALANI ALIYORUZ
HESAP7=HESAP7/10 '/10 DU
E:
LCDOUT $FE,1,#HESAP6,"yco*pion"' HESAP6"
LCDOUT $FE,$C0,#HESAP7,"yco*pion kal" '  HESAP7"
PAUSE 1000
'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ

CEVRE_TAM= hesap1+hesap2+hesap4+hesap6


HESAP30 VAR WORD:HESAP30=0
HESAP31 VAR WORD:HESAP31=0
HESAP32 VAR WORD:HESAP32=0

cevre_onda=hesap3+hesap5+hesap7
HESAP30=CEVRE_ONDA DIG 0
HESAP31=CEVRE_ONDA DIG 1 :HESAP31=HESAP31*10
HESAP32=CEVRE_ONDA DIG 2 :HESAP32=HESAP32*100

HESAP20=CEVRE_ONDA DIG 3
HESAP21=CEVRE_ONDA DIG 4 :HESAP21=HESAP21*10

CEVRE_TAM=CEVRE_TAM+HESAP20           '+HESAP21

CEVRE_ONDA=0
CEVRE_ONDA=HESAP30+HESAP31+HESAP32




LCDOUT $FE,1,#cevre_tam,",",#CEVRE_ONDA
lcdout $fe,$C0,"cevre tam","CEVRE ONDA"
PAUSE 1000

ooben

upps !!

teşekürlerimi sunarım şu an çalışıyor. gereksiz lcd out komutlarını kaldırırsanız daha hızlı ve güzel olabilir.
hayal gücünüze bırakıyorum ( ihtiyacı olana )

tekrar teşekkürler.
bulent

Powered by EzPortal