Elektronik / Mikrodenetleyici Projeleri/

Açıklamalı pic16f877 uygulama kodları cod asm c

Sponsorlu Bağlantılar

Altaş Yayıncılık ve Elektronik satışa sunduğu “PIC Programlama Teknikleri ve PIC 16F877A” adlı kitabın ücretsiz dağıtılan uygulama devrelerine ait kaynak assembly ve c yazılımları pic16f877 deneme gelitirme kartları ile çalıştırılabilir. Türkçe açıklamaları olduğu için pic16f877 ile devre kurulabilir yada projelerinizde çözüm bulamadığınız durumlarda komut açıkamaları kullanılan yöntemler yardımcı olabilir ayrıca mplab üzerinde programın çalışmasını test edebileceğiniz .cod dosyalarıda bulunmakta

Hazırayanlar: Hikmet ŞAHİN Ayhan DAYANIK Caner ALTINBAŞAK Emeği geçen hazırayan kişilere teşekkürler

Kodları test edebilmeniz için çeşitli pic16f877 deneme geliştirme kartları PIC16F84 PIC16F877 Deneme devreleri isis simülasyon, Microchip PIC16F877 Test Deney Kartı

PIC 16F877 assembly proje listesi ve örnekler

12_2.asm: Seri LCD kullanımı
12_1.asm: 4-bit arabirim modunda LCD kullanımı
11_5_b.asm: Başka bir PIC’den USART ile senkron veri alımı
11_5_a.asm: 4×4 tuş takımı ile USART senkron iletişim
11_4.asm: 4×4 tuş takımı tasarımı
11_3.asm: Buton kontrolü
4_8.asm: WDT uygulaması.
4_7.asm: WDT uygulaması.
11_2.asm: 4 dijit 7 segment display uygulaması
11_1.asm: 7 segment display uygulaması
10_1.asm: PSP kullanımı
9_3.asm: Seri eeprom ile iletişim.
9_2.asm: Flash program belleğini okuma ve yazma
9_1.asm: Dahili eeprom belleğe veri yazma ve okuma
7_2.asm: A/D modülü ile ısı ölçümü (LM35 ile)
7_1.asm: A/D dönüştürücü uygulaması.
6_1.asm: SFR’siz Asenkron Seri veri İletişimi.
5_3.asm: PWM modülünün kullanılması.
5_2.asm: CCP1 compare modunun kullanılması.
5_1.asm: CCP1 capture modunun kullanılması.
2_2.asm: 0-255 ikilik düzende TMR0 ile dışardan aldığı saat darbesi ile sayan sayıcı
6_6.asm: I²C Protokolü ile Seri Veri İletişimi (PCF8574 kullanılarak).
6_5.asm: MSSP modülü SPI master iletişim (MAX7219 kullanarak).
6_4.asm: MSSP modülünün ile SPI master modunda veri iletişimi 74HC595 kullanarak).
6_3.asm: SFR’siz senkron seri veri iletişimi (74HC597 kullanılarak).
6_2.asm: SFR’siz senkron seri veri iletişimi (74HC595 kullanılarak).
4_6.asm: Timer2’nin Zamanlayıcı Olarak Kullanılması.
4_5.asm: Timer1’in Senkronize Sayıcı Olarak Kullanılması.
4_4.asm: Timer1’in Zamanlayıcı Olarak Kullanılması.
4_3.asm: Timer1’in Zamanlayıcı Olarak Kullanılması görmek.
4_2.asm:Timer0’ın Harici Tetikleme (RB0/INT) İle Sayıcı Olarak Kullanılması.
4_1.asm: Timer0’ın zamanlayıcı olarak kullanılmasını göstermek.
3_6.asm: RB4-RB7 uçlarındaki değişikle uyku modundan çıkışı göstermek.
3_5.asm: Kesmeden çıkmak için tuştan parmağın çekilmesini bekleyen program.
3_4.asm: İki kesmeyi kaynağını beraber kullanmak.
3_3.asm: Kesmeden çıkmak için tuştan parmağın çekilmesini bekleyen program.
3_2.asm: Kesmelerin genel özellikleri ve RB0 harici kesmesi.
3_1.asm: STATUS register’ı içeriğine bakarak karar vermek.
6_7.asm: USART Modülü İle Asenkron Seri Veri İletişimi.
2_1.asm: 0-255 arasında ikilik düzende sayıcı

8_3.asm: Komparatörün ortak referanslı PORTA çıkışlı iki karşılaştırıcı olarak kullanılması

8_2.asm: Komparatör modülünün dahili ortak referanslı 4 girişten seçimli iki karşılaştırıcı modunda kullanılması.

8_1.asm: Komparatör modülünün iki bağımsız karşılaştırıcı olarak kullanılması

6_11_2.asm: USART Modülü İle İki Mikrodenetleyici Arasında Master/Slave Senkron Seri Veri İletişimi.

6_11_1.asm: USART Modülü İle İki Mikrodenetleyici Arasında Master/Slave Senkron Seri Veri İletişimi

6_10.asm: USART modülü ile senkron master mod veriiletişimi(74HC595 kullanarak).

6_9.asm: USART Modülü İle Senkron Master Mod Veri İletişimi (74HC165 kullanarak).

6_8_2.asm: USART Modülü İle Asenkron Seri Veri İletişimi (PIC16F877A ile PIC 16F628A kullanılarak)

6_8_1.asm: USART Modülü İle Asenkron Seri Veri İletişimi (PIC16F877A ile PIC 16F628A kullanılarak).

Satın almak isterseniz kitap detayları :http://www.altaskitap.com/PIC_877kitab%C4%B1.htm uygulama dosyaları: Açıklamalı pic16f877 uygulama kodları cod asm c

Dosya indirme LINK listesi (TXT formatında) link-7256.zip şifre-pass: 320volt.com


;	Dosya Adı		: 9_1.asm
;	Programın Amacı		: Dahili eeprom belleğe veri yazma ve okuma
;	PIC DK2.1a 		: PORTB Çıkış ==> LED
;				: XT ==> 4Mhz

	list p=16F877A
	include "p16F877A.inc"	
	__config H'3F39' 		;Tüm program sigortaları kapalı, 
					;Osilatör XT ve 4Mhz
	ORG 	0			;Reset vektör adresi.
	clrf 	PCLATH			;0. Program sayfası seçildi.
	goto 	ana_program		;ana_programa'a git.
	
	ORG	4			;Kesme vektör adresi.
Kesmeler				;Kesme kullanımı gerekiyorsa 
					;buradan itibaren yazılmalı. 
					;ya da goto komutu ile buradan yönlendirilmeli.
	retfie

; Dahili EEPROM'a veri yazma alt programı:
; Çağrılmadan önce EEADR kaydedicisine yazılacak adres, EEDATA 
; kaydedicisine ise yazılacak veri yüklenmeli.

dahili_EEPROM_yaz
	banksel EECON1			;EECON1'in bulunduğu BANK seçildi.
	bcf	INTCON, GIE		;Genel kesmeler pasif. (Yazmada 
					;işlem akışı bozulmamalı.)
	bsf	EECON1, WREN		;Yazma etkinleştirme bit’i set 
					;edildi.
	movlw	0x55			;Yazma için buradan itibaren 5 
					;satır aynen korunmalı.
	movwf	EECON2
	movlw	0xAA
	movwf	EECON2
	bsf	EECON1, WR		;Yaz komutu verildi.
	bsf	INTCON, GIE		;Genel kesmeler aktif. (Kesme 
					;kullanılmayacaksa silinebilir.)
dahili_ee_j1
	btfsc 	EECON1, WR		;Yazma işlemi tamamlanana kadar 
					;bekle (WR=0 olana kadar).
	goto 	dahili_ee_j1
	bcf 	EECON1, WREN		;Yazma izni kaldırıldı.
	return

; Dahili EEPROM'dan veri okuma alt programı: Çağrılmadan önce EEADR 
; kaydedicisine okunacak verinin adresi yüklenmeli.

dahili_EEPROM_oku
	banksel EECON1
	bsf	EECON1, RD
	banksel EEDATA
	movf	EEDATA, W
	return

; Ana program: 0x0A dahili EEPROM adresine 0x97 bilgisi yükleniyor,
; Daha sonra aynı adresten veri okunarak PORTB'deki LED'lerde 
; görüntüleniyor.

ana_program
	banksel TRISB			;BANK1 seçildi, TRISB bu bankta.
	clrf	TRISB			;PORTB pinleri çıkışa ayarlandı.
	banksel PORTB			;BANK0 seçildi, PORTB bu bankta.
	clrf	PORTB			;İlk anda LED'ler sönük.
	movlw	0x0A			;Yazılacak Dahili EEPROM adresi
	banksel EEADR			;EEADR kaydedicisi için BANK 
					;seçildi.
	movwf 	EEADR			;Adres bilgisi yüklendi.
	movlw	0x97			;Yazılacak veri.
	movwf	EEDATA			;Veri yüklendi.
	call	dahili_EEPROM_yaz	;Yazma alt programını çağır.
	banksel EEADR			;EEADR kaydedicisi için BANK 
					;seçildi.
	movlw	0x0A			;Okunacak Dahili EEPROM adresi.
	movwf	EEADR			;Adres bilgisi yüklendi.
	call	dahili_EEPROM_oku	;Okuma alt programını çağır.
	banksel PORTB			;BANK0'a geç.
	movwf	PORTB			;Okunan değeri LED'lerde görüntüle.
ana_j1
	goto	ana_j1			;Sistem kapatılana yada resetlenene 
					;kadar boş döngü.
	END

;	Dosya Adı		: 9_2.asm
;	Programın Amacı		: Flash program belleğini okuma ve yazma
;	Notlar 			: Proteus programı simülasyonu.
;				: XT ==> 20Mhz

	list p = 16F877A
	include "p16F877A.inc"
	__config H'3B32'	;PWRT on, WRT Enable, diğer 
				;sigortalar kapalı, Osilatör HS ve 
				;20Mhz.

; Buton ve değişken tanımlamaları yapılıyor.

#define ADRESARTIR	1	;Adres artırma butonu.
#define PROGRAMSIL	2	;Program silme butonu.

FlashAdresL	equ	0x20	;Flash adresinin en değersiz byte 
;değişkeni.
FlashAdresH	equ	0x21	;Flash adresinin en değerli byte 
;değişkeni.
FlashDataL	equ	0x22	;Flash'a yazılan ya da okunan 
				;verinin en değersiz byte değişkeni
FlashDataH	equ	0x23	;Flash'a yazılan ya da okunan 
				;verinin en değerli byte değişkeni.
	org	0
	goto	ana_program
	
	org	4
	goto	kesme

; Kesme alt programı.

kesme
	retfie

; Ana program portları yönlendirir ve ilk durumları yükler. 
; ADRESARTIR butonuna her basıldığında 0. adresten başlayarak Flash 
; program belleğini okuyarak PORTB ve PORTC üzerinde görüntüler. 
; ADRESARTIR butonu bırakılana kadar ikinci bir görüntüleme yapmaz. 
; PROGRAMSIL butonuna basıldığı zaman 0. adresten itibaren programı 
; imha eden alt program çalışır.

ana_program
	banksel TRISB				;Bank0 seçildi.
	clrf	TRISB				;PORTB çıkışa ayarlandı.
	clrf	TRISC				;PORTC çıkışa ayarlandı.
	movlw	0x06	
	movwf	ADCON1				;PORTA dijital I/O ayarlandı
	movlw	0xFF
	movwf	TRISA				;PORTA tüm bit’leri giriş. 
	banksel PORTB
	clrf	PORTB				;İlk anda 0. 
	clrf	PORTC				;İlk anda 0.
	clrf	FlashAdresL			;0. adresten itibaren Flash 
						;program belleği okunacak.
	clrf	FlashAdresH
	movlw	0x07
	movwf	CMCON				;Komparatör girişleri 
						;kapatıldı.
ana_j1
	banksel PORTA				;Bank0'a geçildi.
	btfss	PORTA, PROGRAMSIL
	call	Program_Sil	
	btfsc	PORTA, ADRESARTIR		;Bir sonraki adresin 
						;içeriğini görüntülemek için 
						;devam et.
	goto	ana_j1				;Butonlara basılıp 
						;basılmadığını kontrole 
						;devam et.
	call	Flash_Read			;Flash program belleğinin 
						;ilgili adresini oku.
	banksel PORTB				;Bank0'a geçildi.
	movf	FlashDataH, W		
	movwf	PORTB				;Okunan verinin en değerli 
						;byte'ı PORTB çıkışlarında.
	movf	FlashDataL, W
	movwf	PORTC				;Okunan verinin en değersiz 
						;byte'ı PORTC çıkışlarında.
	btfss	PORTA, ADRESARTIR		;ARTIR'ma butonu bırakılana 
						;kadar boş döngü.
	goto	$-1
	incf	FlashAdresL, F			;Adresin yalnızca en 
						;değersiz byte'ını artır.
	goto	ana_j1				

; Flash program belleğine 2 byte veri yazan alt program.
; Adres = FlashAdresH:FlashAdresL,   Veri = FlashDataH:FlashDataL

Flash_Write 
	banksel FlashAdresL			;FlashAdresL kaydedicisinin 
						;bulunduğu banka geç.
	movf	FlashAdresL, W			;Adresin en değersiz byte'ı 
						;EEADR'ye yükleniyor.
	banksel EEADR				;EEADR kaydedicisinin 
						;bulunduğu banka geç.
	movwf	EEADR				;EEADR = FlashAdresL
	banksel FlashAdresH			;FlashAdresH kaydedicisinin 
						;bulunduğu banka geç.
	movf	FlashAdresH, W			;Adresin en değerli byte'ı 
						;EEADRH'a yükleniyor.
	banksel EEADRH				;EEADRH kaydedicisinin 
						;bulunduğu banka geç.
	movwf	EEADRH				;EEADRH = FlashAdresH
	banksel FlashDataL			;FlashDataL kaydedicisinin 
						;bulunduğu banka geç.
	movf	FlashDataL, W			;Verinin en değersiz byte'ı 
						;EEDATA kaydedicisine 
						;yükleniyor.
	banksel EEDATA				;EEDATA kaydedicisinin 
						;bulunduğu banka geç.
	movwf	EEDATA				;EEDATA = FlashDataL
	banksel FlashDataH			;FlashDataH kaydedicisinin 
						;bulunduğu banka geç.
	movf	FlashDataH, W			;Verinin en değerli byte'ı 
						;EEDATH laydedicisine 
						;yükleniyor.
	banksel EEDATH				;EEDATH kaydedicisinin 
						;bulunduğu banka geç.
	movwf	EEDATH				;EEDATH = FlashDataH
	banksel EECON1				;EECON1 kaydedicisinin 
						;bulunduğu banka geç.
	bsf	EECON1, EEPGD			;Program hafızasına erişim etkin
	bsf	EECON1, WREN			;Yazmayı etkinleştir.
	bcf	INTCON, GIE			;Kesmelere izin verme
	movlw	0x55				;Bu değerler EECON 
						;kaydedicisine sıralı 
						;yüklenmeli.
	movwf	EECON2
	movlw	0xAA
	movwf	EECON2
	bsf	EECON1, WR			;Yaz komutu veriliyor.
	nop					;İşlemin tamamlanması için 2 
						;komut çevrimi bekle.
	nop
	bsf	INTCON, GIE			;Kesmelere izin ver.
	bcf	EECON1, WREN			;Yazmayı pasif hale getir.	
	return					;Alt programdan çık.

; Flash program belleğinden 2 byte veri okuyan alt program.
; Adres = FlashAdresH:FlashAdresL,   Veri = FlashDataH:FlashDataL

