DonanımHaber Mini sürüm 2 Ocak 2026 tarihi itibariyle kullanımdan kalkacaktır. Bunun yerine daha hızlı bir deneyim için DH Android veya DH iOS uygulamalarını kullanabilirsiniz.
Arkadaşlar elimde LCD'ye mesaj yazan bir program var.Program ilk başta "merhaba dünya" yazıyor.Sonra 9999'a kadar saymaya başlıyor. Kod "PİC PROGRAMLAMA TEKNİKLERİ ve PIC16F877A" kitabından alınmıştır. Benim problemim şu; Kodlar lcd'nin Data uçlarının PORTB'nin ilk dört bitine göre verilmiş.Benim devrede son dört bitine bağlı.Gerekli birkaç değişikliği yaptım ama ekrandan görüntü almayı beceremedim. Zaten 4bit Modda ilk denemem, kafam iyice karıştı. Sizce kodlarda nasıl bir değiştirme yapmam gerek? Kodlar aşağıda
;******************************************************************* ; 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 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
; 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 ;*******************************************************************
Fikirlerinizi bekliyorum.
(Bu arada @tyilgin1 benim işi birkaç ufak hatyla da olsa hallettim.)
< Bu mesaj bu kişi tarafından değiştirildi strom -- 18 Ocak 2008; 22:25:56 >
1. sayfa
Hizmet kalitesi için çerezleri kullanabiliriz, DH'yi kullanırken depoladığımız çerezlerle ilgili veri politikamıza gözatın.
Kod "PİC PROGRAMLAMA TEKNİKLERİ ve PIC16F877A" kitabından alınmıştır.
Benim problemim şu;
Kodlar lcd'nin Data uçlarının PORTB'nin ilk dört bitine göre verilmiş.Benim devrede son dört bitine bağlı.Gerekli birkaç değişikliği yaptım ama ekrandan görüntü almayı beceremedim.
Zaten 4bit Modda ilk denemem, kafam iyice karıştı.
Sizce kodlarda nasıl bir değiştirme yapmam gerek?
Kodlar aşağıda
Fikirlerinizi bekliyorum.
(Bu arada @tyilgin1 benim işi birkaç ufak hatyla da olsa hallettim.
< Bu mesaj bu kişi tarafından değiştirildi strom -- 18 Ocak 2008; 22:25:56 >