16F877 ile B ve C portlarından uygulanan 4 bitlik iki sayının çarpımını yapıp D portunda göstermek istiyorum nasıl yapabiliriz
şöyle bi kod buldum uyarlamaya çalıştım olmadı
; 4x4 bit multiply
; by Ray Gardiner
; X*Y ; result left in W
; X and Y are 4 bits
;
;
CLRW ; Clear Result
CLRC ; Clear Carry for RLF later ;
BTFSC Y,0 ; ?*1
ADDWF X,W ; W = ?X
RLF X,F ; X = 2X
;
BTFSC Y,1 ; ?*2
ADDWF X,W ; W = ?X + ?2X
RLF X,F ; W = 4X
BTFSC Y,2 ; ?*4
ADDWF X,W ; W = ?X + ?2X + ?4X
RLF X,F ; W = 8X
BTFSC Y,3 ; ?*8
ADDWF X,W ; ?X + ?2X + ?4X + ?8X
Çarpmayı toplama ile bölmeyi de çıkarma işlemi ile yapabilirsin. Tabi taşma olup olmadığınıda kontrol etmek gerek. Gerçi 4 bitlik iki sayının çarpımı bir byte ı geçmez.
Örneğin 3x5 veya 5x3 çarpmada değişim özelliği oldugundan bu işlem farketmez. Dolayısı ile ya 3 kere 5 i yada 5 kere 3 ü toplayarak çarpma işlemi yapılır.
Eğer çarpma da 2^x çarpanı varsa sola kaydırarakta yapılabilir. Örneğin 4*3; 4= 2^2 oldugundan 4<<2 işlemi bize 1100 verir ve çarpma yapılır.
bu kodun çalışması gerekir.4 bitlik çarpma işte. x ve y olarak iki bellek hücresini kullan, sonuç zaten W registerinde. Bunu D portuna gönder.
Yaptığını söylediğin kod nerede?
LIST P=16F877
INCLUDE "P16F877.INC"
X EQU 0X20
Y EQU 0X21
SETUP
BSF STATUS,5
CLRF TRISD
MOVLW 0XFF
MOVWF TRISC
MOVWF TRISB
BCF STATUS,5
CLRF PORTB
CLRF PORTC
CLRF PORTD
MOVF PORTB,X
MOVF PORTC,Y
CLRW ; Clear Result
CLRC ; Clear Carry for RLF later ;
BTFSC Y,0 ; ?*1
ADDWF X,W ; W = ?X
RLF X,F ; X = 2X
;
BTFSC Y,1 ; ?*2
ADDWF X,W ; W = ?X + ?2X
RLF X,F ; W = 4X
BTFSC Y,2 ; ?*4
ADDWF X,W ; W = ?X + ?2X + ?4X
RLF X,F ; W = 8X
BTFSC Y,3 ; ?*8
ADDWF X,W ; ?X + ?2X + ?4X + ?8X
MOVWF PORTD
END
--- C:/Program Files (x86)/Microchip/xc8/v1.30/sources/common/bmul.c ----------------------------------
1: unsigned char
2: __bmul(unsigned char multiplier, unsigned char multiplicand)
0225 00F3 MOVWF multiplier
3: {
4: unsigned char product = 0;
0226 01F2 CLRF k
5:
6: do {
7: if(multiplier & 1)
0227 1C73 BTFSS multiplier, 0x0
0228 2A2C GOTO 0x22C
8: product += multiplicand;
0229 0870 MOVF __pcstackCOMMON, W
022A 00F1 MOVWF byte
022B 07F2 ADDWF k, F
9: multiplicand <<= 1;
022C 1003 BCF STATUS, 0x0
022D 0DF0 RLF __pcstackCOMMON, F
10: multiplier >>= 1;
022E 1003 BCF STATUS, 0x0
022F 0CF3 RRF multiplier, F
11: } while(multiplier != 0);
0230 08F3 MOVF multiplier, F
0231 1D03 BTFSS STATUS, 0x2
0232 2A27 GOTO 0x227
12: return product;
0233 0872 MOVF k, W
0234 0008 RETURN
13: }
0235 3067 MOVLW 0x67
14:
27: TRISB=0XFF;
02DB 30FF MOVLW 0xFF
02DC 1683 BSF STATUS, 0x5
02DD 1303 BCF STATUS, 0x6
02DE 0086 MOVWF PORTB
28: TRISC=0XFF;
02DF 0087 MOVWF PORTC
29: TRISD=0;
02E0 0188 CLRF PORTD
30: PORTD=PORTB*PORTC;
02E1 1283 BCF STATUS, 0x5
02E2 1303 BCF STATUS, 0x6
02E3 0807 MOVF PORTC, W
02E4 00FA MOVWF 0x7A
02E5 00F0 MOVWF __pcstackCOMMON
02E6 0806 MOVF PORTB, W
02E7 120A BCF PCLATH, 0x4
02E8 118A BCF PCLATH, 0x3
02E9 2225 CALL 0x225
02EA 120A BCF PCLATH, 0x4
02EB 118A BCF PCLATH, 0x3
02EC 1283 BCF STATUS, 0x5
02ED 1303 BCF STATUS, 0x6
02EE 0088 MOVWF PORTD
hasankara çok sağol ama kendi kodum üstünden gitmek istiyorum nedir burdaki eksiklik ? b*c=d olucak b ve c giriş portları d ise çıkış
MOVF PORTB,X
MOVF PORTC,Y
burada kullanım hatası var. asm i geride bırakalı çok oldu ama büyük ihtimalle burada hatan var. movf komutu f kopyalıyor sonucu aynı f e mi yoksa w a mı kaydetsin diye ikinci parametre alıyor. yani "movf PORTB,w" mantıklı kullanım olur. bunun anlamı ise portb yi w a geçirir.
burada yapmak istediğini sanırım anladım.
MOVF PORTB,w
MOVWF X,f
MOVF PORTC,w
MOVWF Y,f
önce akümülatöre alıp sonra hedefe yüklüyorsun. ilk gözüme çarpan burasıydı bakayım bakalım başka ne yapmışsın.
mesaj birleştirme:: 22 Ekim 2014, 00:41:08
bir de clrc diye bir komutunun olduğunu hatırlamıyorum 16f877 için. onun yerine bcf STATUS,c diyebilirsin.
16F877 de
MOVF PORTB,X
MOVF PORTC,Y
diye bir komut yoktur,
MOVF PORTB,W
veya
MOVFW PORTB
diyerek portb de ne varsa W registerına alırsın, sonra
MOVWF X
diyerek W registerındaki değeri X file registerına (değişkenine) aktarırsın.
Birde sayılar B ve C portunun alt 4 bitine uygulanıyor diye düşünelim,
(alt mı üst mü 4 bite uygulanıyor belirtmemişsin sanırım)
yukarıda söylediğim şekilde değeri okuduyup X e aktardıktan sonra,
MOVLW h0F
ANDWF X,F
diyerek X registerının üst 4 bitini temizlemekte fayda var.
LIST P=16F877
#INCLUDE <P16F877.INC>
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _XT_OSC & _LVP_ON & _CPD_OFF
INT_VAR UDATA_SHR
w_temp RES 1 ; variable used for context saving
status_temp RES 1 ; variable used for context saving
pclath_temp RES 1 ; variable used for context saving
CBLOCK 0x20
X
Y
ENDC ;
ORG 0x000 ;
GOTO Init ;
INT_VECTOR CODE 0x0004 ; interrupt vector location
GOTO INT_GIT
ORG 0X005
Init
; movlw 0x07 ; Turn comparators off and
; movwf CMCON ; enable pins for I/O functions
BANKSEL TRISD
CLRF TRISD
MOVLW 0XFF
MOVWF TRISC
MOVWF TRISB
BANKSEL PORTB
CLRF PORTB
CLRF PORTC
CLRF PORTD
MOVF PORTB, W
MOVWF X
MOVF PORTC, W
MOVWF Y
;MOVF PORTB,X
;MOVF PORTC,Y
CLRW ; Clear Result
BCF STATUS,C ; Clear Carry for RLF later ;
BTFSC Y,0 ; ?*1
ADDWF X,W ; W = ?X
RLF X,F ; X = 2X
;
BTFSC Y,1 ; ?*2
ADDWF X,W ; W = ?X + ?2X
RLF X,F ; W = 4X
BTFSC Y,2 ; ?*4
ADDWF X,W ; W = ?X + ?2X + ?4X
RLF X,F ; W = 8X
BTFSC Y,3 ; ?*8
ADDWF X,W ; ?X + ?2X + ?4X + ?8X
MOVWF PORTD
dongu
GOTO dongu
INT_GIT
movf pclath_temp,w ; retrieve copy of PCLATH register
movwf PCLATH ; restore pre-isr PCLATH register contents
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
end
ortalığı biraz karıştırdığımın farkındayım...Bu şekilde mplabx üzerinde derlenmekte ve isis üzerinde çalışmakta.
ambar kodları derledim hata veriyor kullandıgım surum mplab7.10
(http://s29.postimg.cc/xd73zu7mb/ASD.jpg) (http://postimg.cc/image/xd73zu7mb/)
sanırım kullandıgım compılerdan kaynaklanıyor kodların hexını gonderebılırsen ya da compilerin linkini atsan
http://www.microchip.com/pagehandler/en-us/family/mplabx/ (http://www.microchip.com/pagehandler/en-us/family/mplabx/)
derleyicinin linki,
:020000040000FA
:020000000528D1
:040002000034003492
:020008002328AB
:06000A00831603138801B8
:10001000FF30870086008312031386018701880161
:100020000608A0000708A1000301031021182007FB
:10003000A00DA1182007A00D21192007A00DA119BE
:1000400020078800222872088A0071088300F00EB9
:04005000700E090025
:02400E00F13F80
:00000001FF
buda hex dosyası
verdiğin kodla devre eksik calısıyor ambar kullandığın şemayı ekleyebilirmisin
(http://s4.postimg.cc/fmj26gso9/Ads_z.jpg) (http://postimg.cc/image/fmj26gso9/)
2*1=4 buluyor sen nasıl calıstırdınn ?
giriş ve çıkışları ters bağlamışsın.1 yazdığı zaman bit0 kırmızı olması gerekir. LSB ve MSB olarak ters bağlı.
girişte ne yazıyor üstteki 100 (ikilik sayı sisteminde) alttaki 1000 (ikilik sayı sisteminde)
sonuçta ne yazıyor 100000 (ikilik sayı sisteminde) sonuç doğru... İstersen bilgisayarın hesap makinesinde deneebilirsin.
Benim şemamda yayınlanacak bir şey yok doğrudan ikilik sayı sisteminde baktım çünkü...
girişler basit LOGICTOGGLE bağlı bunlarla girilen değeri çıkış bacaklarının sonucuna baktım.
Hem displayi hem sayı girişlerini yanlış bağlamışsın,
yaptığın işlem (sw1 4, sw2 8 )
4x8
sonuç ise
32
pice bağlı olan sayı girişlerinin y ekseninde simetriği olacak şekilde bağlamalısın.
Display içinde bulduğun sonucu displayde gösterilebilir hale getirmen lazım,
senin bulduğun 32 sonucu aslında 0x20, veya 0b 0010 0000 şeklindedir.
Picde işlemler hexadecimal (16lık taban) olarak yapılır,
sen sonucu decimal (onluk taban) olarak görmek istiyorsun.
tamamdır sorunu çözdüm yardımlarınız için çok teşekkürler...