Assembly ile bir değişkendeki değeri sorgulatıp işlem yapmak istiyorum
örneğin if(a==5) {}
Bu komut değişkenin değerini sorgulatıyor. Aynısını assembly ile nasıl yaparım?
Hatırladığım kadarıyla şöyle;
movlw 5
subwf a,w
btfss status,z
goto DEGISKEN_5_DEN_FARKLI
goto DEGISKEN_5_E_ESIT
Teşekkürler eşitlik sorgulamasını yaptım. Açıkçası bu asm yi sevmeye başladım.
ASM ile Büyüklük küçüklük sorgulamaları nasıl yapılır?
Çıkartma işlemi ardından Cary flağını test edeceksin.
A-B işleminde
A>B yada A=B ise Cary=1
A<B Cary=0
Evet galiba her türlü çıkartma yapıp status registerinin flaglarını kontrol etmem gerekiyor.
Evet birde Z(h)ero flag var :)
Hocam çıkarma yapmak istemezsen mantıksal işlemleride kullanabilirsin,
yine flaglara bakacaksın sonuçta,
andlw
andwf
iorlw
iorwf
xorwf
xorlw
işi uzatmak için böyle taklalar atılabilir
ör;
bilgi
ANDLW: Bir sayı ile W registerin içeriğine AND (VE) mantıksal işlemini uygula.
kullanımı:
ANDLW k
yukardaki kullanım sonucu pic şunu yapar;
W registerin içinde bulunan değer ile k sayısına and işlemini uygular ve çıkan sonucu W ye yazar.
işlem sonucunda 0 değeri elde edilirse, Status zero biti 1 yapılır.
Misal sayi == 0x0f mi?
movlw 0xf0 ;test için değerin tersini kullanıyoruz (terslemek için 1 ile xor lama kullanılabilir)
andwf sayi,w ;sayi ile w yi andle sonucu w ye yaz (sayi içeriği değişmesin diye
;eğer sonuç 0 ise status zero biti 1 olur,
;and işleminin sonucunun 0 olabilmesi için (sayi=)0x0f and 0xf0 olması gerekir
;0000 1111 sayı
;1111 0000 andlendiği değer
;_________ and işlemi
;0000 0000 sonuç
btfss status,z ;status z biti 1 ise atla
goto sayi_esit
goto esit_degil
yada direk
xorlw
xorwf
kullanılarakta karşılaştırma yapılabilir.
;memo == 0xAA mı kontrolü (memo ==0xAA ise zero = 1 olur)
movlw 0xAA
xorwf memo,w ;memo ile w daki sayıyı xor la, sonucu w ya yaz
btfss status,z ;zero bayrağı 1 mi
goto (aa değilse) ;hayır
goto (aa ise) ;evet
Merhaba,
Projelerimin birinde PC'den giden datanın PIC tarafından algılanıp PC'den klavye"1" basıldığı zaman XORWF ile karşılaştırıp
duruma göre yön veren bir kodu da ben paylaşayım dedim.Kolay gelsin.
;*************
MOVLW B'00110001'
XORWF RCREG
BTFSS STATUS,2
GOTO LED_GONDER
GOTO TESTCD
;*************
Tekrardan bir konu açmaya gerek yok sanırım burdan devam edeyim.
Birkaç sorum olacak.
ASM ile kesme rutini yazdım. Kesme içerisinde display tarıyorum.
Yazdığım kodlar,
;***************************Kesme Rutini*******************************
INTERRUPT
BANKSEL PORTD
MOVLW H'00' ;Eğer INT_SYC=0 ise
SUBWF INT_SYC,W ;INT_SYC Değişkeninden W yi çıkart
BTFSS STATUS,Z ;Z Flagı 1 ise işlem sonucu sıfırdır.
GOTO BOLUM2 ;Z=0 ise INT_SYC sıfırdan farklıdır.
BCF PORTD,2 ;3.Displayi Kapat
MOVLW DIG0 ;1. Displayin Datasını W ye yükle
MOVWF PORTC ;W deki Değeri Displaye gönder
BSF PORTD,0 ;Displayi Aç
GOTO EXIT ;Kesmeden Çık
BOLUM2
MOVLW H'01' ;Eğer INT_SYC=0 ise
SUBWF INT_SYC,W ;INT_SYC Değişkeninden W yi çıkart
BTFSS STATUS,Z ;Z Flagı 1 ise işlem sonucu sıfırdır.
GOTO BOLUM3 ;Z=0 ise INT_SYC sıfırdan farklıdır.
BCF PORTD,0 ;1.Displayi Kapat
MOVLW DIG1 ;2. Displayin Datasını W ye yükle
MOVWF PORTC ;W deki Değeri Displaye gönder
BSF PORTD,1 ;Displayi Aç
GOTO EXIT ;Kesmeden Çık
BOLUM3
MOVLW H'02' ;Eğer INT_SYC=0 ise
SUBWF INT_SYC,W ;INT_SYC Değişkeninden W yi çıkart
BTFSS STATUS,Z ;Z Flagı 1 ise işlem sonucu sıfırdır.
GOTO EXIT ;Z=0 ise INT_SYC sıfırdan farklıdır.
BCF PORTD,1 ;2.Displayi Kapat
MOVLW DIG2 ;3. Displayin Datasını W ye yükle
MOVWF PORTC ;W deki Değeri Displaye gönder
BSF PORTD,2 ;Displayi Aç
GOTO EXIT ;Kesmeden Çık
EXIT
INCF INT_SYC,F ;INT_SYC 1 arttırılır
MOVLW H'03' ;Eğer INT_SYC Değeri 3 ise
SUBWF INT_SYC,W ;INT_SYC Değerini Sıfırla
BTFSS STATUS,Z
GOTO EXIT1
MOVLW H'00' ;INT_SYC Sıfırlandı
MOVWF INT_SYC
EXIT1
BANKSEL TMR0 ;Timer0'ın bulunduğu bank'a geçiliyor.
MOVLW D'99' ;Timer Preload değeri tekrar yükleniyor.
MOVWF TMR0
BCF INTCON,TMR0IF
RETFIE
Burada displaylerin seğment bilgilerini DIG0, DIG1, DIG2 isimli değişkenler tutuyor. Bu değerleri kesme içerisinde ilk önce W ye yükleyip sonra port'a yazıyorum. Fakat debug esnasında örneğin W registerine DIG0 yüklenmesi gerekirken W de saçma sapan değerleri görüyorum. Dolayısıyla W deki Değer Port'a yazdığı için display'de anlamsız değerler çıkıyor. Bunun sebebi ne olabilir?
Diğer bir konu ise yine kesme ile ilgili. Kesme içerisinde W registerini kullandığım için ana programdan kesmeye gelindiğinde W 'de tutulan değer çöpe gitmiş oluyor. Bunun için Context Save işlemini yapmam gerekecek. Bu işlemin içeriği nedir? Sadece kesmeye gelindiğinde W deki değeri alıp, kesmeden çıkarkende tekrar W ye yüklemek yeterlimi?
mplap temp dosysı içinde kesme örneği;
***** VARIABLE DEFINITIONS
w_temp EQU 0x7E ; variable used for context saving
status_temp EQU 0x7F ; variable used for context saving
;**********************************************************************
ORG 0x000 ; processor reset vector
goto main ; go to beginning of program
ORG 0x004 ; interrupt vector location
movwf w_temp ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
; isr code can go here or be located as a call subroutine elsewhere
movf status_temp,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents
retfie ; return from interrupt
evet, belirttiğin gibi yapılabilmekte.
Hocam o kodda anlamadığım bir iki yer var.
Kesme vektörünün hemen altında movwf w_temp komutu ile W deki değer w_temp'e alınıyor. Fakat kesmeden çıkarken neden swapf komutu kullanılmış anlamadım.
swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents
w_temp deki değerin direk W ye yüklenmesi gerekmezmiydi.?
Diğer bir yandan yaşadığım probleme hala yinede anlam veremiyorum. Ana program döngüsünde hiçbirşey yapmıyorum. Yani kesme rutini dışında W registeri kullanılmıyor. W 'ye kim bu değerleri yüklüyor anlamıyorum.
programını bir incele,
dig0,...,dig3 değişken olarak belirtmişsin, ama programda sabit sayı gibi işlem yapmışsın gibi görünüyor...
Doğruya MOVLW ile sabit sayı W'ye yazılıyordu. Benim MOVF kullanmam gerekiyordu. Sorun çözüldü. Context Save işlemlerinide yaparsam tamamdır.
Alıntı yapılan: Mucit23 - 30 Mart 2014, 17:34:46
Hocam o kodda anlamadığım bir iki yer var.
Kesme vektörünün hemen altında movwf w_temp komutu ile W deki değer w_temp'e alınıyor. Fakat kesmeden çıkarken neden swapf komutu kullanılmış anlamadım.
swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents
w_temp deki değerin direk W ye yüklenmesi gerekmezmiydi.?
Aslında bence girerkende swapla alınması iyi olur,
movf komutunun statusu etkileme ihtimali var
o yüzden swapf komutu kullanılıyor, şöyle örnekleyeyim;
misal w register ın içinde sıfır değeri vardı w_temp e alındı,
movf w_temp,w dersek w_temp içindeki sıfır değeri w register ına yazılır ve
yüklenen içerik sıfır olduğu için statusun zero bayrağı set 1 edilir,
eğer kesmeye gi,rerken status,z sıfır olsaydı ve w register ıda böyle sıfırla gelmiş olsaydı
çıkışta status zero bayrağı set edilmiş olacaktı buda hata olacaktı.
Pardon kesmeye girerken swapla almak ekstra bir fayda sağlamıyor,
bazı dökümanlarda karşılaşmıştım gibi hatırladım ama
herhalde burada faydası olmaz yine bakarım bir ara.
Cevap için Teşekkürler,
Bir sorum daha olacak. Assembly ile Mod alma nasıl yaparım?
Amacım şudur. Örneğin 245 verisini hanelerine ayırmam gerekiyor. 2 sayısını bir değişkene, 4 sayısını bir değişkene 5 sayısınıda başka bir değişkene atmam gerekiyor. Bu işlem genelde 7 seğment display kullanırken lazım oluyor. PicBasic veya C gibi dillerde bölme ve mod alma işlemleriyle kolaylıkla yapıyoruz. Bizim kolaylıkla yaptığımız bu işi derleyici nasıl yapar?
245
Ydigit = 0;
x = 245;
ISLEM:
x sayısı ,
99 dan büyükse
Ydigit+1
x-100
goto ISLEM:
;******************************************************************************************************
; Binary olan girişi decimal sayıya çevrim
;******************************************************************************************************
B2D
movwf SAYI
clrf YUZLER
clrf ONLAR
clrf BIRLER
YuzB movlw .100
subwf SAYI,W
btfsc STATUS,C
goto YuzlerBasamagi
OnB movlw .10
subwf SAYI,W
btfsc STATUS,C
goto OnlarBasamagi
movf SAYI,W
movwf BIRLER
return
;--------------------------------------------------------------------------------------------------------
YuzlerBasamagi
incf YUZLER,1
movwf SAYI
goto YuzB
;--------------------------------------------------------------------------------------------------------
OnlarBasamagi
incf ONLAR,1
movwf SAYI
goto OnB
;--------------------------------------------------------------------------------------------------------
;Değişkenler
HexMSB ;Çevrilecek sayının en değerli byte'ı.
HexLSB ;Çevrilecek sayının en değersiz byte'ı.
binler ;Çevrilen sayının binler basamağı burada.
yuzler ;Çevrilen sayının yüzler basamağı burada.
onlar ;Çevrilen sayının onlar basamağı burada.
birler ;Çevrilen sayının birler basamağı burada.
;-------------------------------------------------------------------
; 2 byte binary veriyi bcd koda dönüştürür. Sonuç binler, yüzler,
; onlar ve birler değişkenlerinde saklanır.
;-------------------------------------------------------------------
HexToDec
clrf binler ;binler = 0
clrf yuzler ;yuzler = 0
clrf onlar ;onlar = 0
clrf birler ;birler = 0
binler_kont
movlw 04h ;W'ye 1024 (0x0400) sayısının en değerli
;byte'ını yükle.
subwf HexMSB, W ;HexMSB'den 1024 çıkart.
btfss STATUS, C ;HexMSB > 1024'mü?
goto yuzler_kont2 ;hayır ise yüzleri kontrol et.
incf binler, F ;evet ise binleri bir artır.
movlw 04h ;W'ye 0x04 yükle.
subwf HexMSB, F ;HexMSB'den 1000 çıkart.
movlw 18h ;W'ye 0x18 yükle.
addwf HexLSB, F ;HexLSB'ye (0x18 = 24) ekle.
btfsc STATUS, C ;elde var mı?
incf HexMSB, F ;evet ise bir artır.
goto binler_kont ;binleri yeniden kontrol et.
yuzler_kont2
movlw 0x01 ;256 (0x0100)
subwf HexMSB, W ;HexMSB'den 200 çıkart ve sonucu W'ye
;sakla.
btfss STATUS, C ;sonuç >= 256'mı?
goto yuzler_kont1 ;Hayır ise yüzler basamağını kontrol et
movlw 0x02 ;değilse,
addwf yuzler, F ;yuzler'e 2 ekle.
movlw 0x01 ;W = 1
subwf HexMSB, F ;HexMSB'den 200 çıkart.
movlw 0x38 ;W =0x38 (256'nın 56 lık kısmı).
addwf HexLSB, F ;HexLSB'ye 56'yı ekle.
btfsc STATUS, C ;elde var mı?
incf HexMSB, F ;evet ise HexMSB'yi bir artır.
movlw 0x0A ;W = 10
subwf yuzler, W ;yuzler = 1000 olup olmadığını kontrol et,
btfss STATUS, Z ;sonuç sıfır mı?
goto yuzler_kont2 ;hayır ise yuzleri yeniden kontrol et.
clrf yuzler ;yuzler = 0
incf binler, F ;binler'i artır.
goto yuzler_kont2 ;yuzler'i 200 ya da daha büyük sayı için
;yeniden kontrol et.
yuzler_kont1
movlw 0x64 ;W = 0x64
subwf HexLSB, W ;HexLSB'den 100 çıkart.
btfss STATUS, C ;sonuç >= 100 mü?
goto onlar_kont ;hayır ise onları kontrol et,
incf yuzler, F ;evet ise yuzler'i bir artır.
movlw 0x64 ;W = 0x64 (100)
subwf HexLSB, F ;HexLSB'yi 100 azalt.
movlw 0x0A ;W = 0x0A (10)
subwf yuzler, W ;yuzler = 1000 kontrolü yap.
btfss STATUS, Z ;sonuç = 0 mı?
goto yuzler_kont1 ;hayır ise 100 için yuzler'i yeniden
;kontrol et.
clrf yuzler ;yuzler = 0
incf binler, F ;binleri bir artır.
goto yuzler_kont1 ;100 ya da daha büyük olma durumu için
;yuzleri yeniden kontrol et.
onlar_kont
movlw 0x0A ;W = 0x0A (10)
subwf HexLSB, W ;HexLSB'den 10 çıkart.
btfss STATUS, C ;sonuç >= 10 mu?
goto birler_kont ;hayır ise birleri kontrol et,
incf onlar, F ;evet ise onları bir artır.
movlw 0x0A ;W = 0x0A (10)
subwf HexLSB, F ;HexLSB'den 10 çıkart.
goto onlar_kont ;onlar'ı yeniden kontrol et.
birler_kont
movf HexLSB, W ;W = HexLSB
movwf birler ;birler = W, dönüşüm işlemi tamam.
return ;Alt programdan çık.
bir fikir vermesi açısından...
Teşekkürler arkadaşlar. inceleyelim.
Çok güzel bir dönüştürme yöntemi var
muhtemelen derleyicilerde bu yöntemi kullanıyor;
(https://lh3.googleusercontent.com/-rtwrpK1MwLo/Uzqhf44IfrI/AAAAAAAAAWM/tJxdu7OTJ_w/w820-h437-no/1.JPG)
(https://lh4.googleusercontent.com/IHzKBnElNnowC_sskxv5GlZEMZvh3-ifvEAjU6lw6zc=w820-h418-no)
(https://lh6.googleusercontent.com/lyBdoq3r6fMxMSch-B-P48wSlCWDK54eC5IGOaKuozQ=w710-h545-no)
buda dspic30f2010 için örnek;
pek bunla kafa karıştırmaya gerek yok yukarıdaki yeterli aslında.
;>>>>>>>>>>>> BCDCEVIR YENI VERSİYON W0 DAKİ SAYIYI BCD YE ÇEVİRİP W14:W13 TE SAKLAR>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>> SONRA LCD CEVIR İLE VERI1-8 E YAZAR (VERI9=00) DÖNER>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
BCDCEVIR: NOP
CLR W13
CLR W14
;mov #0x05f5,w1 ;deneme değerleri W14:W13 te
; mov #0xe0ff,w0 ; (dec karşılığı) 9999:9999 oluşturur
DO #30,DONGU
MOV #0x3333,W10
; MOV #0x3330,W9 ;*
; MOV #0x3300,W8 ;*
MOV #0x3000,W7
MOV #0x0300,W6
RLC W0,W0 ;dönüşecek sayı w1:w0 da olsaydı
rlc w1,w1 ;*
RLC W13,W13
RLC W14,W14
ADD W10,W13,W13
ADDC W10,W14,W14
BTSC W13,#3
GOTO T1
SUB #0x0003,W13
SUBB #0x0000,W14
T1: NOP
BTSC W13,#7
GOTO T2
SUB #0x0030,W13
SUBB #0x0000,W14
T2: NOP
BTSC W13,#11
GOTO T3
SUB W13,W6,W13 ;w6 yerine 0300
SUBB #0x0000,W14
T3: NOP
BTSC W13,#15
GOTO T4
SUB W13,W7,W13
SUBB #0x0000,W14
T4: NOP
BTSC W14,#3
GOTO T5
SUB #0x0000,W13
SUBB #0x0003,W14
T5: NOP
BTSC W14,#7
GOTO T6
SUB #0x0000,W13
SUBB #0x0030,W14
T6: NOP
BTSC W14,#11
GOTO T7
SUB #0x0000,W13
SUBB W14,W6,W14
T7: NOP
BTSC W14,#15
GOTO DONGU
SUB #0x0000,W13
SUBB W14,W7,W14
DONGU: NOP
RLC W0,W0
rlc w1,w1
RLC W13,W13
RLC W14,W14
MOV W14,W4
CALL LCDCEVIR
MOV W12,VERI1
MOV W11,VERI2
MOV W10,VERI3
MOV W9,VERI4
MOV W13,W4
CALL LCDCEVIR
MOV W12,VERI5
MOV W11,VERI6
MOV W10,VERI7
MOV W9,VERI8
CLR VERI9
RETURN
@Speedyx,
Hocam sizin kodu aynen denedim. Ama çalıştıramadım. Bir terslik olacak. Giriş verisi olarak 245 verdiğimde çıkışta sayı ve birler değişkeni 1 olup çıkıyor. Giriş verisinin ne olduğu farketmiyor.
@Ramu hocam sizin resimdeki işlemlerde sanki farklı bir işlem yapılıyor. Mantığı çözemedim bir türlü.
Aslında tamda burda sorun yaşıyorum. İşin mantığını nedir bunu anlayamıyorum. Bana kod vermek yerine işin mantığını anlatırsanız daha iyi olur benim için.
Merhaba,
Kodu tekrar inceledim, W=245 vermiş gibi akışa baktım, 2-4-5 çıkarır.
movlw .245
call B2D
yazmak yeterli. Bir hata varsa göremedim şu an, PIC lerle yıllardır çalışmıyorum gerçek işlemcide deneme imkanım yok. MPLAB da adım adım simüle edip davranışı görebilirsin.
subwf SAYI,W -> W = SAYI - W işlemi yapıyor, burada 145 = 245-100 şeklinde ve sonuç pozitif olduğundan status,C = 1 oluyor. YuzlerBasamagi'nda YUZLER++ yapıyor ve SAYI=145 oluyor, tekrar aynı işlemi yapıyor; 45 = 145-100 ve C=1, yine YUZLER++ yapılıyor ve değer 2ye ulaşıyor, SAYI=45. Tekrar 45-100 işlemi C=0 olmasına sebep oluyor ve onlar kısmına geçiliyor, orada da aynı mantık tekrarlanıyor, 35=45-10, C=1, ONLAR++, SAYI=35 (4 defa) ve ardından 5-10 işlemiyle C=0 oluyor ve birler kısmına geçip SAYI değişkeninin değeri olan 5 BIRLER değişkenine yükleniyor. Bu kodda SAYI hiç kullanılmayıp BIRLER değişkeni onun yerine kullanılabilirmiş, 1 byte kâr.
Olay şu;
md de değişkenler hex olarak kaydediliyor ve kullanılıyor,
misal reg_hex içinde bir işlem sonucu elde ettiğimiz 0xA2 sayısı olsun,
reg_hex içindeki sayıyı lcd de veya 7 seg displayde göstermek zorunda olalım,
o zaman bu sayının bize onluk karşılığı gerekiyor
ama bu onluk karşılığıda yine md miz hex sanacak yani hexmiş gibi kaydedecek,
misal md. onluk tabanda çalışsaydı incf reg_x (arttırma komutu) işleminde
1 2 3 4 . . . 9 10 11 12 ... 99 sonra arttırılırsa yine 0 olacaktı
ama hex olduğundan
1 2 3 4 ... 9 A B C D . . . FF sonra arttırdığımızda 0 olacak,
şimdi her halükarda arttırma işlemi doğru ama
10luk taban 2 lik tabanla güzel ilişkili değil
16lık taban çok rahat ilişkili
misal 0xA2 nin 2lik karşılığı hemen A nın ve 2 nin ikilik karşılıklarını yanyana yazmakyan ibaret 1010 0010
neyse bunları biliyoruz zaten,
şimdi amacımız
reg_hex içindeki sayıyı (0xA2) onluk tabana çevirmek
kelem kağıtla yapınca ne yapıyoruz aynı onluk tabandaki gibi
A2
| |-----> birler x 1 = 2x1 = 2
|-------> onalılar x 16 = 10x16 = 160
+ ------------
162 onluk tabanda sayımız oluyor.
Bunu medye yaptırmak için basitinden şöyle bir yöntem kullanabiliriz;
reg_hex sayısı sıfırmı diye bakarız,
reg_hex sayısını bir azaltırız,
reg_dec sayısının birler basamağı 9 mu diye bakarız,
değilse olusan_sayı değerini 1 arttırırız,
evet 9 ise reg_dec in onlar basamağını bir arttırırız
(onluk tabanda A olamaz bu yüzden onlar basamağını bir arttırırız)
ve birler basamağını sıfır yaparız,
böylece reg_hex sıfır oluncaya kadar devam ederiz,
(ama burada ancak onluk 99 a kadar sayıyı çevirebiliriz
bu nedenle reg_dec için yüzler basamağıda gerekiyor,
çünkü reg_hex de FF varsa oluşacak onluk sayı 255 olacak,
aynı mantıkla onlar basamağı 9 oldumu kontrolü yapılır ve
ona göre yüzler basamağı bir arttırılır.)
Fakat bu işlem her zaman aynı sürede tamamlanmıyor
misal reg_hex içinde 3-5 varken çok kısa
reg_hex içinde 0xE9 0xFD gibi sayı varken çok uzun sürüyor,
bunun yerine reg_hex sayısını
decimal 100 100 azaltıp reg_dec sayısının yuzler basamağını arttırabilriz
sonra reg_hex sayısını decimal on on azaltıp
reg_dec in onlar basamağını arttırabiliriz,
en son reg_hex birler basamağını (0 F arası bir değerdedir) reg_dec e ekleriz,
ama yinede bu işlemde hep farklı sürelerde çalışır,
Bu yüzden verdiğim algoritma türemiş,
kim yazmış nasıl yazmış bende anlamadım
içinde çok güzel bir algoritma var
neye göre çıkarmış bende anlamadım
çok değilsede üzerinde iyi bir süre düşündüm bulamadım nasıl olduğunu,
verdiğim algoritma hep aynı sürede tamamlanıyor
8 bitlik sayı için 8 defa döngü oluyor
döngüde yapılan işlemler fotodaki anlatımda mevcut
sürekli ekleme yapıp 3. ve 7. bite bakma durumu var
ve sonra elde edilen sayı her döngüde
reg_decyüzler ve reg_deconlarbirler birer defa sola kaydırılıyor
en son yani 8. döngüde kaydırma yapılmıyor,
olayın mantığını çözersen banada anlat hocam
ama bu algoritma gerçekten çok iyi.
merhaba P16F877A ile bir termometre devresi yapmam lazım belli bir derecede bir sinyal verecek.Mesela 30 dereceyi aştığı zaman bir sinyal verecek normal termometre devresi kodları bu aşağıda.Araya komut eklemem gerekiyor yardımcı olur musunuz?
#include <P16F877A.inc>
DEGER EQU 0x20
SAYAC1 EQU 0x21
SAYAC2 EQU 0x22
VERI EQU 0x23
ONLAR EQU 0x24
BIRLER EQU 0x25
ARADEGER EQU 0x26
ORG 0x00
START
BANKSEL TRISB
CLRF TRISB
MOVLW 0xFF
MOVWF TRISA
BSF ADCON1,7
BANKSEL ADCON0
MOVLW b'11000001'
MOVWF ADCON0
CALL LCDTEMIZLE
CALL LCDKUR
CALL LCDADRES
CLRF ONLAR
CLRF BIRLER
YAZDIR
CLRF ONLAR
CLRF BIRLER
CALL BASLA
MOVWF ARADEGER
CALL ONLARBAS
CALL ADCYAZ
BASLA
BSF ADCON0,GO
CALL GECIKME
KONTROL
btfsc ADCON0,GO
GOTO KONTROL
BSF STATUS,RP0
RRF ADRESL,W
BCF STATUS,RP0
MOVWF ARADEGER
ONLARBAS
MOVLW d'10'
SUBWF ARADEGER,0
btfss STATUS,C
GOTO BIRLERBAS
INCF ONLAR,1
MOVLW d'10'
SUBWF ARADEGER,1
GOTO ONLARBAS
BIRLERBAS
MOVF ARADEGER,0
MOVWF BIRLER
ADCYAZ
MOVLW 0X80
MOVWF DEGER
CALL LCDADRES
MOVLW 'S'
CALL VERIYAZ
MOVLW 'I'
CALL VERIYAZ
MOVLW 'C'
CALL VERIYAZ
MOVLW 'A'
CALL VERIYAZ
MOVLW 'K'
CALL VERIYAZ
MOVLW 'L'
CALL VERIYAZ
MOVLW 'I'
CALL VERIYAZ
MOVLW 'K'
CALL VERIYAZ
MOVLW '='
CALL VERIYAZ
BSF ONLAR,4
BSF ONLAR,5
MOVF ONLAR,0
CALL VERIYAZ
MOVLW b'00110000'
IORWF BIRLER,0
CALL VERIYAZ
MOVLW ' '
CALL VERIYAZ
MOVLW 0xDF
CALL VERIYAZ
MOVLW 'C'
CALL VERIYAZ
CALL YAZDIR
KOMUTYAZ
MOVWF VERI
SWAPF VERI,W
ANDLW 0x0F
MOVWF PORTB
BCF PORTB,4
CALL PULSE
MOVF VERI,W
ANDLW 0x0F
MOVWF PORTB
BCF PORTB,4
CALL PULSE
RETURN
VERIYAZ
MOVWF VERI
SWAPF VERI,W
ANDLW 0X0F
MOVWF PORTB
BSF PORTB,4
CALL PULSE
MOVF VERI,W
ANDLW 0X0F
MOVWF PORTB
BSF PORTB,4
CALL PULSE
RETURN
LCDTEMIZLE
MOVLW 0x01
CALL KOMUTYAZ
RETURN
LCDADRES
MOVF DEGER,0
CALL KOMUTYAZ
RETURN
LCDKUR
MOVLW 0x03
CALL KOMUTYAZ
MOVLW 0x03
CALL KOMUTYAZ
MOVLW 0x03
CALL KOMUTYAZ
MOVLW 0x02
CALL KOMUTYAZ
MOVLW 0x0C
CALL KOMUTYAZ
MOVLW 0x28
CALL KOMUTYAZ
MOVLW 0x80
CALL KOMUTYAZ
RETURN
PULSE
BSF PORTB,5
CALL GECIKME
BCF PORTB,5
GECIKME
MOVLW 0xAA
MOVWF SAYAC1
D1
MOVLW 0x10
MOVWF SAYAC2
D2
DECFSZ SAYAC2
GOTO D2
DECFSZ SAYAC1
GOTO D1
RETURN
END
#include <P16F877A.inc>
DEGER EQU 0x20
SAYAC1 EQU 0x21
SAYAC2 EQU 0x22
VERI EQU 0x23
ONLAR EQU 0x24
BIRLER EQU 0x25
ARADEGER EQU 0x26
ORG 0x00
START
BANKSEL TRISB
CLRF TRISB
MOVLW 0xFF
MOVWF TRISA
BSF ADCON1,7
BANKSEL ADCON0
MOVLW b'11000001'
MOVWF ADCON0
CALL LCDTEMIZLE
CALL LCDKUR
CALL LCDADRES
CLRF ONLAR
CLRF BIRLER
YAZDIR
CLRF ONLAR
CLRF BIRLER
CALL BASLA
MOVWF ARADEGER
CALL ONLARBAS
CALL ADCYAZ
BASLA
BSF ADCON0,GO
CALL GECIKME
KONTROL
btfsc ADCON0,GO
GOTO KONTROL
BSF STATUS,RP0
RRF ADRESL,W
BCF STATUS,RP0
MOVWF ARADEGER
ONLARBAS
MOVLW d'10'
SUBWF ARADEGER,0
btfss STATUS,C
GOTO BIRLERBAS
INCF ONLAR,1
MOVLW d'10'
SUBWF ARADEGER,1
GOTO ONLARBAS
BIRLERBAS
MOVF ARADEGER,0
MOVWF BIRLER
ADCYAZ
MOVLW 0X80
MOVWF DEGER
CALL LCDADRES
MOVLW 'S'
CALL VERIYAZ
MOVLW 'I'
CALL VERIYAZ
MOVLW 'C'
CALL VERIYAZ
MOVLW 'A'
CALL VERIYAZ
MOVLW 'K'
CALL VERIYAZ
MOVLW 'L'
CALL VERIYAZ
MOVLW 'I'
CALL VERIYAZ
MOVLW 'K'
CALL VERIYAZ
MOVLW '='
CALL VERIYAZ
BSF ONLAR,4
BSF ONLAR,5
MOVF ONLAR,0
CALL VERIYAZ
MOVLW b'00110000'
IORWF BIRLER,0
CALL VERIYAZ
MOVLW ' '
CALL VERIYAZ
MOVLW 0xDF
CALL VERIYAZ
MOVLW 'C'
CALL VERIYAZ
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Bu araya koyacagimiz program ONLAR ve BIRLER basamagina bakarak
;karsilastirma yapacak ve cikis verecek
BCF ONLAR,4
BCF ONLAR,5
BCF BIRLER,4
BCF BIRLER,5
movf 0x03,w ;KARSILASTIRMA YAPLACAK SAYININ ONLAR BASAMAGI (ORNEGIN 32 DERECE ICIN 3 DEGERI)
subwf ONLAR,w
btfsc STATUS,Z
goto checkOtherDigit
btfsc STATUS,C
startSignal
call generateSignal
continueToProcess
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CALL YAZDIR
KOMUTYAZ
MOVWF VERI
SWAPF VERI,W
ANDLW 0x0F
MOVWF PORTB
BCF PORTB,4
CALL PULSE
MOVF VERI,W
ANDLW 0x0F
MOVWF PORTB
BCF PORTB,4
CALL PULSE
RETURN
VERIYAZ
MOVWF VERI
SWAPF VERI,W
ANDLW 0X0F
MOVWF PORTB
BSF PORTB,4
CALL PULSE
MOVF VERI,W
ANDLW 0X0F
MOVWF PORTB
BSF PORTB,4
CALL PULSE
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
checkOtherDigit
movf 0x02,w ;KARSILASTIRMA YAPLACAK SAYININ BIRLER BASAMAGI (ORNEGIN 32 DERECE ICIN 2 DEGERI)
subwf BIRLER,w
btfsc STATUS,Z
goto startSignal
btfsc STATUS,C
goto startSignal
goto continueToProcess
generateSignal
BSF PORTB,7
CALL bigDelay
BCF PORTB,7
return
bigDelay
;999997 cycles 1saniyelik gecikme yapar (4mhz kristal icin)
movlw 0x08
movwf d1
movlw 0x2F
movwf d2
movlw 0x03
movwf d3
Delay_0
decfsz d1, f
goto $+2
decfsz d2, f
goto $+2
decfsz d3, f
goto Delay_0
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LCDTEMIZLE
MOVLW 0x01
CALL KOMUTYAZ
RETURN
LCDADRES
MOVF DEGER,0
CALL KOMUTYAZ
RETURN
LCDKUR
MOVLW 0x03
CALL KOMUTYAZ
MOVLW 0x03
CALL KOMUTYAZ
MOVLW 0x03
CALL KOMUTYAZ
MOVLW 0x02
CALL KOMUTYAZ
MOVLW 0x0C
CALL KOMUTYAZ
MOVLW 0x28
CALL KOMUTYAZ
MOVLW 0x80
CALL KOMUTYAZ
RETURN
PULSE
BSF PORTB,5
CALL GECIKME
BCF PORTB,5
GECIKME
MOVLW 0xAA
MOVWF SAYAC1
D1
MOVLW 0x10
MOVWF SAYAC2
D2
DECFSZ SAYAC2
GOTO D2
DECFSZ SAYAC1
GOTO D1
RETURN
END
Alıntı yapılan: XX_CİHAN_XX - 26 Aralık 2016, 11:29:09
#include <P16F877A.inc>
DEGER EQU 0x20
SAYAC1 EQU 0x21
SAYAC2 EQU 0x22
VERI EQU 0x23
ONLAR EQU 0x24
BIRLER EQU 0x25
ARADEGER EQU 0x26
ORG 0x00
START
BANKSEL TRISB
CLRF TRISB
MOVLW 0xFF
MOVWF TRISA
BSF ADCON1,7
BANKSEL ADCON0
MOVLW b'11000001'
MOVWF ADCON0
CALL LCDTEMIZLE
CALL LCDKUR
CALL LCDADRES
CLRF ONLAR
CLRF BIRLER
YAZDIR
CLRF ONLAR
CLRF BIRLER
CALL BASLA
MOVWF ARADEGER
CALL ONLARBAS
CALL ADCYAZ
BASLA
BSF ADCON0,GO
CALL GECIKME
KONTROL
btfsc ADCON0,GO
GOTO KONTROL
BSF STATUS,RP0
RRF ADRESL,W
BCF STATUS,RP0
MOVWF ARADEGER
ONLARBAS
MOVLW d'10'
SUBWF ARADEGER,0
btfss STATUS,C
GOTO BIRLERBAS
INCF ONLAR,1
MOVLW d'10'
SUBWF ARADEGER,1
GOTO ONLARBAS
BIRLERBAS
MOVF ARADEGER,0
MOVWF BIRLER
ADCYAZ
MOVLW 0X80
MOVWF DEGER
CALL LCDADRES
MOVLW 'S'
CALL VERIYAZ
MOVLW 'I'
CALL VERIYAZ
MOVLW 'C'
CALL VERIYAZ
MOVLW 'A'
CALL VERIYAZ
MOVLW 'K'
CALL VERIYAZ
MOVLW 'L'
CALL VERIYAZ
MOVLW 'I'
CALL VERIYAZ
MOVLW 'K'
CALL VERIYAZ
MOVLW '='
CALL VERIYAZ
BSF ONLAR,4
BSF ONLAR,5
MOVF ONLAR,0
CALL VERIYAZ
MOVLW b'00110000'
IORWF BIRLER,0
CALL VERIYAZ
MOVLW ' '
CALL VERIYAZ
MOVLW 0xDF
CALL VERIYAZ
MOVLW 'C'
CALL VERIYAZ
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Bu araya koyacagimiz program ONLAR ve BIRLER basamagina bakarak
;karsilastirma yapacak ve cikis verecek
BCF ONLAR,4
BCF ONLAR,5
BCF BIRLER,4
BCF BIRLER,5
movf 0x03,w ;KARSILASTIRMA YAPLACAK SAYININ ONLAR BASAMAGI (ORNEGIN 32 DERECE ICIN 3 DEGERI)
subwf ONLAR,w
btfsc STATUS,Z
goto checkOtherDigit
btfsc STATUS,C
startSignal
call generateSignal
continueToProcess
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CALL YAZDIR
KOMUTYAZ
MOVWF VERI
SWAPF VERI,W
ANDLW 0x0F
MOVWF PORTB
BCF PORTB,4
CALL PULSE
MOVF VERI,W
ANDLW 0x0F
MOVWF PORTB
BCF PORTB,4
CALL PULSE
RETURN
VERIYAZ
MOVWF VERI
SWAPF VERI,W
ANDLW 0X0F
MOVWF PORTB
BSF PORTB,4
CALL PULSE
MOVF VERI,W
ANDLW 0X0F
MOVWF PORTB
BSF PORTB,4
CALL PULSE
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
checkOtherDigit
movf 0x02,w ;KARSILASTIRMA YAPLACAK SAYININ BIRLER BASAMAGI (ORNEGIN 32 DERECE ICIN 2 DEGERI)
subwf BIRLER,w
btfsc STATUS,Z
goto startSignal
btfsc STATUS,C
goto startSignal
goto continueToProcess
generateSignal
BSF PORTB,7
CALL bigDelay
BCF PORTB,7
return
bigDelay
;999997 cycles 1saniyelik gecikme yapar (4mhz kristal icin)
movlw 0x08
movwf d1
movlw 0x2F
movwf d2
movlw 0x03
movwf d3
Delay_0
decfsz d1, f
goto $+2
decfsz d2, f
goto $+2
decfsz d3, f
goto Delay_0
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LCDTEMIZLE
MOVLW 0x01
CALL KOMUTYAZ
RETURN
LCDADRES
MOVF DEGER,0
CALL KOMUTYAZ
RETURN
LCDKUR
MOVLW 0x03
CALL KOMUTYAZ
MOVLW 0x03
CALL KOMUTYAZ
MOVLW 0x03
CALL KOMUTYAZ
MOVLW 0x02
CALL KOMUTYAZ
MOVLW 0x0C
CALL KOMUTYAZ
MOVLW 0x28
CALL KOMUTYAZ
MOVLW 0x80
CALL KOMUTYAZ
RETURN
PULSE
BSF PORTB,5
CALL GECIKME
BCF PORTB,5
GECIKME
MOVLW 0xAA
MOVWF SAYAC1
D1
MOVLW 0x10
MOVWF SAYAC2
D2
DECFSZ SAYAC2
GOTO D2
DECFSZ SAYAC1
GOTO D1
RETURN
END
Teşekkür ederim ilginiz için.Bu kodu proteusta çalıştıramadım 32 dereceye geldiğinde 32 derecenin altına veya üstüne çıktığında çıkış vermiyor.Led bağladım portb nin 7. bitine çıkış vermiyor.Onu değiştirdim farklı bir bite mesela portc nin 2. bitine verdim çıkışı ama yine olmadı
(https://s24.postimg.cc/xhuo4j8qp/Ads_z.png) (https://postimg.cc/image/xhuo4j8qp/)
Proteus dosyani ve mplab projesini upload edersen bakarım.
Alıntı yapılan: XX_CİHAN_XX - 26 Aralık 2016, 15:04:32
Proteus dosyani ve mplab projesini upload edersen bakarım.
Proteus ve mplap dosyaları burda çok teşekkür ederim ilginiz için.
http://dosya.co/2fd43nd8qn0j/term.rar.html
(http://dosya.co/2fd43nd8qn0j/term.rar.html)
Alıntı yapılan: XX_CİHAN_XX - 26 Aralık 2016, 15:04:32
Proteus dosyani ve mplab projesini upload edersen bakarım.
Proteus ve mplap dosyaları burda çok teşekkür ederim ilginiz için.
https://mega.nz/#!tAUEDYRS!9kNL7Qg7UUzqXStxUybZ3xEct6OdBZiR6Twm-PySDQo
(https://mega.nz/#!tAUEDYRS!9kNL7Qg7UUzqXStxUybZ3xEct6OdBZiR6Twm-PySDQo)
Alıntı YapBu yüzden verdiğim algoritma türemiş,
kim yazmış nasıl yazmış bende anlamadım
içinde çok güzel bir algoritma var
neye göre çıkarmış bende anlamadım
"Decimal Adjust" "Nibble"a 6 eklediğinde Decimal Cary oluşuyorsa bir sonraki nibble değerini artırma işlemdir.
Örneğin 0...9 sayılarına 6 eklenirse sonuç 0x10 dan küçüktür. Yani olduğu gibi kullanılabilir.
Fakat A...F rakamlarına 6 eklenirse Decimal Cary oluşur.
Bu durumda Cary bir üst "nibble'a eklenir.
Ramu"nun verdiği algoritmada 2 ile çarpılmış sayıya 6 eklemek yerine sayıya 3 ekleyip taşma varmı diye sınıyor ve aynı hesaba geliyor.
DAA Decimal Adjust Accumulator gibi bir komutun olmadığı işlemciler için DAA algoritması kullanılmış.