DEĞİŞKEN TAŞMASI

Başlatan Diagnosis3, 12 Şubat 2017, 18:54:24

Diagnosis3

Sayın Ete hocam;

Bizim tanımladığımız değişkenlerde taşma oluştuğu zaman, bunu bildiren bir flag var mıdır.

Örneğin Byte değişkeni tanımladık ve sürekli buna bir sayıyı toplayarak gidiyoruz, 255'te taşma yaptığından haberdar olabilir miyiz.

ete

Otomatik haber verme sistemi yok. Sen takip edeceksin.
Ete

Diagnosis3

Teşekkür ederim hocam.

Peki şöyle bir işlemde takip nasıl yapılabilir.

DIM SAY AS BYTE
DIM ARALIK AS BYTE

BASLA:
SAY=SAY+ARALIK (Aralık değişkeni 2 ile 20 arasında)

Böyle bir durumda say değişkeni 255 değerini aştığında bir başka değişkeni 1 artırması için nasıl bir yordam kullanabiliriz? Burada beni zorlayan durum aralık değişkeninin sabit olmayışı.

ete

Say=say+aralık işleminde her sonuç bir öncekinden daha büyük olmalıdır. Çünki bu bir toplama işlemidir. Ancak taşma olunca sonuç bir öncekinden küçük olacaktır.
Örnek veriyorum.
Say=240 olsun Aralık=10 olsun
Say=say+aralık=250 olur. Bir kere daha yaparsan aynı işlemi say=4 olacaktır. Çünki 250+10=260 eder. Bundan 256 yı çıkartırsan sonuç 4 olarak bulunur.
Buradan da taşma olduğunu anlarsın.
Demekki daima bir önceki say değerini bilmen gerekiyor. Yeni değer öncekinden büyük ise sorun yok ama küçük ise taşma oldu demektir .
Ete

Hattuşa

#4
hocam birde ben fikrimi söylesem;

dim sayı as word
dim Tasti as bit
tasti =0
sayi =0

Main:

sayi.lowbyte =sayi.lowbyte +1

if sayi.highbyet =1 then tasti =1

goto main


burda byte değişkeninin sayımında eğer byte mertebesinde taşma olunca bunu sayi değişkenin 2. bytenden anlayamayız mı? bunun takibinide tasti adlı bir bayrakla kontrol edebiliriz diye düşünüyorum.
yanlışmıyım?

ete

Bir WORD tipi değişkende taşma diye söz konusu değil. Çünki zaten kendisi 16 bitlik sayı taşma ancak 65535 de meydana gelir.
Bu değişkenin LOW Byte kısmı 255i geçince kendisi zaten otomatikman HIGH Byte kısmını bir artırıyor.
Ete

Diagnosis3

Hocam çok teşekkür ederim. Sayenizde büyük bir dertten kurtulmuş oldum. Fakat Pro-TR arkadaşımızın dediği de mantıklı olabilir. Word tipi değişken highbyte ve lowbyte olarak iki farklı değişken gibi kullanılabilir. Sonuçta amaç bir değişkene bağımlı diğer değişkenin değerini 1 artırmak. Lowbyte 255 aşınca highbyte bitini 1 artırdığına göre highbyte değeri artırmak istediğimiz değişken yerine kullanılabilir. Birbirinden kıymetli fikirler.

ete

Amaç ortaya koyulmadığı çin insan öneride bulunmak istemiyor doğrusu. Yoksa 8 bitlik değişken yerin
e direk 16 bit kullansan bu istediğin otomatik yapılıyor zaten. Yapman gereken sadece sayı değerinin 65535'i aşmamasını sağlamak o kadar.
Hatta 18F serisi bir entegre kullanıyorsan LONG tipi değişken kullanıp 32 bitlik sayı bile kullanabilirsin. Bu durumda sayı değerin,4.294.967.295'e kadar ulaşabilir.
Ete


Diagnosis3

Sayın hocam başınızı ağrıtıyorum ama, bir sorum daha olacak. 18F serisinde hardware multiplier modülü var. Buna ait komut MULWF. Bu komutu protonda yazdığımda yeşil rengi alıyor, ki bu da kodun tanındığını gösterir. Fakat nasıl kullanılacağını bir türlü bulamadım. Assembly örneklerden başka Protona ait örnek bulamadım. Bununla ilgili bilginiz var mıdır acaba.

ete

#9
Görmüştüm öyle bir şey ama ilk baktığımda Assembly ile ilgili bir şey deyip incelememiştim.
Bilgim yok maalesef.
Ete

