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).
; 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
PIC16F877 C dili ile hazırlanan proje listesi ve örnekler
GrafikLCD.c: T6963C tabanlı Grafik LCD’ye text yazar ve çizgi çizer.
15_1.c: Terminal Projesi
14_13.c: MPX4115 basınç sensörü uygulaması
14_12.c: MT8870 ile DTMF ton kod çözücü uygulaması
14_11_2.c: RF alıcı modülü programı
14_11_1.c: RF verici modülü programı
14_10.c: Rotary pulse encoder ile ses üretme
14_9.c: Rotary pulse encoder uygulaması
14_8.c: DS1868 dijital potansiyometre uygulaması
14_7.c: DS1990(i-button) uygulaması
14_6.c: PCF8583 ile saat uygulaması
14_5.c: DS1307 RTC
14_4.c: DS1302 RTC
14_3.c: DS18B20 ısı sensörü ile ısı ölçümü
14_2.c: DS1621 ısı sensörü ile ısı ölçümü
14_1.c: DS1620 ısı sensörü ile ısı ölçümü
13_3.c: L297 ve L298 ile step motor kontrolü
13_3.c: L297 ve L298 ile step motor kontrolü
13_2.c: Step motor kontrolü (ULN2003 ile)
13_1.c: DC motor hız ve yön kontrolü
// Dosya Adı : 15_1.c // Açıklama : Terminal Projesi // PIC DK 2.1 : PORTB Çıkış ==> LCD display // : A/D seçim anahtarı RA1 A, diğerleri D konumunda // : XT ==> 4 MHz // Hi ve Lo fonksiyonları için başlık dosyası programa katılıyor. #include "built_in.h" // Alarm fonksiyonu ile ilgili tanımlamalar yapılıyor. #define ALARMPORT PORTE #define ALARMTRIS TRISE #define ALARMCIKIS F0 #define ALARMKURULU F1 #define ALARMKAPAT PORTA.F4 // Alarm kesme butonu // Sensörler için analog kanal tanımlamaları yapılıyor. #define LM35 0 // 0. adc kanalına bağlı #define LDR 1 // 1. adc kanalına bağlı // Global değişken tanımlamaları yapılıyor. unsigned short tmp,i; unsigned char ControlReg, TaskControl, RxBuffer; unsigned char saat, dakika, saniye, a_saat, a_dakika, AlarmCnt; unsigned int isi, isik, epadres, adr; unsigned short PWMDuty; // Kesme Alt Programı. void interrupt(void) { // Timer1 kesmesi işleniyor. if (PIR1.TMR1IF) { TaskControl.F3 = 1; TMR1L = 0x00; // Ön değerler atanıyor 4096 artış sonrası TMR1H = 0xF0; // taşma gerçekleşecek PIR1.TMR1IF = 0; } // RX seri iletişim veri alma kesmesi işleniyor. if (PIR1.RCIF) { // alınan karakter RCREG'de if(RCSTA.FERR || RCSTA.OERR) { RCSTA.CREN = 0; asm nop // Bit işlemleri arasında 1us kadar bekle RCSTA.CREN = 1; } PIR1.RCIF = 0; // Alma kesme bayrağını sil. RxBuffer = RCREG; // Alınan veriyi değişkene ata. ControlReg.F7 = 1; // Veri alındı kontrol bitini set et TaskControl.F0 = 1; // Terminal için görev kontrol // bayrağını set et. PIR1.RCIF = 0; } } // EEPROM’a veri yazar. void e2eprom_write(unsigned int adr, unsigned short data) { I2C_Start(); // I2C start sinyali gönder I2C_Wr(0xA0); // I2C donanım adresi + yazma komutu gönder I2C_Wr(Hi(adr)); // Yazılacak adresin yüksek byte'ını gönder I2C_Wr(Lo(adr)); // Yazılacak adresin alçak byte'ını gönder I2C_Wr(data); // Yazılacak veriyi gönder I2C_Stop(); // I2C iletişimi durdur Delay_ms(100); // işlemlerin tamamlanması için 100ms bekle } // EEPROM’dan veri okur. unsigned short e2eprom_read(unsigned int adr) { unsigned short data; I2C_Start(); // I2C start sinyali gönder I2C_Wr(0xA0); // I2C donanım adresi + yazma komutu gönder I2C_Wr(Hi(adr)); // Yazılacak adresin yüksek byte'ını gönder I2C_Wr(Lo(adr)); // Yazılacak adresin alçak byte'ını gönder I2C_Repeated_Start(); // I2C reStart sinyali gönder I2C_Wr(0xA1); // I2C donanım adresi + okuma komutu gönder data = I2C_Rd(0u); // Veriyi oku (NO acknowledge) I2C_Stop(); // I2C iletişimi durdur return data; // okunan veriyi fonksiyon dışına taşı } // USART birminden bir karakter alır. char GetChar() { while(!(ControlReg.F7)); // Seri porttan 1 karakter alınana kadar // bekle ControlReg.F7 = 0; // Karakter alındı bayrağını sil return RxBuffer; // Alınan karakteri çıkışa aktar } // USART'a bir karakter gönderir. void sendChar(char c) { if(!(TXSTA.TXEN)) TXSTA.TXEN = 1; // Veri gönderme kesmesini // etkinleştir. while(!(PIR1.TXIF)); // Veri gönderilene kadar bekle PIR1.TXIF = 0; // Veri gönderildi, bayrağı sil TXREG = c; } // USART'a string yazar. void writeString(const char *s) { char i=0; // Gönderilecek stringin karakter sırası while( s[i]!=0 ) sendChar(s[i++]); // stringin sıradaki // karakterini gönder } // Karakteri hex değere dönüştürür. unsigned short Char_to_Hex(unsigned short gec) { ControlReg.F6 = 0; if (gec>47 && gec<58) { gec=gec-48; return gec; } else if (gec>64 && gec<71) // A, B, C, D, E, F girişleri için { gec=gec-65; gec=gec+0x0A; return gec; } else if (gec>96 && gec<103) // a, b, c, d, e, f girişleri için { gec=gec-97; gec=gec+0x0A; return gec; } // Hatalı karakter ControlReg 6. bit set et. Gerekirse bu bit // kontrol edilerek hatalı girişler engellenebilir. ControlReg.F6 = 1; return 0; } // USART'dan hex bilgi alır ve USART'a gönderir. unsigned short GetSendHexByte() { unsigned short ch; ch = GetChar(); sendChar(ch); tmp = Char_to_Hex(ch); asm swapf _tmp,F ch = GetChar(); sendChar(ch); ch = Char_to_Hex(ch); if (ControlReg.F6) return 0xFF; // Hatalı karakter ise 0xFF // aktar tmp = tmp + ch; return tmp; } // USART'dan desimal bilgi alır ve USART'a gönderir. unsigned short GetSendDecByte() { return Bcd2Dec(GetSendHexByte()); } // USART'a Desimal olarak 1 byte yazar void sendDecByte(unsigned short data) { unsigned short onlar, birler; onlar = 0; birler = 0; while( data>=10) { onlar++; data = data - 10; } birler = data; sendChar('0'+ onlar); sendChar('0'+ birler); } // LCD'ye Desimal olarak 1 byte yazar void LCD_DecWrite(unsigned short data) { unsigned short onlar, birler; onlar = 0; birler = 0; while( data>=10) { onlar++; data = data - 10; } birler = data; Lcd_Chr_Cp('0'+ onlar); Lcd_Chr_Cp('0'+ birler); } // LM35 ISI sensörü ile ilgili fonksiyonlar void IsiOlc() { // LM35'in bağlı olduğu ADC kanalından ısı şiddetini al ve // dönüştür Isi = Adc_Read(LM35) >> 1; // 2'ye bölerek gerçek ısı değerini bul yaklaşık her bir artış // değeri 5 mV, 2 arttığında 10 mV yani 1 derece, Bu nedenle // 2'ye bölüyoruz. Sonuç gerçek ısı değerine çok yakın. // İstenirse yarım derece hassasiyet ile ısı görüntülenebilir. // Ayrıca referans gerilim ayarlanarak daha hassas ve daha doğru // ısı ölçümleri gerçekleştirilebilir. } void IsiGoruntule() { // Isı şiddetini PC terminalinde görüntüle sendDecByte(Isi);sendChar(' ');sendChar('C'); } // LDR IŞIK sensörü ile ilgili fonksiyonlar void IsikOlc() { // LDR'nin bağlı olduğu ADC kanalından ışık şiddetinin en // değersiz byte'ını al Isik = Adc_Read(LDR); } void IsikGoruntule() { // Işık şiddetini PC terminalinde görüntüle sendDecByte(Isik); } // Zaman ile ilgili fonksiyonlar void ZamanAyarla() { saat = GetSendDecByte(); sendChar(':'); dakika = GetSendDecByte(); } void ZamanGoruntule() { // Saati PC terminalinde görüntüle SendDecByte(saat); sendChar(':'); SendDecByte(Dakika); } // Alarm ile ilgili fonksiyonlar void AlarmAyarla() { // Alarm saat ve dakika bilgisini al ve eeproma kaydet a_saat = GetSendDecByte(); sendChar(':'); a_dakika = GetSendDecByte(); Eeprom_Write(0x10, a_saat); Eeprom_Write(0x11, a_dakika); } void AlarmGoruntule() { // Alarmı eepromdan oku ve PC terminalinde görüntüle a_saat = Eeprom_Read(0x10); a_dakika = Eeprom_Read(0x11); sendDecByte(a_saat); sendChar(':'); sendDecByte(a_dakika); } // Saat ile ilgili fonksiyonlar void ZamanIsle() { saniye++; if(saniye>59) { saniye = 0; dakika++; if(dakika>59) { dakika = 0; saat++; if(saat>23) saat = 0; // Her saat başı saat bilgisi ve ısı bilgisi e2eproma // kaydediliyor. IsiOlc(); e2eprom_write(epadres, saat); epadres++; e2eprom_write(epadres, Isi); epadres++; } // 40 dk boyunca alarm susturulmadı ise alarmı kes if (ControlReg.ALARMCIKIS) { AlarmCnt++; if (AlarmCnt>=40) { ControlReg.ALARMCIKIS = 0; ControlReg.ALARMKURULU = 0; ALARMPORT.ALARMCIKIS = 0; AlarmCnt = 0; } } } // Alarm kurulu ise alarm zamanını kontrol et if (ControlReg.ALARMKURULU) if ((saat == a_saat) && (dakika == a_dakika)) { ALARMPORT.ALARMCIKIS = 1; ControlReg.ALARMCIKIS = 1; } // LCD'de saat:dakika:saniye bilgilerini görüntüle Lcd_Out(1,1, ""); LCD_DecWrite(saat);Lcd_Chr_Cp(':'); LCD_DecWrite(dakika);Lcd_Chr_Cp(':'); LCD_DecWrite(saniye); // LCD'de ısı bilgisini görüntüle IsiOlc(); Lcd_Out(2,1, "ISI: "); LCD_DecWrite(Isi); Lcd_Chr_Cp('C'); } // PC ile iletişim kuran terminal fonksiyonu void TerminalProgram() { unsigned short ch,tmp,i; ch=GetChar(); if (ch==13) while(ch!=48) { do { // PC Terminalinde menü yazdırılıyor. writeString("\r\n\r\n DK 2.1 Iletisim Menusune Hosgeldiniz"); writeString("\r\n Copyright © Ayhan DAYANIK - 2006 [email protected]"); writeString("\r\n\r\n MENU SECENEKLERI:\n\r"); writeString(" <1> Isi goster..\n\r"); writeString(" <2> Isik siddeti goster..\n\r"); writeString(" <3> Saati goster..\n\r"); writeString(" <4> Alarmi goster..\n\r"); writeString(" <5> e2eprom'dan saat-isi bilgilerini listele..\n\r"); writeString(" <6> Saati ayarla..\n\r"); writeString(" <7> Alarmi kur..\n\r"); writeString(" <8> PWM darbe genisligi ayarla..\n\r"); writeString(" <0> Cikis..\n\r\n\r"); writeString(" SECIMINIZ: "); ch=GetChar(); // PC terminalinden karakter al } while(ch<48 || ch>57); // Alınan seçim 0-8 arasında // değilse tekrar giriş al // Alınan seçim bilgisini PC terminaline yaz sendDecByte(ch-48);writeString("\n\r "); // Alınan karakteri kontrol et ve görevi yerine getir. switch(ch) { // Alınan karakter '0' ise ch = 0 olduğundan while // döngüsünden dolayısı ile Terminal Program'dan // çıkılır. case 48:writeString("\n\r Menuye girmek icin ENTER'e basiniz.. \n\r"); break; // Isı değerini ölç ve PC terminalinde göster case 49:writeString("\n\r Isi degeri: "); IsiOlc(); sendDecByte(Isi);sendChar(' ');sendChar('C'); break; // Işık şiddetini ölç ve PC terminalinde göster, Burada ışık şiddeti // işlenmemiş bir şekilde görüntülendi. Işık şiddetini doğru olarak // görüntülemek için okunan değerin logaritmik olarak işlenmesi // gerekmektedir. Projemizde ışık şiddeti ısı kadar önemli // olmadığından ve programın anlaşılırlığını korumak için dönüşüm // yapılmamıştır. İstenirse okunan belirli değerlerde ışık şiddeti // hesaplama yöntemi yerine bilgisayar ortamında hesaplanmış bir // tablo kullanmak daha yerinde olacaktır. case 50:writeString("\n\r Isik siddeti: "); Isik = Adc_Read(LDR); sendDecByte(Isik); break; // PC terminalinde saat:dakika formatında zaman // görüntülenir. case 51:writeString("\n\r Saat: "); SendDecByte(saat); sendChar(':'); SendDecByte(Dakika); break; // PC terminalinde alarm kurulu ise alarm zamanını, // kurulu değil ise alarmın kurulu olmadığına dair // mesaj görüntüler. case 52:if(ControlReg.ALARMKURULU) { a_saat = Eeprom_Read(0x10); a_dakika = Eeprom_Read(0x11); writeString("\n\r Alarm zamani: "); sendDecByte(a_saat); sendChar(':'); sendDecByte(a_dakika); } else writeString("\n\r Alarm kurulmamis.."); break; // PC terminalinde ESC tuşuna basana kadar ya da eeprom // sonuna yakın bir değere ulaşana kadar 10'ar 10'ar // belirli zamanlarda ölçülmüş ısı değerini görüntüle case 53:adr = 0; tmp = 1; do { writeString("\n\r Saat - Isi \n\r"); writeString("\n\r ----------- \n\r"); for ( i=0;i<10;i++) { writeString(" "); ch = e2eprom_read(adr); if (ch > 23) {tmp = 0; ch = 27; break;} sendDecByte(ch); writeString(" --- "); adr++; ch = e2eprom_read(adr); sendDecByte(ch); writeString("\n\r"); adr++; } if (tmp) { writeString("\n\r Cikis icin ESC tusuna basiniz..\n\r"); ch = GetChar(); } else { if (adr < 0xFF0) ch = 0; else ch = 27; } } while (ch!=27); break; // PC terminalinden saat:dakika girişini alarak zamanı ayarlar case 54:writeString("\n\r Saat ve dakika giriniz ( HH:MM ): "); saat = GetSendDecByte(); sendChar(':'); dakika = GetSendDecByte(); break; // PC terminalinden alarma ait saat:dakika girişini alarak // alarm zamanını ayarlar case 55:writeString("\n\r Alarm zamanini giriniz ( HH:MM ): "); a_saat = GetSendDecByte(); sendChar(':'); a_dakika = GetSendDecByte(); Eeprom_Write(0x10, a_saat); Eeprom_Write(0x11, a_dakika); ControlReg.ALARMKURULU = 1; // Alarm etkinleştirildi break; // PC terminalinden PWM darbe genişliğini alarak darbe // genişliğini ayarlar case 56:writeString("\n\r PWM darbe genisligini giriniz (00-FF): "); PWMDuty = GetSendHexByte(); PWM_Stop(); PWM_Init(1000); // PWM frekansı 1KHz seçildi PWM_Change_Duty(PWMDuty); PWM_Start(); break; } } } // Kullanılan birimlerin kullanıma hazır getirildiği ve bazı // değişkenlere ilk değer atamalarının yapıldığı alt program void main_init() { TRISC.F1 = 1; // Timer1 için RC1 giriş yapıldı ALARMTRIS.ALARMCIKIS = 0; // Çıkışa yönlendirildi ALARMPORT.ALARMCIKIS = 0; // İlk anda alarm çalmıyor //Port yönlendir TX çıkış, RX giriş TRISC.F6 = 0; // TX ucu çıkış yapıldı TRISC.F7 = 1; // RX ucu girişe ayarlandı TXSTA = 0; // TXSTA ilk anda sıfır RCSTA = 0; // RCSTA ilk anda sıfır // SPBRG = 129; // 20 Mhz de 9600 baud hız için SPBRG = 25; // 4 Mhz de 9600 baud hız için // SPBRG = 50; // 8 Mhz de 9600 baud hız için TXSTA = 0x26; RCSTA = 0x90; PIE1.RCIE = 1; // Saat ile ilgili ilk değerler atanıyor. saat = 0; dakika = 0; saniye = 0; AlarmCnt = 0; // LCD kullanıma hazırlanıyor. Lcd_Config(&PORTB,4,5,7,3,2,1,0); // LCD bağlantı tanımlamaları Lcd_Cmd(LCD_CLEAR); // LCD'yi sil Lcd_Cmd(LCD_CURSOR_OFF); // İmleci gizle I2C_Init(100000); // I2C iletişimi 100 KHz epadres = 0; // eprom adresi sıfırlandı a_saat = Eeprom_Read(0x10); // Alarm saatini oku a_dakika = Eeprom_Read(0x11); // Alarm dakikasını oku T1CON.TMR1ON = 0; // ilk anda timer1 kapalı TMR1L = 0x00; // Ön değerler atanıyor 4096 artış // sonrası 32.768 kHz kristal için TMR1H = 0xF0; // taşma gerçekleşecek T1CON = 0x3A; // 1:8 prescaler, senkronizeli ext. // clock, PIE1.TMR1IE = 1; T1CON.TMR1ON = 1; // zamanlayıcı çalıştırıldı PWM_Init(1000); // PWM frekansı 1KHz seçildi PWM_Change_Duty(0x80); // Duty cycle %50 seçildi PWM_Start(); ADCON1 = 0x84; // RA0, RA1, RA3 analog, diğerleri // dijital, sonuç sağa dayalı TRISA.F4 = 1; // Alarm susturma butonu için giriş // yapıldı ControlReg = 0; // Kontrol kaydedicisini sil TaskControl = 0; // Görev kontrol kaydedicisini sil INTCON.PEIE = 1; // Çevresel kesmeleri etkinleştir. INTCON.GIE = 1; // Etkinleştirilen kesmelere izin ver } // ANA PROGRAM void main() { main_init(); // İlk işlemler alt programını çağır while(1) { // Aşağıda görevler yer almaktadır. Kesme içerisinde set olan // görev bayrakları burada sırası ile işlenirler. Öncelik // sıralaması görevin önceliğine göre tespit edilmelidir. // Seri iletişim görevi, Veri alındı ve işlenmesi gerekiyor if (TaskControl.F0) { TerminalProgram(); // Seri iletişim menüsünü PC'de // göster ve menü işlemlerini yap TaskControl.F0 = 0; // Yeni görev için silinmelidir. } // LM35 ısı sensöründen ısı okuma zamanı geldi if (TaskControl.F1) { IsiOlc(); // Isı şiddeti ölç TaskControl.F1 = 0; // Yeni görev için silinmelidir. } // LDR ışık sensöründen ışık şiddeti okuma zamanı if (TaskControl.F2) { IsikOlc(); // Işık şiddeti ölç TaskControl.F2 = 0; // Yeni görev için silinmelidir. } // 1 sn geçti. Zamanı işle, alarm zamanını kontrol et if (TaskControl.F3) { ZamanIsle(); // Saati işle TaskControl.F3 = 0; // Yeni görev için silinmelidir. } // Alarm susturma ve iptal butonuna basıldı mı? if (!ALARMKAPAT) { ControlReg.ALARMCIKIS = 0; // Alarm çalma bayrağını sil. ControlReg.ALARMKURULU = 0;// Alarm kurulu bayrağını sil ALARMPORT.ALARMCIKIS = 0; // Alarmı sustur AlarmCnt = 0; // Alarm süresi kaydedicisini sil } // Bu bölüme varsa diğer görevler eklenebilir } }
// Dosya Adı : 14_13.c // Açıklama : MPX4115 basınç sensörü uygulaması // Notlar : XT ==> 4 MHz // MPX4115 Basınç sensörünün mikrodenetleyiciye bağlantıları // tanımlanıyor. #define mpx4115 PORTA #define mpx4115_tris TRISA #define mpx4115_pin 2 // Değişken tanımlamaları yapılıyor. unsigned int mpx4115_data, ondalik; char *str=" . kP\0"; // Bir byte'lık hexadesimal sayıyı 2 basamaklı desimal sayıya // dönüştürür. char Hex2Dec(char ch) // 2 digit dönüşüm { char tmp = 0; // Geçici değişkeni sıfırla // sayının onlar basamağı bulunuyor while(ch>=10) {tmp++; ch -= 10;} tmp = (tmp<<4) + ch; // Birler basamağını sayıya ekle return tmp; // Sonucu fonksiyon dışına taşı } // hexadesimal değeri LCD'de görüntülemek için text'e dönüştürür. void BintoStr(unsigned short tam, unsigned short ondalik) { // tam kısım 200 ve üzerinde ise str'nin ilk karakteri 2, değilse // 100 ve üzerinde olduğu kontrol edilir. 100 ve üzerinde ise // str'nin ilk karakteri 1. Eğer tam kısım 100'den küçükse str'nin // ilk karakteri boşluk. Tam kısmın 100 ve üzerindeki değeri tam'dan // düşülür. if(tam >= 200) {str[0] = 50; tam -= 200; } else if (tam >= 100) { str[0] = 49; tam -= 100; } else str[0] = 32; // tam kısım artık 100'den küçüktür. 2 basamak desimal dönüşüme // uygundur. tam = Hex2Dec(tam); // Kalan tam kısmı desimale dönüştür. str[1]= 48 + ((tam & 0xF0) >> 4); // Onlar basamağını elde et // Eğer yüzler ve onlar basamağının her ikiside sıfır ise str'de // onlar basamağına yani str'nin 2. karakterine boşluk yaz if ((str[0] == 32) && (str[1] == 48)) str[1] = 32; // en değersiz dört bit text'e dönüştürülüyor str[2]= 48 + (tam & 0x0F); // ondalık kısmı str'nin 5. karakterine yazılıyor str[4]= 48 + ondalik; } // Portları ve LCD birimini kullanıma hazırlar. void init() { // Analog girişler seçildi, Vref+ = Vdd, Vref- = Vss seçildi. ADCON1 = 0x80; TRISA = 0xFF; LCD_Config(&PORTB,4,5,7,3,2,1,0); LCD_Cmd(LCD_CURSOR_OFF); delay_ms(500); } // MPX4115 basınç sensöründen analog basınç bilgisi elde edilir. Bu // bilgi MPX4115'in bağlandığı analog pinden 10 bit çözünürlüğünde // sayısal bilgiye dönüştürülür. Elde edilen bilgi işlenerek basınç // değeri tam ve ondalıklı kısmı elde edilir ve fonksiyon dışına // taşınır. unsigned short mpx4115_read() { // tam kısmı tutacak değişken tanımlanıyor. unsigned short tmp; unsigned i, hata; // döngü ve hata değişkeni tanımlanıyor. // Basınç değeri sayısal değere dönüştüülüyor mpx4115_data = Adc_Read(mpx4115_pin); // 15 kP'lık ilk değer çıkartılıyor. mpx4115_data -= 56; hata = 0; // hata payı ilk durumda sıfır. // Hata oranı tespit ediliyor. for(i = 9; i <= mpx4115_data ; i +=15) hata++; mpx4115_data += hata; // Hata payı ekleniyor // tam kısım elde ediliyor ve 15 kP'lık ilk değer ekleniyor. tmp = mpx4115_data/10 + 15; ondalik = mpx4115_data%10; // ondalıklı kısım elde ediliyor. return tmp; // tam kısım fonksiyon dışına taşınıyor. } // Ana program MPX4115 basınç sensöründen analog basınç bilgisini // alarak sayısal değere dönüştürüp işleyerek basınç değerini %1 // hata payı ile hesaplar. Sonucu LCD display'de 500 ms ara ile // görüntüler. void main() { // 1 byte işaretsiz geçici değişken tanımlanıyor. unsigned short tmp; // Portlar ve LCD kullanıma hazırlanıyor. init(); do // do - while döngüsü ile sonsuz çevrim başlıyor. { // MPX4115'ten basınç değerinin sayısal karşılığının tam kısmı ve // ondalıklı kısmı elde ediliyor. tmp = mpx4115_read(); // Tam ve ondalıklı kısım str dizisine aktarılıyor. BintoStr(tmp, ondalik); Lcd_Out(1,1, "Basinc= "); // str dizisi LCD'de görüntüleniyor. Lcd_Out_Cp(str); Delay_ms(500); } while(1); // Ana program çevrimine devam et }
// Dosya Adı : 14_11_2.c // Açıklama : RF alıcı modülü programı // Notlar : XT ==> 4 MHz // Sabit tanımlamalar yapılıyor. // Anlamlı bir karakter olması önemli değil. Sonuçta sadece kontrol // içi kullanılacak LCD ya da terminalde yazdırılmayacak. Ancak // RF verici modülündeki kodlar ile aynı olmak zorunda. #define ST1 0xA9 #define ST2 0xAE // Genel değişken tanımlamaları yapılıyor unsigned short i, Data[3]; unsigned char ControlReg, RxBuffer; char txt[]=" \0"; char ch; // RF_read fonksiyonu RF modülünden 1 byte veri alır unsigned short RF_read() { // Yerel geçici değişkenler tanımlanıyor. unsigned short tmp, i; i = 0; // Karakter sayacı sıfırlanıyor. do { if (Usart_Data_Ready()) { // Eğer veri alındı ise tmp = Usart_Read(); // Alınan veriyi oku switch(i) { // 0. karakter alındı ise ve alınan karakter ST1 kontrol karakterine // eşitse Data[0]'a kaydet ve i sayacını artır. case 0: if (tmp == ST1) {Data[0] = tmp; i++;} break; // 1. karakter alındı ise ve alınan karakter ST2 kontrol karakterine // eşitse Data[1]'e kaydet ve i sayacını artır. Aksi halde i alınan // karakter sayacını sıfırla. Çünkü kontrol karakterleri hatalı, // dolayısıyle veri alımı hatalı olduğundan başa dön ve yeniden // almaya başla case 1: if (tmp == ST2) {Data[1] = tmp; i++;} else i = 0; break; // İlk 2 karakter doğru alındı ise 3. karakterde doğru gelecektir. // 3. karakter bizim gerçek verimizdir. İstenirse verilerin daha // hatasız ulaşması için kontrol karakter sayısı artırılabilir. case 2: Data[2] = tmp; i++; break; default: break; } } PORTD = tmp; // 3 karakterde alındı ise do-while döngüsünden çık } while (i<3); return tmp; // Son alınan veriyi fonksiyon dışına taşı } // LCD ve Usart birimlerini kullanıma hazırlar void init() { Usart_Init(2400); LCD_Config(&PORTB,4,5,7,3,2,1,0); LCD_Cmd(LCD_CURSOR_OFF); } // Ana program RF modülünden aldığı verileri LCD'de görüntüler void main() { init(); // LCD ve Usart birimlerini kullanıma hazırla do { i = 0; Lcd_Cmd(LCD_FIRST_ROW); do { // RF modülünden alınan karakteri LCD'ye yaz ch = RF_read(); Lcd_Chr_Cp(ch); i++; // karakter sayacını artır } while (i<16); } while(1); // Okuma ve görüntüleme işlemine devam }
// Dosya Adı : 14_10.c // Açıklama : Rotary pulse encoder ile ses üretme // Notlar : Proteus programı simülasyonu // : XT ==> 4 MHz // Rotary Encoder'in mikrodenetleyiciye bağlantısı tanımlanıyor. #define RotaryEncoder PORTE #define RotaryEncoder_tris TRISE // Rotary Encoder'in mikrodenetleyiciye bağlantısı tanımlanıyor. #define Buzzer PORTC #define Buzzer_pin 1 // Global değişken tanımlamaları yapılıyor. char Encoder, oldEncoder; unsigned tmp, sayac; char txt[5]; // Portları ve LCD'yi kullanıma hazırlar, değişkenlere ilk değer // atamaları yapar. void init() { LCD_Config(&PORTB,4,5,7,3,2,1,0); LCD_Cmd(LCD_CURSOR_OFF); // Buzzer'ın bulunduğu port ses çıkışı için hazırlandı Sound_Init(&Buzzer, Buzzer_pin); ADCON1 = 0x06; // Analog girişleri kapat. RotaryEncoder = 0; // Portun ilk durumu sıfırlanıyor. RotaryEncoder = 0x03; // Rotary Encoder portu giriş yapıldı // Rotary encoder'in değerini tutan değişkene ilk değer veriliyor. Encoder = 0x03; sayac = 0; // sayac değeri sıfırlanıyor. Lcd_Out(1,1,"Sayac:"); } // Ana program Rotary encoder'den gelen bilgiyi değerlendirerek sağa // ya da sola doğru çevrildiğini belirler ve rotary encoder sağa // çevrilmiş ise sayac değerini 1 artırır, sola çevrildi ise sayacı // 1 azaltır ve sayac değerini LCD'de görüntüler ve sayac değerinin // 10 katı frekansta ses üzetir. Aynı zamanda herhangi bir // değişiklik yoksa değişim olana kadar rotary encoder'den gelen // bilgiyi bir önceki bilgi ile kıyaslamaya devam eder. void main() { init(); do { // yeni değer eski değere yükleniyor oldEncoder = Encoder; // 2 byte'lık sayac desimale dönüştürülüyor tmp = Bcd2Dec16(sayac); // desimale dönüştürülün değer text'e çevriliyor. WordToStr(tmp, txt); Lcd_Out(1,1,"Sayac:"); Lcd_Out(2,4,txt); // Rotary encoder'in eski değeri ile yeni değerini karşılaştır. // Birbirinden farklı olana kadar (rotay encoder çevrilene kadar) // karşılaştırmaya ve sayac frekansında ses üretmeye devam et. while(Encoder == oldEncoder) { // Rotary encoder'in değeri okunuyor Encoder = RotaryEncoder & 0x03; // sayac*10 frekansında, 150 peryotluk ses Sound_Play(sayac, 50); } // eski değerin 1. biti yeni değerin 0. bitinden farklı ise ve eski // değerin 0. biti yeni değerin 1. bitine eşit ise rotary encoder // sağa doğru çevrilmiştir, bu durumda sayac 254'den küçükse artır. if(oldEncoder.F1 !=Encoder.F0) { if(oldEncoder.F0 == Encoder.F1) if(sayac<254) sayac++; } else // eski değerin 0. biti yeni değerin 1. bitinden farklı ise ve eski // değerin 1. biti yeni değerin 0. bitine eşit ise rotary encoder // sola doğru çevrilmiştir, bu durumda sayac 0'dan büyükse azalt. if(oldEncoder.F0 != Encoder.F1) { if(oldEncoder.F1 == Encoder.F0) if(sayac>0) sayac--; } } while(1); // Ana program çevrimine devam et }
// Dosya Adı : 14_9.c // Açıklama : Rotary pulse encoder uygulaması // Notlar : Proteus programı simülasyonu // : XT ==> 4 MHz // Rotary Encoder'in mikrodenetleyiciye bağlantısı tanımlanıyor. #define RotaryEncoder PORTE #define RotaryEncoder_tris TRISE // Global değişken tanımlamaları yapılıyor. char Encoder, oldEncoder; unsigned tmp, sayac; char txt[5]; // Portları ve LCD'yi kullanıma hazırlar, değişkenlere ilk değer // atamaları yapar. void init() { LCD_Config(&PORTB,4,5,7,3,2,1,0); // LCD bağlantısı tanımlanıyor LCD_Cmd(LCD_CURSOR_OFF); // imleci gizle ADCON1 = 0x06; // Analog girişleri kapat. RotaryEncoder = 0; // Portun ilk durumu sıfırlanıyor. RotaryEncoder = 0x03; // Rotary Encoder portu giriş yapıldı // Rotary encoder'in değerini tutan değişkene ilk değer veriliyor. Encoder = 0x03; sayac = 0; // sayac değeri sıfırlanıyor. Lcd_Out(1,1,"Sayac:"); } // Ana program Rotary encoder'den gelen bilgiyi değerlendirerek sağa // ya da sola doğru çevrildiğini belirler ve rotary encoder sağa // çevrilmiş ise sayac değerini artırır, sola çevrildi ise sayacı // azaltır ve sayac değerini LCD'de görüntüler. Herhangi bir // değişiklik yoksa değişim olana kadar rotary encoder'den gelen // bilgiyi bir önceki bilgi ile kıyaslamaya devam eder. void main() { init(); do { // yeni değer eski değere yükleniyor oldEncoder = Encoder; // 2 byte'lık sayac desimale dönüştürülüyor tmp = Bcd2Dec16(sayac); // desimale dönüştürülün değer text'e çevriliyor. WordToStr(tmp, txt); Lcd_Out(1,1,"Sayac:"); // sayac değeri LCD'de görüntüleniyor. Lcd_Out(2,4,txt); // Rotary encoder'in eski değeri ile yeni değerini karşılaştır. // Birbirinden farklı olana kadar (rotay encoder çevrilene kadar) // karşılaştırmaya devam et. while(Encoder == oldEncoder) Encoder = RotaryEncoder & 0x03; // eski değerin 1. biti yeni değerin 0. bitinden farklı ise ve eski // değerin 0. biti yeni değerin 1. bitine eşit ise rotary encoder // sağa doğru çevrilmiştir, bu durumda sayac 9999'dan küçükse artır. if(oldEncoder.F1 !=Encoder.F0) { if(oldEncoder.F0 == Encoder.F1) if(sayac<9999) sayac++; } else // eski değerin 0. biti yeni değerin 1. bitinden farklı ise ve eski // değerin 1. biti yeni değerin 0. bitine eşit ise rotary encoder // sola doğru çevrilmiştir, bu durumda sayac 0'dan büyükse azalt. if(oldEncoder.F0 != Encoder.F1) { if(oldEncoder.F1 == Encoder.F0 ) if(sayac>0) sayac--; } } while(1); // Ana program çevrimine devam et }
// Dosya Adı : 14_2.c // Açıklama : DS1621 ısı sensörü ile ısı ölçümü // Notlar : Proteus programı simülasyonu // : XT ==> 4 MHz // i2c adres tanımlanıyor #define DS1621_WRITE_ADDR 0x90 #define DS1621_READ_ADDR 0x91 // Komutlar #define DS1621_ACCESS_CONFIG_CMD 0xAC #define DS1621_START_CONVERSION_CMD 0xEE #define DS1621_STOP_CONVERSION_CMD 0x22 #define DS1621_READ_TEMPERATURE_CMD 0xAA #define DS1621_ACCESS_TEMP_HIGH_CMD 0xA1 #define DS1621_ACCESS_TEMP_LOW_CMD 0xA2 #define DS1621_READ_COUNTER_CMD 0xA8 #define DS1621_READ_SLOPE_CMD 0xA9 // Config kaydedicisinin bit tanımlamaları #define DS1621_ONE_SHOT_BIT F0 #define DS1621_OUTPUT_POLARITY_BIT F1 #define DS1621_NVRAM_BUSY_BIT F4 #define DS1621_TEMP_LOW_BIT F5 #define DS1621_TEMP_HIGH_BIT F6 #define DS1621_CONVERSION_DONE_BIT F7 // Config kaydedicisinin başlangıç değeri #define DS1621_CONFIG_INIT_VALUE 0x00 // IsıKontrol kaydedicisinin bit tanımlamaları #define ERROR F7 #define NEG F6 #define ONDABES F5 //Değişken tanımlamaları char *str=" \0"; char IsiKontrol; // DS1621 ilk işlemleri gerçekleştirir. Konfigürasyon kaydedicisine // ilk değer verir. void ds1621_init(void) { I2C_Start(); I2C_Wr(DS1621_WRITE_ADDR); I2C_Wr(DS1621_ACCESS_CONFIG_CMD); I2C_Wr(DS1621_CONFIG_INIT_VALUE); I2C_Stop(); } //Isı okuma çevrimini başlatır. void ds1621_start_conversion(void) { I2C_Start(); I2C_Wr(DS1621_WRITE_ADDR); I2C_Wr(DS1621_START_CONVERSION_CMD); I2C_Stop(); } // Isı bilgisi DS1621'den okunur ve en değerli byte'ı fonksiyon // dışına taşınır. char ds1621_read_temperature(void) { char data_low, data_high; I2C_Start(); // I2C iletişimi başlat I2C_Wr(DS1621_WRITE_ADDR); I2C_Wr(DS1621_READ_TEMPERATURE_CMD); I2C_Repeated_Start(); I2C_Wr(DS1621_READ_ADDR); // Isının en değerli byte'ı okunur ve ACK gönderilir data_high = I2C_Rd(1); // I2C hattı meşgul olduğu sürece bekle while(I2C_Is_Idle() == 0); // Isının en değersiz byte'ı okunur ve NOT ACK gönderilir data_low = I2C_Rd(0); // I2C hattı meşgul olduğu sürece bekle while(I2C_Is_Idle() == 0); I2C_Stop(); // Isı Kontrol kaydedicisinin 0. biti set ise bir hata olduğu // anlaşılır. if(data_low == 0xFF) if(data_high == 0xFF) {IsiKontrol.ERROR = 1; return(0);} else IsiKontrol.ERROR = 0; // Eğer ısı 0 derecenin altında ise data_high byte'ın en değerli // biti set olur. Bu durumda data_high değerinin 2.tamlayanı // alınarak ısı değeri elde edilir ve bu ısının negatif olduğunu // belirtmek için IsiKontrol kaydedicisinin NEGATIF bayrağı set // edilir. if(data_high & 0x80) { // Isının negatif olduğu kontrol kaydedicisine yazılır IsiKontrol.NEG = 1; // Isının en değerli byte'ının 2. tamlayanı alınır data_high = ~data_high + 1; if(data_low) data_high--; // 1/2 C kısmı var ise bir eksilt } else IsiKontrol.NEG = 0; // ısı pozitif // data_low büyük 0 ise 1/2 C değeri var, o halde IsiKontrol // kaydedicisinin ilgili bitini set et data_low = 0 ise 1/2 C değeri // yoktur. Bu durumda IsiKontrol kaydedicisinin ilgili biti silinir. if(data_low) IsiKontrol.ONDABES = 1; else IsiKontrol.ONDABES = 0; // Isı değeri 99'dan büyükse 99 olarak kabul et if(data_high > 99) return 99; return data_high; } // Eğim değerini fonksiyon dışına taşır. char ds1621_read_slope(void) { char slope; I2C_Start(); I2C_Wr(DS1621_WRITE_ADDR); I2C_Wr(DS1621_READ_SLOPE_CMD); I2C_Repeated_Start(); I2C_Wr(DS1621_READ_ADDR); slope = I2C_Rd(0); I2C_Stop(); return slope; } // Sayac değerini fonksiyon dışına taşır. char ds1621_read_counter(void) { char counter; I2C_Start(); I2C_Wr(DS1621_WRITE_ADDR); I2C_Wr(DS1621_READ_COUNTER_CMD); I2C_Repeated_Start(); I2C_Wr(DS1621_READ_ADDR); counter = I2C_Rd(0); I2C_Stop(); return counter; } // Bir byte'lık hexadesimal sayıyı 2 basamaklı desimal sayıya // dönüştürür. char Hex2Dec(char ch) // 2 digit dönüşüm { char tmp = 0; // Geçici değişkeni sıfırla // sayının onlar basamağını bulur while(ch>=10) {tmp++; ch -= 10;} // Birler basamağını sayıya ekler tmp = (tmp<<4) + ch; return tmp; // Sonucu fonksiyon dışına taşı } // Bir byte'lık sayıyı text'e dönüştürür. void BintoStr(char data) { data = Hex2Dec(data); // Desimale dönüştür // Text'e dönüştürür (ilk karakter) str[0] = 48 + ((data & 0xF0) >> 4); // sayının 10'lar basamağı sıfır ise boşluk yazar if (str[0] == 48) str[0] = 32; // Text'e dönüştürür (ikinci karakter) str[1]= 48 + (data & 0x0F); } // İlk işlemler alt programı LCD, I2C ve DS1621'i kullanıma hazırlar // ve ısı dönüşümünü başlatır. void init() { LCD_Config(&PORTB,4,5,7,3,2,1,0); // LCD bağlantısını tanımla LCD_Cmd(LCD_CURSOR_OFF); // imleci gizle I2C_Init(100000); // I2C iletişimi hazırla, full master mode IsiKontrol = 0; // Isı kontrol kaydedicisinin ilk değeri sıfır. ds1621_init(); // Isı sensörünü başlat ds1621_start_conversion(); // Isı dönüşümünü başlat } // Ana program, ısı bilgisini DS1621'den okuyarak LCD üzerinde // görüntüler. void main(void) { char isi; init(); // ilk işlemleri gerçekleştir while(1) // Bu blok içerisindeki işlemler sistem kapatılana { // ya da resetlenene kadar tekrarlar. isi = ds1621_read_temperature(); // Isıyı ölç if(IsiKontrol.ERROR) continue; // Hata var yeniden ölç LCD_Out(1,1,"Isi = "); // Negatif ısı ise - işareti yaz, değilse boşluk koy if(IsiKontrol.NEG) LCD_Out_Cp("-"); else LCD_Out_Cp(" "); BintoStr(isi); // Isıyı text'e dönüştür (2 dijit) LCD_Out_Cp(str); // Isıyı yazdır if(IsiKontrol.ONDABES) LCD_Out_Cp(".5"); else LCD_Out_Cp(".0"); // ondalıklı kısmı yazdır Lcd_Chr_Cp(0xDF); // derece işareti LCD_Out_Cp("C"); // C yazdır Delay_ms(1000); // yeni ölçüm için 1 saniye bekle } }
// Dosya Adı : 13_3.c // Açıklama : L297 ve L298 ile step motor kontrolü // Notlar : Proteus programı simülasyonu // : XT ==> 4 MHz // Step motor bağlantı tanımlamaları. #define stepMotor PORTB // Step motor kontrol uçlarının // bağlandığı port. #define stepMotorTris TRISB // Step motorun bağlı olduğu // portun yönlendirme kaydedicisi #define enable F0 // L297 step motor sürücüsünü // etkinleştiren pin tanımı. #define reset F1 // L297'nin reset ucunun bağlı // olduğu pin tanımı. #define halffull F2 // Bu pin 1 ise half modda, // 0 ise full modda. #define direction F3 // Yön kontrol pini, 1 ise saat // yönünde (ileri), 0 ise geri. #define clock F4 // L297 için saat darbesi üreten // pin tanımı. #define home F5 // Bu pin step motorun her tam // dönüşünde işlemciye saat // darbesi üretir. #define control F6 // Kontrol pini tanımı. // Step motoru half moda alır (45 derecelik açılar ile dönüş modu). void half_mode() { stepMotor.halffull = 1; //L297'yi yarım adım moduna alır. } // Step motoru full moda alır (90 derecelik açılar ile dönüş modu). void full_mode() { stepMotor.halffull = 0; // L297'yi tam adım moduna alır. } // Step motoru istenilen adım kadar saat ibresi yönünde döndürür. void ileri(unsigned int adim) { stepMotor.reset = 1; // L297'yi resetle. stepMotor.enable = 1; // L297'yi etkinleştir. stepMotor.direction = 1; // Yön saat ibrelerinin yönünde do // do - while döngüsü açılıyor. { stepMotor.clock = 1; // Yükselen darbe kenarı. asm nop stepMotor.clock = 0; // İnen darbe kenarı ile L297 // tetikleniyor. delay_ms(50); // 50ms bekle. }while(--adim); } // Step motoru istenilen adım kadar saat ibresinin tersi yönünde // döndürür. void geri(unsigned int adim) { stepMotor.reset = 1; // L297'yi resetle. stepMotor.enable = 1; // L297'yi etkinleştir. stepMotor.direction = 0; // saat ibresinin tersi yönünde do // do - while döngüsü açılıyor. { stepMotor.clock = 1; // Yükselen darbe kenarı. asm nop stepMotor.clock = 0; // İnen darbe kenarı ile L297 // tetikleniyor. delay_ms(50); // Step motor yeni konumu alması // için kısa bir süre bekle. // Bu süre step motorun tepki // süresinden büyük olmalıdır. // Örneğimizde 50 ms seçilmiştir. }while(--adim); } // L297'yi resetler. void resetle() { stepMotor.reset = 0; // L297 resetlendi. stepMotor.enable = 0; // L297 pasif yapıldı. delay_ms(1000); } // Ana program ilk işlemler alt programı port yönlendirir. void init() { stepMotor = 0; // ilk çıkışlar sıfır. stepMotorTris.enable = 0; // enable pini çıkış yapıldı. stepMotorTris.reset = 0; // enable pini çıkış yapıldı. stepMotorTris.halffull = 0; // half/full pini çıkış yapıldı. stepMotorTris.direction = 0; // direction pini çıkış yapıldı. stepMotorTris.clock = 0; // clock pini çıkış yapıldı. stepMotorTris.home = 1; // home pini giriş yapıldı. stepMotorTris.control = 0; // control pini çıkış yapıldı. resetle(); // L297'yi resetle } // Ana program: Step motoru half ve full modlarda ileri ve geri // yönlerde aralarında 1 sn bekleyerek döndürür ve aynı işlemleri // sistem resetlenene ya da kapatılana kadar devam ettirir. void main() { init(); // İlk işlemler yapılıyor. while(1) // Sonsuz döngü açılıyor. { // while bloğu başlangıcı. half_mode(); // Half modda çalıştırılacak. ileri(50); // 50 adım saat ibresi yönünde. delay_ms(1000); // 1 sn bekle. geri(100); // 100 adım saat ibresinin tersi // yönünde dön. delay_ms(1000); full_mode(); // Full modda çalıştırılacak. ileri(100); // 100 adım saat ibresi yönünde. delay_ms(1000); geri(50); // 50 adım saat ibresinin tersi. delay_ms(1000); } // while bloğu sonu. }
Satın almak isterseniz kitap detayları :http://www.altaskitap.com/PIC_877kitab%C4%B1.htm
Şifre-Pass: 320volt.com
Yayım tarihi: 2009/06/09 Etiketler: microchip pic projeleri, PIC 16f877 uygulamaları, pic c uygulama, pic16f877 geliştirme, pic16f877 proje
Paylaşımda büyük emek var teşekkürler 😉
Allah razı olsun emegine sağlık
işte bizim hocalarımız ellerinize sağlık…
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
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.
ldr ile step motor kontrolü nasıl yapılır
14_6.c: PCF8583 ile saat uygulaması nı bulamadım yardımcı olurmusunuz
dosya içinde “Prog_14_6.c”
Allah razı olsun. emeğine sağlık.