Digital saat hakkında

Başlatan 0u2h4n, 27 Ağustos 2010, 02:51:22

0u2h4n

Hakan Karakaş'ın İleri PIC Uygulamaları-1 Kitabını aldım ve oradaki DigitalSaat programını bilgisayarda yazıp isis ile denedim fakat bir sorunla karşılaştım. Sorunum şu:
Devreyi çalıştırınca 4 display arasındaki geçiş gözün farkedebildiği hızda oluyor ve bu yüzden sayılar hep ekranda kalmıyor her display tek tek yanıp sönüyor. Kodları bikaç kere incelemem rağmen bunun çözümünü bulamadım ve bu foruma üye olup burada sormaya karar verdim. Yardımcı olursanız çok yararlı olur. Ayrıca o kitaptaki tüm uygulamaları tek tek yazıp denedim isteyenlerle paylaşabilirim

Devre: http://img825.imageshack.us/i/digitalsaat.png/
;=======================DİGİTAL_SAAT.ASM=============================
;Digital saat SS:DD, 00:00 gösteriminde 24 saat formunda...
;--------------------------------------------------------------------------
	LIST	P=16F84
	INCLUDE	<P16F84.INC>
	RADIX	HEX
	__CONFIG	_CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;--------------------------------------------------------------------------
i		EQU		0x0C	;Dizi boyutu
_STATUS	EQU		0x0D	;STATUS registerının kopyası
_W		EQU		0x0E	;Working registerın kopyası
SAYI	EQU		0x10	;Sayı dizisi.Display içeriği
SAYI1	EQU		0x14	;Klavyeden girilen sayı
SN		EQU		0x1A	;1 SN için sayaç
DK		EQU		0x1B	;1 DK için sayaç
COUNT	EQU		0x1C	;DISPLAYler için döngü
INT2	EQU		0x1D	;2.defa interrupt
TUS		EQU		0x1E	;Tuş değeri
RA4		EQU		0x1F

		ORG		0x00
		GOTO	BASLA
		ORG		0x04
		GOTO	INTERRUPT
;--------------------------------------------------------------------------
BASLA
	CALL	KURULUM		;PIC16F84ün portlarını ayarla
	CALL	CLEAR		;Register içeriklerini sıfırla
	MOVLW	.2			;24:00 değerini
	MOVWF	SAYI1+3		;SAYI1
	MOVLW	.4			;registerında
	MOVWF	SAYI1+2		;sakla
	CLRW
	MOVWF	SAYI1+1
	MOVWF	SAYI1
	CALL	DISPLAY		;Displaylere yaz
	GOTO	$-1			;Bir satır geri git
;--------------------------------------------------------------------------
KURULUM
	BSF		STATUS,RP0	;BANK1e geç
	MOVLW	h'F0'		;W = 11110000
	MOVWF	TRISB		;PORTB = 11110000
	CLRF	TRISA		;PORTA = 00000000
	MOVLW	b'10000100'	;Prescaler = 32, dahili komut saykılı seçili
	MOVWF	OPTION_REG
	BCF		STATUS,RP0	;BANK0a dön
	CLRF	PORTA		;LEDleri söndür
	MOVLW	b'10101000'	;GIE, RBIE ve T0IE aktif olarak
	MOVWF	INTCON		;INTCON registerı kur
	RETURN
;--------------------------------------------------------------------------
CLEAR
	MOVLW	SAYI		;Ilk register adresini
	MOVWF	FSR			;tut
	MOVLW	0x1F		;15 adet değişkeni
	MOVWF	i			;sıra ile
SIFIR
	CLRF	INDF		;sıfırla
	INCF	FSR
	DECFSZ	i
	GOTO	SIFIR
	RETURN
;--------------------------------------------------------------------------
DISPLAY
	MOVLW	4			;Sayı dizisinin boyutu
	MOVWF	i			;i = 4
	MOVLW	SAYI		;Sayı dizisinin başlangıç adresini
	MOVWF	FSR			;FSR'e yaz
	MOVLW	b'11111110'	;1.digiti seç (LSB)
	MOVWF	PORTB
TARA
	MOVF	INDF,W		;Dizinin elemanını W'e yaz
	IORWF	RA4,W
	MOVWF	PORTA		;PORTA'dan gönder
	CALL	TIMER		;Bir süre bekle
	INCF	FSR			;Dizinin bir sonraki elemanının adresine ulaş
	BSF		STATUS,C	;Carry set
	RLF		PORTB,F		;aktif olan digit bir soldaki
	DECFSZ	i			;dizinin son elemanına ulaşıldı mı?
	GOTO	TARA		;Hayır, Taramaya devam et
	RETURN				;Evet, alt programdan çık
;--------------------------------------------------------------------------
TIMER
	MOVLW	h'FF'
	MOVWF	COUNT
DONGU1
	DECFSZ	COUNT,F		;Evet, COUNT = COUNT - 1 , Sonuç 0 mı?
	GOTO	DONGU1		;Hayır, DONGU1'e git
	RETURN				;Evet, TIMER alt programından çık