Not:
şimdi baktım hatırladığım doğru ancak birişlem yapmış şöyle;
ARG1 ile ARG2 yi çarpacak,
MOVF      ARG1, W
MULWF    ARG2
Sonucu da PRODH ile PRODL den alıyorsun
Ben 18F45K22 data sheetine baktım. Orada 16bit x 16 bit de mevcut.
Tabiiki her şey assembly de hallediliyor.
Bütün espirisi bu sistemi kullanırsan aritmetik işlemleri daha az kod harcıyormuş.


Diagnosis3

#10
Hocam çok sağolun. Buraya yapıştırıyorum izninizle. 18f serisi için donanımsal çarpmaya ihtiyacı olan olur elbette. Zira normal çarpıma göre 10 kat daha hızlı işliyor.

BASLA:
ESKIACI=SAY
SAY=SAY + 5
SEKTOR=SAY.HighByte
If SEKTOR>6 Then SAY.HighByte=0
ACI = SAY.LowByte

Asm
Movf ACI, W
Mulwf SEKTOR ; ARG1 * ARG2 ->
Movf PRODH,PERIOD
Movf PRODL,CW
EndAsm

PERIOD.LowByte=PRODL
PERIOD.HighByte=PRODH

Print At 1,1, Dec PERIOD
DelayMS 200
Cls
GoTo BASLA

Not: PRODH ve PRODL talep edilirken önce PRODL talep edilmeli. Yoksa PRODH önce istenirse PRODL sıfır olarak geliyor.

Diagnosis3

#11
Hocam ADC için protonun kodunu kullanmam bir süre beklememi gerektiriyor. Aşağıdaki kod da çalışmıyor. Nerede hata yapıyorum acaba inceleyebilir misiniz. Yapmayı amaçladığım iş ise ADC interrupt ile istediğim zamanda tek çevrim sonuç almak. Çünkü farklı 2 kanalı okumaya çalışıyorum.

Device=18F4431

'--------------------------------------CONFIGURATION BITS-----------------------
Config_Start
OSC=HS , FCMEN=OFF , IESO=OFF 'CONFIG1H
PWRTEN=On , BOREN=Off , BORV=20 'CONFIG2L
WDTEN=OFF 'CONFIG2H
PWMPIN=Off , HPOL=High , LPOL=High , T1OSCMX=OFF 'CONFIG3L
MCLRE=On , EXCLKMX=RC3 , PWM4MX=RB5 , SSPMX=RD1 , FLTAMX=RC1 'CONFIG3H
Debug=OFF , LVP=OFF , STVREN=On 'CONFIG4L
CP3=OFF , CP2=OFF , CP1=OFF , CP0=OFF 'CONFIG5L
CPD=OFF , CPB=OFF 'CONFIG5H
WRT3=OFF , WRT2=OFF , WRT1=OFF , WRT0=OFF 'CONFIG6L
WRTB=OFF , WRTC=OFF , WRTD=OFF 'CONFIG6H
EBTR3=OFF , EBTR2=OFF , EBTR1=OFF , EBTR0=OFF 'CONFIG7L
EBTRB=OFF 'CONFIG7H
Config_End
Xtal=40

OSCCON=%00000000

INTCON=%11010001
INTCON2.7=1
INTCON3.3=0

PIE1.6=1
IPR1.6=1


On_Interrupt GoTo KESME
'------------------------------------------------
Declare LCD_Type 0
Declare LCD_DTPin PORTD.0
Declare LCD_ENPin PORTD.4
Declare LCD_RSPin PORTD.5
Declare LCD_Interface 4
Declare LCD_Lines 4
'------------------------------------------------
ADCON0=%00100001
ADCON1=%00010000
ADCON2=%10110110
ADCON3=%11000000
ADCHS=%00000000
ANSEL0=%00000001
ANSEL1=0

Dim ADC As Word

BASLA:
ADC.LowByte=ADRESL
ADC.HighByte=ADRESH
Print At 1,1,Dec ADC
Print At 2,1,Dec ADRESH
Print At 3,1,Dec ADRESL
DelayMS 500
Cls
GoTo BASLA

KESME:
Context Save
Disable
PIR1.6=0
Context Restore
Enable
End
Stop

Hattuşa

hocam adc interrupt oluştuğu anda adresl ve adresh değerlerini değişkene atmalısınız ki doğru ölçüm olsun yani;


BASLA:
adcon0.6 =1
delayus 5
Print At 1,1,Dec ADC
Print At 2,1,Dec ADRESH
Print At 3,1,Dec ADRESL
DelayMS 500
Cls
GoTo BASLA