Flash_Read
	banksel FlashAdresL			;FlashAdresL kaydedicisinin 
						;bulunduğu banka geç.
	movf	FlashAdresL, W			;Adresin en değersiz byte'ı 
						;EEADR'ye yükleniyor.
	banksel EEADR				;EEADR kaydedicisinin 
						;bulunduğu banka geç.
	movwf	EEADR				;EEADR = FlashAdresL
	banksel FlashAdresH			;FlashAdresH kaydedicisinin 
						;bulunduğu banka geç.	
	movf	FlashAdresH, W			;Adresin en değerli byte'ı 
						;EEADRH'a yükleniyor.
	banksel EEADRH				;EEADRH kaydedicisinin 
						;bulunduğu banka geç.
	movwf	EEADRH				;EEADRH = FlashAdresH
	banksel EECON1				;EECON1 kaydedicisinin 
						;bulunduğu banka geç.
	bsf	EECON1, EEPGD			;Program hafızasına erişim 
						;etkin.
	bsf	EECON1, RD			;Okumayı etkinleştir.
	nop					;İşlemin tamamlanması için 2 
						;komut çevrimi bekle.
	nop
	banksel EEDATA				;EEDATA kaydedicisinin 
						;bulunduğu banka geç.
	movf	EEDATA, W			;EEDATA W aracılığı ile 
						;FlashDataL kaydedicisine 
						;aktarılacak.
	banksel FlashDataL			;FlashDataL kaydedicisinin 
						;bulunduğu banka geç.
	movwf	FlashDataL			;FlashDataL = EEDATA
	banksel EEDATH				;EEDATH kaydedicisinin 
						;bulunduğu banka geç.
	movf	EEDATH, W			;EEDATH W aracılığı ile 
						;FlashDataL kaydedicisine 
						;aktarılacak.
	banksel FlashDataH			;FlashDataH kaydedicisinin 
						;bulunduğu banka geç.
	movwf	FlashDataH			;FlashDataH = EEDATH
	return					;Alt programdan çık.

; Flash program belleğinin 0x0000-0x00FF adres bölgesini 0x00 
; bilgileri ile doldurarak programı siler Programı silerken 
; Flash_Write alt programının bulunduğu adres bölgesinde program 
; işleyişi kontrolden çıkmaktadır. Bunun nedeni kendisini imha 
; ederken bir sonraki veriyi silmeye çalıştığında hatalı kodlar ile 
; karşılaşmasıdır.


;	Dosya Adı		: 10_1.asm
;	Programın Amacı		: PSP kullanımı
;	Notlar 			: Proteus programı simülasyonu
;				: XT ==> 20Mhz

	list p = 16F877A
	include "p16F877A.inc"
	__config H'3F3A' 		;Tüm program sigortaları kapalı, 
					;Osilatör HS ve 20Mhz

; Genel değişken tanımlamaları

#define PSP_errorFlag	7
#define PSP_inputFlag	6
#define PSP_outputFlag	5

PSP_CtrlByte		equ 0x20
PSP_inputBuffer		equ 0x21
PSP_outputBuffer	equ 0x21

	ORG	0
	clrf	PCLATH
	goto	Ana_Program

	ORG	4

; PSP'den gelen kesmeleri işler. Veri alındı ise alınan veriyi 
; PSP_inputBuffer'a yazar ve verinin alındığına dair PSP_inputFlag 
; bayrağını set eder. Master cihazdan okuma komutu geldi ise ve 
; gönderilecek bir veri daha önceden PSP_outputBuaffer'a yazıldı ise 
; Master cihaza PORTD üzerinden veriyi transfer eder. Ve Verinin 
; hazır olduğunu belirten PSP_outputFlag bayrağı siler.

interrupt
	banksel PIR1
	btfss	PIR1, PSPIF		;PSP kesmesi oluştu ise (veri geldi 
					;ya da veri gönderildi ise) komut 
					;atla.
	goto	int_son			;Kesme sonuna git ve kesmeden çık.
	banksel TRISE
	btfss	TRISE, IBF		;Veri alındı ise komut atla.
	goto	int_j1
	banksel PSP_CtrlByte
	bsf	PSP_CtrlByte, PSP_inputFlag	;Veri alındı bayrağını 
						;set et.
	movf	PORTD, W			;Gelen veriyi W'ye al. 
	movwf	PSP_inputBuffer			;W'yi giriş buffer değişkenine 
						;aktar.
int_j1
	banksel TRISE				;Bank1'e geç.
	btfss	TRISE, OBF			;Veri gönderildi ise komut atla.
	goto	int_j2
	banksel PSP_CtrlByte			;Bank0 seçildi, bu değişken ve 
						;PORTD aynı bankda.
	btfss	PSP_CtrlByte, PSP_outputFlag	;veri gönderme bayrağı 
						;set ise komut atla.
	goto	int_j2
	movf	PSP_outputBuffer, W		;Çıkış buffer değişkenine 
						;yüklenen veriyi
	movwf	PORTD				;PORD'ye gönder.
	bcf	PSP_CtrlByte, PSP_outputFlag	;Veri göndermeye hazır 
						;bayrağını sil.
int_j2
	banksel TRISE				;Bank1'e geç.
	btfss	TRISE, IBOV			;PSP'de hata oluştuysa komut atla.
	goto	int_son
	banksel PSP_CtrlByte
	bsf	PSP_CtrlByte, PSP_errorFlag	;Hata bayrağını set et
	bcf	TRISE, IBOV	
	bcf	PIR1, PSPIF			;PSP kesme bayrağını sil.
int_son
	retfie	

; PSP iletişimi ayarlar, portları yönlendirir ve kesmeleri 
; aktifleştirerek PSP iletişimi başlatır.

init
	banksel TRISE			;Bank1'e geçildi.
	movlw	B'00110111'
	movwf	TRISE			;PSPMODE aktif hale getirildi, RD, 
					;WR ve CS uçları giriş yapıldı.
	clrf	TRISB			;PORTB çıkış yapıldı.
	movlw	0x07
	movwf	ADCON1			;Analog girişler kapatıldı. 
					;PORTE'nin RD, WR ve CS girişleri 
					;için
	banksel PORTB			;Bank0'a geçildi.
	clrf	PORTB			;PORTB'nin ilk çıkışları LOW 
					;yapıldı.
	clrf	PSP_CtrlByte		;PSP değişkenlerinin ilk durumu 
					;sıfırlanıyor.
	clrf	PSP_inputBuffer
	clrf	PSP_outputBuffer
	banksel PIE1
	bsf	PIE1, PSPIE		;Paralel Slave Port kesmesi 
					;etkinleştirildi.
	bsf	INTCON, PEIE		;Çevresel kesmeler etkinleştirildi.
	bsf	INTCON, GIE		;Etkinleştirilen kesmelere izin
					;verildi.
	return

; Ana program PSP'den yazma sinyali geldiğinde gelen veriyi alır ve 
; PORTB üzerinde bağlı olan LED’ler üzerinde görüntüler. Veri okuma 
; kısmı uygun bir master cihaz kullanılmadığı ve kurulan devremiz 
; uygun olmadığı için boş bırakılmıştır, fakat gerekli ipucu 
; verilmiştir.

Ana_Program
	call	init
ana_j1
	banksel PSP_CtrlByte
	btfss	PSP_CtrlByte, PSP_inputFlag
	goto	ana_j2
	movf	PSP_inputBuffer, W
	movwf	PORTB
	bcf	PSP_CtrlByte, PSP_inputFlag	;Veri alındı bayrağını 
						;sil.
ana_j2
	btfsc	PSP_CtrlByte, PSP_outputFlag	;Çıkış verisi hazır 
						;bayrağı sıfır ise 
						;komut atla.
	goto	ana_j1

;Buraya gönderilecek veriyi çıkış buffer değişkenine yazan kodlar 
;eklenecek. Örneğin sayac diye bir değişken içeriğini çıkışa 
;transfer etmek istersek

	;movf	sayac, W
	;movwf	PSP_outputBuffer		

;sayac içeriği çıkış buffer'ına yazıldı, gönderilmek için beklemede

	bsf	PSP_CtrlByte, PSP_outputFlag	;Veri gönderme 
;bayrağını set et 
;(veri gönderilmeye hazır).

;Eğer MASTER cihazdan okuma (RD) sinyali gelirse TRISE'nin OBF bit’i 
;set olur, kesmede ilgili kısım çalışır. PSP_outputBuffer'a yüklenen 
;veri kesme içerisinden Master cihaza gönderilir ve PSP_outputFlag 
;bayrağı silinir.
	goto	ana_j1

	END