;--------------------------------------------------------------------------
INTERRUPT
	MOVWF	_W
	MOVF	STATUS,W
	MOVWF	_STATUS
	BTFSS	INTCON,RBIF	;Klavye int.?
	GOTO	$+3			;Hayır, timer interrupt sorgula satırına git
	CALL	KLAVYE_INT	;Klavye alt programını çağır
	GOTO	INT_SON
	BTFSC	INTCON,T0IF	;Timer interrupt var mı?
	CALL	TIMER_INT	;Evet, timer alt programına git
INT_SON
	MOVF	_STATUS,W	;STATUS değerini geri yükle
	MOVWF	STATUS
	MOVF	_W,W		;W değerini geri yükle
	RETFIE				;Interrupt alt programından çık
;--------------------------------------------------------------------------
TIMER_INT
	BCF		INTCON,T0IF	;T0IF bayrağını temizle
	INCF	SN			;SN = SN + 1
	MOVLW	.125
	SUBWF	SN,W
	BTFSS	STATUS,Z
	GOTO	TIMER_SON	;Hayır
	COMF	RA4,F		;LED'in son durumunun tersini al
	MOVLW	b'00010000'
	ANDWF	RA4,F
	CLRF	SN			;Evet, SN = 0
	INCF	DK
	MOVLW	.60
	SUBWF	DK,W
	BTFSS	STATUS,Z
	GOTO	TIMER_SON
	INCF	SAYI		;SAYI = SAYI + 1
	CLRF	DK 
	CALL	TEST_ARTTIR	
	CALL	TEST_2400
TIMER_SON
	RETURN
;--------------------------------------------------------------------------
KLAVYE_INT
	BCF		INTCON,RBIF	;RBIF sıfırla
	BCF		INTCON,T0IF
	BCF		RA4,4
	INCF	INT2		;INT2 = INT2 + 1
	BTFSC	INT2,1		;Tuş serbest bırakıldı mı
	GOTO	KLY_CIK		;Evet,klavye alt programından çık
	SWAPF	PORTB,W
	ANDLW	0x0F		;Üst 4 biti sıfırla
	SUBLW	0x0F		;Sonuç sıfır mı?
	BTFSC	STATUS,Z	;Evet
	GOTO	KLY_SON		;Tuş serbest alt programdan çık
	BCF		INTCON,T0IE ;Rakamlar girilirken sayıcıyı durdur
	SWAPF	PORTB,W
	ANDLW	0x0F		;Üst 4 biti sıfırla
	MOVWF	TUS			;Sonucu PORTA'ya gönder
	SUBLW	0x0A		;Basılan tuş ENTER mı?
	BTFSS	STATUS,Z
	GOTO	RAKAM
	CALL	RAKAM_TEST	;Girilen sayı değeri uygun mu?Test et
	CLRF	SN
	CLRF	DK
	BSF		INTCON,T0IE	;Rakam girildiğinde sayıcıyı yeniden başlat
	GOTO	KLY_SON
RAKAM
	MOVF	SAYI+2,W	;Dijitleri sola kaydır
	MOVWF	SAYI+3		;Yeni tuş değerini
	MOVF	SAYI+1,W	;en sağdaki dijite
	MOVWF	SAYI+2		;yaz
	MOVF	SAYI,W
	MOVWF	SAYI+1
	MOVF	TUS,W
	MOVWF	SAYI
	GOTO	KLY_SON
KLY_CIK
	CLRF	INT2
KLY_SON
	RETURN
;--------------------------------------------------------------------------
TEST_ARTTIR
	MOVLW	.10			;Sayı kaydedicisi 10 ise içeriğini sıfırlar
	SUBWF	SAYI,W		;Bir sonraki basamağı arttırır
	BTFSS	STATUS,Z	;SAYI[0] = 10 ?
	GOTO	A_END		;Hayır, alt pogramdan çık
	CLRF	SAYI		;Evet, sayı[0] = 0
	INCF	SAYI+1
	MOVLW	.6
	SUBWF	SAYI+1,W
	BTFSS	STATUS,Z	;SAYI[1] = 10 ?
	GOTO	A_END		;Hayır, alt pogramdan çık
	CLRF	SAYI+1		;Evet, sayı[1] = 0
	INCF	SAYI+2
	MOVLW	.10
	SUBWF	SAYI+2,W
	BTFSS	STATUS,Z	;SAYI[2] = 10 ?
	GOTO	A_END		;Hayır, alt pogramdan çık
	CLRF	SAYI+2		;Evet, sayı[2] = 0
	INCF	SAYI+3
A_END
	RETURN	
;--------------------------------------------------------------------------
TEST_2400
	MOVF	SAYI,W
	SUBWF	SAYI1,W
	BTFSS	STATUS,Z
	GOTO	C_END
	MOVF	SAYI+1,W
	SUBWF	SAYI1+1,W
	BTFSS	STATUS,Z
	GOTO	C_END
	MOVF	SAYI+2,W
	SUBWF	SAYI1+2,W
	BTFSS	STATUS,Z
	GOTO	C_END
	CLRF	SAYI
	CLRF	SAYI+1
	CLRF	SAYI+2
	CLRF	SAYI+3
C_END
	RETURN
;--------------------------------------------------------------------------
RAKAM_TEST
	MOVLW	.10
	SUBWF	SAYI,W		;D0 > 10 ?
	BTFSS	STATUS,C
	GOTO	$+2			;Hayır, küçük, diğer dijiti test et
	GOTO	HATALI_SAYI	;Evet, Ekrana 00:00 yaz
	MOVLW	.6
	SUBWF	SAYI+1,W	
	BTFSS	STATUS,C	;D10 > 6 ?
	GOTO	$+2			;Hayır, küçük, diğer dijiti test et
	GOTO	HATALI_SAYI	;Evet, Ekrana 00:00 yaz
	MOVLW	.3
	SUBWF	SAYI+3,W	;S10 > 3 ?
	BTFSS	STATUS,C
	GOTO	$+2			;Hayır, küçük, diğer dijiti test et
	GOTO	HATALI_SAYI	;Evet, Ekrana 00:00 yaz	
	MOVLW	.2
	SUBWF	SAYI+3,W	;S10 = 2 ?
	BTFSS	STATUS,Z
	GOTO	$+6			;Hayır, küçük, diğer dijiti test et
	MOVLW	.4			;Evet, S10 = 2
	SUBWF	SAYI+2,W	;S1 > 4 ?
	BTFSS	STATUS,C
	GOTO	$+2			;Hayır, küçük, diğer dijiti test et
	GOTO	HATALI_SAYI	;Evet, Ekrana 00:00 yaz
	MOVLW	.10			;S1 > 10 ?
	SUBWF	SAYI+2,W
	BTFSS	STATUS,C
	GOTO	ALTSON
HATALI_SAYI
	CLRF	SAYI+1
	CLRF	SAYI+2
	CLRF	SAYI+3
ALTSON
	RETURN
	END
;==========================================================================

Gökhan BEKEN

bu proje tarama yöntemi kullandığından tarama süresini kısaltırsanız sorun olmaz
aşağıdaki bölümde taramaların süresini call komutu ile çağırıyor daha doğrusu alt programa dallanıyor
CALL   TIMER      ;Bir süre bekle bu komutla dallanmayı sağlıyor
TARA
   MOVF   INDF,W      ;Dizinin elemanını W'e yaz
   IORWF   RA4,W
   MOVWF   PORTA      ;PORTA'dan gönder
   CALL   TIMER      ;Bir süre bekle
   INCF   FSR         ;Dizinin bir sonraki elemanının adresine ulaş
   BSF      STATUS,C   ;Carry set
   RLF      PORTB,F      ;aktif olan digit bir soldaki
   DECFSZ   i         ;dizinin son elemanına ulaşıldı mı?
   GOTO   TARA      ;Hayır, Taramaya devam et
   RETURN   



bekleme fonksiyonu ise aşağıdaki kısımda
TIMER
   MOVLW   h'FF'
   MOVWF   COUNT
DONGU1
   DECFSZ   COUNT,F      ;Evet, COUNT = COUNT - 1 , Sonuç 0 mı?
   GOTO   DONGU1      ;Hayır, DONGU1'e git
   RETURN            ;Evet, TIMER alt programından çık
;--------------------------------------------------------------------------


MOVLW   h'FF' komutunda h'FF' yerine d'0' dan d'255' e kadar bir sayı yazabilirsiniz
h hexadesimal demek yani 16 lık sayı sistemidir. Eğer biliyorsanız 16 tabanda yazmanızda bir sakınca yok.
d decimal demek yani 10 luk sistem yani günlük hatatta kullandığımız sayı sistemidir isiste sorun çıkartmayan bir değeri deneme yanılma ile 0-255 arasında bulabilirsiniz. Bu simüle için geçerlidir gerçek devrede programın orjinal sayısını kullanın çünkü isis ve gerçek devre arasında zaman uyuşmazlığı vardır.
Özel mesaj okumuyorum, lütfen göndermeyin.

tnen

Proteusta similasyon esnasında CPU yüküne bak ondan kaynaklanıyordur. Projeyi yaparsan bunu farketmezsin

acemi2010


proteus'da simülasyonu durdur; pic'in üzerine çift tıkla; çıkan penceredeki osilatör frekansını arttır. Sonra tekrar simülasyonu çalıştır

Timuçin

radres

Devren gerçek hayatta  çalışır. PROTEUS'tan kaynaklanan bir sorun bu.

0u2h4n

Herkese teşekkürler.
Fakat osc frekansını baya bi arttırmama, kodlamadaki döngüyü 0-255 arası denememe rağmen bir türlü yeterli zamanı bulamadım. Bu simülasyonu ISIS'te yapmamın imkanı yok mu?

radres

Proteusta 2 tane displayi transistör ile kontrol ettiğinde bile taramayı göremedim ben. Bu nedenle dediğim gibi PROTEUS'ta taramayı görmen zor.

camby

sorun yok , display 'e çift tıklayarak minimum triger time süresini değiştirmeyi/azaltmayı deneyin