KESME:
Context Save
Disable
ADC.LowByte=ADRESL
ADC.HighByte=ADRESH
PIR1.6=0
adcon0.6 =0
Context Restore
Enable
End



birde adc kesmesinin ne zaman oluşmasını istiyorsanız go-done yi 1 yapıp picin datsheetinde yazan süre kadar beklemelisiniz. yukarıda ben bekleme süresini afaki verdim.

Diagnosis3

Sanırım Register hatası yapıyorum biryerlerde. Sonuç hala olumsuz.

ete

Registerleri kullanarak ADC okuması yapmak için rehberiniz her zamanki gibi DATASHEET. Neden oraya bakmak kimsenin aklına gelmiyor anlamak gerçekten zor.
Bu işlemci sanki ADC okumaları için yaratılmış. Çok hızlı okuma yapabiliyor.
Data sheet'in 248 inci sayfasında bir ADC okuması için takip edilecek adımlar şunlardır diye adam liste vermiş.

The following steps should be followed to initialize the A/D module:
1. Configure the A/D module:  A/D Modülü ayarlayın diyor. Nasıl olacağınıda madde madde açıklamış
a) Configure the analog pins, voltage reference and digital I/O.  Analog pinleri ayarlayın , Voltaj referansını ve digital giriş çıkışları ayarlayın
b) Select the A/D input channels.  Analog giriş Kanallarını seçin
c) Select the A/D Auto-Conversion mode (Single-Shot or Continuous Loop). A/D Otomatik çevirme modunu seçin tek yada sürekli döngü
d)    Select the A/D conversion clock.  A/D çevirim clock seçin
e)    Select the A/D conversion trigger. A/D çevirim Trigger (tetik) seçimini yapın
2. Configure the A/D interrupt (if required):  Kesme oluşturulacak ise Kesmeyi ayarlayın
a)    Set the GIE bit.  GIE bitini set edin
b)    Set the PEIE bit. PEIE bitini set edin
c)    Set the ADIE bit.  ADIE Bitini Set edin
d)    Clear the ADIF bit. ADIF bayrağını temizleyin (silin)
e)    Select the A/D trigger setting.   A/D Trigger ayarlarını yapın
f)    Select the A/D interrupt priority. Kesme önceliğini seçin
3.  Turn on ADC:  ADC yi aktif edin
a)    Set the ADON bit in the ADCON0 register.  Bunun için ADCON0 registerinde ADON bitini Set edin.
b)    Wait  the  required  power-up  setup  time, about 5-10 us. Power-up setup zamanı kadar bekleyin, yaklaşık 5-10 us
4. Start the sample/conversion sequence:  Örnekleme /Çevrim işlemini başlatın
a)    Sample  for  a  minimum  of  2  TAD  and  start the conversion by setting the GO/DONE  bit. The  GO/DONE   bit  is  set  by  the  user  in software  or  by  the  module  if  initiated  by  a trigger.   2 TAD örnekleme den sonra  GO/DONE bitini set ederek çevrimi başlatın.
b)    If TACQ  is assigned a value (multiple of TAD),then  setting  the  GO/DONE  bit  starts  a sample period of the TACQ
value, then starts a conversion.  Şayet TACQ ya bir değer verilmiş ise (Çoklu TAD) sonra GO/DONE biti set edilerek TACQ örnekleme peryodu başlar ardından çevirm başlar.
5. Wait for A/D  conversion/conversions  to complete using one of the following options: A/D çevrimi için aşağıdakilerden birinin tamamlanmasını bekle
a)    Poll for the GO/DONE   bit to be cleared if in Single-Shot mode. Tekli ölçüm modunda  GO/DONE bitinin sıfırlanmasını bekle
b)    Wait for the A/D Interrupt Flag (ADIF) to be set.  A/D kesme bayrağının set edilmesini bekle
c) Poll  for  the  BFEMT  bit  to  be  cleared  to signify that at least the first conversion has completed.  BFEMT bitinin siinmesini bekle bu en azından ilk çevrimin tamamlandığına dair işaretdir.
6. Read  the  A/D  results,  clear  the  ADIF  flag, reconfigure the trigger.  A/D sonucunu okuyarak ADIF bayrağının silinmesini sağla ve triggeri yeniden kur    

Çok detaylı bir çalışma bu. Bence direk ADCIN komutunu kullansan daha iyi olur senin içn.

Ete

Powered by EzPortal