;	Dosya Adı		: 12_1.asm
;	Programın Amacı		: 4-bit arabirim modunda LCD kullanımı
;	PIC DK2.1a 		: PORTB Çıkış ==> LCD display
;				: XT ==> 4Mhz

	list p=16F877A
	include "p16F877A.inc" 
	__config H'3F31' 		;PWRT on, diğerleri kapalı, 
					;Osilatör XT ve 4Mhz

; Değişken tanımları yapılıyor: Her bir değişken başlangıç 
; adresinden itibaren birbirinin peşi sıra 1 byte yer kaplar.

	CBLOCK	0x20	;16F877A'nın RAM başlangıç adresi, 
	sayacH		;sayacın yüksek byte'ı.
	sayacL		;sayacın düşük byte'ı.

	LCD_data	;LCD için geçici veri değişkeni.
	LCD_tmp0	;LCD için geçici veri değişkeni.
	LCD_tmp1	;LCD için geçici veri değişkeni.
	LCD_line	;LCD için satır bilgisini tutan değişken.
	LCD_pos		;LCD için sütun bilgisi tutan değişken.

	HexMSB		;Desimale çevrilecek sayının en değerli byte'ı.
	HexLSB		;Desimale çevrilecek sayının en değersiz byte'ı.
	binler		;Desimale çevrilen sayının binler basamağı.	
	yuzler		;Desimale çevrilen sayının yüzler basamağı.	
	onlar		;Desimale çevrilen sayının onlar basamağı.	
	birler		;Desimale çevrilen sayının birler basamağı. 

	delay_s_data	;Gecikme alt programları için veri değişkeni.	
	delay_data	;Gecikme alt programları için veri değişkeni.
	ENDC

	ORG 	0 
	pagesel Ana_program	 
	goto 	Ana_program	;Ana programa git.

	ORG 	4		;Kesme alt programı bu adresten başlıyor.
	goto	kesme

; LCD ile ilgili temel tanımlamalar ve mesajlar.

; LCD'nin bağlı olduğu port tanımları yapılıyor.
#define LCD_DataPort PORTB		;Data pinlerinin bağlı olduğu port 
					;(D7-D4  -> RB3-RB0 ).
#define LCD_CtrlPort PORTB		;Kontrol pinlerinin bağlandığı port

; LCD'nin kontrol pinlerinin bağlı olduğu mikrodenetleyici pinleri 
; tanımlanıyor.
#define LCD_RS	4		;LCD RS pini RB4'e bağlı.
#define LCD_EN	5		;LCD E pini RB5'e bağlı.
#define LCD_RW	6		;LCD RW pini RB6'ya bağlı.

mesajlar			;LCD'ye gönderilecek mesajlar buraya yazılıyor.
	addwf	PCL, F			;mesaj adresini yükle.
msg0	dt	"Merhaba ", 0		;0 sonlandırma karakteri.
msg1	dt	"DUNYA!..", 0
msg2	dt	"HEX:", 0
msg3	dt	"DEC:", 0

; LCD ile ilgili macro tanımları:

LCD_RS_HIGH	macro			;LCD'nin RS girişini HIGH yaparak 
	banksel LCD_CtrlPort		;veri alma modu seçilir.
	bsf	LCD_CtrlPort, LCD_RS
	endm

LCD_RS_LOW	macro			;LCD'nin RS girişini LOW yaparak 
	banksel LCD_CtrlPort		;komut alma modu seçilir.
	bcf	LCD_CtrlPort, LCD_RS	
	endm

LCD_EStrobe macro			;LCD'ye veri ya da komut 
	banksel LCD_CtrlPort		;gönderildiğinde LCD'nin 
	bsf	LCD_CtrlPort, LCD_EN	;bunu işlemesini sağlar.
	movlw	.20			;20us kadar bekle. 
	call	delay_us
	bcf	LCD_CtrlPort, LCD_EN
	endm

LCD_Locate	macro	line, pos
  	movlw 	line			;Satır bilgisini yükle.
	movwf	LCD_line	
 	movlw 	pos			;Sütun bilgisini yükle.
	movwf	LCD_pos				
	call	LCD_SetPos		;Kursörü konumlandır.
	endm

; ----------------LCD ile ilgili fonksiyonlar.---------------------

; 4 bit iletişim modunda LCD'ye veri transferi yapar.

LCD_NybbleOut                       
	andlw	0x0F			;En değersiz 4 bit W'de,
	movwf	LCD_tmp0		;geçici değişkene alınıyor.
	movf	LCD_DataPort,W		;LCD'nin data pinlerinin bağlı 
					;olduğu port bilgisi W'de.
	andlw	0xF0			;Port bilgisinin en değerli 4 bit’i 
					;korunuyor.
	iorwf	LCD_tmp0, W		;Korunan bilgi ile veri 
					;birleştiriliyor.
	movwf	LCD_DataPort		;PortA transfer ediliyor.
	LCD_EStrobe			;LCD'nin veriyi alması sağlanıyor.
	movlw	.255			;250us kadar bekle. Bu süre LCD 
					;içerisindeki işlemlerin tamamlanması
	call	delay_us		;için gerekli ( en az 160us kadar ).
	return

; LCD'ye 1 byte komut transfer eder.

LCD_SendCmd         	         	
	movwf	LCD_data	 	;Komutu geçici değişkene al.
	swapf	LCD_data, W   		;En değerli 4 bit’i gönder.
	LCD_RS_LOW			;RS = 0 (komut modu)
call	LCD_NybbleOut
	movf	LCD_data, W		;En değersiz 4 bit’i gönder.
	LCD_RS_LOW			;RS = 0 (komut modu)
	call	LCD_NybbleOut			
	return

; LCD'ye bir rakam ya da bir karakter göndermek için kullanılır.

LCD_SendASCII						
	addlw	'0'			;LCD'ye rakamı ASCII koda 
					;dönüştürerek göndermek için.
LCD_SendCHAR				;LCD'ye karakter göndermek için 
					;çağrılacak.
	movwf	LCD_data		;Komutu geçici değişkene al.
	swapf	LCD_data, W		;En değerli 4 bit’i gönder.
	LCD_RS_HIGH			;RS = 1 ( veri gönderme modu )
	call	LCD_NybbleOut
	movf	LCD_data, W		;En değersiz 4 bit’i gönder.
	LCD_RS_HIGH			;RS = 1 ( veri gönderme modu )
	call	LCD_NybbleOut
	return

; 1 byte veriyi hexadesimal formda LCD'ye yazar.

LCD_SendHEX	
	movwf	LCD_tmp1
	sublw	0x9F			;sayı > 0x9F mi? 
	btfss	STATUS, C		;hayır ise bir komut atla.
	goto	LCD_HEX_j0
	swapf	LCD_tmp1, W
	andlw	0x0F			;En değerli 4 bit W'nin en 
	call	LCD_SendASCII		;değersiz 4 bit’inde.
	goto	LCD_HEX_j1
LCD_HEX_j0
	swapf	LCD_tmp1, W
	andlw	0x0F			;En değerli 4 bit W'nin en 
	addlw	.55			;değersiz 4 bit’inde.
	call	LCD_SendCHAR
LCD_HEX_j1
	movf	LCD_tmp1, W
	andlw	0x0F			;En değersiz 4 bit W'nin en 
	movwf	LCD_tmp1		;değersiz 4 bit’inde.
	sublw	0x09			;sayı > 0x09 mi? 
	btfss	STATUS, C		;hayır ise bir komut atla.
	goto	LCD_HEX_j2
	movf	LCD_tmp1, W	
	call	LCD_SendASCII
	return
LCD_HEX_j2
	movf	LCD_tmp1, W
	addlw	.55
	call	LCD_SendCHAR
	return

; 1 byte veriyi binary formda LCD'ye yazar.

