dsPIC – ASM30 ile Uart

dspic_kucuk4 Merhaba, Bu yazımızda microchip asm30 ile uart haberleşmesini gerçekleştireceğiz. Bu bölümde port değiştirme (led veya role sürme) gibi bir uygulamadan başlamak istemedim. Microchip asm30 derleyicisini ve dsPIC,PIC24 serinin registerlerini C optimizasyonu için özel olarak ayarlamış. C’deki while, do-while, işlemlerini yapan asm30 komutları ve regsiterleri var. Küçük bir örnek olarak asm30 “repeat #k” komutu kendisinden sonraki komutu k+1 kez çalıştırır. Bu yapı C’deki while{} yapısına benzer.

Aslında Microchip projelerimde C30 kullanıyorum ama şimdiye kadar intenette de doğru düzgün asm30 kod görmediğim için referans olması açısından bir kaç uygulama eklemek isteyorum. Açıkçası Microchip’in PIC24 ve dsPIC serisini beğendim.PIC24 serisinde özellikle kullanmak istediğin modulun port çıkışlarını seçmek için registerler koymaları çok iyi, bu pcb çizenlere de kolaylık sağlar. dsPIC’te ise 40bitlik çarpma işlemlerini gerçekleştirebilen bir donanıma sahip.

Burada yazdığım kodları yukarıda resmini verdiğim dsPIC30F4011 geliştirme boardunda denedim. Geliştirme board’unuda 2006’da ben hazırlamıştım. Resim üzerinde yine daha önce yaptığım nokia lcd üzerinde animasyon ve kayan yazı uygulamasından küçük örnek var. (LQFP kılıf uc olan board LPC2148 board’u)

dspic_buyuk3

/*********************************************************/
Aykut ULUSAN, Elektronik Mühendisi, IZMIR

Aşağıda 38400bps ile 0,5 saniyede bir KUTAY table'ı uart1'den gönderilir.

/*********************************************************/

.equ __30F3010, 1				             ; kullanılacak işlemci
.include "p30fxxxx.inc"
config	__FOSC, CSW_FSCM_OFF &XT_PLL8    ; 10Mhz*8 =80Mhz
config	__FWDT, WDT_OFF				         ;  WDT off
config	__FBORPOR, MCLR_EN &PBOR_OFF &PWRT_16	; Brown-out off, MCLR enable, Power_up timer 16msn
config 	__FGS, CODE_PROT_OFF			       ; Kod koruması off

.equiv	flag_bit, 0					; zamanın dolduğunu bildirir
.equiv	FCY, 20000000				    ; Osc 80Mhz / FCY=20Mhz =20MIPS
.equiv	BAUDRATE, 38400				  ; RS232 baudrate 38400

.macro 	MOVFF	F1,F2				   ; F1, F2'ye atılır
mov	\F1,wreg
mov	wreg,\F2
.endm

.macro	MOVLF	L,F					; Literal file'a atılır
mov	\L,w0
mov	w0,\F
.endm

;=============================================================================================
; global atamalar yapılır, C30 içinde kullanacağımız tüm altprogramlar global olmalı
;=============================================================================================

.global	__reset					; Device resetten sonra hemen  __reset etiketini gördüğü yere gider, linker içinde tanımlanmıştır.
.global	__T1Interrupt			      ; Artık asm içinde  interrupt,

.section 	.const, "r"  				; PSV içinde Kutay adlı bir table tutalım, r=read only data
KUTAY:
.asciz	"asm30 ile uart1, 38400bps by EEMKUTAY"	; asciz, zero ile sonlanır

.text							; program buradan başlar, code yazma başlangıcı

__T1Interrupt:						; işlemci 0,5 sn'de bir buraya gelir
bclr  	IFS0, #T1IF				; flag'i sil
bset	W1, #flag_bit				; RS232 flag biti set et
retfie						    ; interrupt'an geri dön

__reset:
mov	#__SP_init, W15				; __SP_init , işlemciye göre linker içinde tanımlı, W15 stack pointer
MOVLF	#__SPLIM_init,SPLIM			; Stack Pointer limiti gir, linker içinde tanımlı
nop						        ; SPLIM ayarlanması için bir nop gerekli
; Şimdi working registerleri clear edeceğiz
clr	W0					      ; W0
mov	W0, W14 				; W14, adres pointer  oldu  ve  W14=0 adresini gösterir(adres pointer) yani W0'ın adresini
repeat	#12                                        ; next komut 13 kez repeat
mov	W0, [++W14]				; W1 - W13'ü clear yapar
clr	W14					; Counter'i silelim, W14=0

rcall	PORTLARI_HAZIRLA			; portları hazırla
rcall	INIT_TIMER1				; timer1'i  0,5 saniye için ayarla
rcall	INIT_UART1				; uart1 hazırlanır
bclr	W1, #flag_bit				; 0,5sn dolmadan table'ı gönderme
; table okuma ve yazma komutlarıyla , string okuyalım
mov	#tblpage(KUTAY),w0			;Kutay table'ın  page’ını w0’a at
mov	w0, _TBLPAG

main_loop:
btss	W1, #flag_bit				; 0,5 sn doluncaya kadar bekle
bra	main_loop				; zaman dolmamış
bclr	W1, #flag_bit				; zaman dolmuş flag'i clear et
mov	#tbloffset(KUTAY), W2 ; w2'yi pointer olarak kullanacağız (w2, KUTAY table'ın adresini tutuyor)
clr		W0				; w0=0 yap çünkü byte yükleyeceğiz (bit15-8 arası 0 olsun)

wrt_loop:
mov.b	[W2++], W0				; harfi W0'a yükle (byte modunda Program counter 1 artar)
cp0	W0					     ; karakter 0 ise string sonu
bra	z, main_loop				   ; Z=1 ise main loop'a git
mov	W0, U1TXREG				; harfi buffer'a at
xmt_loop:
btss	U1STA, #TRMT				; gönderildi mi?( gönderilince 1 olur)
bra	$-2					       ; Gönderilinceye kadar bekle
bra	wrt_loop				     ; next harfi gönder

PORTLARI_HAZIRLA:
clr	LATF					; portu temizle
mov	#0xFF,w0
mov	w0,TRISF
return

; Instruction cycle = 20MIPS
; ds30f3010 üzerinde TMR1 A tipi timerdır. (50ns x prescale x PR1 = zaman)
; zaman =0,5sn için, prescale=1/256  (0,5sn= 500ms=500 000us)
; 50nsx256=12580ns=12,8us
; PR1 = 500 000us / 12,8us = 39765=0x9B41
INIT_TIMER1:
clr	TMR1
MOVLF	#0x9B41,PR1				; PR1'e yükle
MOVLF	#0x8030, T1CON				; 1:256 prescale ve timer1 on
bclr	IFS0, #T1IF				; TMR1 interrupt flag clear
bset	IEC0, #T1IE				; TMR1 interrupt set
return

INIT_UART1:
clr 	U1MODE					; Uart mode clear et, bit ile ayarlayacağız
clr 	U1STA					; status biti clear et,  bit ile ayarlayacağız
;	bset	U1MODE, #ALTIO				; U1ATX/U1ARX pinlerini kullan
bset 	U1MODE, #UARTEN 			; Enable UART
mov 	#(((FCY/BAUDRATE) / 16) - 1), w0
mov 	w0, U1BRG				; BRG ayarla
return

.end

/*********************************************************/

6 Yorum

Yorum ekle

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir