asm için yavaştan bir kütüphane oluşturmaya çalışıyorum aslında burada bittiğinede paylaşacaktım ama çok ta vaktim olmuyor belki katkı gelirse herkes bir el atarsa farklı algoritmalara çabucak ulaşılabilir sonuca.
not: kütüphaneler makrolardan oluşuyor dolayısı ile 32 bit çarpma, bölme ,pause komutu, bank değiştirme, movff gibi rutin işler için birde manchester kodu için dönüşümleri yapan bir makro hazırladım.
;****************************************************************
;* MUL : 16 x 16 = 32 multiply *
;* *
;* Input : R3 * R1 *
;* Output : R2, W = low word *
;* : R0, R2 + 1 = mid word *
;* : R0 = high word *
;* *
;* Notes : *
;****************************************************************
CARP MACRO R3,R3+1,R1,R1+1
MUL
MOVLW .16 ; For 16 shifts
MOVWF R4
CLRF R0 + 1
CLRF R0
mulloop
BCF STATUS, C
RRF R3 + 1, F
RRF R3, F
BTFSS STATUS, C ;
GOTO mull1 ; Skip add
MOVF R1, W ; 16-bit add with carry out
ADDWF R0, F
MOVF R1 + 1, W
BTFSC STATUS, C
INCFSZ R1 + 1, W
ADDWF R0 + 1, F
mull1
RRF R0 + 1, F
RRF R0 ,F
RRF R2 + 1,F
RRF R2 ,F
DECFSZ R4 ,F
GOTO mulloop
DONE
CLRF R3
CLRF R3+1
CLRF R1
CLRF R1+1
ENDM
;****************************************************************
;* DIV : 16 x 16 (31 x 15) divide *
;* *
;* Input : R0 / R1 *
;* Output : R0, R0+1 = bolüm *
;* : R2 = remainder kalan *
;* *
;* Notes : R2 = R0 MOD R1 *
;****************************************************************
BOL MACRO R0 ,R0+1 ,R1 ,R1+1
CLRF R2
CLRF R2+1
BCF STATUS,C
DIV32DIV
movlw .16
movwf R5
divloop
rlf R0 + 1, W
rlf R2, F
rlf R2 + 1, F
movf R1, W
subwf R2, F
movf R1 + 1, W
btfss STATUS, C
incfsz R1 + 1, W
subwf R2 + 1, F
btfsc STATUS, C
goto divok
movf R1, W
addwf R2, F
movf R1 + 1, W
btfsc STATUS, C
incfsz R1 + 1, W
addwf R2 + 1, F
bcf STATUS, C
divok
rlf R0, F
rlf R0 + 1, F
decfsz R5, F
goto divloop
movf R0, W ; Get low byte to W
ENDM
;////////////////////////// MOVFF KOMUTU////////////////////////////////////
; giriş ram = ram
MOVFF MACRO R5,R6
;R5 =BANK0--------R6 = BANK0
IF (R5) < 0X80 && (R6) < 0X80
MOVF R5 ,W
MOVWF R6
ENDIF
;////////////R5 =BANK0--------R6 = BANK1/////////////////
IF (R5) < 0X80 && (R6) > 0X7F&&(R6)<0X100
MOVF R5 ,W
BSF STATUS ,RP0
MOVWF R6
ENDIF
;-------------------R5=BANK0--------R6=BANK2/////////////////
IF (R5) < 0X80 && (R6) > 0XFF&&(R6)<0X180
MOVF R5 ,W
BSF STATUS ,RP1
MOVWF R6
ENDIF
;-------------------R5=BANK0--------R6=BANK3/////////////////
IF (R5) < 0X80 && (R6) > 0X17F
MOVF R5 ,W
BSF STATUS ,RP1
BSF STATUS ,RP0
MOVWF R6
ENDIF
; ;/////////////R5=BANK1-------R6=BANK0//////////////////
IF (R5) > 0X7F&&(R5)<0X100 && (R6) < 0X80
MOVF R5 ,W
BCF STATUS ,RP0
MOVWF R6
ENDIF
;/////////////R5=BANK1-------R6=BANK1//////////////////
IF (R5) > 0X7F&&(R5)<0X100 && (R6) > 0X7F && (R6) < 0X100
MOVF R5 ,W
MOVWF R6
ENDIF
;/////////////R5=BANK1-------R6=BANK2//////////////////
IF (R5) > 0X7F&&(R5)<0X100 && (R6) > 0XFF && (R6) < 0X180
MOVF R5 ,W
BCF STATUS ,RP0
BSF STATUS ,RP1
MOVWF R6
ENDIF
;/////////////R5=BANK1-------R6=BANK3//////////////////
IF (R5) > 0X7F&&(R5)<0X100 && (R6) > 0X17F
MOVF R5 ,W
BSF STATUS ,RP1
MOVWF R6
ENDIF
;/////////////R5=BANK2-------R6=BANK0//////////////////
IF (R5) > 0XFF && (R5) < 0X180 && (R6) < 0X80
MOVF R5 ,W
BCF STATUS ,RP1
MOVWF R6
ENDIF
;/////////////R5=BANK2-------R6=BANK1//////////////////
IF (R5) > 0XFF&& (R5)< 0X180 && (R6) > 0X7F && (R6) < 0X100
MOVF R5 ,W
BSF STATUS ,RP0
BCF STATUS ,RP1
MOVWF R6
ENDIF
;/////////////R5=BANK2-------R6=BANK2//////////////////
IF (R5) > 0XFF&& (R5)< 0X180 && (R6) > 0XFF && (R6) < 0X180
MOVF R5 ,W
MOVWF R6
ENDIF
; ;/////////////R5=BANK2-------R6=BANK3//////////////////
IF (R5) > 0XFF&& (R5)< 0X180 && (R6) > 0X17F
MOVF R5 ,W
BSF STATUS ,RP0
MOVWF R6
ENDIF
;/////////////R5=BANK3-------R6=BANK3//////////////////
IF (R5) > 0X17F && (R6) > 0X17F
MOVF R5 ,W
MOVWF R6
ENDIF
; ;/////////////R5=BANK3-------R6=BANK2//////////////////
IF (R5) > 0X17F && (R6) > 0XFF && (R6) < 0X180
MOVF R5 ,W
BCF STATUS ,RP0
MOVWF R6
ENDIF
; ;/////////////R5=BANK3-------R6=BANK1//////////////////
IF (R5) > 0X17F && (R6) > 0X7F && (R6) < 0X100
MOVF R5 ,W
BCF STATUS ,RP1
MOVWF R6
ENDIF
;/////////////R5=BANK3-------R6=BANK0//////////////////
IF (R5) > 0X17F && (R6) < 0X80
MOVF R5 ,W
BCF STATUS ,RP0
BCF STATUS ,RP1
MOVWF R6
ENDIF
ENDM
;//////////////////////MANCHESTER KODU///////////////////////
;///////// 8 BİT VERİYİ MENCHESTER KODUNA DÖNÜŞTÜRME///////
;///////////////// R2-R2+1 MANCHESTER KODU//////////////////
MNCOD MACRO R3
MOVLW 0X08
MOVWF R1
CLRF R2
CLRF R2+1
LL:
BCF STATUS ,C
RRF R3 ,W
RRF R2+1
RRF R2
; MOVLW 0X80 ;G.E. Thomas STANDARDI İÇİN BU AÇILACAK
; XORWF R2+1
BCF STATUS ,C
RRF R3
RRF R2+1
RRF R2
MOVLW 0X80 ;IEEE 802.3 STANDARDI İÇİN BU AÇILACAK
XORWF R2+1
DECFSZ R1
GOTO LL
ENDM
;/////////////////////////MANCHESTER KODU BİNARY KODA ÇEVİRME///////////
; R3 = BINARY
;
;
MNCOD_IN MACRO R2 ,R2+1
MOVLW .8
MOVWF R1
CLRF R3
CLRF R3+1
BCF STATUS ,C
RRF R2+1
RRF R2
RRF R3
BCF STATUS ,C
RRF R2+1
RRF R2
DECFSZ R1
GOTO $-8
ENDM
;//////////////////////PAUSE ///////////////////
;///////////////////////MS/////////////////////
PAUSE MACRO R0
IFDEF OSC_8
IF R0 == 1
movlw .151
movwf _TMP0
movlw .3
movwf _TMP1
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
nop
nop
ENDIF
IF R0 == 2
movlw .48
movwf _TMP0
movlw .6
movwf _TMP1
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
nop
ENDIF
IF R0==3
movlw .201
movwf _TMP0
movlw .8
movwf _TMP1
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
nop
nop
ENDIF
IF R0==4
movlw .98
movwf _TMP0
movlw .11
movwf _TMP1
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
nop
ENDIF
IF R0==5
movlw .251
movwf _TMP0
movlw .13
movwf _TMP1
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
nop
nop
ENDIF
IF R0==10
movlw .248
movwf _TMP0
movlw .26
movwf _TMP1
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
nop
ENDIF
IF R0==50
movlw .220
movwf _TMP0
movlw .130
movwf _TMP1
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
ENDIF
IF R0==100
movlw .186
movwf _TMP0
movlw .4
movwf _TMP1
movlw .2
movwf _TMP2
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
decfsz _TMP2,F
goto $-5
ENDIF
IF R0==150
movlw .150
movwf _TMP0
movlw .134
movwf _TMP1
movlw .2
movwf _TMP2
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
decfsz _TMP2,F
goto $-5
ENDIF
ENDIF
ENDM
tamamen bitmedi bazı kısımlar örneğin pause komutu her süre için yazılmadı çok uzun olacağı için birde movff komutu sadece ilk 4 bank arası veri kaydı için hazır.
birde bölme ve çarpma makroları pic basic pro dan modifiye farklı olarak 32 bit sonuç verebiliyorlar.
bu makroları xxxx.inc şeklinde kaydedip ana programa include ederek komutları kullanabilirsiniz
ayrıca meblab ide için if ve ifdef komutlarına basit örnek olabilecek komutlar da var içinde tabi destek atarsanız sevinirim örneğin işaretli sayılar ile işlemler için makro yazabiliriz.
Video güzel olmuş. Emeğiniz için teşekkür ederiz.
8 bit çarpma makrosunu kopyalayıp yapıtırabileceğimiz şekilde alabilir miyiz?
Videoya bakıp elle mi yazalım hocam?
;///////////////8X8 = 16 BİT////////////////////
MUL MACRO R3,R1
mult:
CLRF R2 ;Sonucu temizle
CLRF R2+1
MOVLW 0x08 ;Bit
counter:
MOVWF R4
MOVF R3 ,W ;çarpılanı w ye yaz
loop:
RRF R1 ,F ;çarpanı sağa kaydır
SKPNC ;taşmayı kontrol et
ADDWF R2+1 ,F ;sonuc ile topla
RRF R2+1 ,F ;sağa kaydır
RRF R2,F
DECFSZ R4,F ;8 kere tekrar
GOTO loop
ENDM
;****************************************************************
;* MUL : 16 x 16 = 32 multiply *
;* *
;* Input : R3 * R1 *
;* Output : R2, W = low word *
;* : R0, R2 + 1 = mid word *
;* : R0 = high word *
;* *
;* Notes : *
;****************************************************************
CARP MACRO R3,R3+1,R1,R1+1
MULL
MOVLW .16 ; For 16 shifts
MOVWF R4
CLRF R0 + 1
CLRF R0
mulloop
BCF STATUS, C
RRF R3 + 1, F
RRF R3, F
BTFSS STATUS, C ;
GOTO mull1 ; Skip add
MOVF R1, W ; 16-bit add with carry out
ADDWF R0, F
MOVF R1 + 1, W
BTFSC STATUS, C
INCFSZ R1 + 1, W
ADDWF R0 + 1, F
mull1
RRF R0 + 1, F
RRF R0 ,F
RRF R2 + 1,F
RRF R2 ,F
DECFSZ R4 ,F
GOTO mulloop
DONE
CLRF R3
CLRF R3+1
CLRF R1
CLRF R1+1
ENDM
;****************************************************************
;* DIV : 16 x 16 (31 x 15) divide *
;* *
;* Input : R0 / R1 *
;* Output : R0, R0+1 = bolüm *
;* : R2 = remainder kalan *
;* *
;* Notes : R2 = R0 MOD R1 *
;****************************************************************
BOL MACRO R0 ,R0+1 ,R1 ,R1+1
CLRF R2
CLRF R2+1
BCF STATUS,C
DIV32DIV
movlw .16
movwf R5
divloop
rlf R0 + 1, W
rlf R2, F
rlf R2 + 1, F
movf R1, W
subwf R2, F
movf R1 + 1, W
btfss STATUS, C
incfsz R1 + 1, W
subwf R2 + 1, F
btfsc STATUS, C
goto divok
movf R1, W
addwf R2, F
movf R1 + 1, W
btfsc STATUS, C
incfsz R1 + 1, W
addwf R2 + 1, F
bcf STATUS, C
divok
rlf R0, F
rlf R0 + 1, F
decfsz R5, F
goto divloop
movf R0, W ; Get low byte to W
ENDM
;////////////////////////// MOVFF KOMUTU////////////////////////////////////
; giriş ram = ram
MOVFF MACRO R5,R6
;R5 =BANK0--------R6 = BANK0
IF (R5) < 0X80 && (R6) < 0X80
MOVF R5 ,W
MOVWF R6
ENDIF
;////////////R5 =BANK0--------R6 = BANK1/////////////////
IF (R5) < 0X80 && (R6) > 0X7F&&(R6)<0X100
MOVF R5 ,W
BSF STATUS ,RP0
MOVWF R6
ENDIF
;-------------------R5=BANK0--------R6=BANK2/////////////////
IF (R5) < 0X80 && (R6) > 0XFF&&(R6)<0X180
MOVF R5 ,W
BSF STATUS ,RP1
MOVWF R6
ENDIF
;-------------------R5=BANK0--------R6=BANK3/////////////////
IF (R5) < 0X80 && (R6) > 0X17F
MOVF R5 ,W
BSF STATUS ,RP1
BSF STATUS ,RP0
MOVWF R6
ENDIF
; ;/////////////R5=BANK1-------R6=BANK0//////////////////
IF (R5) > 0X7F&&(R5)<0X100 && (R6) < 0X80
MOVF R5 ,W
BCF STATUS ,RP0
MOVWF R6
ENDIF
;/////////////R5=BANK1-------R6=BANK1//////////////////
IF (R5) > 0X7F&&(R5)<0X100 && (R6) > 0X7F && (R6) < 0X100
MOVF R5 ,W
MOVWF R6
ENDIF
;/////////////R5=BANK1-------R6=BANK2//////////////////
IF (R5) > 0X7F&&(R5)<0X100 && (R6) > 0XFF && (R6) < 0X180
MOVF R5 ,W
BCF STATUS ,RP0
BSF STATUS ,RP1
MOVWF R6
ENDIF
;/////////////R5=BANK1-------R6=BANK3//////////////////
IF (R5) > 0X7F&&(R5)<0X100 && (R6) > 0X17F
MOVF R5 ,W
BSF STATUS ,RP1
MOVWF R6
ENDIF
;/////////////R5=BANK2-------R6=BANK0//////////////////
IF (R5) > 0XFF && (R5) < 0X180 && (R6) < 0X80
MOVF R5 ,W
BCF STATUS ,RP1
MOVWF R6
ENDIF
;/////////////R5=BANK2-------R6=BANK1//////////////////
IF (R5) > 0XFF&& (R5)< 0X180 && (R6) > 0X7F && (R6) < 0X100
MOVF R5 ,W
BSF STATUS ,RP0
BCF STATUS ,RP1
MOVWF R6
ENDIF
;/////////////R5=BANK2-------R6=BANK2//////////////////
IF (R5) > 0XFF&& (R5)< 0X180 && (R6) > 0XFF && (R6) < 0X180
MOVF R5 ,W
MOVWF R6
ENDIF
; ;/////////////R5=BANK2-------R6=BANK3//////////////////
IF (R5) > 0XFF&& (R5)< 0X180 && (R6) > 0X17F
MOVF R5 ,W
BSF STATUS ,RP0
MOVWF R6
ENDIF
;/////////////R5=BANK3-------R6=BANK3//////////////////
IF (R5) > 0X17F && (R6) > 0X17F
MOVF R5 ,W
MOVWF R6
ENDIF
; ;/////////////R5=BANK3-------R6=BANK2//////////////////
IF (R5) > 0X17F && (R6) > 0XFF && (R6) < 0X180
MOVF R5 ,W
BCF STATUS ,RP0
MOVWF R6
ENDIF
; ;/////////////R5=BANK3-------R6=BANK1//////////////////
IF (R5) > 0X17F && (R6) > 0X7F && (R6) < 0X100
MOVF R5 ,W
BCF STATUS ,RP1
MOVWF R6
ENDIF
;/////////////R5=BANK3-------R6=BANK0//////////////////
IF (R5) > 0X17F && (R6) < 0X80
MOVF R5 ,W
BCF STATUS ,RP0
BCF STATUS ,RP1
MOVWF R6
ENDIF
ENDM
;//////////////////////MANCHESTER KODU///////////////////////
;///////// 8 BİT VERİYİ MENCHESTER KODUNA DÖNÜŞTÜRME///////
;///////////////// R2-R2+1 MANCHESTER KODU//////////////////
MNCOD MACRO R3
MOVLW 0X08
MOVWF R1
CLRF R2
CLRF R2+1
LL:
BCF STATUS ,C
RRF R3 ,W
RRF R2+1
RRF R2
; MOVLW 0X80 ;G.E. Thomas STANDARDI İÇİN BU AÇILACAK
; XORWF R2+1
BCF STATUS ,C
RRF R3
RRF R2+1
RRF R2
MOVLW 0X80 ;IEEE 802.3 STANDARDI İÇİN BU AÇILACAK
XORWF R2+1
DECFSZ R1
GOTO LL
ENDM
;/////////////////////////MANCHESTER KODU BİNARY KODA ÇEVİRME///////////
; R3 = BINARY
;
;
MNCOD_IN MACRO R2 ,R2+1
MOVLW .8
MOVWF R1
CLRF R3
CLRF R3+1
BCF STATUS ,C
RRF R2+1
RRF R2
RRF R3
BCF STATUS ,C
RRF R2+1
RRF R2
DECFSZ R1
GOTO $-8
ENDM
;//////////////////////PAUSE ///////////////////
;///////////////////////MS/////////////////////
PAUSE MACRO R0
IFDEF OSC_8
IF R0 == 1
movlw .151
movwf _TMP0
movlw .3
movwf _TMP1
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
nop
nop
ENDIF
IF R0 == 2
movlw .48
movwf _TMP0
movlw .6
movwf _TMP1
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
nop
ENDIF
IF R0==3
movlw .201
movwf _TMP0
movlw .8
movwf _TMP1
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
nop
nop
ENDIF
IF R0==4
movlw .98
movwf _TMP0
movlw .11
movwf _TMP1
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
nop
ENDIF
IF R0==5
movlw .251
movwf _TMP0
movlw .13
movwf _TMP1
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
nop
nop
ENDIF
IF R0==10
movlw .248
movwf _TMP0
movlw .26
movwf _TMP1
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
nop
ENDIF
IF R0==50
movlw .220
movwf _TMP0
movlw .130
movwf _TMP1
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
ENDIF
IF R0==100
movlw .186
movwf _TMP0
movlw .4
movwf _TMP1
movlw .2
movwf _TMP2
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
decfsz _TMP2,F
goto $-5
ENDIF
IF R0==150
movlw .150
movwf _TMP0
movlw .134
movwf _TMP1
movlw .2
movwf _TMP2
decfsz _TMP0,F
goto $-1
decfsz _TMP1,F
goto $-3
decfsz _TMP2,F
goto $-5
ENDIF
ENDIF
ENDM
hazır makroların tamamı
q
32 bit işraretli sayılarla işlemlerin yapıldığı kodları nihayet buldum internetten.işaretsiz kısmını zaten yapmıştık .kodları makro formatına sokup düzenledikten sonra paylaşacağım.belki bir video ile gene çalışma mantığını da anlatmaya çalışırım dilim döndüğünce.böylelikle matematik 4 işlem ile ilgili bütün makrolar tamamlanmış olacak İNŞALLAH. sonrasında duruma göre cos,sin falan gidebildiği yere kadar.
Alıntı yapılan: alikeskinkilic - 29 Ocak 2023, 16:08:5632 bit işraretli sayılarla işlemlerin yapıldığı kodları nihayet buldum internetten.işaretsiz kısmını zaten yapmıştık
Bu işlemleri sadece PIC için yapıyorsanız işinizi kolaylaştıracak bir tavsiye vereyim. Proton(positron) derleyici ile istediğiniz işlemi yazıp derledikten sonra ürettiği asm kodu açıp inceleyin. Direkt referans alabileceğiniz kadar düzenli, optimal ve anlaşılır bir asm çıktısı üretiyor. Sanki bir derleyici tarafından değil de insan tarafından üretilmiş hissi veriyor. Deneme sürümünde mcu modeli dışında bir sınırlama yok. İşinizi daha da hızlandırabilir.
güzel fikir disasembly yapılabilir üretilen kod aslında negatif sayıları hallettim neredeyse zor yoldan.belki float sayılarla işlem destekliyorsa bir örnek yapıp hex kodunu paylaşabilirseniz bayağı iyi olabilir.sonrasında kurmaya çalışayım bedava bir uygulama bulursam:) tabi C derleyici ile de derlenmiş hex dosyası olabilir aralarındaki işlem farkını da görmüş oluruz .kodun sadeliği bakımından örnek olarak a=10 b=0,2 c=a*b şeklinde bir kodun derlenmesi şeklinde kısa bir kod iyi olur.yerdım ederseniz sevinirim.tabi şöyle bir sorun oluşuyor disasembly kodlarında bazen işlemler koşullara bağlı oluyor örneğin negatif sayılarda işlemler için en değerli bitin durumu değerlendirilmek zorunda ona göre negatif için işlem yada pozitif için işlem yapılıyor disasembly kodlarında bu koşul görünmüyor sadece koşul sonucunda çıkan kod görüldüğü için geri kalan kısmını gene bizim bulmamız gereiyor en mantıklısı .lib uzantılı dosyadan direk kütüphanenin asm kodunu bulmak ama nedense pic basic pro haricinde hiç bir derleyicinin lib dosyasında asm kod bulamadım .
PIC18F25K22 için positron da bir derleme yaptım. Kodun içeriğinde 3 adet float değişken kullandım. 2 adet float değişkenine tam sayı olmayan değerler yükledim. Sonra sırasıyla bu sayıları üçüncü float değişkenine topladım, çıkarttım, çarptım ve böldüm. Programın bütün ön atamaları dahil toplam hafızadan 914 byte ram dan ise 28 byte kullandı. Aynı işlemi değişkenleri byte olarak kullandığımda program hafızadan her şey dahil 104 byte ram dan 9 byte kullandı. Çok başarılı bir sonuç olduğunu düşünüyorum.
Seçili Mcu lar için ücretsiz ve sınırsız versiyonu buradan indirebilirsiniz. (https://drive.google.com/file/d/1xN8HewwTQ1kOlt7a1WyJeNkjCisZVXd6/view) Listedeki MCU lar gayet yeterli.
Alıntı Yap"FREE" 14-bit core Devices:
PIC16F84, PIC16F628, PIC16F628A, PIC16F877, PIC16F877A, PIC12F1552, PIC16F1614, and PIC16F1937
"FREE" 18F devices:
PIC18F13K50, PIC18F25K20, PIC18F25K22 PIC18F452, PIC18F45K20, and PIC18F46K20
"FREE" 16-bit devices:
PIC24EP128MC202, PIC24FJ64GA002, PIC24FJ64GA004, and dsPIC33FJ128GP802
Device = 18F25K22
Declare Xtal = 4
Dim Float1 As Float = 3.14
Dim Float2 As Float = 2.15
Dim Float3 As Float
Main:
Float3 = Float1 + Float2 '2 Kayar noktatlı değişkenin toplanması
Float3 = Float1 - Float2 '2 Kayar noktatlı değişkenin çıkartılması
Float3 = Float1 * Float2 '2 Kayar noktatlı değişkenin çarpılması
Float3 = Float1 / Float2 '2 Kayar noktatlı değişkenin bölünmesi
End
Buradan da derlenen dosyaları inceleyebilirsiniz. (https://dosya.co/fbn0aylczi0c/flt_4_i%C5%9Flem.zip.html)
İlave Not: disasembly yapmanıza gerek yok zaten kendisi asm dosyası üretiyor. İhtiyaç duyarsanız kod içerisinde bildirim yaparak cof çıktısı üretmesini de sağlayabiliyorsunuz.
hocam 18 serisi ile 16 serisi arasında asm komut farkları var zahmet olmazssa 16 serisi bir işlemci ile aynı kodu derleyebilirmisiniz. hatta tüm işlemler için ayrı derlerseniz görünüşe göre tüm ram bölgesini dolduruyor böyle olunca çözmesi çok zor teker teker olursa süper olur
PIC16F84A için derlendi. Değişkenler hem float hem byte olarak kullanıldığı 2 ayrı dosya mevcut. Float lu olan derleme program hafızadan 529, ram dan 28 byte, Byte kullanılan derleme program hafızadan 76, ram dan 12 byte kullandı.
https://dosya.co/ojlwe62o11sa/4_işlem.zip.html (https://dosya.co/ojlwe62o11sa/4_i%C5%9Flem.zip.html)
float IEEE-754 formatında işleniyor formattan hiç birşey anlamadım aşırı gereksiz yer kaplıyor.halbuki 3.14 0.14 kısmını 100 ile çarpsa ve toplamda iki byte de saklasa daha mantıklı değilmi hem okuması hem çözmesi daha kolay olmazmı IEEE-754 mantığı nedir bilen açıklayabilirmi.3.14 için kaydedilen float karşılığı hex olarak 0x4048f5c3 çok saçma
Alıntı yapılan: alikeskinkilic - 30 Ocak 2023, 13:20:28float IEEE-754 formatında işleniyor formattan hiç birşey anlamadım aşırı gereksiz yer kaplıyor.halbuki 3.14 0.14 kısmını 100 ile çarpsa ve toplamda iki byte de saklasa daha mantıklı değilmi hem okuması hem çözmesi daha kolay olmazmı IEEE-754 mantığı nedir bilen açıklayabilirmi.3.14 için kaydedilen float karşılığı hex olarak 0x4048f5c3 çok saçma
Hiç öyle şey olur mu :) . Bu mantıkla 3.14 den 0.14 ü niçin ayırsın. Direkt 3.14*100 yapsın bu mantıkta aynı şey. Fakat noktadan sonra 8-7 hane devam ediyorsa ne olacak o zaman. Çözünürlük kötüleşir. 24 bit ve 32 bit floating yapısını ve mantığını öğrenmenizi tavsiye ederim.
Alıntı YapFormat Exponent Mantissa 0 Mantissa 1 Mantissa 2
IEEE-754 sxxx xxxx yxxx xxxx xxxx xxxx xxxx xxxx
Microchip xxxx xxxy sxxx xxxx xxxx xxxx xxxx xxxx
"Fakat noktadan sonra 8-7 hane devam ediyorsa ne olacak o zaman." işte bende onu anlamıyorum hocam diyelim 3.000001 sayısının karşılığı ıeee standardında hata payıyla çıkıyor zaten şöyle bir sayıya denk geliyor ram da tutulan bilgi "3.00000095367431640625" zaten kendinden hatalı format onun yerine 3.000001 sayısını 1 000 000 sayısı ile çarpınca sonuçta 3000001 sayısı çıkıyor üstelikte hata yok ve 32 bit uzunlukta da değil.herşeyi geçtim gene 32 bit yer kaplasın tamam benim dediğim mantıkla hata almadan kayan nokta alınabilirken ve komut sayısı bakımından da yarı yarıya fark varken.neden avantajını merak ediyorum sadece dönşümler bu sitede yapılmıştır https://float.exposed/0x40400004
virgülden sonrasını çarpmamın sebebi örneğin proton kütüphanesi 32 bit tutuyorya sayıyı bunun yerine 3,5 için 2 byte tutsa zaten virgüllü sayı kullanılması durumunda ayrılan ram bölgesi farklı atanmış yani eğer virgüllü sayı kullanılırsa hep ayrılmış ram bölgelerine kaydediliyor gene aynı mantıkla 0,5 için 0000 0101 şeklinde yada kütüphanede olduğu şekli ile alt 23 biti içerisinde 5 sayısını tutsa tam sayıdan farklı şekilde işlem görüyor zaten kütüphane içinde de .şunu denedim acaba bu formatta 32 bitlik bir sayının ardına ondalık bir sayıyı kabul ediyormu diye etmiyor taşıyor yani ondalık ile tam sayı arasında ödünleşme var tam sayı ne kadar büyükse ondalık kısmı o kadar küçülmek zorunda aynı şekilde tersi de geçerli bir farkı yokki o zaman
Alıntı yapılan: alikeskinkilic - 30 Ocak 2023, 15:17:54"Fakat noktadan sonra 8-7 hane devam ediyorsa ne olacak o zaman." işte bende onu anlamıyorum hocam diyelim 3.000001 sayısının karşılığı ıeee standardında hata payıyla çıkıyor zaten şöyle bir sayıya denk geliyor ram da tutulan bilgi "3.00000095367431640625" zaten kendinden hatalı format onun yerine 3.000001 sayısını 1 000 000 sayısı ile çarpınca sonuçta 3000001 sayısı çıkıyor üstelikte hata yok ve 32 bit uzunlukta da değil.herşeyi geçtim gene 32 bit yer kaplasın tamam benim dediğim mantıkla hata almadan kayan nokta alınabilirken ve komut sayısı bakımından da yarı yarıya fark varken.neden avantajını merak ediyorum sadece dönşümler bu sitede yapılmıştır https://float.exposed/0x40400004
IEEE754 örneklerine bakarsan neden böyle bir gösterime ihtiyaç duyulmuş kavrarsın. Çok büyük ve küçük sayıları -ki bazı gösterimlerde bir miktar hata olacaktır- sabit uzunlukta (32 Bit) ifade etmeni sağlar. Ondalık kısmı her zaman 23 bitle ifade edilir boyutu değişmez, tam sayı kısmı ise 8 bit ile fiade edilir o da değişmez ve son olarak da 1 bit işaret içerir. Bu gösterim ile sınırlı bir alanda -32 bit- mümkün olduğunca çok değeri gösterebilmek istiyorsun bu yüzden bazı değerlerde hata kaçınılmaz olacaktır, fakat çoğu durumda kabul edilebilir seviyededir.
Örneğin Float32 nin temsil aralığı şu şekilde -3.4028234664 × 10^38 ile +3.4028234664 × 10^38 Bu büyüklükte sayıları bahsettiğiniz yöntemle kaydetmeye kalksaydık ne olurdu?
Peki her işlemde genişletmek için kullanılacak katsaysyı nasıl seçeçceksin ? Bir yerde 1M yeterken başka bir yerde başka bir katsayı kullandığında ne olacak?
Alıntı yapılan: alikeskinkilic - 30 Ocak 2023, 15:54:13virgülden sonrasını çarpmamın sebebi örneğin proton kütüphanesi 32 bit tutuyorya sayıyı bunun yerine 3,5 için 2 byte tutsa zaten virgüllü sayı kullanılması durumunda ayrılan ram bölgesi farklı atanmış yani eğer virgüllü sayı kullanılırsa hep ayrılmış ram bölgelerine kaydediliyor gene aynı mantıkla 0,5 için 0000 0101 şeklinde yada kütüphanede olduğu şekli ile alt 23 biti içerisinde 5 sayısını tutsa tam sayıdan farklı şekilde işlem görüyor zaten kütüphane içinde de .şunu denedim acaba bu formatta 32 bitlik bir sayının ardına ondalık bir sayıyı kabul ediyormu diye etmiyor taşıyor yani ondalık ile tam sayı arasında ödünleşme var tam sayı ne kadar büyükse ondalık kısmı o kadar küçülmek zorunda aynı şekilde tersi de geçerli bir farkı yokki o zaman
İyi de o zaman Long, Dword değişken tiplerini kullanırsın. Kayar noktalı değişken olmasının bir anlamı yok ki. Bu derleyicilere has bir şey değil. Microchip kendi çiplerinde kendi floating point standardını oluşturduğu için ona uyulması gerektiği için kullanılmış. Sizin tarif ettiğiniz yöntemde noktanın kayması gibi bir durum söz konusu değil. Yani tam sayı olmayan kısım sabit bir uzunluk, tam sayı başka bir kısımda. Buda doğrudan çözünürlüğü etkiliyor. Yani pi sayısını 3.14159265359 gibi işleme varken 3.14 olarak işlemek oluyor. Yada 1234 sayısının karekökten çıkartırken 111,1080555135405 yerine 111,1'i tercih etmek oluyor. Kayar noktalı yapıyı daha iyi anlamak için Link (http://talhakum.com/2017-01-04-kayan-noktali-sayilar/) deki örnekleri inceleyin.
Tamamdır hocam teşekkürler anladım olayı . Şu kısmı hala saçma geliyor o başka Bu büyüklükleri dandik bir 16 serisinde ne diye kullanırlar orası ayrı tabi.neyse uğraşıcaz bi şekilde çözmeye
O zaman dikkat etmen gereken bir noktaya daha parmak basmak gerekli. Bilgisayarımız da kullandığımız işlemcilerin floating işleme standardı IEEE754 dür. Fakat microchip in kullandığı formatın mantığı aynı olmasına rağmen bit sıralamarında bazı değişikler mevcuttur (hangi sivri zekalıdan çıktıysa bu fikir tepesi deline tez vakitte). Floting point donanıma sahip mcu lar için kod üretirken buna dikkat etmek gerekir. Ayrıca 24bit, 32bit ve 64bit formatlarında olduğu unutulmamalı.
Alıntı yapılan: alikeskinkilic - 30 Ocak 2023, 22:22:59... Şu kısmı hala saçma geliyor o başka Bu büyüklükleri dandik bir 16 serisinde ne diye kullanırlar orası ayrı tabi.neyse uğraşıcaz bi şekilde çözmeye
Aslında zaman zaman ihtiyaç olabiliyor. Mesela bazı enerji analizörlerinde registerlar kayar noktalı olarak saklanıyor. Modbus üzerinde bu veriyi okuyup işlemek istediğinde o zaman bu dönüşüme ihtiyaç oluyor. Proton bunu 12f serisi için bile yapıyor. Ne gerek var diyebilirsiniz. Ama insanları anlamak mümkün olmuyor bazen. Burası dışında bir forumda ardunio donanımla yaptığı bir işi 20 yıl öncesine ait teknolojiye sahip pic12f675 yapmaya çalışıp derleyiciler buna da destek versin diye oflayan puflayan insanlar var.
size güzel bir tüyo daha vereyim program başında "radix dec" velya "list r=dec " ifadesi ile program içerisinde vereceğimiz değerlerde şu tarz oynamalar yapabiliriz
BASLA:
CLRF STATUS
MOVLW -8*11
MOVWF SAYI
MOVLW (28<<2)-42
MOVWF KERE
ADDWF SAYI ,W ;TOPLAMA SONUCUNU 0XEE(-18) ŞEKLİNDE BULUR
sonucunu 8 bit için doğru verir yani SAYI= 0xA8 yani -88 KERE =0x46 yani 70 olur.işe yarar kısmı negatif sayı verirken comf yapmak zorunda kalmazssınız işlemleri de hatasız yapar.radix dec belirtilmezse hex sayı üzerinden de aynı işlemler yapılır anlaması zor olur ve negatif sayıları karıştırır sadece
32 Bit işaretli sayıları paket halinde değişkenlere yazmak için makro yazılan değer 2.147.483.647 ile -2.147.483.648 arası olabilir .
#include p16F690.inc
RADIX DEC :desimal sayılar ile işlem yapabilmek için gerekli
CBLOCK 0x20
Out0 :5 ;res 1 ;
ENDC
PAKET32 MACRO Var, Address ;Address meblab ide için Cblock yada udata kullanıldığında ram başlangıç adresidir(otm)
BANKSEL Address
movlw Address
movwf FSR ;fsr ye adresi yükler
movlw Var & H'FF' ;en değersiz byte filtrelenip yazılır
movwf INDF ;fsr nin işaretlediği adrese değeri yazar
movlw Var >>8 & H'FF' ; Var 8 bit kaydırılır filtrelenip fsr 1 arttırılır(bir sonraki ram bölgesi yazılır)
incf FSR,F
movwf INDF
movlw Var >>16 & H'FF'
incf FSR,F
movwf INDF
movlw Var >>24 & H'FF'
incf FSR,F
movwf INDF
ENDM
ORG 0
START
PAKET32 12345678,Out0 ; PAKET32 -12345678,Out0 yazıldığında da negatif değeri yazabilir adreslere
goto START
END
@alikeskinkilic neden asm ile derinlemesine uğraşıyorsun? Yanlış anlama bende asm temelliyim, ağır ticari projelerde yaptım (yakın zamanda)
Temel asm bilmenin ve programlama dillerinin nasıl geliştiğini bilmenin bir yazılımcı için zorunlu olması gerektiğini düşünüyorum ama
çokta asm üzerine yoğunlaşmamak lazım çok kısır bir kullanım alanı var, bunun yerine
sürdürülebilir, geliştirilebilir, ekip olarak rahatlıkla beraber çalışılabilir, kolay anlaşılabilir belli formatlı, üç ay üç yıl sonra bakılınca anlaşılabilir, başka kişilerinde sonradan dahil olabileceği insana daha yakın dilleri ortamları kullanmak daha faydalı.
Artık mcu programlamak için C dahi yetmiyor ve çok iyi işler için Matlab, Simulink, Embedded Coder ile model tabanlı tasarım yapıp hazır kod üreticiler ile kod üretiliyor, test ediliyor, revize edilip hatalar gideriliyor, sonradan rahatlıkla ekleme çıkarma yapılabiliyor kolaylıkla geliştirme gerçekleştirme yapılıyor.
Cevap Seviyorum.ayrıca kısır kullanım alanı olduğu gerçek değil çünkü kodu c le uçarcasına yazsanız da c yi geliştirenlerin ASM yazma becerisi kadar iyi olabilirsiniz fazlası değil.şöyle düşünebilirsiniz parlement alacak param var ama ben sigaramı kendim sararak içmeyi seviyorum .paylaşımları da ilgisini çeken biri belki faydalanır diye yapıyorum.
Seviyorsan güzel, takıntı olmasın yeter. Konuyu tartışmaya çevirme niyetim yok çünkü aynı kısır tartışmaları bende zamanında yaptım, asm candır gerisi heyecandır kıvamına geliyordum,
1960 ta kalmaya gerek yok. Kısaca sigara içmek zevkli ama zararlı ne içtiğinin önemi yok, önemli olan sigara satmak.
Bende eski asm algoritma çalışmalarımdan birini ekleyeyim hex to BCD dönüştürücü:
Asm hali https://www.picproje.org/index.php/topic,52348.msg396670.html#msg396670
C karşılığı
https://www.picproje.org/index.php/topic,54453.msg416052.html#msg416052
Buda denediğim birşey forumdada paylaşmışımdır, umarım sende asmden bir önceki adıma inmezsin.
http://danamlund.dk/pic_microcontroller_blinking_led_without_cheating.html
saygı duyarım ,tartışmayı da isterim de burada değil bir başlık açın diller arasında artısı eksisi tartışırız faydalı da olur ama burada başlık ASM birşeyler paylaşıyorum yani ASM öğrenmek isteyenler için konu faydasız yerlere gider.bırakın konu ile ilgili paylaşımlar yapılsın lütfen
EEPROM yazma ve okuma makrosu
;/////////////////////////////////////////////////////////////////
;EEPROM YAZMA
;/////////////////////////////////////////////////////////////////
WRITE MACRO R3,R1
BCF INTCON, GIE
MOVF R3 , W;adresi w ye yaz
BANKSEL EEADR
MOVWF EEADR ;adresi seç
BANKSEL R1
MOVF R1 , W; veriyi w ye yaz
BANKSEL EEDAT
MOVWF EEDAT ;veriyi yaz
BANKSEL EECON1
BCF EECON1, EEPGD ;kayıt için eeprom u seç
BSF EECON1, WREN ;yazmayı aç
MOVLW 0X55
MOVWF EECON2 ;Write 55h
MOVLW 0XAA
MOVWF EECON2 ;Write AAh
BSF EECON1 ,WR ; WR biti ile yazmaya başla
BTFSC EECON1 ,WR ; yazma tamamlanınca WR otm 0 olur
GOTO $-1
BCF EECON1, WREN ;yazmayı kapat
BCF STATUS,RP1
BCF STATUS,RP0 ;Bank 0
ENDM
;////////////////////////////////////////////////////////////////
;EEPROM OKUMA
;////////////////////////////////////////////////////////////////
READ MACRO R3
MOVF R3, W ; adresi W ye yaz
BANKSEL EEADR
MOVWF EEADR ;adrese git
BANKSEL EECON1
BCF EECON1, EEPGD ;eeprom u seç
BSF EECON1, RD ;okumayı aç
BTFSC EECON1, RD ; okuma tamamlanınca ptm 0 olur
GOTO $-1
BANKSEL EEDAT
MOVF EEDAT, W ;W = EEDAT
BANKSEL PORTA
ENDM
makro kullanımı yazma için WRITE ADRES, DATA
okuma için READ ADRES şeklinde olacak.okuma sonucu W ye yazılır.
TOGGLE MACRO PORT?,R0
MOVLW 0X01<<R0
XORWF PORT? ,F
ENDM
Ana program içerisinde TOGGLE PORT?,5 (soru işareti yerine portun adı yazılacak A-B-C vb gibi)yazdığımızda pinin o anki durumunu tersleyecektir.Not.makrodaki soru işaretine ellemeyin kalacak meplab soru işaretini bizim ana programda yazdığımızla dolduracaktır.
koşullu dallanmalar için (<=,< ve =) içim makro tersi koşulları yazmadım zaten true/false çıkış verdiği için aynı makrolarla işlenebilir oldu.kod çıktısı diğer dillerin yarısından az tabi artı kısmı.kullanımını kodun başlığında açıklamaya çalıştım.denemeleri yaptım bi hata göremedim sorusu olan veya hata bulan olursa yazar.
;///////////////////DEĞER KIYASLAMASI//////////////////////////////////
;KULLANIMI= KARŞILAŞTIRILACAK HER BİR "WORD" DEĞERİ ARDIŞIK RAM BÖLGELERİNDE TUTULMALI
;R4 VE R5 DEĞERLERİNİ ASCII DEĞERLER OLARAK İLGİLİ İŞARETLER OLARAK SEÇTİM
;MAKRODA "=" SENBOLÜ KABUL EDİLMEDİĞİ İÇİN DEC KARŞILIĞI YAZILDI
;AMA ANA PROGRAMDA KULLANILABİLİR OLDU
;ÖRNEK KODLAR= KIYAS A,"<","=",B
; KIYAS A,"<"," ",B
; KIYAS A,"="," ",B
; BTFSS R6 ,0
; GOTO ****
; GOTO ****
;BOŞ BIRAKILAN SEMBOL YERİNE ASCII BOŞLUK BIRAKILMALI
;R6 ADRESİNİN İLK BİTİ TRUE/FALSE DÖNDÜRÜR
;MAKRO ÇIKIŞI R6 , 0 BİTİ KONTROL EDİLEREK İŞLEM YAPILIR
;" > " YADA ">=" İŞARETİ İÇİN AYRI BİR İŞLEME GEREK YOK MEVCUT İŞLEMLERİN TERSİ OLDUĞUNDAN SADECE DEĞİŞKEN YERİ DEĞİŞECEK
KIYAS MACRO R0,R4,R5,R2
IF R4 == "<" && R5 == 61
MOVF R0+1 ,W ;IF Y <= ART THEN GOTO KAPA
SUBWF R2+1 ,W ;
BTFSS STATUS ,C ;
GOTO YANLIS ;GOTO SAG_KAPA
BTFSS STATUS ,Z
GOTO DOGRU ;GOTO SAG_AC
MOVF R0 ,W
SUBWF R2 ,W
BTFSS STATUS ,C
GOTO YANLIS
GOTO DOGRU
ENDIF
IF R4 == "<" && R5 == 32
MOVF R0+1 ,W ;IF Y < ART THEN
SUBWF R2+1 ,W ;
BTFSS STATUS ,C ;
GOTO YANLIS ;GOTO SAG_KAPA
BTFSS STATUS ,Z
GOTO DOGRU ;GOTO SAG_AC
MOVF R0 ,W
SUBWF R2 ,W
BTFSC STATUS ,Z
GOTO YANLIS
BTFSS STATUS ,C
GOTO YANLIS
GOTO DOGRU
ENDIF
IF R4 == 61 && R5 == 32 ;IF A=B
MOVF R0+1 ,W
XORWF R2+1 ,W
BTFSS STATUS ,Z
GOTO YANLIS
MOVF R0 ,W
XORWF R2 ,W
BTFSS STATUS ,Z
GOTO YANLIS
GOTO DOGRU
ELSE
GOTO EXT
ENDIF
YANLIS:
BCF R6 ,0
GOTO EXT
DOGRU:
BSF R6 ,0
GOTO EXT
EXT:
ENDM
;////////////////////////////////FOR-NEXT DÖNGÜSÜ///////////////////////////////
;KULLANIMI
; FOR 0,255 ; 256 TAKRAR YAPARAK FOR NEXT ARASINDAKİ KODU ÇALIŞTIRIR
; KODLAR
; ......
; NEXT
;*******************************************************************************
FOR MACRO R0,R2
; BCF INTCON ,7 ; KESMELER KAPATILMAK İSTENİRSE YORUMU KALDIRABİLİRSİNİZ
MOVLW R2
MOVWF R4
MOVLW R0
SUBWF R4 ,F
FOR1:
ENDM
NEXT MACRO
DECFSZ R4 ,F
GOTO FOR1
; BSF INTCON ,7 ;kesmeler çevrim boyunca kapatıldıysa çıkışta açılabilir
ENDM
;///////////////////////////////////////////////////////////////////////////////
;******************************************************************************
8 bit derinliğinde for next döngüsü için makro. kullanımı pic basic ile benzer.
Map fonksiyonu için makro bildiğimiz arduino map fonksiyonu ile aynı çalışıyor hayırlı olsun :)
ufak bir hata yapmışım düzeltip tekrar yayınlarım
MAP Fonksiyonunu düzelttim bölme makrosunun değişmesi gerekiyordu önceden 32 bit bölemiyordu şu an işaretli 32 bit bölme yapabiliyor.
MAP MACRO R0,R0+1,VAR,VAR1,VAR2,VAR3,ADDRESS
;{
;return ((value - fS) * (tE - tS)) / ((fE - fS) + tS);
;map(value,fS, fE, tS,tE)
;map(512, 0, 1023,0, 2000) ((512-0)*(2000-0)/(1023-0)+0)
BANKSEL ADDRESS
movlw ADDRESS ;
movwf FSR ;fsr ye adresi yükler
movlw VAR & H'FF' ;;en değersiz byte filtrelenip yazılır
movwf INDF ;fsr nin işaretlediği adrese değeri yazar
movlw VAR >>8 & H'FF' ;; Var 8 bit kaydırılır filtrelenip fsr 1 arttırılır(bir sonraki ram bölgesi yazılır)
incf FSR ,F
movwf INDF
MOVLW VAR1 &0XFF
INCF FSR ,F
MOVWF INDF
MOVLW VAR1>>8 & 0XFF
INCF FSR ,F
MOVWF INDF
MOVLW VAR2 & 0XFF
INCF FSR ,F
MOVWF INDF
MOVLW VAR2 >> 8 &0XFF
INCF FSR ,F
MOVWF INDF
MOVLW VAR3 & 0XFF
INCF FSR ,F
MOVWF INDF
MOVLW VAR3 >> 8 &0XFF
INCF FSR ,F
MOVWF INDF
;*******************************************************************FONKSİYONLAR**************************
MOVF R1 ,W
SUBWF R0 ,F
BTFSS STATUS ,C
INCF R1+1 ,F ;VALUE-FS
MOVF R1+1 ,W ;SONUC R0
SUBWF R0+1 ,F
;///////////////////////////////
MOVF R3 ,W
SUBWF R4 ,W
MOVWF R5
BTFSS STATUS ,C
INCF R3+1 ,F ;TE-TS
MOVF R3+1 ,W ;SONUC R5
SUBWF R4+1 ,W
MOVWF R5+1
;********************************
MULL32 R5,R5+1,R0,R0+1 ;((value - fS) * (tE - tS)) ;SONUC= XSL-XSH 32BİT
MOVF R1 ,W ; 60 62 64 66 68 ADRESLER
SUBWF R2 ,W
MOVWF R5 ; R0 R1 R2 R3 R4 DEĞİŞKENLER
BTFSS STATUS ,C ; MAP SAYI,0,1023,800,2200,R1 HARİTA
INCF R1+1 ,F ; (1023-0)+800 İŞLEM
MOVF R1+1 ,W ; map(value,fS, fE, tS,tE)
SUBWF R2+1 ,W
MOVWF R5+1 ; R2 - R1 + R3
;((fE - fS) + tS);
CLRF R6 ;SONUÇ = R2
CLRF R6+1
BOL XSL,XSL+1,XSH,XSH+1,R5,R5+1,R6,R6+1
MOVF R3 ,W
ADDWF XSL ,F
MOVF R3+1 ,W
BTFSC STATUS ,C
INCF XSL+1 ,F
ADDWF XSL+1 ,F
BTFSC STATUS ,C
INCFSZ XSH
GOTO $+2
INCF XSH+1
MOVF XSL ,W
MOVWF MAP_SNC
MOVF XSL+1 ,W
MOVWF MAP_SNC+1
MOVF XSH ,W
MOVWF MAP_SNC+2
MOVF XSH ,W
MOVWF MAP_SNC+3
ENDM
fonksiyon içinde kullanılan makrolar güncellendi aşağıdadır
MULL32 MACRO X1,X1+1,X2,X2+1
MUL3:
MOVLW .16 ; For 16 shifts
MOVWF XX
CLRF XSH + 1
CLRF XSH
mulloop:
BCF STATUS, C
RRF X1 + 1, F
RRF X1, F
BTFSS STATUS, C ;
GOTO mull1 ; Skip add
MOVF X2, W ; 16-bit add with carry out
ADDWF XSH, F
MOVF X2 + 1, W
BTFSC STATUS, C
INCFSZ X2 + 1, W
ADDWF XSH + 1, F
mull1:
RRF XSH + 1, F
RRF XSH ,F
RRF XSL + 1,F
RRF XSL ,F
DECFSZ XX ,F
GOTO mulloop
DONE:
CLRF X1
CLRF X1+1
CLRF X2
CLRF X2+1
ENDM
;****************************************************************
;* DIV : 16 x 16 (31 x 15) divide *
;* *
;* Input : R0 / R1 *
;* Output : R0, R0+1 = bolüm *
;* : R2 = remainder kalan *
;* *
;* Notes : R2 = R0 MOD R1 *
;****************************************************************
; ----BÖLÜNEN--- ----BÖLEN----
;*** 32 BIT SIGNED DIVIDE ***
;REGA / REGB -> REGA
;Remainder in REGC
;Return carry set if overflow or division by zero
;*** 32 BIT SIGNED DIVIDE ***
;REGA / REGB -> REGA
;Remainder in REGC
;Return carry set if overflow or division by zero
BOL MACRO D0,D1,D2,D3,B0,B1,B2,B3
divide:
clrf DD1 ;Reset sign flag
call absa ;Make dividend (REGA) positive
skpc
call absb ;Make divisor (REGB) positive
skpnc
return ;Overflow
clrf DR0 ;Clear remainder
clrf DR1
clrf DR2
clrf DR3
movlw D'32' ;Loop counter
movwf DD
;call slac ;Purge sign bit
dvloop:
call slac ;Shift dividend (REGA) msb into remainder (REGC)
movf B3,w ;Test if remainder (REGC) >= divisor (REGB)
subwf DR3,w
skpz
goto dtstgt
movf B2,w
subwf DR2,w
skpz
goto dtstgt
movf B1,w
subwf DR1,w
skpz
goto dtstgt
movf B0,w
subwf DR0,w
dtstgt:
skpc ;Carry set if remainder >= divisor
goto dremlt
movf B0,w ;Subtract divisor (REGB) from remainder (REGC)
subwf DR0,f
movf B1,w
skpc
incfsz B1,w
subwf DR1,f
movf B2,w
skpc
incfsz B2,w
subwf DR2,f
movf B3,w
skpc
incfsz B3,w
subwf DR3,f
clrc
bsf D0,0 ;Set quotient bit
dremlt:
decfsz DD,f ;Next
goto dvloop
btfsc DD1,0 ;Check result sign
call negatea ;Negative
GOTO DIVCIK
;/////////////////////////////////////////////////////////////////
absa:
rlf D3,w
skpc
return ;Positive
negatea:
movf D3,w ;Save sign in w
andlw 0x80
comf D0,f ;2's complement
comf D1,f
comf D2,f
comf D3,f
incfsz D0,f
goto nega1
incfsz D1,f
goto nega1
incfsz D2,f
goto nega1
incf D3,f
nega1:
incf DD1,f ;flip sign flag
addwf D3,w ;Return carry set if -2147483648
return
;/////////////////////////////////////////////////////////////////
absb:
rlf B3,w
skpc
return ;Positive
negateb:
movf B3,w ;Save sign in w
andlw 0x80
comf B0,f ;2's complement
comf B1,f
comf B2,f
comf B3,f
incfsz B0,f
goto negb1
incfsz B1,f
goto negb1
incfsz B2,f
goto negb1
incf B3,f
negb1
incf DD1,f ;flip sign flag
addwf B3,w ;Return carry set if -2147483648
return
;///////////////////////////////////////////////////////////
slac:
rlf D0,f
rlf D1,f
rlf D2,f
rlf D3,f
slc:
rlf DR0,f
rlf DR1,f
rlf DR2,f
rlf DR3,f
return
DIVCIK:
ENDM
buda örnek kod
__CONFIG 0x0024
LIST P = PIC16F690
INCLUDE "p16f690.inc"
list r=dec
INCLUDE "KTPNE.INC"
#define _C STATUS,0
#define _Z STATUS,2
#DEFINE OSC_8
; #DEFINE PWM 0X60
; #DEFINE KP
;udata
CBLOCK 0X20
SAYI :2
KERE :2
MAP_SNC:4
ENDC
R0 EQU 0X60
R1 EQU 0X62
R2 EQU 0X64
R3 EQU 0X66
R4 EQU 0X68
R5 EQU 0X6A
R6 EQU 0X6C
R7 EQU 0X6E
;BÖLME DEĞİŞLENKERLİ
CBLOCK 0X50
D0
D1
D2
D3
B0
B1
B2
B3
DR0
DR1
DR2
DR3 ;0X5B
DD
DD1 ;0X5D
ENDC
;ÇARPMA DEĞİŞKENLERİ
CBLOCK 0X70
X1 :2
X2 :2
XSL :2
XSH :2
XX
ENDC
ORG 0X00
GOTO AYAR
ORG 0X04
AYAR:
BANKSEL TRISA
MOVLW 0x00
MOVWF TRISA
MOVLW 0xFF
MOVWF TRISC
MOVLW 0x00
MOVWF TRISB
MOVLW 0x82
MOVWF OPTION_REG
MOVLW 0x70
MOVWF OSCCON
BCF STATUS, RP0 ;BANK0
MOVLW 0x00
MOVWF ADCON0
MOVLW 0x00
MOVWF PORTA
MOVWF PORTB
MOVWF PORTC
BSF STATUS,RP1 ;BANK2
MOVLW 0x00
MOVWF ANSEL
MOVLW 0x00
MOVWF ANSELH
BCF CM1CON0,7
BCF CM2CON0,7
CLRF WPUB
BSF IOCB ,7
BANKSEL PSTRCON
CLRF PSTRCON
BCF STATUS,RP1
BCF STATUS,RP0 ;BANK0
MOVLW 0X00
MOVWF INTCON
CLRF PORTA
CLRF PORTB
CLRF PORTC
BASLA:
PAKET16 512,SAYI
MAP SAYI,,0,1023,0,2000,R1
GOTO BASLA
END
işlem sonucunu MAP_SNC değişkenine 32 bit şeklinde yazar
bölme makrosunu değiştirdim artık 32 bitin tamamını her seferde kaydır çıkar yapmak zorunda değil en üst bitte 1 bulana kadar sadece kaydırarak sayının büyüklüğüne göre küçük sayılarda iki kat hızlandı neredeyse.makro adı ve kullanımını da değiştirdim daha bir kullanıcı dostu oldu hayırlı olsun
DIV32 MACRO ;? == A,A+1,A+2,A+3
;?0== B,B+1,B+2,B+3
divide:
clrf DD1 ;Reset sign flag
call absa ;Make dividend (REGA) positive
skpc
call absb ;Make divisor (REGB) positive
skpnc
return ;Overflow
movlw D'33' ;Loop counter
movwf DD
BASAMAK:
CALL TEST
SKPC
GOTO BASAMAK
CALL GERIAL
clrf DR0 ;Clear remainder
clrf DR1
clrf DR2
clrf DR3
; movlw D'32' ;Loop counter
; movwf DD
;call slac ;Purge sign bit
dvloop:
call slac ;Shift dividend (REGA) msb into remainder (REGC)
movf ?0+3,w ;Test if remainder (REGC) >= divisor (REGB)
subwf DR3,w
skpz
goto dtstgt
movf ?0+2,w
subwf DR2,w
skpz
goto dtstgt
movf ?0+1,w
subwf DR1,w
skpz
goto dtstgt
movf ?0,w
subwf DR0,w
dtstgt:
skpc ;Carry set if remainder >= divisor
goto dremlt
movf ?0,w ;Subtract divisor (REGB) from remainder (REGC)
subwf DR0,f
movf ?0+1,w
skpc
incfsz ?0+1,w
subwf DR1,f
movf ?0+2,w
skpc
incfsz ?0+2,w
subwf DR2,f
movf ?0+3,w
skpc
incfsz ?0+3,w
subwf DR3,f
clrc
bsf ? , 0 ;Set quotient bit
dremlt:
decfsz DD,f ;Next
goto dvloop
btfsc DD1,0 ;Check result sign
call negatea ;Negative
GOTO DIVCIK
;/////////////////////////////////////////////////////////////////
absa:
rlf ?+3,w
skpc
return ;Positive
negatea:
movf ?+3,w ;Save sign in w
andlw 0x80
comf ? ,f ;2's complement
comf ?+1 ,f
comf ?+2 ,f
comf ?+3,f
incfsz ? ,f
goto nega1
incfsz ?+1,f
goto nega1
incfsz ?+2,f
goto nega1
incf ?+3,f
nega1:
incf DD1,f ;flip sign flag
addwf ?+3 ,w ;Return carry set if -2147483648
return
;/////////////////////////////////////////////////////////////////
absb:
rlf ?0+3,w
skpc
return ;Positive
negateb:
movf ?0+3,w ;Save sign in w
andlw 0x80
comf ?0 ,f ;2's complement
comf ?0+1,f
comf ?0+2,f
comf ?0+3,f
incfsz ?0,f
goto negb1
incfsz ?0+1,f
goto negb1
incfsz ?0+2,f
goto negb1
incf ?0+3,f
negb1
incf DD1,f ;flip sign flag
addwf ?0+3,w ;Return carry set if -2147483648
return
;///////////////////////////////////////////////////////////
slac:
rlf ?,f
rlf ?+1,f
rlf ?+2,f
rlf ?+3,f
slc:
rlf DR0,f
rlf DR1,f
rlf DR2,f
rlf DR3,f
return
TEST:
DECF DD ,F
rlf ?,f
rlf ?+1,f
rlf ?+2,f
rlf ?+3,f
RETURN
GERIAL:
RRF ?+3,f
RRF ?+2,f
RRF ?+1,f
RRF ? ,f
RETURN
DIVCIK:
ENDM
program içerisinde kullanımı ise
CBLOCK 0X20
A :4
B :4
endc
BASLA:
DIV32 A,B
GOTO BASLA
END
işlem sonucunu gene A ya yazar
kütüphaneye yeni soluk geldi :)
eprom bölgesinin verimli ve uzun ömürlü kullanılması için kaydedilen verilerin kaç kez kaydedildiğini tutup istediğimiz kayıt sayısına ulaşınca (ben 254 yaptım)tutulan veri miktarı kadar adresi ileri taşıyarak yazmaya oradan devam eden tüm bölgeler yazıldıktan sonra da tekrar ilk adresten yazmaya başlayıp aynı süreci takip eden bir algoritmadır.kodun işleyişini program içinde yorum olarak yazdım okuması kolay olsun diye
ilgili makroları (yazma ve okuma)aşağıda ayrıca attım
EEPROM:
VERI_AL:;/////////////////// EPROMM OKU///////////////////
;ilk başlangıçta eeproma kayıtlı limit değeri
;alınıp program içinde kullanılan değişkenlere atanır
MOVLW 0 ;epromun ilk adresinden itibaren 0xFF harici veriyi arıyoruz
MOVWF ADR1 ;o veri bizim en son kayıtlarımızı yaptığımız adresin başlangıcı .
CALL EEPROM_OKU ;bu yüzden ilk adresimizin 0xFF e ulaşmayacak şekilde ayarladığım
XORLW 0XFF ;kayıt sayısını 254 e sınırlayıp yazıyorum.
BTFSS STATUS ,Z
GOTO $+3
INCF ADR1 ,F
GOTO $-5
MOVFF ADR1,ADR2 ;adresimizi bulduk şimdi başlangıcı ADR2 ye yedekliyoruz
CALL EEPROM_OKU ;ki ADR1 program içerisinde sürekli değişecek referansımız ADR2 olacak
MOVWF KAYIT_SAYISI ;ADRES1 = KAYIT ADEDİ 1 byte (aynı aderse kaç kayıt yapıldığını tutar)
INCF ADR1 ,F
CALL EEPROM_OKU ;ADRES2 = mod 1 BYTE DEĞERİNİ TUTAR
MOVWF MODE
INCF ADR1 ;setu =2 byte yer tutuyor toplamda 4 byte alan kullanıyoruz
CALL EEPROM_OKU
MOVWF SETU
INCF ADR1
CALL EEPROM_OKU
MOVWF SETU+1
MOVFF ADR2,ADR1
BTFSC PORTA ,2
GOTO START
BTFSC PORTA ,1
GOTO START
MOVFF ADR2,ADR1
INCF ADR1
TOGGLE MODE ,0
MOVFF MODE,EE
CALL EEPROM_YAZ
MOVFF ADR2,ADR1
GOTO START ;programda kullanılacak epromdaki veriler alınıp ilgili değişkenlere atandı
;kapatılıp açılmadıkça bura ile işimiz bitti daha uğramayacak
;////////////////////////*****************************///////////////////////////
EEPROM_YAZ: ;karaını program içerisinde verdiğimiz (örn bir tuşa basmak yada bir kesme olması)
EWRITE ADR1,EE ;eproma kayıt yapar
MOVFF ADR2,ADR1 ;İLK ADRESİ GÜNCELLE
MOVLW 0XFE ;kayıt sayısı 254 oldu ise adres değiştirmeye gidiyor
XORWF KAYIT_SAYISI ,W ; değilse kayıt sayısını 1 artırıp devam ediyor
BTFSS STATUS ,Z ;İlk ADRESTEKİ KAYIT SAYISINI BİR ARRTIR VE GÜNCELLE
GOTO XXX
;254 KAYIT SAYISI OLDUYSA
GOTO ADRES_DEGIS
XXX: ;ADRES DEĞİŞ
MOVFF KAYIT_SAYISI ,EE
EWRITE ADR1,EE
GOTO DEVAM
;///////////////////////ADRES DEĞİŞ/////////////////
ADRES_DEGIS: ;Değişecek olan adreslerdeki verileri değişkenlere yedekliyoruz
MOVFF ADR2,ADR1 ;İLK ADRESİ AL( KAYIT SAYISI)
CALL EEPROM_OKU
MOVWF KAYIT_SAYISI
INCF ADR1 ,F ; verileri sıra ile AL
CALL EEPROM_OKU
MOVWF MODE
INCF ADR1 ,F
CALL EEPROM_OKU
MOVWF SETU
; MOVWF SETUA
INCF ADR1 ,F
CALL EEPROM_OKU
MOVWF SETU+1
; MOVWF SETUA+1
MOVFF ADR2,ADR1
MOVLW 0XFF ;ADRES TUTUCUDAKİ ADRES BAŞLANGIÇ SAYISINI VERİ SAYISI KADAR ARTTIR
MOVWF EE
MOVLW .4 ;ÖNCEKİ ADRESLERE 0XFF YAZ 4 byte yer tuttuğu için 4 tekrar yapıyor her seferinde adresi 1 artırıp
MOVWF _TMP0
; MOVFF ADR2,ADR1
CALL EPROMYAZ
INCF ADR1 ,F ;MODE
DECFSZ _TMP0
GOTO $-3
MOVF ADR2 ,W ;adres 248 oldu ise adresi 0 dan tekrar başlat(limit değeri veri miktarımızın katı olmak zorunda yoksa ADR2 limitimizi geçer haberimiz olmaz)
XORLW 0XF8 ;ADR2 de tuttuğumuz adres başlangıcının değeri istediğimiz limite ulaştı ise
BTFSS STATUS ,Z
GOTO YZX
YYY:
CLRF ADR2 ;eprom en başından başlayarak tekrar yazmaya başlar
CLRW ;ADR2 sıfırlanır
GOTO XYZ
YZX:
MOVLW 4 ;eğer limite ulaşmadı ise mevcut adrese ADR2 ye 4 eklenir(veri sayısı )
MOVWF _TMP0
XYZ:
ADDWF ADR2 ;ve değişkenlere yedeklerini aldığımız tüm veriler
MOVFF ADR2,ADR1 ;yeni adreslerine yazılır.
CLRF KAYIT_SAYISI
MOVFF KAYIT_SAYISI,EE ;KAKYIT_SAYISI ;KAYDEDİLEN VERİLER 3 ADET
CALL EPROMYAZ
INCF ADR1
MOVFF MODE,EE
CALL EPROMYAZ
INCF ADR1
MOVFF SETU,EE
CALL EPROMYAZ
INCF ADR1
MOVFF SETU+1,EE
CALL EPROMYAZ
MOVFF ADR2,ADR1
GOTO DEVAM
EPROMYAZ:
EWRITE ADR1,EE ;eeprom yazma makrosu
; INCF ADR1 ,F
RETURN
DEVAM:
RETURN
EEPROM_OKU:
EREAD ADR1 ;eeprom okuma makrosu
RETURN
START:
EEPROM okuma ve yazma makroları
;/////////////////////////////////////////////////////////////////
;EEPROM YAZMA
;/////////////////////////////////////////////////////////////////
EWRITE MACRO ?3,?1 ;WRITE ADRES , DATA
BCF INTCON ,GIE ;KESMELERİ KAPAR (ÖNEMLİ KESME OLMAMALI YAZMA ESNASINDA)
BCF PIR2 ,EEIF ;BAYRAĞI İNDİR
MOVF ?3 ,W ;
BANKSEL EEADR
MOVWF EEADR ;BELİRTTİĞİMİZ ADRESİ EEADR E YAZ(YAZILACAK ADRESİ SEÇ)
BANKSEL ?1
MOVF ?1 ,W ;
BANKSEL EEDAT
MOVWF EEDAT ;VERİYİ ADRESE YAZ
BANKSEL EECON1
BCF EECON1 ,EEPGD ;eeprom veya program hafızası seçilebilir.burada eeprom seçili
BSF EECON1 ,WREN ;yazmayı aç
MOVLW 0X55
MOVWF EECON2 ;yazma için rutin olan h55 ve hAA komutları eecon2 ye sırası ile yazılmalı
MOVLW 0XAA
MOVWF EECON2 ;eecon2 ye sırası ile yazılmalı
BSF EECON1 ,WR ;yazmaya başla
BTFSC EECON1 ,WR
GOTO $-1 ;bitene kadar takıl
BANKSEL PIR2
BTFSS PIR2 ,EEIF ;TAMAMLANINCA BAYRAK KALKAR DEVAM
GOTO $-1
BANKSEL EECON1
BCF EECON1 ,WREN ;yazmayı kapat
BCF STATUS ,RP1
BCF STATUS ,RP0 ;Bank 0
BCF PIR2 ,EEIF ;BAYRAĞI İNDİR
; BSF INTCON ,GIE
ENDM
;////////////////////////////////////////////////////////////////
;EEPROM OKUMA
;////////////////////////////////////////////////////////////////
EREAD MACRO ?
MOVF ?, W;
BANKSEL EEADR
MOVWF EEADR ;Data Memory ;Address to read
BANKSEL EECON1
BCF EECON1, EEPGD ;Point to DATA memory
BSF EECON1, RD ;EE Read
BTFSC EECON1, RD
GOTO $-1
BANKSEL EEDAT
MOVF EEDAT, W ;W = EEDAT
BANKSEL PORTA
ENDM
evet devam kendi yazdığım makrolarda hız sağlam oldu fakat birbiri ile ilişkilendirme konusunda kusurları var her program için uyum sağlayamadım bende http://www.piclist.com/techref/microchip/math/index.htm (http://www.piclist.com/techref/microchip/math/index.htm) sitesinde paylaşılan math kütüphanelerini kullanarak makro oluşturma kararı aldım biraz daha fazla zaman harcıyorlar ama en azından her seferinde stabil çalışıyorlar.makro ve sub asm dosyası halinde paylaşıyorum kullanımları kodların içinde yapmaya çalıştım. örnek ana program
__CONFIG 0x30E4
radix dec
LIST P = PIC16f690
INCLUDE "p16f690.inc"
; INCLUDE "EPROM.INC"
INCLUDE "MATH.INC"
; INCLUDE "fload.inc"
RADIX DEC
extern REGA0,REGB0,REGC0,subtract,add,multiply,divide,clrba,sqrt,DCOUNT,DCOUNT
;
; GLOBAL MAPS
; EXTERN ;FLO1624,INT2416,FPM24,FLO2424;R0,R1,R2,R3,R4,DIZ0,DIZ1,R6,R7,R8,R9,R10,R11,R12,R13,R14,R15,R16,R17;,D0,D1,D2,D3,DS,DR,M0,M1,M2,MS,IF0,IF1,F0,F1,DIV32L
; ENDC
VAR UDATA 0X20
X RES 4
Y RES 4
ZB RES 4
DIG RES 10
_TMP0 EQU 0X70
_TMP1 EQU 0X71
_TMP2 EQU 0X72
ORG 0X00
GOTO AYAR
ORG 0X04
AYAR:
PAKET32 301 ,X
PAKET32 302 ,Y
BASLA:
; TOPLA32 X,Y,ZB;
;DIV32 X,Y,ZB
;KAREKOK X,ZB
; MULL32 X,Y,ZB
; BCD X,DIG
; DIV32 ZB,Y,ZB
EGER X,"Z",Y
GOTO $+2
HESAP:
GOTO BASLA
GOTO BASLA
END
burada farkettinizmi bilmiyorum kullanılan komutlar (makrolar) sayesinde neredeyse farklı bir dil oluşmaya başlıyor amacım da tam olarak bu sadece makrolar kullanılarak çok basit herkesin komutun ne iş yaptığını anlayacağı makrolar oluşturarak işlemcinin tüm ayarlarının yapılabildiği alt işlemlerin tek satırda yazılabildiği,takılan harici donanımların ve seri iletişim aygıtlarının halledilebildiği bir dil oluşturmak böylelikle C nin bıkkınlık veren her seferinde yazmak zorunda olduğumuz { vs | gibi kafa karıştıran işaretlemeleri yerine daha sade bir dil oluşması tabiki sadece PIC işlemciler için bu
21 Ocak 2024, 12:16:59
math kütüphanesi (math.asm) subasm alt dosya
INCLUDE "p16f690.inc"
INCLUDE "MATH.INC"
UDATA 0X56
REGA0 RES 1 ;lsb
REGA1 RES 1
REGA2 RES 1
REGA3 RES 1 ;msb
REGB0 RES 1 ;lsb
REGB1 RES 1
REGB2 RES 1
REGB3 RES 1 ;msb
REGC0 RES 1 ;lsb
REGC1 RES 1
REGC2 RES 1
REGC3 RES 1 ;msb
DSIGN RES 1 ;Digit Sign. 0=positive,1=negative
;DIGIT1 RES 1 ;MSD
;DIGIT2 RES 1
;DIGIT3 RES 1
;DIGIT4 RES 1
;DIGIT5 RES 1 ;Decimal (BCD) digits
;DIGIT6 RES 1
;DIGIT7 RES 1
;DIGIT8 RES 1
;DIGIT9 RES 1
;DIGIT10 RES 1 ;LSD
MTEMP RES 1
MCOUNT RES 1
DCOUNT RES 1
;*** 32 BIT SIGNED SUTRACT ***
;REGA - REGB -> REGA
;Return carry set if overflow
GLOBAL REGA0,REGB0,REGC0,subtract,add,multiply,divide,clrba,sqrt,DCOUNT,DCOUNT
CODE
subtract:
call negateb ;Negate REGB
skpnc
return ;Overflow
;*** 32 BIT SIGNED ADD ***
;REGA + REGB -> REGA
;Return carry set if overflow
add:
movf REGA3,w ;Compare signs
xorwf REGB3,w
movwf MTEMP
call addba ;Add REGB to REGA
clrc ;Check signs
movf REGB3,w ;If signs are same
xorwf REGA3,w ;so must result sign
btfss MTEMP,7 ;else overflow
addlw 0x80
return
;*** 32 BIT SIGNED MULTIPLY ***
;REGA * REGB -> REGA
;Return carry set if overflow
multiply:
clrf MTEMP ;Reset sign flag
call absa ;Make REGA positive
skpc
call absb ;Make REGB positive
skpnc
return ;Overflow
call movac ;Move REGA to REGC
call clra ;Clear product
movlw D'31' ;Loop counter
movwf MCOUNT
muloop:
call slac ;Shift left product and multiplicand
rlf REGC3,w ;Test MSB of multiplicand
skpnc ;If multiplicand bit is a 1 then
call addba ;add multiplier to product
skpc ;Check for overflow
rlf REGA3,w
skpnc
return
decfsz MCOUNT,f ;Next
goto muloop
btfsc MTEMP,0 ;Check result sign
call negatea ;Negative
return
;*** 32 BIT SIGNED DIVIDE ***
;REGA / REGB -> REGA
;Remainder in REGC
;Return carry set if overflow or division by zero
divide:
clrf MTEMP ;Reset sign flag
movf REGB0,w ;Trap division by zero
iorwf REGB1,w
iorwf REGB2,w
iorwf REGB3,w
sublw 0
skpc
call absa ;Make dividend (REGA) positive
skpc
call absb ;Make divisor (REGB) positive
skpnc
return ;Overflow
clrf REGC0 ;Clear remainder
clrf REGC1
clrf REGC2
clrf REGC3
call slac ;Purge sign bit
movlw D'31' ;Loop counter
movwf MCOUNT
dvloop:
call slac ;Shift dividend (REGA) msb into remainder (REGC)
movf REGB3,w ;Test if remainder (REGC) >= divisor (REGB)
subwf REGC3,w
skpz
goto dtstgt
movf REGB2,w
subwf REGC2,w
skpz
goto dtstgt
movf REGB1,w
subwf REGC1,w
skpz
goto dtstgt
movf REGB0,w
subwf REGC0,w
dtstgt:
skpc ;Carry set if remainder >= divisor
goto dremlt
movf REGB0,w ;Subtract divisor (REGB) from remainder (REGC)
subwf REGC0,f
movf REGB1,w
skpc
incfsz REGB1,w
subwf REGC1,f
movf REGB2,w
skpc
incfsz REGB2,w
subwf REGC2,f
movf REGB3,w
skpc
incfsz REGB3,w
subwf REGC3,f
clrc
bsf REGA0,0 ;Set quotient bit
dremlt:
decfsz MCOUNT,f ;Next
goto dvloop
btfsc MTEMP,0 ;Check result sign
call negatea ;Negative
return
;*** ROUND RESULT OF DIVISION TO NEAREST INTEGER ***
round:
clrf MTEMP ;Reset sign flag
call absa ;Make positive
clrc
call slc ;Multiply remainder by 2
movf REGB3,w ;Test if remainder (REGC) >= divisor (REGB)
subwf REGC3,w
skpz
goto rtstgt
movf REGB2,w
subwf REGC2,w
skpz
goto dtstgt
movf REGB1,w
subwf REGC1,w
skpz
goto rtstgt
movf REGB0,w
subwf REGC0,w
rtstgt:
skpc ;Carry set if remainder >= divisor
goto rremlt
incfsz REGA0,f ;Add 1 to quotient
goto rremlt
incfsz REGA1,f
goto rremlt
incfsz REGA2,f
goto rremlt
incf REGA3,f
skpnz
return ;Overflow,return carry set
rremlt:
btfsc MTEMP,0 ;Restore sign
call negatea
return
;*** 32 BIT SQUARE ROOT ***
;sqrt(REGA) -> REGA
;Return carry set if negative
sqrt:
rlf REGA3,w ;Trap negative values
skpnc
return
call movac ;Move REGA to REGC
call clrba ;Clear remainder (REGB) and root (REGA)
movlw D'16' ;Loop counter
movwf MCOUNT
sqloop:
rlf REGC0,f ;Shift two msb's
rlf REGC1,f ;into remainder
rlf REGC2,f
rlf REGC3,f
rlf REGB0,f
rlf REGB1,f
rlf REGB2,f
rlf REGC0,f
rlf REGC1,f
rlf REGC2,f
rlf REGC3,f
rlf REGB0,f
rlf REGB1,f
rlf REGB2,f
setc ;Add 1 to root
rlf REGA0,f ;Align root
rlf REGA1,f
rlf REGA2,f
movf REGA2,w ;Test if remdr (REGB) >= root (REGA)
subwf REGB2,w
skpz
goto ststgt
movf REGA1,w
subwf REGB1,w
skpz
goto ststgt
movf REGA0,w
subwf REGB0,w
ststgt:
skpc ;Carry set if remdr >= root
goto sremlt
movf REGA0,w ;Subtract root (REGA) from remdr (REGB)
subwf REGB0,f
movf REGA1,w
skpc
incfsz REGA1,w
subwf REGB1,f
movf REGA2,w
skpc
incfsz REGA2,w
subwf REGB2,f
bsf REGA0,1 ;Set current root bit
sremlt:
bcf REGA0,0 ;Clear test bit
decfsz MCOUNT,f ;Next
goto sqloop
clrc
rrf REGA2,f ;Adjust root alignment
rrf REGA1,f
rrf REGA0,f
return
;*** 32 BIT SIGNED BINARY TO DECIMAL ***
;REGA -> DIGITS 1 (MSD) TO 10 (LSD) & DSIGN
;DSIGN = 0 if REGA is positive, 1 if negative
;Return carry set if overflow
;Uses FSR register
;bin2dec:
; clrf MTEMP ;Reset sign flag
; call absa ;Make REGA positive
; skpnc
; return ;Overflow
; call clrdig ;Clear all digits
; movlw D'32' ;Loop counter
; movwf MCOUNT
;b2dloop:
; rlf REGA0,f ;Shift msb into carry
; rlf REGA1,f
; rlf REGA2,f
; rlf REGA3,f
; movlw DIGIT10
; movwf FSR ;Pointer to digits
; movlw D'10' ;10 digits to do
; movwf DCOUNT
;adjlp:
; rlf INDF,f ;Shift digit and carry 1 bit left
; movlw D'10'
; subwf INDF,w ;Check and adjust for decimal overflow
; skpnc
; movwf INDF
; decf FSR,f ;Next digit
; decfsz DCOUNT,f
; goto adjlp
; decfsz MCOUNT,f ;Next bit
; goto b2dloop
; btfsc MTEMP,0 ;Check sign
; bsf DSIGN,0 ;Negative
; clrc
; return
;
;
;;*** 32 BIT SIGNED DECIMAL TO BINARY ***
;;Decimal DIGIT1 thro DIGIT(X) & DSIGN -> REGA
;;Set DSIGN = 0 for positive, DSIGN = 1 for negative values
;;Most significant digit in DIGIT1
;;Enter this routine with digit count in w register
;;Return carry set if overflow
;;Uses FSR register
;
;dec2bin:
; movwf MTEMP ;Save digit count
; movlw D'32' ;Outer bit loop counter
; movwf MCOUNT
;
;d2blp1:
; movlw DIGIT1-1 ;Set up pointer to MSD
; movwf FSR
; movf MTEMP,w ;Inner digit loop counter
; movwf DCOUNT
;
; movlw D'10'
; clrc ;Bring in '0' bit into MSD
;
;d2blp2:
; incf FSR,f
; skpnc
; addwf INDF,f ;Add 10 if '1' bit from prev digit
; rrf INDF,f ;Shift out LSB of digit
;
; decfsz DCOUNT,f ;Next L.S. Digit
; goto d2blp2
;
; rrf REGA3,f ;Shift in carry from digits
; rrf REGA2,f
; rrf REGA1,f
; rrf REGA0,f
;
; decfsz MCOUNT,f ;Next bit
; goto d2blp1
;
; movf INDF,w ;Check for overflow
; addlw 0xFF
; skpc
; rlf REGA3,w
; skpnc
; return
;
; btfsc DSIGN,0 ;Check result sign
; call negatea ;Negative
; return
;
;
;UTILITY ROUTINES
;Add REGB to REGA (Unsigned)
;Used by add, multiply,
addba:
movf REGB0,w ;Add lo byte
addwf REGA0,f
movf REGB1,w ;Add mid-lo byte
skpnc ;No carry_in, so just add
incfsz REGB1,w ;Add carry_in to REGB
addwf REGA1,f ;Add and propagate carry_out
movf REGB2,w ;Add mid-hi byte
skpnc
incfsz REGB2,w
addwf REGA2,f
movf REGB3,w ;Add hi byte
skpnc
incfsz REGB3,w
addwf REGA3,f
return
;Move REGA to REGC
;Used by multiply, sqrt
movac:
movf REGA0,w
movwf REGC0
movf REGA1,w
movwf REGC1
movf REGA2,w
movwf REGC2
movf REGA3,w
movwf REGC3
return
;Clear REGB and REGA
;Used by sqrt
clrba:
clrf REGB0
clrf REGB1
clrf REGB2
clrf REGB3
;Clear REGA
;Used by multiply, sqrt
clra:
clrf REGA0
clrf REGA1
clrf REGA2
clrf REGA3
return
;Check sign of REGA and convert negative to positive
;Used by multiply, divide, bin2dec, round
absa:
rlf REGA3,w
skpc
return ;Positive
;Negate REGA
;Used by absa, multiply, divide, bin2dec, dec2bin, round
negatea:
movf REGA3,w ;Save sign in w
andlw 0x80
comf REGA0,f ;2's complement
comf REGA1,f
comf REGA2,f
comf REGA3,f
incfsz REGA0,f
goto nega1
incfsz REGA1,f
goto nega1
incfsz REGA2,f
goto nega1
incf REGA3,f
nega1:
incf MTEMP,f ;flip sign flag
addwf REGA3,w ;Return carry set if -2147483648
return
;Check sign of REGB and convert negative to positive
;Used by multiply, divide
absb:
rlf REGB3,w
skpc
return ;Positive
;Negate REGB
;Used by absb, subtract, multiply, divide
negateb:
movf REGB3,w ;Save sign in w
andlw 0x80
comf REGB0,f ;2's complement
comf REGB1,f
comf REGB2,f
comf REGB3,f
incfsz REGB0,f
goto negb1
incfsz REGB1,f
goto negb1
incfsz REGB2,f
goto negb1
incf REGB3,f
negb1:
incf MTEMP,f ;flip sign flag
addwf REGB3,w ;Return carry set if -2147483648
return
;Shift left REGA and REGC
;Used by multiply, divide, round
slac:
rlf REGA0,f
rlf REGA1,f
rlf REGA2,f
rlf REGA3,f
slc:
rlf REGC0,f
rlf REGC1,f
rlf REGC2,f
rlf REGC3,f
return
;Set all digits to 0
;Used by bin2dec
;
;clrdig:
; clrf DSIGN
; clrf DIGIT1
; clrf DIGIT2
; clrf DIGIT3
; clrf DIGIT4
; clrf DIGIT5
; clrf DIGIT6
; clrf DIGIT7
; clrf DIGIT8
; clrf DIGIT9
; clrf DIGIT10
; return
END
BCD kısmını kapattım isteyen açabilir
21 Ocak 2024, 12:20:40
math.inc dosyası makrolar var içinde .
;//////////////// RAM ADRESİNDEN RAM ADRESİNE VERİ TRANSFERİ TAŞIMA ////////////////
;1 BYTE KULLANIMI= MOVFF A,B
;2 BYTE KULLANIMI= MIVFF16 A,B
;4 BYTE KULLANIMI= MIVFF32 A,B
;MOVFFL MAKROSU FARKLI BANKLARDA BULUNAN REGİSTERLER ARASINDA TAŞIMA YAPAR
MOVFF MACRO ?0,?1
MOVF ?0 ,W
MOVWF ?1
ENDM
MOVFF16 MACRO ?0,?1
MOVF ?0 ,W
MOVWF ?1
MOVF (?0+1) ,W
MOVWF ?1+1
ENDM
MOVFF32 MACRO ?0,?1
MOVF ?0 ,W
MOVWF ?1
MOVF ?0+1 ,W
MOVWF ?1+1
MOVF ?0+2 ,W
MOVWF ?1+2
MOVF ?0+3 ,W
MOVWF ?1+3
ENDM
MOVFFL MACRO ?0,?1
BANKSEL ?0
MOVF ?0 ,W
BANKSEL ?1
MOVWF ?1
BANKSEL ?0
ENDM
MOVFF16L MACRO ?0,?1
BANKSEL ?0
MOVF ?0 ,W
BANKSEL ?1
MOVWF ?1
BANKSEL ?0
MOVF ?0+1 ,W
BANKSEL ?1
MOVWF ?1+1
BANKSEL ?0
ENDM
MOVFF32L MACRO ?0,?1
BANKSEL ?0
MOVF ?0 ,W
BANKSEL ?1
MOVWF ?1
BANKSEL ?0
MOVF ?0+1 ,W ;26 KOMUT
BANKSEL ?1
MOVWF ?1+1
BANKSEL ?0
MOVF ?0+2 ,W
BANKSEL ?1
MOVWF ?1+2
BANKSEL ?0
MOVF ?0+3 ,W
BANKSEL ?1
MOVWF ?1+3
BANKSEL ?0
ENDM
;///////////////////////////32 BİT İARETLİ SABİT YAZMA//////////////////
;ÖRNEK= PAKET32 12345678,Out0 ; PAKET32 -12345678,Out0 yazıldığında da negatif değeri yazabilir adreslere
;RADIX DEC YAPILMALI DESİMAL SAYILAR İÇİN
;///////////////////////////////////////////////////////////////////////////////////////////////
PAKET32 MACRO Var, Address ;Address meblab ide için Cblock yada udata kullanıldığında ram başlangıç adresidir(otm)
BANKSEL Address
movlw Address ;
movwf FSR ;fsr ye adresi yükler
movlw Var & H'FF' ;;en değersiz byte filtrelenip yazılır
movwf INDF ;fsr nin işaretlediği adrese değeri yazar
movlw Var >>8 & H'FF' ;; Var 8 bit kaydırılır filtrelenip fsr 1 arttırılır(bir sonraki ram bölgesi yazılır)
incf FSR,F
movwf INDF
movlw Var >>16 & H'FF'
incf FSR,F
movwf INDF
movlw Var >>24 & H'FF'
incf FSR,F
movwf INDF
ENDM
;////////////////////16 BİT PAKET DEĞİŞKENLERE YAZILMASI///////////////////////////////////////////////
PAKET16 MACRO VAR,ADDRESS
BANKSEL ADDRESS
movlw ADDRESS ;
movwf FSR ;fsr ye adresi yükler
movlw VAR & H'FF' ;;en değersiz byte filtrelenip yazılır
movwf INDF ;fsr nin işaretlediği adrese değeri yazar
movlw VAR >>8 & H'FF' ;; Var 8 bit kaydırılır filtrelenip fsr 1 arttırılır(bir sonraki ram bölgesi yazılır)
incf FSR,F
movwf INDF
ENDM
;/////////////////////////////////MATEMATİK İŞLEMLERİ (4 İŞLEM)///////////////////////////////////
;//////////////////////////////KULLANIMI İÇİN MATH.ASM TANITILMALI////////////////////////////////
;///////////////KULLANIMI TOPLA A,B,C ŞEKLİNDE A İLE B TOPLANIR C YE YAZILIR//////////////////////
;BÖLME İŞLEMİNDE KALAN HATILATICI OLARAK KULLANILAN REGC DE TUTULUT SONUÇ İSE GENE A/B=C ŞEKLİNDEDİR
;//////32BİT İŞARETLİ TOPLAMA////
TOPLA32 MACRO ?0,?1,?2
MOVFF32 ?0,REGA0
MOVFF32 ?1,REGB0
CALL add
MOVFF32 REGA0,?2
;CALL clrba
ENDM
;//////32BİT ÇARPMA İŞARETLİ/////
MULL32 MACRO ?0,?1,?2
MOVFF32 ?0,REGA0
MOVFF32 ?1,REGB0
CALL multiply
MOVFF32 REGA0,?2
ENDM
;///////32BİT İŞARETLİ BÖLME////
DIV32 MACRO ?0,?1,?2
MOVFF32 ?0,REGA0
MOVFF32 ?1,REGB0
CALL divide
MOVFF32 REGA0,?2
ENDM
;///////KAREKÖK alma/////////
KAREKOK MACRO ?0,?2
MOVFF32 ?0,REGA0
CALL sqrt
MOVFF32 REGA0,?2
ENDM
;////////BCD ÇEVİRİCİ/////////////
BCD MACRO ?0,?1
MOVFF32 ?0,REGA0
CALL bin2dec
ENDM
;////////////////////////////////////////////////////////////////////////////
;//////////////////////////////////////////////////////////////////////////////
;///////////////////////////BİR BİTİ TERSLER/////////////////////////////
;ÖRNEK= TOGGLE PORTA,5
;/////////////////////////////////////////////////////////////////////
TOGGLE MACRO PORT? ,?0
MOVLW 0X01<<?0
XORWF PORT? ,F
ENDM
;////////////////////////////////FOR-NEXT DÖNGÜSÜ///////////////////////////////
;KULLANIMI "FOR 0,255" ; 255 TAKRAR YAPARAK FOR NEXT ARASINDAKİ KODU ÇALIŞTIRIR
; KODLAR
; ......
; NEXT
;*******************************************************************************
FOR MACRO ?0,?1 ;R10,R11
MOVLW ?1 ;R11
MOVWF R12
MOVLW ?0 ;R10
SUBWF R12 ,F
MOVF PCL ,W
MOVWF R13
ENDM
NEXT MACRO
MOVF R13 ,W
DECFSZ R12
MOVWF PCL
ENDM
;//////////////////////////////IF-THEN KOŞULLARI////////////////////////////////////
;KULLANIMI (EGER A,"<",B) KOMUT KARŞILIĞINDA KOŞUL DOĞRU İSE İKİ ALT SATIRA YANLIŞSA BİR ALT SATIRA GİDER
; (EGER A,"Z",B) A KÜÇÜK EŞİTSE ( Z İŞARETİ KÜÇÜK EŞİT İŞARETİNE EN ÇOK BENZEDİĞİ İÇİN SEÇİLDİ)
; (EGER A,"=",B) A VE B EŞİTSE
;///////////////////DEĞER KIYASLAMASI//////////////////////////////////
;KULLANIMI= KARŞILAŞTIRILACAK HER BİR "WORD" DEĞERİ ARDIŞIK RAM BÖLGELERİNDE TUTULMALI
;R15 VE R16 DEĞERLERİNİ ASCII DEĞERLER OLARAK İLGİLİ İŞARETLER OLARAK SEÇTİM
;MAKRODA "=" SENBOLÜ KABUL EDİLMEDİĞİ İÇİN DEC KARŞILIĞI YAZILDI
;AMA ANA PROGRAMDA KULLANILABİLİR OLDU
;BOŞ BIRAKILAN SEMBOL YERİNE ASCII BOŞLUK BIRAKILMALI
;R6 ADRESİNİN İLK BİTİ TRUE/FALSE DÖNDÜRÜR
;MAKRO ÇIKIŞI "R4" , 0 BİTİ KONTROL EDİLEREK İŞLEM YAPILIR
;" > " YADA "?" İŞARETİ İÇİN AYRI BİR İŞLEME GEREK YOK MEVCUT İŞLEMLERİN TERSİ OLDUĞUNDAN SADECE DEĞİŞKEN YERİ DEĞİŞECEK
EGER MACRO ?0,?2,?1;,?2
BCF STATUS ,C
BCF STATUS ,Z
; MOVF ?0 ,W
; MOVWF R15 ;R0
; MOVF ?0+1 ,W
; MOVWF R15+1 ;R0+1
; MOVF ?1 ,W
; MOVWF R16 ;R3
; MOVF ?1+1 ,W
; MOVWF R16+1 ;R3+1
IF ?2=="<" ;????????
MOVF ?0+1 ,W ;R0+1 ,W ;IF Y <= ART THEN GOTO KAPA
SUBWF ?1+1 ,W ;R3+1 ,W ;
BTFSS STATUS ,C ;
GOTO $+6
BTFSS STATUS ,Z
GOTO $+5
MOVF ?0 ,W ;R0 ,W
SUBWF ?1 ,W ;R3 ,W
BTFSS STATUS ,C
ELSE
; IF R1 == "<" && R2 == .32
IF ?2=="Z"
MOVF ?0+1 ,W ;IF Y < ART THEN
SUBWF ?1+1 ,W ;
BTFSS STATUS ,C ;
GOTO $+8
BTFSS STATUS ,Z
GOTO $+7
MOVF ?0 ,W
SUBWF ?1 ,W
BTFSC STATUS ,Z
GOTO $+3
BTFSS STATUS ,C
ELSE
IF ?2=="="
; IF R1 == .61 && R2 == .32
MOVF ?0+1 ,W
XORWF ?1+1 ,W
BTFSS STATUS ,Z
GOTO $+5
MOVF ?0 ,W
XORWF ?1 ,W
BTFSC STATUS ,Z
GOTO $+2
ENDIF
ENDIF
ENDIF
ENDM
MOVFF32L Şeklinde olan makrolar farklı banklardaki değerleri birbiri üzerine taşımak için ayrı yaptım normalde tek makro ile olabilirdi ama her seferinde bank değiştirmek zaman alıyor o yüzden gerekirse kullanılsın diye böyle yaptım kafalar karışmasın
Alıntı yapılan: alikeskinkilic - 22 Mart 2023, 09:11:24
for nex döngüsü için makro içinde pcl kullanmıştım makroyu birden fazla kullanımda iki kere yazma sorunu olmaması için fakat gerek te yokmuş makro içerisinde kullandığımız lable ve değişkenleri "local for1,for2
şeklinde makro başlangıcında tanımladığımızda her makro için farklı adresi lokal olarak tanımlıyormuş yani
FOR MACRO ?0,?1 ;R10,R11
local for1
MOVLW ?1 ;R11
MOVWF R12
MOVLW ?0 ;R10
SUBWF R12 ,F
;MOVF PCL ,W
;MOVWF R13
for1:
ENDM
NEXT MACRO
MOVF R13 ,W
DECFSZ R12
goto for1;MOVWF PCL
ENDM
şeklinde yazarsak da ardarda kullanımlarda sorun olmayacaktır
yeni bir dil oluşturma çabalarımı biraz uçuk bulabilirsiniz tabiki anlarım ama örnek olarak ;///////////////////////////////////////////////////////////////////////////////
;///////////////////////UART_SET/////////////////////////////////////////////
; UART_SET BAUD,9OR8,TERS-DÜZ
; UART_SET 9600,8,0
UART_SET MACRO VAR,VAR1,VAR2
BANKSEL TXSTA
BCF TRISB ,7 ;tx
BSF TRISB ,5
MOVLW 0X24 ; TXEN,BRGH
MOVWF TXSTA
IF VAR2>0
BANKSEL BAUDCTL
MOVLW 0X18 ;İNVERTED
MOVWF BAUDCTL
ELSE
BANKSEL BAUDCTL
MOVLW 0X08
MOVWF BAUDCTL
; CLRF BAUDCTL ;NONİNVERTED
ENDIF ;
BANKSEL RCSTA ;
MOVLW 0X80 ;SPEN,CREN
MOVWF RCSTA
BANKSEL TRISA
IFDEF OSC_8
IF VAR==9600
MOVLW .207 ;
MOVWF SPBRG
BANKSEL PORTA
ENDIF
IF VAR==10417
MOVLW .191 ;
MOVWF SPBRG
BANKSEL PORTA
ENDIF
IF VAR==19200
MOVLW .103 ;
MOVWF SPBRG
BANKSEL PORTA
ENDIF
IF VAR==57600
MOVLW .34 ;
MOVWF SPBRG
BANKSEL PORTA
ENDIF
IF VAR==115200
MOVLW .16 ;
MOVWF SPBRG
BANKSEL PORTA
ENDIF
IF VAR==230400
MOVLW .8 ;
MOVWF SPBRG
BANKSEL PORTA
ENDIF
IF VAR1==8
BCF RCSTA ,RX9
ENDIF
IF VAR1==9
BSF RCSTA ,RX9
ENDIF
ENDIF
ENDM
;//////////////////////////////PRİNTF///////////////////UART HABERLEŞME SERİ GÖNDERME
PRINTF MACRO ?0
BANKSEL PORTA
BCF R9 ,0
BTFSC INTCON ,GIE
GOTO $+2
GOTO $+3
BCF INTCON ,7
BSF R9 ,0
MOVF ?0,W
MOVWF TXREG
BSF STATUS ,RP0
BTFSS TXSTA ,TRMT
GOTO $-1
BCF STATUS ,RP0
MOVF ?0+1,W
MOVWF TXREG
BSF STATUS ,RP0
BTFSS TXSTA ,TRMT
GOTO $-1
BCF STATUS ,RP0
; MOVLW .10
; MOVWF TXREG
; BSF STATUS ,RP0
; BTFSS TXSTA ,TRMT
; GOTO $-1
; BCF STATUS ,RP0
;
; MOVLW .13
; MOVWF TXREG
; BSF STATUS ,RP0
; BTFSS TXSTA ,TRMT
; GOTO $-1
; BCF STATUS ,RP0
BTFSC R9 ,0
BSF INTCON ,7
ENDM
;////////////////////////////ASCİİ GÖNDERME//////////////////////////////
PRINTA MACRO ?0
BCF R9 ,0
BANKSEL PORTA
BTFSC INTCON ,GIE
GOTO $+2
GOTO $+3
BCF INTCON ,7
BSF R9 ,0
MOVLW ?0
MOVWF TXREG
BSF STATUS ,RP0
BTFSS TXSTA ,TRMT
GOTO $-1
BCF STATUS ,RP0
BTFSC R9 ,0
BSF INTCON ,7
ENDM
bu tarz kısaltmalar işlemcinin her aşamasında her bir işleminde uygulanabilmekte bir adxl345 için yada herhangi bir telekominikasyon formatı içinde kütüphane yazması sadece zaman alıcı ama imkanlar dahilinde oluyor tabi biraz da takviye şart
nasıl adlandırılıyor bilmiyorum ama bir değişkeni sıra ile boyutunu kendimizin belirlediği adette bir dizi değişkene yazma ilgili bir makrodur.ben genellikle adxl tarzı bir sensörden okuduğum verileri ard arda dizip ortalamasını almak için yada dataloger yapmak için kayıt yapmakta kullanıyorum.
kullanımı "DIZ A,DIZI,10" Şeklindedir A bizim sensörden okuduğumuz değeri tutan değişken DIZI burada 10 byte uzunluğunda bir alanın ilk adresini temsil ediyor. komut sonrasında eğer DIZI registeri tamamen doldurulmuşsa iki satır alta sıçrar eğer henüz belirttiğimiz sayıda kayıt yapılmamışsa bir alt satıra gider BTFSS gibi yani Örnek:
CBLOCK;Yada UDATA
DIZI :10 ;10 Byte uzunluğunda değişken
endc
SAYAC EQU 0X73 ;Her banktan ulaşılabilir olması için sayaç değişkenleri 0x70 üstüne yazılıyor
ADXL_OKU:
......
movwf A
DIZ A,DIZI,10
GOTO ADXL_OKU
GOTO OKUMA_TAMAM
Macro kodu ise :
DIZ MACRO ?0,?1,?2 ;?2 = kayıt sayısı
;?1 = kayıt yapılan dizi değişkeni ilk adresi yada adı
MOVLW ?1 ;?0 = kaydedeceğimiz değişken
ADDWF SAYAC ,W
MOVWF FSR
MOVFF ?0,INDF
INCF SAYAC ,F
MOVF SAYAC ,W
XORLW ?2
BTFSS STATUS ,Z
GOTO $+3
CLRF SAYAC
GOTO $+2
ENDM
aynı makronun 2 byte versiyonu.DIZ16 MACRO ?0,?1,?2
MOVLW ?1
ADDWF SAYAC ,W
MOVWF FSR
MOVFF ?0,INDF
INCF FSR ,F
MOVFF ?0+1,INDF
INCF SAYAC
INCF SAYAC
MOVF SAYAC ,W
XORLW ?2
BTFSS STATUS ,Z
GOTO $+3
CLRF SAYAC
GOTO $+2
ENDM
kayıt sayısı veri boyutu 2 byte olduğundan yarıya düşecek ona göre dizi değişkeni boyutunu ve kayıt sayısını 2 kat fazla ayarlayın sonra olmadı demeyin.
yeni makro MEDIAN filtre(bir dizi değerin orta noktasını bulma) uygulamalarında kullanabileceğiniz bir dizi değişkendeki tüm değerleri karşılaştırıp en küçük değeri en başa taşıyan bir makrodur dizi boyutuna bağlı olarak ard arda çalıştırıldığında tüm listeyi küçükten büyüğe sıralar.makro içerisindeki for next döngüsünü işlem içerisinde çalışabilmesi için modifiyeli halini de attım onu da farklı bir makro yaptım diğer türlü çevrime sokamadım bu hali ile iyi çalışıyor daha kısa bir yolunu bulamadım henüz .örnek kod
__CONFIG 0x30E4
radix dec
LIST P = PIC16f690
INCLUDE "p16f690.inc"
; INCLUDE "EPROM.INC"
INCLUDE "MATH.INC"
; INCLUDE "fload.inc"
RADIX DEC
extern REGA0,REGB0,REGC0,subtract,add,multiply,divide,clrba,sqrt,DCOUNT,DCOUNT,subtract
;
; GLOBAL SAYAC
; EXTERN FLO1624,INT2416,FPM24,FLO2424;R0,R1,R2,R3,R4,DIZ0,DIZ1,R6,R7,R8,R9,R10,R11,R12,R13,R14,R15,R16,R17,D0,D1,D2,D3,DS,DR,M0,M1,M2,MS,IF0,IF1,F0,F1,DIV32L
; ENDC
VAR UDATA 0X20
X RES 4
Y RES 4
ZB RES 4
DIG RES 20
_TMP0 EQU 0X70
_TMP1 EQU 0X71
_TMP2 EQU 0X72
SAYAC EQU 0X73
RAM0 EQU 0X74
RAM1 EQU 0X75
RAM2 EQU 0X76
RAM3 EQU 0X77
RAM4 EQU 0X78
RAM5 EQU 0X79
RAM6 EQU 0X7A
RAM7 EQU 0X7B
ORG 0X00
GOTO AYAR
ORG 0X04
AYAR:
PAKET32 200 ,X
PAKET32 302 ,Y
SELF:
DECF X ,F
BASLA:
; TOPLA32 X,Y,ZB;
; DIV32 X,Y,ZB
; KAREKOK X,ZB
; MULL32 X,Y,ZB
; BCD X,DIG
; DIV32 ZB,Y,ZB
; EGER X,"Z",Y
; CIKAR32 X,Y,X
DIZ X,DIG,5 ;x in değerini her seferinde bir azaltarak sıra ile DIG in ilk 5 adresine yazar
GOTO SELF
SIRALA DIG,5 ; ilk değeri diğer tüm değerler arasından en küçüğü ile değişir
SIRALA DIG+1,4 ; ikinci değeri kalan değerler arasından en küçüğü ile değişir
SIRALA DIG+2,3 ; öylece devam eder
SIRALA DIG+3,2
HESAP:
GOTO $
GOTO BASLA
END
23 Ocak 2024, 14:46:44
makrosu:
SIRALA MACRO ?0,?1 ; ?0 DİZİ DEĞİŞKENİ BAŞLANGIÇ ADRESİ
LOCAL KAR,TARA,AYRIL,BITIR,SONRAKI
MOVLW 1
MOVWF RAM4
MOVLW ?0 ; SIRALANACAK BYTE SAYISI
MOVWF FSR
MOVLW ?1-1
MOVWF RAM3
TARA:
FORR 0,RAM3
MOVFF INDF,RAM0
MOVFW RAM4
ADDWF FSR ,F
MOVFF INDF,RAM1
EGER RAM0,"<",RAM1
CALL KAR
CALL SONRAKI
NEXT
GOTO BITIR
KAR:
MOVFF RAM0,INDF
MOVFW RAM4
SUBWF FSR ,F
MOVFF RAM1,INDF
RETURN
SONRAKI:
INCF RAM4,F
DECFSZ RAM3,F
RETURN
BITIR:
ENDM
23 Ocak 2024, 14:48:07
for makrosu için extra next makrosuna gerek yok diğerininkini ortak kullanabiliyor
FORR MACRO ?0,?1 ;R10,R11
;LOCAL R12,R13
MOVFW ?1 ;R11
MOVWF 0X7A
MOVLW ?0 ;R10
SUBWF 0X7A ,F
MOVF PCL ,W
MOVWF 0X7B
ENDM
sadece for next makrosundaki R11 gibi değişkenler yerine tüm banklardan erişilebilir 0x7a ve 0x7b değişkenlerini kullandım diğerinde de değiştirirseniz sorunsuz ikisi de çalışır
NEXT MACRO
MOVF 0X7B ,W
DECFSZ 0X7A
MOVWF PCL
ENDM
işlevi resimlerde daha rahat görünebilir
(https://i.ibb.co/q93CNTy/Ads-z.png) (https://ibb.co/q93CNTy)
Not sırala komutu sadece iki değeri karşılaştırmaz listenin tümünü karşılaştırır bu yüzden de birazcık zaman alır işlenmesi listenin büyüklüğüne bağlı olarak.
basic karşılığı "if a>b call yerdedıs
"if a>c call yerdegıs
.....n şeklinde devam eder
yerdegıs: r= a
a=b
b=r
return"
olabilir