LCD_SendBIN
	movwf	LCD_tmp1		;Geçici değişkene al.
	movlw	.0
	btfss	LCD_tmp1, 7		;7. bit 1 ise bir komut atla.
	call	LCD_SendASCII		;0 yazdır.
	movlw	.1
	btfsc	LCD_tmp1, 7		;7. bit 0 ise bir komut atla.
	call	LCD_SendASCII		;1 yazdır.

	movlw	.0
	btfss	LCD_tmp1, 6		;6. bit 1 ise bir komut atla.
	call	LCD_SendASCII		;0 yazdır.
	movlw	.1
	btfsc	LCD_tmp1, 6		;6. bit 0 ise bir komut atla.
	call	LCD_SendASCII		;1 yazdır.

	movlw	.0
	btfss	LCD_tmp1, 5		;5. bit 1 ise bir komut atla.
	call	LCD_SendASCII		;0 yazdır.
	movlw	.1
	btfsc	LCD_tmp1, 5		;5. bit 0 ise bir komut atla.
	call	LCD_SendASCII		;1 yazdır.

	movlw	.0
	btfss	LCD_tmp1, 4		;4. bit 1 ise bir komut atla.
	call	LCD_SendASCII		;0 yazdır.
	movlw	.1
	btfsc	LCD_tmp1, 4		;4. bit 0 ise bir komut atla.
	call	LCD_SendASCII		;1 yazdır.

	movlw	.0
	btfss	LCD_tmp1, 3		;3. bit 1 ise bir komut atla.
	call	LCD_SendASCII		;0 yazdır.
	movlw	.1
	btfsc	LCD_tmp1, 3		;3. bit 0 ise bir komut atla.
	call	LCD_SendASCII		;1 yazdır.
	movlw	.0
	btfss	LCD_tmp1, 2		;2. bit 1 ise bir komut atla.
	call	LCD_SendASCII		;0 yazdır.
	movlw	.1
	btfsc	LCD_tmp1, 2		;2. bit 0 ise bir komut atla.
	call	LCD_SendASCII		;1 yazdır.

	movlw	.0
	btfss	LCD_tmp1, 1		;1. bit 1 ise bir komut atla.
	call	LCD_SendASCII		;0 yazdır.
	movlw	.1
	btfsc	LCD_tmp1, 1		;1. bit 0 ise bir komut atla.
	call	LCD_SendASCII		;1 yazdır.
	
	movlw	.0
	btfss	LCD_tmp1, 0		;0. bit 1 ise bir komut atla.
	call	LCD_SendASCII		;0 yazdır.
	movlw	.1
	btfsc	LCD_tmp1, 0		;0. bit 0 ise bir komut atla.
	call	LCD_SendASCII		;1 yazdır.
	return

; LCD ekran belleğini siler.

LCD_Clear
	movlw	0x01			;LCD görüntü belleğini sil, 
					;dolayısı ile 
	call	LCD_SendCmd		;LCD'de görünen bilgileri de sil.
	movlw	.5
	call	delay_ms
	return

; Kursörü göster

LCD_CursorOn
	movlw	0x0F			;Display'i aç, kursörü göster. 
	call	LCD_SendCmd		;Blink ON.
	return


; Kursörü gizle

LCD_CursorOff
	movlw	0x0C			;Display'i aç, kursörü gizle,
	call	LCD_SendCmd		;Blink OFF.
	return

; LCD ekranı kullanıma hazırlar.

LCD_init
	bsf	STATUS, RP0		;BANK1 seçildi. Yönlendirme 
					;kaydedicileri bu bankta.
	movf	LCD_DataPort, W
	andlw	0xF0			;Portun en değersiz 
					;dörtlüsü çıkış yapıldı.
	movwf	LCD_DataPort		;Port yönlendirildi.
	bcf	LCD_CtrlPort, LCD_EN	;LCD_CtrlPort'un LCD_EN 
					;pini çıkışa yönlendirildi.
	bcf	LCD_CtrlPort, LCD_RS	;LCD_RS pini çıkış yapıldı. 
	bcf	LCD_CtrlPort, LCD_RW	;LCD_RW pini çıkış yapıldı.
	bcf	STATUS, RP0		;BANK0 seçildi.
	clrf	LCD_DataPort

	movlw	.50
	call	delay_ms		;40-50 ms kadar bekle.
	LCD_RS_LOW
	movlw	0x03			;8 bit iletişim komutu verildi.
	call	LCD_NybbleOut	
	
	movlw	.5			;LCD'nin hazır olması için 
					;bekleniyor.
	call delay_ms

	LCD_EStrobe			;8 bit iletişim için komut 
					;yinelendi.
	movlw	.255			;160-255us kadar bekle. 
	call	delay_us
	
	LCD_EStrobe			;8 bit iletişim için komut 
					;yinelendi.
	movlw	.255			;160-255us kadar bekle. 
	call	delay_us

	LCD_RS_LOW
	movlw	0x02			;LCD, 4 Bit iletişim moduna alındı.
	call	LCD_NybbleOut	

	movlw	.255			;160-255us kadar bekle. 
	call	delay_us

	movlw	0x28			;4 bit iletişim, 2 satır LCD, 5x7 
call	LCD_SendCmd			;font seçildi.
	movlw	0x10			;LCD'de yazının kayması engellendi.
	call	LCD_SendCmd
	movlw	0x01			;LCD görüntü belleğini sil.
	call	LCD_SendCmd

	movlw	.5			;5 ms bekle.
	call	delay_ms

	movlw	0x06			;Kursör her karakter yazımında bir 
	call	LCD_SendCmd		;ilerlesin.
	movlw	0x0C			;Display'i aç, kursörü gizle.
	call	LCD_SendCmd
	return

; Mesaj etiketi (adresi) W’ye yüklenen mesajı LCD ekranda görüntüler                       

LCD_SendMessage
	Movwf	FSR		;İlk karaktere işaret et (onun adresini 
LCD_SMsg:			;tut).
	Movf	FSR, W		;İşaret edilen karakter sırasını W'ye al.
	incf	FSR, F		;Bir sonraki karaktere konumlan.
	Call	mesajlar	;Mesajlardan ilgili karakteri al.
	iorlw  0		;Mesaj sonu mu? 0 bilgisi alındı ise 
				;mesaj sonu demektir.
	btfsc  STATUS, Z	;Mesaj sonu değil ise bir komut atla.
	return			;Mesaj sonu ise alt programdan çık.
	call   LCD_SendCHAR	;Karakteri LCD'ye yazdır.
	goto   LCD_SMsg		;Bir sonraki karakter için 
				;işlemleri tekrarla.

; Kursörü LCD'de istenilen satır ve sütuna konumlandırır. Text'in 
; nereye yazılacağını belirler. 1 - 2 satır olan LCD'ler için 
; yazıldığına dikkat ediniz. 4 satır LCD'ler için LCD_line değerinin
; 0, 1, 2 veya 3 olması durumuna göre DDRAM başlangıç adresleri 
; tespit edilmelidir.

LCD_SetPos
	movlw	0x80		;0. satır için DDRAM adres başlangıç 
	movf	LCD_line, F	;değeri.
	btfss	STATUS, Z	;0. satır ise bir komut atla.
	movlw	0xC0		;1. satır için 0x80 adresine ilave 
				;edilecek değer.
	addwf	LCD_pos, W	;Kursör pozisyonu da ilave edilerek 
				;DDRAM'deki adres bulunuyor.
	call	LCD_SendCmd
	return

; 2 byte binary veriyi bcd'ye dönüştürür. Sonuç binler, yüzler, 
; onlar ve birler  değişkenlerinde saklanır.

HexTODec
	clrf binler			;binler = 0
	clrf yuzler			;yuzler = 0
	clrf onlar			;onlar = 0
	clrf birler			;birler = 0
binler_kont
	movlw	04h			;W'ye 1024 (0x0400) sayısının en 
					;değerli byte'ını yükle.
	subwf	HexMSB, W		;HexMSB'den 1024 çıkart.
	btfss	STATUS, C		;HexMSB > 1024'mü?
	goto	yuzler_kont2		;hayır ise yüzleri kontrol et.
	incf	binler, F		;evet ise binleri bir artır.
	movlw	04h			;W'ye 0x04 yükle.
	subwf	HexMSB, F		;HexMSB'den 1000 çıkart.
	movlw	18h			;W'ye 0x18 yükle.
	addwf	HexLSB, F		;HexLSB'ye (0x18 = 24) ekle 
	btfsc	STATUS, C		;elde var mı?
	incf	HexMSB, F		;evet ise bir artır.
	goto	binler_kont		;binleri yeniden kontrol et
yuzler_kont2
	movlw	0x01			;256 (0x0100)
	subwf	HexMSB, W		;HexMSB'den 200 çıkart ve sonucu 
					;W'ye sakla.
	btfss	STATUS, C		;sonuç >=256'mı?
	goto	yuzler_kont1		;Hayır ise 100'ün katlarını
					;kontrol et.
	movlw	0x02			;değilse,
	addwf	yuzler, F		;yuzler'e 2 ekle
	movlw	0x01			;W = 1
	subwf	HexMSB, F		;HexMSB'den 200 çıkart.
	movlw	0x38			;W =0x38 (256'nın 56 lık kısmı)
	addwf	HexLSB, F		;HexLSB'ye 56'yı ekle.
	btfsc	STATUS, C		;elde var mı?
	incf	HexMSB, F		;evet ise HexMSB'yi bir artır.
	movlw	0x0A			;W = 10
	subwf	yuzler, W		;yuzler = 1000 olup olmadığını 
					;kontrol et.
	btfss	STATUS, Z		;sonuç sıfır mı?
	goto	yuzler_kont2		;hayır ise yuzleri yeniden kontrol 
	clrf	yuzler			;et. yuzler = 0
	incf	binler, F		;binler'i artır.
	goto	yuzler_kont2		;yuzler'i 200 ya da daha büyük 
					;sayı için yeniden kontrol et.
yuzler_kont1 
	movlw	0x64			;W = 0x64
	subwf	HexLSB, W		;HexLSB'den 100 çıkart.
	btfss	STATUS, C		;sonuç >= 100 mü?
	goto	onlar_kont		;hayır ise onları kontrol et.
	incf	yuzler, F		;evet ise yuzler'i bir artır.
	movlw	0x64			;W = 0x64 (100)
	subwf	HexLSB, F		;HexLSB'yi 100 azalt.
	movlw	0x0A			;W = 0x0A (10)
	subwf	yuzler, W		;yuzler = 1000 kontrolü yap.
	btfss	STATUS, Z		;sonuç = 0 mı?
	goto	yuzler_kont1		;hayır ise 100 için yuzler'i 
					;yeniden kontrol et.
	clrf	yuzler			;yuzler = 0
	incf	binler, F		;binleri bir artır.
	goto	yuzler_kont1		;100 ya da daha büyük olma durumu 
					;için yüzleri yeniden kontrol et.
onlar_kont
	movlw	0x0A			;W = 0x0A (10)
	subwf	HexLSB, W		;HexLSB'den 10 çıkart.
	btfss	STATUS, C		;sonuç >= 10 mu?
	goto	birler_kont		;hayır ise birleri kontrol et.
	incf	onlar, F		;evet ise onları bir artır.
	movlw	0x0A			;W = 0x0A (10)
	subwf	HexLSB, F		;HexLSB'den 10 çıkart.
	goto	onlar_kont		;onlar'ı yeniden kontrol et.
birler_kont
	movf	HexLSB, W		;W = HexLSB
	movwf	birler			;birler = W, dönüşüm işlemi tamam
	return				;alt programdan çık.

; 1-255 sn arasında gecikme sağlayan alt program.

delay_s
	movwf	delay_s_data
delay_s_j0:
	movlw	.250			;4 * 250 = 1000 ms bekle,
	call	delay_ms		;her çevrim 1 sn.
	movlw	.250
	call	delay_ms
	movlw	.250					
	call	delay_ms
	movlw	.250
	call	delay_ms
	decfsz	delay_s_data
	goto	delay_s_j0
	return


; 1-255 ms arasında gecikme sağlayan alt program.

delay_ms
	movwf	delay_data
delay_ms_j0
	movlw	.142
	movwf	delay_data+1
	nop
	nop
delay_ms_j1
	nop
	nop
	nop
	nop
	decfsz	delay_data+1, F
	goto	delay_ms_j1
	nop
	decfsz	delay_data, F
	goto	delay_ms_j0
	nop
	return

; 16-255 µs gecikme sağlayan alt program.

delay_us
	movwf	delay_data
	rrf	delay_data, F
	rrf	delay_data, F
	movlw	.63
	andwf	delay_data, F
	movlw	.3
	subwf	delay_data, F
	nop
	decfsz	delay_data, F
	goto	$ - 2
	nop
	return

; Kesme programı (kullanılacak ise LCD ya da zamanlamanın önemli
; olduğu cihazlarla çalışırken iletişimin kesilmemesine dikkat 
; ediniz).

kesme
	retfie

; Ana program

Ana_program
	call	LCD_init		;LCD’yi kullanıma hazırlar.
Ana_j0:
	call	LCD_Clear		;LCD'deki bilgileri sil.
	call	LCD_CursorOff		;Kursörü gizle.
	clrf	sayacH			;sayac = 0
	clrf	sayacL

	LCD_Locate	0, 0		;0. satır, 0. sütuna konumlan.
	movlw	msg0-6			;mesaj0 yaz (adresi 6 eksiği).
call	LCD_SendMessage
	LCD_Locate	1, 0		;1. satır, 0. sütuna konumlan
	movlw	msg1-6			;mesaj1 yaz.
    	call	LCD_SendMessage

	movlw	.10
	call	delay_s			;10 saniye bekle.

Ana_j1:
	call	LCD_Clear		;LCD'deki bilgileri sil.

					;sayac değerini hexadesimal formda 0. satıra yaz.		
	LCD_Locate	0, 0		;0. satır, 0. sütuna konumlan.	
	movlw	msg2-6			;mesaj2 yaz.
	call	LCD_SendMessage
	movf	sayacH, W
	call	LCD_SendHEX
	movf	sayacL, W
	call	LCD_SendHEX

;sayaç değerini desimal formda 1. satıra yaz.		
	LCD_Locate	1, 0		;0. satır, 0. sütuna konumlan.	
	movlw	msg3-6			;mesaj2 yaz.
	call	LCD_SendMessage
	movf	sayacH, W		;HexMSB = sayacH
	movwf	HexMSB
	movf	sayacL, W		;HexLSB = sayacL
	movwf	HexLSB
	call	HexTODec		;Desimale dönüştür.
	movf	binler, W		;binler basamağını yaz.
	call	LCD_SendASCII
	movf	yuzler, W		;yüzler basamağını yaz.
	call	LCD_SendASCII
	movf	onlar, W		;onlar basamağını yaz.
	call	LCD_SendASCII
	movf	birler, W		;birler basamağını yaz.
	call	LCD_SendASCII

	movlw	.1			;1 sn bekle.	
	call	delay_s

; sayacL değerini binary formda 1. satıra yaz (0. satırda aynı 
; sayının HEX değeri var).		
	LCD_Locate	1, 0		;0. satır, 0. sütuna konumlan.	
	movf	sayacL, W
	call	LCD_SendBIN		;sayacL değerini binary formda 
					;göster.
; sayaç değerini 10000 olana kadar bir artır, 10000 ise en başa dön
	incf	sayacL, F		;sayacL'yi bir artır.
	btfsc	STATUS, Z		;sayacL sıfırdan farklı ise bir 
					;komut atla.
	incf	sayacH, F		;sayacH'i bir artır.
	movlw	0x27
 	subwf	sayacH, W
	btfss	STATUS, Z		;sayacH = 0x27 ise bir komut atla.
	goto	Ana_j2			;sayac henüz 10000'e ulaşmadı, o 
					;halde devam et.
	movlw	0x10
 	subwf	sayacL, W
	btfss	STATUS, Z		;sayacL = 0x10 ise bir komut atla.
	goto	Ana_j2			;sayac henüz 10000'e ulaşmadı, o 
					;halde devam et.
	goto	Ana_j0			;En başa dönerek işlemleri tekrar 
Ana_j2:				;et.
	movlw	.1			;1 sn bekle.
	call	delay_s
	goto	Ana_j1			;sayma işlemine devam.
	
	end

;	Dosya Adı		: 6_3.asm
;	Programın Amacı		: SFR’siz senkron seri veri iletişimi
;				 (74HC597 kullanılarak).
;	PIC DK 2.1 		: PORTB<0:4> Çıkış ==> LED
;				: XT ==> 4Mhz

	list p=16F877A
	include "p16F877A.inc"	
	__config H'3F31' 	;PWRT on, diğerleri kapalı, 
				;Osilatör XT ve 4Mhz.

; Genel tanımlamalar ve değişken tanımlamaları yapılıyor.

#define hc597_port	PORTB		;74HC597’ün bağlı olduğu 
					;port tanımı yapılıyor.
#define LOAD_Pin	0		;Load pininin işlemciye bağlı 
					;olduğu pin tanımlanıyor.
#define DATA_Pin	1		;Data pininin işlemciye bağlı 
					;olduğu pin tanımlanıyor.
#define CLK_Pin	2			;Clock pininin işlemciye bağlı 
					;olduğu pin tanımlanıyor.
#define LATCH_Pin	3		;Latch pininin işlemciye bağlı 
					;olduğu pin tanımlanıyor.

delay_ms_data		equ 0x20 	;delay_ms için 2 byte'lık değişken 
					;tanımı yapılıyor.
i			equ 0x22 	;Transfer edilecek verinin bit 
					;sırasını tespit değişkeni.
hc597_data		equ 0x23 	;Okunacak veriyi tutan değişken.

	ORG 	0			;Reset vektör adresi burası. 
	pagesel Ana_program		;Ana programın bulunduğu program 
					;sayfası seçildi.
	goto 	Ana_program		;Ana programa git.

	ORG 	4

; hc597_Oku alt programı, 1 byte veriyi donanım modüllerini
; kullanmadan yalnızca yazılım ile 74HC597 entegresinden okuyup 
; işlemciye transfer eder.

hc597_Oku
	Banksel hc597_port		;hc597_port'nin bulunduğu 
					;bank seçildi.
	bsf	hc597_port, LATCH_Pin	;Anahtarlardan bilgi Latch'a 
					;alınıyor.
	nop
	bcf	hc597_port, LATCH_Pin
	bcf	hc597_port, LOAD_Pin	;Latch'taki bilgi kaydırmalı 
					;kaydediciye aktarılıyor.
	nop
	bsf	hc597_port, LOAD_Pin

	movlw	8			;i değişkenine 8 bilgisi yüklendi.
	movwf	i			;i, 8 bit’in de alındığını kontrol 
					;etmek için kullanılıyor.
hc597_j0
	rlf	hc597_data, F
	btfss	hc597_port, DATA_Pin	;Data pininden gelen veri 1 
					;ise bir komut atla.
	goto	hc597_j1		;Gelen veri 0, o halde 
					;hc597_j1'e git.
	bsf	hc597_data, 0		;hc597_data değişkeninin 0.
					;bit’ini set et.
	goto	hc597_j2		;Clock palsi için devam.
hc597_j1
	bcf	hc597_data, 0		;hc597_data değişkeninin 0. 
					;bit’ini reset et.
hc597_j2
	bsf	hc597_port, CLK_Pin	;74HC597'in CLK pinine inen 
					;darbe kenarı uygulanıyor.
	nop
	bcf	hc597_port, CLK_Pin
	decfsz	i, F			; i sayacını bir azalt ve 8 bit’in
					;tamamı okundu ise bir komut atla.
	goto	hc597_j0
	return

; delay_ms alt programı 1-255 ms arasında değişken bekleme süresi 
; sağlar delay_ms_data yüksek byte değişkenine yüklenecek değer 
; kadar ms olarak gecikme sağlar.

delay_ms
delay_j0
	movlw	D'142'			;1 ms gecikme için taban değer.
	movwf	delay_ms_data+1		;delay parametresinin düşük 
					;byte'ına yüklendi.
	nop				;2 us bekle.
	nop
delay_j1
	nop				;4 us gecikme.
	nop
	nop
	nop
	decfsz	delay_ms_data+1, F	;delay parametresinin düşük 
					;byte'ını azalt sıfırsa komut atla.
	goto	delay_j1		;Henüz 1 ms gecikme sağlanamadı, 
					;düşük byte'ı azaltmaya devam et
	nop				;1 us bekle.
	decfsz	delay_ms_data, F	;delay parametresinin yüksek 
					;byte'ını azalt sıfırsa komut atla.
	goto	delay_j0		;1 ms beklemeyi tekrarla.
	nop				;1 us bekle.
	return				;Alt programdan çıkış.

; delay_5s alt programı 5 saniye gecikme için 20 kez 250 ms gecikme 
; işlemi gerçekleştirir. Delay sonucunda 5 saniyeye çok yakın bir 
; gecikme sağlanır.

delay_5s
	movlw	0x14			;20 * 250ms = 5000ms 
	movwf	i
delay_5s_j0	
	movlw	D'250'			;250 ms değerini delay_ms_data 
					;değişkenine yaz.
	movwf	delay_ms_data	
	call	delay_ms		;250 ms bekle.
	decfsz	i, F
	goto	delay_5s_j0
	return

; Ana program 74HC597 entegresine bağlı anahtarlardan alınan 
; bilginin donanım modülleri kullanılmadan yalnızca yazılım ile 
; okunarak PORTB’nin en değerli 4 çıkışında (RB7 - RB4) 5 sn 
; aralıklarla görüntülenmesini sağlar.

Ana_program
	banksel TRISB			;TRISB’nin bulunduğu banka geç.
	movlw	2
	movwf	TRISB			;PORTB’nin RB1 pini giriş, diğer 
					;pinleri çıkış yapıldı.
	Banksel PORTB			;PORTB’nin bulunduğu banka geç.
	clrf	PORTB			;PORTB'nin pinlerinin ilk andaki 
					;çıkışları sıfır.
Ana_j0
	call	hc597_Oku		;hc597_data değişkenindeki değeri 
					;74HC597’e yaz.
	movf	hc597_data, W		;hc597_data değişkeninde bulunan 
					;veriyi W’ye aktar.
	andlw	0xF0			;Verinin en değerli 4 bit’ini al.
	movwf	PORTB			;En değerli 4 anahtarın konumlarını 
					;PORTB’nin RB7-RB4 çıkışlarında 
					;göster.
	call	delay_5s		;5 saniye bekle.
	swapf	hc597_data, W		;hc597_data değişkeninde bulunan 
					;verinin en değerli ve en değersiz 
					;4 bit’ini yer değiştirerek W’ye 
					;aktar.
	andlw	0xF0			;Verinin en değersiz 4 bit’i artık 
					;W’nin en değerli 4 bit’i durumunda
	movwf	PORTB			;En değersiz 4 anahtarın 
					;konumlarını PORTB’nin RB7-RB4 
					;çıkışlarında göster.
	call	delay_5s		;5 sn bekle.
	goto	Ana_j0			;Ana_j0 etiketine git.

	END

;	Dosya Adı		: 6_7.asm
;	Programın Amacı		: USART Modülü İle Asenkron Seri Veri
;				  İletişimi.
;	PIC DK 2.1 		: PORTC<6:7> RS232 kablosuyla PC’ye
;				: XT ==> 20 Mhz
 
	list p=16F877A	 
	include "p16F877A.inc"	
	__config H'3F3A' 		;Tüm program sigortaları kapalı, 
					;Osilatör HS ve 20 Mhz.

; Değişken tanımları

RS232_Data	equ	0x20
	org	0
	clrf	PCLATH
	goto	Ana_program
	org	4

; Kesme alt programı: Varsa istenen kesmelerin işlenmesinde 
; kullanılabilir.

interrupt
	;Bu kısımda gerekirse usart modülünden veri alma ya da 
	;gönderme kesmeleri, A/D kesmesi, TRM0, TMR1, TMR2, CCP1IF, 
	;CCP2IF kesmeleri işlenebilir. Kesmelerin işlenmesindeki 
	;öncelik sıraları belirlenebilir. Örneğimizde veri gönderme 
	;ve almada kesme alt programına girmeden yalnızca kesme 
	;bayrakları kontrol edilerek usart birimine ait asenkron veri 
	;iletişimi gerçekleştirilmiştir.
	retfie				;Kesmeden çıkış

; RS232 portunda 1 byte veri yazar. Yazılacak veri RS232_Data 
; değişkenine yüklenmelidir.

RS232_Karakter_Gonder
	banksel PIR1
	btfss	PIR1, TXIF
	goto	$ - 1			;Daha önceden bir veri gönderilmiş 
					;ise aktarılana kadar bekle.
	bcf	PIR1, TXIF		;Veri gönderme kesme bayrağını sil.
	movf	RS232_Data, W	
	banksel TXREG
	movwf	TXREG			;RS232_Data değişkenindeki veriyi 
					;TXREG kaydedicisine yükle. Böylece 
					;veri çıkış buffer'ına yazılmış olur.	
	return				;Alt programdan çıkış.

; RS232 portundan 1 byte veri alır.

RS232_Karakter_Al
	banksel PIR1
	btfss	PIR1, RCIF	;Bilgi alındı ise bir komut atla.
	goto	$ - 1		;Bir komut geriye gel.
	bcf	PIR1, RCIF	;Alma gerçekleşti kesme bayrağını sil.
	movf	RCREG, W	;RCREG seri bilgi alış buffer'ındaki 
				;veriyi W'ye yükle.
	return			;RS232_Karakter_Al alt programından çıkış.

; Usart modülünün asenkron iletişimi için ilk ayarları 
; gerçekleştirir.

RS232_ilk_islemler
	banksel TRISC		;BANK1 seçildi. TRISC bu bankta
	bcf	TRISC, 6	;TX çıkışa
	bsf	TRISC, 7	;RX girişe yönlendirildi
	movlw	0x81		;SPBRG = 129 Fosc = 20 MHz'de 9600 baud 
				;hız için.
	movwf	SPBRG
	movlw	0x26
	movwf	TXSTA		;USART mod: asenkron, high speed, 8 bit 
				;iletişim, TXEN set edildi.
	movlw	0x90
	bcf	STATUS, RP0	;BANK0 seçildi RCSTA için.
	movwf	RCSTA		;Seri port etkin, 8 bit veri alış, CREN 
				;set : sürekli alış. 
	bsf	STATUS, RP0
	bsf	PIE1, TXIE	;TXIE set edildi.
	bsf	PIE1, RCIE	;RCIE set edildi.
	bsf	INTCON, PEIE	;Çevresel kesmelere izin verildi.
	return			;RS232_ilk_islemler alt programından çıkış

; Ana program: RS232 seri portttan aldığı verileri tekrar seri porta
; gönderir.

Ana_program
	call	RS232_ilk_islemler	;RS232 iletişimi için ilk işlemler.
	bcf	INTCON, GIE		;Kesme alt programı kullanılmadığı 
					;için GIE = 0 yap.
Ana_j1
	call	RS232_Karakter_Al	;RS232 portundan 1 byte veri al.
	movwf	RS232_Data		;Alınan veriyi RS232_Data 
					;değişkenine aktar.
	call	RS232_Karakter_Gonder	;RS232'deki veriyi RS232 
					;portuna gönder.
	goto	Ana_j1			;Aynı işlemleri tekrarla.
	END

;	Dosya Adı		: 6_9.asm
;	Programın Amacı		: USART Modülü İle Senkron Master Mod Veri
;				  İletişimi (74HC165 kullanarak).
;	Notlar 			: XT ==> 4Mhz
 
	list p=16F877A		
	include "p16F877A.inc"	
	__config H'3F31' 		;PWRT on, diğerler sigortaları 
					;kapalı, Osilatör XT ve 4 Mhz.

; Değişkenler tanımlanıyor ve derleyici direktifleri veriliyor.
; Kodun anlaşılmasını kolaylaştırmak için sembolik adlar kullanıldı.

#define hc165_SHLD	PORTC, 0	;74HC165 entegresinin SH/LD' girişi 
					;RC0'a bağlı.
#define OKU_BUTONU	PORTB, 0	;OKU butonu için pin tanımı yapıldı.
hc165_data	equ	0x20		;hc165_Veri_Oku alt program 
					;değişkeni.
	ORG	0
	clrf	PCLATH			;0. program sayfası kullanılıyor.
	goto	Ana_program		;Ana programa git.

; 74HC165, USART modülü senkron master modda iletişim için hazırlanıyor.

hc165_Ilk_islemler
	movlw	0x09		;(Synchronous) Baud Rate = Fosc/(4(X+1))
				;Baud Rate 	= 4.000.000/(4*(9+1))
				;	= 4.000.000/40 = 100.000 Hz.
	banksel SPBRG
	movwf	SPBRG		;Baud Rate değeri SPBRG kaydedicisine 
				;yüklendi.
	bsf	TXSTA, SYNC	;Senkron iletişim seçildi.		
	bsf	TXSTA, CSRC	;Clock kaynağı seçme bit’i set 
				;edildi. Kaynak: BRG kaydedicisi.
	bcf	STATUS, RP0	;BANK0'a geç. RCSTA bu bankta.
	bcf	RCSTA, CREN	;Sürekli okuma modu kapatıldı.
	bcf	RCSTA, RX9	;RX9 kullanılmıyor, 8 bit veri iletişimi.
	bsf	RCSTA, SPEN	;Senkron master seri port aktif hale 
				;getirildi.
	return

; USART modülü Senkron master mod kullanarak veri 74HC165'ten 
; işlemciye transfer ediliyor.

hc165_Veri_Oku
	bcf	STATUS,RP0		;BANK0'a geç, RCSTA ve 74HC165'in 
					;SH/LD' ayağının bağlı olduğu port 
					;bu bankta.
	bcf	hc165_SHLD		;Entegre girişlerden veri 
					;alabilmesi için LOAD yükleme 
					;moduna alınıyor.
	bsf	hc165_SHLD		;74HC165 Shift moduna alınıyor. 
					;(Veri transferi için.)
	bsf	RCSTA,SREN		;Tek byte veri oku.
hc165_j1
	btfsc	RCSTA, SREN		;Reset ise veri okumuş demektir, 
					;bir komut atla.
	goto	hc165_j1		;Bir geriye git. Tekrar kontrol et. 
					;(goto $-1 ;kullanılabilir) 	
					;Alma işlemi tamamlandığında SREN 
					;reset olur.
	movf	RCREG, W		;Okunan değer W'ye alınıyor
	movwf	hc165_data		;ve hc165_data değişkenine transfer 
					;ediliyor.
	return 

; Ana program USART modülü senkron master modu kullanarak
; 74HC165’ten işlemciye veri transferini gösteriyor.

Ana_program
	banksel TRISB		;TRISB ve TRISC'nin bulunduğu bank seçildi
	bsf	TRISB,0		;RB0 girişe yönlendirildi.
	movlw	0x80		;W = 0x80
	movwf	TRISC		;RC7/RX/DT pini giriş diğerleri çıkış.	
	clrf	TRISD		
				;PORTD sonuçları görüntülemek için çıkışa 
				;yönlendirildi.
	bcf	STATUS, RP0	;BANK0'a geç.
	clrf	PORTC		;PORTC'nin ilk durumda tüm pinleri LOW.	
	clrf	PORTD
call	hc165_Ilk_islemler	;74HC165 için USART modülü Senkron 
				;Master moda alındı.
Ana_j1
	btfsc	OKU_BUTONU	;Oku butonuna basıldı mı? Evet ise 
				;bir komut atla.
	goto	Ana_j1		;Bir komut geriye, kontrole devam.
	call	hc165_Veri_Oku	;74HC165 kaydedicisinden veri oku
	movf	hc165_data, W	;Okunan veriyi W'ye yükle.
	movwf	PORTD		;Anahtar konumlarını PORTD'de 
				;görüntüle.
	goto	Ana_j1		;İşlemi sürekli yap.

	END
  • Mustafa

    Paylaşımda büyük emek var teşekkürler ;)

  • aakiph

    Allah razı olsun emegine sağlık

  • emrah

    işte bizim hocalarımız ellerinize sağlık…

  • merty

    emeğine sağlık usta.Benim bir projem var , 16f877 ile ilgili. içinde dac-adc konvertorler ve lcd ekran olacak. hangi butona basarsak lcd ekranda “su butona bastınız ” ve yanında da ” x v ” yazacak.yani hem hangi butona basıldığını hem de o butonun üzerındeki gerilimi ekrana yazdıracak. yardımcı olursanız sevinirim. herkese iyi günler

  • omer

    Paylaşımlarınız için çok teşekkürler , ancak benim elimde de pic16f877 var ve kodlarınızı indirdim ama ya çalışmıyor ya bozuk çalışıyor , neden olabilir yardımcı olursanız sevinirim.