Ynt: Karakter LCD temelleri

Başlatan Ateş Erim, 08 Aralık 2013, 12:51:09

Ateş Erim

İyi pazarlar,
Pic programlamaya yeni başladım. Eh yeni olunca kedi yavrusu gibi oluyor insan. Herşey yeni, herşey merak uyandırıcı ve herşey korkunç görünüyor :)
Bir süredir karakter LCD ile aramızda bir gerginlik vardı. İnternette araştırırken  http://www.8051projects.net/lcd-interfacing/introduction.php adresinde, karakter LCD'lerin çalışmasını  temel seviyede anlatan bir yazı buldum. Hem forumda da bulunsun diye, hem de ingilizcesi yetersiz arkadaşlarımız da faydalanabilsinler diye tercüme ettim ve bu giriş yazısının altına ekliyorum.

Not1: Okudum çevirdim de karakter LCD'yi yaladım yuttum sanmayın. Hala anlamadığım yerler var. Yazının sonunda sorularım olacak.
Not2: Benden veya yazının editöründen kaynaklanan yanlış/eksik kısımlar varsa ve bilenler düzeltirlerse memnun olurum.

Birilerinin işine yaraması dileklerimle.
Ateş Erim
12/2013 Bozburun

------------------------------------------------------------------------------------

GİRİŞ :
Piyasada en sık kullanılan karakter LCD'ler, Hitachi firmasının HD44780 işlemcisnin kullanıldığı setlerdir. Diğer setlerdeki işlemciler de, HD44780'le uyumludurlar. Yazımız boyunca, karakter LCD'ler, karakter LCD'lerin değişik MCU'larla ara yüzü, değişik sürme biçimleri (4 bit/8 bit), programlama, özel detaylar ve ip uçlarını konuşacağız.
HD44780 işlemcisinin detaylı bilgi föyüne http://web.mit.edu/6.115/www/datasheets/44780.pdf adresinden ulaşabilirsiniz.

Bacak Bağlantıları :

Günümüzde LCD'ler, çoğunlukla 1 satır, 2 satır veya 4 satır olarak bulunmaktadır ve çoğunlukla 1 işlemcilidirler. 1 işlemcili LCD'ler 80 karaktere kadar destekler. 80 karakterden fazla destekleyen setlerde, 2 adet HD44780 işlemcisi kullanılır.
Tek işlemcili LCD setleri çoğunlukla 14 bacaklı, iki işlemcili LCD setleri de 16 bacaklıdır. Her iki model için de arka plan aydınlatması için fazladan 2 bacak daha vardır.
LCD setlerinin bacak bağlantıları ve bunların açıklamaları aşağıdaki gibidir:



Bacak No.   İsim   Açıklama
1           VSS   Güç kaynağı (-) ucu. (GND)
2           VCC   Güç kaynağı (+) ucu. (+5V)
3           VEE   Kontrast ayarı.
4           RS   0 = Komut girişi. 1 = Data girişi.
5           R/W   0 = LCD'ye yazma işlemi yapılacağını belirtir. 1 = LCD'den okuma işlemi yapılacağını belirtir.
6           EN   İzin sinyali
7           D0   Data ucu 0 (LSB)
8           D1   Data ucu  1
9           D2   Data ucu  2
10           D3   Data ucu  3
11           D4   Data ucu  4
12           D5   Data ucu  5
13           D6   Data ucu  6
14           D7   Data ucu  7 (MSB)
Tablo 1: Tek işlemcili karakter LCD bacak bağlantıları


Bacak No.   İsim   Açıklama
1           D7   Data ucu  7 (MSB)
2           D6   Data ucu  6
3           D5   Data ucu  5
4           D4   Data ucu  4
5           D3   Data ucu  3
6           D2   Data ucu  2
7           D1   Data ucu  1
8           D0   Data ucu  0 (LSB)
9           EN1   Satır 0 ve 1 için izin sinyali (1. işlemci)
10           R/W   0 = LCD'ye yazma işlemi yapılacağını belirtir.1 = LCD'den okuma işlemi yapılacağını belirtir.
11           RS   0 = Komut girişi. 1 = Data girişi.
12           VEE   Kontrast ayarı.
13           VSS   Güç kaynağı (-) ucu. (GND)
14           VCC   Güç kaynağı (+) ucu. (+5V)
15           EN2   Satır 2 ve 3 için izin sinyali (2. işlemci)
16           NC   Bağlı değil
Tablo 2: İki işlemcili karakter LCD bacak bağlantısı

Günümüzde piyasada genellikle tek işlemcili LCD setleri bulunmaktadır. Bu sebeple, yazımızın devamında tek işlemcili setler üzerine konuşacağız. Çift işlemcili setlerin işleyişi hariç her şeyi tek işlemcili setler gibidir.

DDRAM (Display Data RAM)
Ekranda gösterilecek bilgi, DDRAM içerisinde 8 bit olarak tutulur. DDRAM'ın kapasitesi 80 X 8 bit'e (veya bir başka deyişle 80 karaktere) kadar çıkar. DDRAM'daki bu alan, sadece display için değil, genel RAM olarak da kullanılabilir.  DDRAM'a gönderilen bilgi her halukarda ekranda görüntülenebilir. 1 X 16 gibi LCD setlerinde sadece 16 karakter gösterilebilir.  Bu tip bir LCD'de, isterseniz 16 karakterden fazlasını da DDRAM'a yazabilirsiniz fakat kullanıcı bunları göremez.

Aşağıdaki şekillerde, 1, 2 ve 4 satırlık LCD setlerinde DDRAM adreslemeleri gösterilmiştir :





CGROM (Character Generator ROM)
Şimdi muhtemelen, DDRAM'a bir ascii karakter yolladığımızda, nasıl olup ta onun ekranda bir karakter olarak göründüğünü merak ediyorsunuzdur. Bu sorunun cevabı CGROM'dur. CGROM, kendisine gelen 8 bit formatındaki karakter kodundan, 5x8 veya 5x10 nokta boyutlarında karakter desenini üretir.  Detaylı bilgi için şeki 5 ve 6'ya bakabilirsiniz. CGROM 5x8 nokta boyutlarında 208 adet; 5x10 nokta boyutlarındaysa 32 adet karakter deseni üretebilir.





Her iki kod haritasından da görüleceği üzere, 0x00'dan 0x07'ye kadar olan karakter kodları, CGRAM karakterleri veya kullanıcıların tanımladığı karakterler için ayrılmıştır.
Örneğin, kullanıcı dördüncü özel karakteri ekrana bastırmak isterse, 0x03 karakter kodunu kullanmalıdır. Kullanıcı, LCD'nin DDRAM'ına 0x03 kodunu yolladığında, ekranda kullanıcı tarafından yaratılmış dördüncü karakter (veya desen) görüntülenir.


CGRAM - Character Generator RAM
CGRAM, adından da anlaşılacağı gibi, LCD setinde kullanıcıların yarattığı özel karakterler (desenler) için kullanılan bir alandır. Kullanıcılar, CGRAM alanında, program vasıtasıyla kendilerine ait özel karakterleri(desenleri) yazıp okuyabilirler. CGRAM alanına, 5x8 LCD'ler için 8 özel karakter, 5x10 LCD'ler niçin ise 4 özel karakter yazılabilir. Yazının ilerleyen bölümlerinde, CGRAM alanının özel karakterler için nasıl kullanıldığı açıklanacaktır.

BF - Busy Flag (mesgul bayrağı)
Busy flag, LCD'nin durumunu gösteren bir bayraktır. LCD'ye bir komut veya data yolladığımız zaman, LCD setinin işlemcisinin bu komut veya data'yı işlemesi  için bir süreye ihtiyacı vardır. Biz bir komut veya data gönderir göndermez, LCD'nin işlemcisi BF bayrağını kaldırır (BF=1). İşlemci işini bitirir bitirmez de hemen BF bayrağını indirir (BF=0). Bu bayrak, LCD işlemcisinin meşgul olup olmadığı konusunda bize bilgi vermek açısından oldukça faydalıdır.
Busy Flag'ı okuyabilmek için, RS=0 ve RW=1 olmalıdır. Bu şaretlar sağlandıktan sonra, LCD setinin D7 bitini (bacağını) okuduğumuzda elde ettiğimiz bilgi BF'dır. BF=1'in anlamı, LCD işlemcisi henüz meşgul ve yeni bir komut veya data yollarsak bunu kabul edemeyecek. BF=0'ın anlamı ise, LCD işlemcisi serbest durumda ve gönderilen komut veya datayı işleyebilir.


Instruction Register (IR) and Data Register (DR) (Talimat Yazmacı ve Data Yazmacı)
HD44780 işlemcisinde IR ve DR isminde iki adet 8 bitlik yazmaç bulunur.
Talimat yazmacı (IR), LCD setine yolladığımız, LCD'yi silme, sağa veya sola kaydırma vs gibi komutlar içindir.
Data yazmacı ise (DR), LCD ekjranında görüntülenecek bilgiler içindir. Data yazmacına bilgiyi yazmak için öncelikle D0...D7 bacaklarına bu bilgiyi gönderiririz. E(nable) bacağına sinyal göndermemizle birlikte, D0...D7 bacaklarındaki bilgi içeri data yazmacına (DR) aktarılır, arkasından bilgi otomatik olarak DDRAM'a aktarılır ve bunun sonucu olarak ta LCD ekranında görüntülenir.
Data yazmacı (DR) sadece DDRAM veya CGRAM için kullanılmaz, ayrıca, LCD'ye talimat verme işlerinde de kullanılabilir. Yazının ilerleyen bölümlerinde LCD talimatlarıyla ilgili daha fazla konuşacağız.
MCU'lar, sadece talimat yazmaçını (IR) ve data yazmaçını (DR) kontrol edebilirler. Değişik hızdaki ve çevre birimlerindeki MCU'larla haberleşebilmek için, LCD kendi içindeki işlemlere başlamadan önce, kontrol bilgisi, geçici olarak bu yazmaçlarda depolanır.
LCD, kendi içindeki işlemleri yaparken MCU tarafından yollanan sinyallere göre ne yapacağına karar verir. Bu sinyaller, yazmaç seçimi (RS), Okuma/yazma (R/W) ve data sinyalleri (D0...D7) dir. Bu sinyaller, hep birlikte LCD'nin şekillendirilmesinde kullanılanılırlar (tablo 3).
Talimatlar 4 ana kategoriye ayrılabilir :
•   LCD fonksiyonlarını belirlemek (gösterim formatı, data uzunluğu vs);
•   Dahili RAM adresinin setr edilmesi;
•   Dahili RAM'a bilgi transferinin sağlanması;
•   Ivır zıvır fonksiyonların sağlanması;


Tablo 3: HD44780  işlemcili LCD için komut ve talimat seti

Yukarıdaki tabloya bakarak kendi komutlarınızı oluşturabilir ve test edebilirsiniz.
AşağıdaLCD ile çalışırken sıklıkla kullanılan komutların kısa bir listesini bulacaksınız :



Yukarıdaki tablo, program yazarken size yardımcı olacaktır. Fakat konuyu iyice pekiştirmek için,benim tavsiyem, tablo 4'ü iyice anladıktan sonra, tablo 3'ü kullanarak, kendi komutlarınızı oluşturup denemenizdir. Bir sonraki bölümde, LCD'nin ilk kullanıma hazırlanmasıyla ilgili C dilinde ve asembly dilinde yazılmış örnekler göreceğiz.

LCD'nin ilk kullanıma açılması :
Bir LCD setini kullanıma açmak için ya LCD setinin dahili reset devreleriyle veya dışarıdan göndereceğimiz talimatlarla ilk kullanıma açılması (hazır hale getirilmesi) gerekmektedir.  LCD'nin ilk kullanıma açılmasının setin dahili reset devresiyle mi, dışarıdan verilen talimatlarla mı olacağına kullanıcı karar verir. Her iki yöntemi de adım adım tartışacağız.

Dahili reset devresiyle ilk kullanıma hazırlama :
HD44780U işlemcisi olan setlerde, sete enerji verilince dahili reset devresi, LCD setini ilk kullanıma hazır hale getirir. Dahili reset devresi aşağıdaki işlemleri yapar. Dahili reset devresi işini bitirene kadar meşgul bayrağı (BF), LCD setinin dışarıdan gelecek talimatlara yanıt veremeyeceğini belirtmek amacıyla kaldırılır (BF = 1). Meşgul durumu, besleme gerilimi (VCC) 4.5Volta ulaştıktan sonra 10ms daha sürer. 
•   Ekran temizlenir
•   Ana fonksiyonlar set edilir :
o   DL = 1 ; 8 bit haberleşme.
o   N = 0 ; 1 satır.
o   F = 0 ; 5x8 nokta font
•   Ekran açık/kapalı kontrolü :
o   D = 0 ; Ekran kapalı.
o   C = 0 ; imleç kapalı.
o   B = 0 ; imleçin yanıp sönmesi kapalı.
•   Giriş modu seçimi :
o   I/D = 1 ; 1 artan
o   S = 0 ; ekran kaydırma yok
NOT : Eğer aşağıdaki elektriksel karakteristikler sağlanmamışsa, HD44780U, dahili reset devresini çalıştırmaz. Bu durumda, LCD seti MCU vasıtasıyla ilk kullanıma hazırlanmalıdır.
Notta da bahsedildiği gibi, eğer kullanıcı dahili reset devresinin çalışmasını istiyorsa, tablo 5'teki  koşulların mutlaka sağlanması   gereklidir.
Dahili reset devresinin çalıştırılması için gerekli besleme koşulları:

Madde                                           Sembol        Min        tipik           Max          ünit         Test koşulu
Besleme gerilimi yükselme zamanı     tcc               01          -              10            ms             Şekil 7
Besleme gerilimi off zamanı              toff              1            -               -                                         
Tablo 5: Dahili reset devresi için besleme kaynağı koşulları

Şekil 7 Dahili reset devresinin aktif olabilmesi için gerekli test koşullarını göstermektedir.




Dahili reset devresiyle ilgili problem, dahili reset devresinin besleme kaynağına çok bağımlı olmasıdır. Besleme kaynağının dahili reset devresinin istediklerini karşılaması çok da zor bir şey olmamakla birlikte, basit uygulamalarda, bu koşulları tutturmaya uğraşmaktansa, ikinci yol olan, MCU tarafından yollanan Komutlarla LCD setini ilk kullanıma hazırlama yolu tercih edilir.

Talimatlarla ilk kullanıma hazırlama :
LCD setini talimatlarla ilk kullanıma hazırlama işi aslında oldukça basittir. Aşağıdaki akış diagramı, bize LCD'ye enerji verilmesinden itibaren neler yapmamız gerektiğini anlatmaktadır.



Akış diagramından görülebileceği gibi, LCD'nin ilk kullanıma hazırlanması aşaması şu adımları içerir :
1.   8 bit haberleşmeyi kullanarak LCD'ye 0x30 Komutı yolla,
2.   20 ms bekle,
3.   8 bit haberleşmeyi kullanarak tekrar 0x30 Komutı yolla,
4.   20 ms bekle,
5.   8 bit haberleşmeyi kullanarak tekrar 0x30 Komutı yolla,
6.   20 ms bekle,
7.   Ana fonksiyonları set eden Komutı yolla (Detay için Tablo 4'e bakınız),
8.   Ekranı silme Komutı yolla,
9.   LCD'yi giriş moduna geçirme komutu yolla

İlk 3 komuta genellikle gerek kalmaz fakat eğer 4 bit haberleşmeyi kullanılıyorsa, bu komutların  kullanılması önerilir. 8 bit haberleşmeyi kullanılıyorsa, 7. Adımdan başlanabilir.

LCD giriş modu:
Tablo 3'teki Komutlardan göreceğiniz gibi, LCD'nin giriş moduna 2 bit vasıtasıyla karar verilir.
a)   I/D  (artan/Azalan) ve
b)   S Ekran kaydırma.
Bu 2 bit ile 4 farklı giriş modu seçebiliriz. Bunlar 0x04, 0x05, 0x06 ve 0x07'dir. (Detaylar için Tablo 3'e bakınız). Sonuç olarak bu 4 değişik giriş modu seçimiyle, LCD'ye yolladığımız ascii karakterler, ekranda 4 farklı şekilde görünür. Normalde 0x06 giriş modu seçilir ki bunun anlamı, kaydırma yok, ve artan (yani karakterler geldikçe, yeni gelen karakteri  bir önce gelenin sağına yerleştir) demektir. Olası tüm giriş modlarını seçerek sonucunu kendi gözünüzle görmenizi şiddetle tavsiye ederim.

LCD'yi ilk kullanıma hazırlama için kod örnekleri :
İlk örnce asembly:

1.	LCD_data equ P2    ;LCD Data port
2.	LCD_D7   equ P2.7  ;LCD D7/Busy Flag
3.	LCD_rs   equ P1.0  ;LCD Register Select
4.	LCD_rw   equ P1.1  ;LCD Read/Write
5.	LCD_en   equ P1.2  ;LCD Enable
6.	 
7.	LCD_init:
8.	         mov   LCD_data,#38H  ;Function set: 2 Line, 8-bit, 5x7 dots
9.	         clr   LCD_rs         ;Selected command register
10.	         clr   LCD_rw         ;We are writing in instruction register
11.	         setb  LCD_en         ;Enable H->L
12.	         clr   LCD_en
13.	         acall LCD_busy       ;Wait for LCD to process the command
14.	         mov   LCD_data,#0FH  ;Display on, Curson blinking command
15.	         clr   LCD_rs         ;Selected instruction register
16.	         clr   LCD_rw         ;We are writing in instruction register
17.	         setb  LCD_en         ;Enable H->L
18.	         clr   LCD_en
19.	         acall LCD_busy       ;Wait for LCD to process the command
20.	         mov   LCD_data,#01H  ;Clear LCD
21.	 
22.	         clr   LCD_rs         ;Selected command register
23.	         clr   LCD_rw         ;We are writing in instruction register
24.	         setb  LCD_en         ;Enable H->L
25.	         clr   LCD_en
26.	 
27.	         acall LCD_busy       ;Wait for LCD to process the command
28.	         mov   LCD_data,#06H  ;Entry mode, auto increment with no shift
29.	         clr   LCD_rs         ;Selected command register
30.	         clr   LCD_rw         ;We are writing in instruction register
31.	 
32.	         setb  LCD_en         ;Enable H->L
33.	         clr   LCD_en
34.	         acall LCD_busy       ;Wait for LCD to process the command
35.	         ret                  ;Return from routine


Şimdi de aynı kodun C ile yazılmışı. Örnekler Keil C ile yazılmıştır. Sizler bunu değişik derleyicilere kolaylıkla uyarlayabilirsiniz.

1.	#include .
2.	#define LCD_data P2
3.	#define LCD_D7   P2_7
4.	#define LCD_rs   P1_0
5.	#define LCD_rw   P1_1
6.	#define LCD_en   P1_2
7.	
8.	void LCD_init()
9.	{
10.	     LCD_data = 0x38;     //Function set: 2 Line, 8-bit, 5x7 dots
11.	     LCD_rs   = 0;        //Selected command register
12.	     LCD_rw   = 0;        //We are writing in data register
13.	     LCD_en   = 1;        //Enable H->L
14.	     LCD_en   = 0;
15.	     LCD_busy();          //Wait for LCD to process the command
16.	     LCD_data = 0x0F;     //Display on, Curson blinking command
17.	     LCD_rs   = 0;        //Selected command register
18.	     LCD_rw   = 0;        //We are writing in data register
19.	     LCD_en   = 1;        //Enable H->L
20.	     LCD_en   = 0;
21.	     LCD_busy();          //Wait for LCD to process the command
22.	     LCD_data = 0x01;     //Clear LCD
23.	     LCD_rs   = 0;        //Selected command register
24.	     LCD_rw   = 0;        //We are writing in data register
25.	     LCD_en   = 1;        //Enable H->L
26.	     LCD_en   = 0;
27.	     LCD_busy();          //Wait for LCD to process the command
28.	     LCD_data = 0x06;     //Entry mode, auto increment with no shift
29.	     LCD_rs   = 0;        //Selected command register
30.	     LCD_rw   = 0;        //We are writing in data register
31.	     LCD_en   = 1;        //Enable H->L
32.	     LCD_busy();
33.	
34.	}


Yukarıdaki kodlar LCD'nin ilk kullanıma hazırlanması işlemini yaparlar. Şimdi sırada, yukarıdaki kodda kullanılan fonksiyonların/alt programlarının yazılmasına geldi. Örneğin LCD_busy fonksiyonu/alt programı, LCD'nin meşgul olduğu zaman diliminde, yeni bir Komut/data yollanmamasını sağlar.

İlk bölüm biraz uzun oldu sanırım. Burada kısa bir ara veriyorum. Devamı gelecek.

mesaj birleştirme:: 08 Aralık 2013, 13:46:36

Soğutmadan devam  ;)

Meşgul bayrağının (BF) okunması :
LCD'ye gönderdiğimiz Komutlar/data'lar arasında belli gecikmeler olması gerektiğini  ve nedenlerini yazımızın önceki bölümlerinde  görmüştük. Bu gecikmeleri, gecikme çevrimleri yardımıyla, LCD'nin ihtiyacı olan zamandan biraz daha uzun süreler vererek yapabiliriz .  Bu yol biraz daha kolay olsa da, gereksiz zaman kayıplarına sebep olur. Veya ikinci yol olarak, LCD'nin meşgul bayrağını (BF) okuyarak işlemlerimizi fazladan zaman kaybetmeden tam zamanında yapabiliriz. Bu ikinci yol biraz daha karmaşık olsa da da bu yolu kullanmanızı tavsiye ederim.

Meşgul bayrağını (BF) okumanın adımları :
LCD'ye bir Komut yollar yollamaz, LCD'nin D7 biti hemen 1 olur (BF = 1), LCD yollanan Komutu işler işlemez tekrar D7 bitini 0'a çeker (BF = 0). Meşgul bayrağını okumak için :
•   Komut yazmacını seç,
•   Okuma modunu seç,
•   Enable sinyali gönder,
•   Bayrağı (D7) oku.
Yukarıda yazılı adımları koda dönüştürürsek şöyle bir şey çıkar karşımıza :
Tabii önce asembly  :)

1.	;Ports used are same as the previous example
2.	 
3.	LCD_busy:
4.	         setb   LCD_D7        ;Make D7th bit of LCD data port as i/p
5.	         setb   LCD_en        ;Make port pin as o/p
6.	         clr    LCD_rs        ;Select command register
7.	         setb   LCD_rw        ;we are reading
8.	check:
9.	         clr    LCD_en        ;Enable H->L
10.	         setb   LCD_en
11.	         jb     LCD_D7,check  ;read busy flag again and again till it becomes 0
12.	         ret                  ;Return from busy routine



Yukarıdaki kodun C eşdeğeri ise şöyledir :

1.	void LCD_busy()
2.	{
3.	 
4.	     LCD_D7   = 1;           //Make D7th bit of LCD as i/p
5.	     LCD_en   = 1;           //Make port pin as o/p
6.	     LCD_rs   = 0;           //Selected command register
7.	     LCD_rw   = 1;           //We are reading
8.	 
9.	     while(LCD_D7){          //read busy flag again and again till it becomes 0
10.	           LCD_en   = 0;     //Enable H->L
11.	           LCD_en   = 1;
12.	     }
13.	 
14.	}


Yukarıdaki kod parçaları, LCD işlemcisinin kendisine gönderilen talimatları işleyebilmesi için gerekli gecikmenin tam gerektiği kadar olmasını sağlar. Böyle bir kod yazdığınız zaman, aynı kodu, daha hızlı veya yavaş işlemciye sahip LCD setleri için de kullanabilirsiniz. Buna rağmen hala meşgul bayrağını (BF) kullanmak istemiyorsanız, aşağıdaki basit gecikme döngülerini  kullanarak ta işinizi görebilirsiniz :

1.	LCD_busy:
2.	         mov  r7,#50H
3.	back:
4.	         mov  r6,#FFH
5.	         djnz r6,$
6.	         djnz r7,back
7.	         ret                  ;Return from busy routine
1.	void LCD_busy()
2.	{
3.	         unsigned char i,j;
4.	         for(i=0;i<50;i++)        //A simple for loop for delay
5.	            for(j=0;j<255;j++);
6.	}


Evet, artık LCD'yi ilk başlatma yordamımız ve meşgul bayrağını okuma yordamımız hazır. Bundan sonra, LCD'ye nasıl Komut ve data göndereceğimizi göreceğiz.

LCD'ye komut yollama :
LCD'ye komut yollayabilmek için tek yapmamız gereken şey komut yazmacını seçmektir. Sonrası aynen LCD'yi ilk başlatma işlemlerine benzer. Ortak adımları tek bir alt yordama yazarak özetleyeceğiz. Ortak adımlar aşağıdadır :
•   Data'yı LCD'nin portlarına yolla,
•   Komut yazmacını seç,
•   Yazma işlemini seç,
•   Enable sinyalini yolla,
•   LCD'nin komutu işlemesini bekle.
Bu adımları aklımızda tutarsak, LCD kodlarını kolayca yazabiliriz.
Her zamanki gibi önce asambly:

1.	;Ports used are same as the previous example
2.	;Routine to send command to LCD
3.	 
4.	LCD_command:
5.	         mov   LCD_data,A     ;Move the command to LCD port
6.	         clr   LCD_rs         ;Selected command register
7.	         clr   LCD_rw         ;We are writing in instruction register
8.	         setb  LCD_en         ;Enable H->L
9.	         clr   LCD_en
10.	         acall LCD_busy       ;Wait for LCD to process the command
11.	         ret                  ;Return from busy routine
12.	 
13.	; Usage of the above routine
14.	; A will carry the command for LCD
15.	; e.g. we want to send clear LCD command
16.	;
17.	; mov   a,#01H         ;01H is command for clearing LCD
18.	; acall LCD_command    ;Send the command


Yukarıdaki kodun C eşdeğeri ise şöyledir :

1.	void LCD_command(unsigned char var)
2.	{
3.	     LCD_data = var;      //Function set: 2 Line, 8-bit, 5x7 dots
4.	     LCD_rs   = 0;        //Selected command register
5.	     LCD_rw   = 0;        //We are writing in instruction register
6.	     LCD_en   = 1;        //Enable H->L
7.	     LCD_en   = 0;
8.	     LCD_busy();          //Wait for LCD to process the command
9.	}
10.	// Using the above function is really simple
11.	// var will carry the command for LCD
12.	// e.g.
13.	//
14.	// LCD_command(0x01);


İmlecin LCD üzerindeki pozisyonunu ayarlama :
İmlecin LCD üzerindeki pozisyonunu ayarlamak için ihtiyacımız olan tek şey, LCD'ye DDRAM adresini yollamaktır.

1.   Bit7  Bit6   Bit5   Bit4   Bit3   Bit2   Bit1   Bit0
2.    1     AD6   AD5   AD4   AD3   AD2   AD1   AD0

LCD'ye DDRAM adresini yolladığımızı belirtmek için 7. bit 1 olmalıdır. Takip eden 6..0 arasındaki bitler DDRAM'ın adres bitleridir. Örneğin, imleci ekranın ilk pozisyonuna (pozisyon 0) yollamak istersek, göndereceğimiz DDRAM adresi binary olarak 0bx000 0000 olacaktır. 7. Bitin de 1 olması gerektiğini bildiğimize göre, adresin tamamı binary olarak 0b1000 0000 yani 0x80 olacaktır. (Bakınız şekil 2,3 ve 4)
2 satır ve 16 karakterlik bir LCD setinde, 1. Satırın başlangıç DDRAM adresi 0x80 olduğuna göre, ekranda görebileceğimiz 16. Karakterin (15. İmleç pozisyonu) adresi 0x8F olacaktır. Şekil 3'e bakarsak, ikinci satır için başlangıç adresininin 0x40 (0bx100 0000) olduğunu görürüz. 7. Bitin de 1 olması gerektiğini bildiğimize göre imleci 2. satırın başlangıç pozisyonuna götürmek istediğimizde LCD'ye yollamamız gereken DDRAM adresi : 0b1100 0000 yani 0xC0 olacaktır. 2. satırın ekranda görülebilen son karakteri olan 16. karakterin (yani 2. satır, 15. pozisyon) DDRAM adresi ise 0xCF'dir. 0x8F ve 0xCF adreslerinden sonraki DDRAM adresler ise kullanılabilir fakat ekranı kaydırmadan görülemezler. Eğer bu durumu test etmek isterseniz, LCD'ye 16 karakterden uzun bir string yollayın, sonra ekranı kaydırma komutu yollayarak ekranı sola kaydırın. Ekranı kaydırdıkça, ilk başta ekranda görülmeyen karakterlerin teker teker görüldüğünü, fakat 0. Pozisyondan başlayarak en soldaki karakterlerin de teker teker kaybolduğunu göreceksiniz.
Aşağıdaki örnek kod, imleç pozisyonunu set etmek içindir.

1.	;We are placing the cursor on the 4th position
2.	;so the DDRAM address will be 0x03
3.	;and the command will be 0x80+0x03 = 0x83
4.	mov a,#83H           ;load the command
5.	acall LCD_command    ;send command to LCD
1.	// to do the same thing is C
2.	// as we done before
3.	LCD_command(0x83);


LCD'ye data yollamak :
LCD'ye data yollamak için ihtiyacımız olan şey, data yazmacını seçmektir. Sonrası komut göndermekle hemen hemen aynıdır. LCD'ye data yollamanın adımları şöyledir:
•   Data'yı LCD'nin portlarına yolla,
•   Data yazmacını seç,
•   Yazma işlemini seç,
•   Enable sinyalini yolla,
•   LCD'nin komutu işlemesini bekle.
•   Bu adımları aklımızda tutarsak, LCD kodlarını kolayca yazabiliriz.
Önce asembly :

1.	;Ports used are same as the previous example
2.	;Routine to send data (single character) to LCD
3.	 
4.	LCD_senddata:
5.	         mov   LCD_data,A     ;Move the command to LCD port
6.	         setb  LCD_rs         ;Selected data register
7.	         clr   LCD_rw         ;We are writing
8.	         setb  LCD_en         ;Enable H->L
9.	         clr   LCD_en
10.	         acall LCD_busy       ;Wait for LCD to process the data
11.	         ret                  ;Return from busy routine
12.	 
13.	; Usage of the above routine
14.	 
15.	; A will carry the character to display on LCD
16.	; e.g. we want to print A on LCD
17.	;
18.	; mov   a,#'A'         ;Ascii value of 'A' will be loaded in accumulator
19.	 
20.	; acall LCD_senddata   ;Send data


Ve C eşdeğeri:

1.	void LCD_senddata(unsigned char var)
2.	{
3.	     LCD_data = var;      //Function set: 2 Line, 8-bit, 5x7 dots
4.	     LCD_rs   = 1;        //Selected data register
5.	     LCD_rw   = 0;        //We are writing
6.	     LCD_en   = 1;        //Enable H->L
7.	     LCD_en   = 0;
8.	     LCD_busy();          //Wait for LCD to process the command
9.	}
10.	// Using the above function is really simple
11.	// we will pass the character to display as argument to function
12.	// e.g.
13.	//
14.	// LCD_senddata('A');


Artık, LCD'ye komut veya data yollamanın ne kadar kolay olduğunu görmüşsünüzdür. Şimdi sıra, elimizde bir string varsa bunu LCD'ye nasıl gönderirize geldi.
Aslında basit, göndereceğimiz string'i MCU'nun içinde tutarız ve bunu karakter karakter çağırarak LCD'ye yollarız.
Buyrun asembly örnek :

1.	;Sending string to LCD Example
2.	 
3.	LCD_sendstring:
4.	         clr   a                 ;clear Accumulator for any previous data
5.	         movc  a,@a+dptr         ;load the first character in accumulator
6.	         jz    exit              ;go to exit if zero
7.	         acall lcd_senddata      ;send first char
8.	         inc   dptr              ;increment data pointer
9.	         sjmp  LCD_sendstring    ;jump back to send the next character
10.	exit:
11.	         ret                     ;End of routine
12.	 
13.	; Usage of the above routine
14.	; DPTR(data pointer) will carry the address
15.	; of string to send to LCD.
16.	; e.g. we want to print "LCD Tutorial" on LCD then
17.	;
18.	 
19.	; mov   dptr,#my_string   ;my_string is the label where the string is stored
20.	 
21.	; acall LCD_sendstring    ;Send string
22.	 
23.	;
24.	 
25.	; To store a string..
26.	 
27.	; my_string:
28.	 
29.	; DB   "LCD Tutorial", 00H
30.	 
31.	; 00H indicate that string is finished.


Aynı kodun C ile yazılmışı :

1.	void LCD_sendstring(unsigned char *var)
2.	{
3.	     while(*var)              //till string ends
4.	       LCD_senddata(*var++);  //send characters one by one
5.	}
6.	// Using the above function is really simple
7.	// we will pass the string directly to the function
8.	// e.g.
9.	//
10.	// LCD_sendstring("LCD Tutorial");


Artık LCD'ye data ve komut gönderebiliyoruz. Son olarak, LCD setinde kendimize ait bir karakter (desen) yaratmayı ve onu ekrana bastırmayı göreceğiz.

CGRAM ve karakter oluşturma :
Önceki bölümlerde konuşmuştuk. HD44780 temelli her LCD setinde, kullanıcıların özel karakter oluşturmasına olanak sağlamak için bir CGRAM bölümü vardır. Özel desenleri yapmak için ihtiyacımız olan şey, 5x7 (veya 5x10) noktalardan oluşan bir hanenin hangi noktalarının koyu (1), hangilerinin açık renk (0) olduğu bilgisini CGRAM'a yazmaktır. Bu bilgi, CGRAM'ın 0x40'dan başlayan adresine yazılır. Eğer adresin neden 0x40'dan başladığını merak ediyorsanız, cevap aşağıdadır :



Yukarıdaki tablo parçasının, aslında tablo 3'ün bir parçası olduğunu hatırlayacaksınız. CGRAM'a ulaşmak için bit 7 = 0 ve bit 6 = 1 olmak zorunda olduğunu buradan görüyoruz. Geri kalanlar da CGRAM adresi (Acg) olduğuna göre, başlangıç adresimiz 0b01000 0000 yani 0x40'dır. Aslında bu 0x40, CGRAM'ın 0. Adresine ulaşmak için kullanacağımız (LCD'ye göndereceğimiz) komuttaki adrestir. Bu adresi kullanarak, esasında CGRAM'ın 0x00 adresine (Acg = 0x00) ulaşmış oluyoruz. CGRAM'ın toplam büyüklüğü 64 byte'tır. 5x8 nokta (her bir hanesi 5 nokta sütun, 8 nokta satır) bir LCD kullanıyorsak, her bir hanedeki her bir satır için 1 byte'lık bilgiye ihtiyacımız vardır. Bu durumda, 5x8 noktalık bir LCD'de her bir hane için 8 byte'a ihtiyacımız olacaktır. CGRAM'ın toplam alanı 64 byte olduğuna göre, en fazla 64/8 = 8 adet özel karakter(desen) tanımlaması yapabiliriz.  Yok eğer 5x10 bir LCD kullanıyorsak, o zaman en fazla 4 özel karakter tanımlayabiliriz.??
Hadi şimdi bir özel karakter oluşturalım.  Bütün yapmamız gereken, 5x7 noktadan oluşan bir hanelik özel karakterin her bir nokta satırı için bir pixel haritası çıkartmak ve bunları hex'e çevirmektir. Oluşturacağımız özel karakterdeki koyu renk olmasını istediğimiz pixel'lerin yerine 1, açık renk olmasını istediğimiz pixel'lerin yerineyse 0 koyacağız ve bunu hex'e çevireceğiz.  7. satırın da pixel haritasını çıkarttıktan sonra 7 byte'ı CGRAM'a birer birer yollayacağız. Evet LCD'mizin her bir hanesinin 8 nokta satırından oluştuğunu biliyorum (5x8 demiştik ya). Son satır genellikle imlecin görülebilmesi için tüm pixel'leri sönük (0x00) olarak bırakılır. Bu şart değildir. İsterseniz 8. satırı da kullanabilir ve birazcık daha büyük bir özel karakter elde edebilirsiniz.
Yukarıda anllattıklarımızı açıklamak için şu aşağıdaki örneğe bakmak yerinde olacaktır.
Örneğin bir çan şekli oluşturmak istersek, aşağıdaki değerleri elde ederiz :
Aşağıda 5x8'lik bir LCD'nin tek bir hanesi görülüyor. Burada her bir satır için, açık renk gördüğümüz yerlere 0, koyu renk gördüğümüz yerlere ise 1 koyarak elde ettiğimiz binary sayıyı hex'e çeviriyoruz.





Oluşturduğumuz desende 8. satırı kullanmadık. 8. Satırı boş bırakmak için 0b00000 yazdık. Evet, artık CGRAM'a yazacağımız bilgileri oluşturduk. Artık ihtiyacımız olan tek şey, bunları CGRAM'a yazmak.  Öncelikle CGRAM'ın özel karakterler için ayrılmış 8 bölümünden hangisine yazacağımıza karar vermemiz gerekir. Aşağıdaki tabloda bu 8 karakterden her birinin başlangıç ve bitiş adresleri vardır



İmlecin CGRAM adresini işaret edecek şekilde komut yollamak için, 0x40+Acg formulünü kullanmamız gerekir. Detaylı bilgi için lütfen tablo 4'e bakınız. Oluşturduğumuz bu çan desenini, CGRAM'daki 2. Özel karakter alanına koymak istediğimizi var sayalım. Yukarıdaki tabloya bakarak, 2. özel karakter alanının adresinin (Acg) 0x08'den başladığını görürüz. O halde formülümüzü hatırlayalım, 0x40 + Acg. Yani LCD'ye ilk önce 0x48 (0x40 + 0x08) komutunu göndererek imlecin CGRAM'deki 2. Özel karakter alanının başlangıcını işaret etmesini sağlamalı, ardından da bu adrese koyacağımız ilk datayı yani oluşturacağımız özel karakterin en üst satırının karşılığı olan datayı (bizim örneğimizde 0x04) göndermeliyiz. Ardından satır 2, 3...8'in datalarını göndermeliyiz. Acg adresini 2. ve takip eden satırların datalarını göndermeden önce tekrar tekrar yollamamıza gerek yoktur. Zira bir kere başlangıç adresi verdikten sonra, her bir 1 byte'lık data geldikçe, adres sayacı da bir byte ilerlemektedir.
Aşağıda bir örnek kod vardır :

1.	;LCD Ports are same as discussed in previous sections
2.	 
3.	LCD_build:
4.	         mov   A,#48H         ;Load the location where we want to store
5.	         acall LCD_command    ;Send the command
6.	         mov   A,#04H         ;Load row 1 data
7.	         acall LCD_senddata   ;Send the data
8.	         mov   A,#0EH         ;Load row 2 data
9.	         acall LCD_senddata   ;Send the data
10.	         mov   A,#0EH         ;Load row 3 data
11.	         acall LCD_senddata   ;Send the data
12.	         mov   A,#0EH         ;Load row 4 data
13.	         acall LCD_senddata   ;Send the data
14.	         mov   A,#1FH         ;Load row 5 data
15.	         acall LCD_senddata   ;Send the data
16.	         mov   A,#00H         ;Load row 6 data
17.	         acall LCD_senddata   ;Send the data
18.	         mov   A,#04H         ;Load row 7 data
19.	         acall LCD_senddata   ;Send the data
20.	         mov   A,#00H         ;Load row 8 data
21.	         acall LCD_senddata   ;Send the data
22.	         ret                  ;Return from routine


Yukarıdaki asembly kod, çan deseninde bir karakteri CGRAM'ın 2. özel karakter bölümüne yazar. Oluşturulan bu özel karakteri ekrana bastırmak için, önce desenin lokasyonu (0,1,2...7) yüklenir, ardından LCD_senddata alt programı çağrılır.
Aynı programın C karşılığı da şöyledir :

1.	//LCD Ports are same as discussed in previous sections
2.	void LCD_build(){
3.		LCD_command(0x48);       //Load the location where we want to store
4.		LCD_senddata(0x04);      //Load row 1 data
5.		LCD_senddata(0x0E);      //Load row 2 data
6.		LCD_senddata(0x0E);      //Load row 3 data
7.		LCD_senddata(0x0E);      //Load row 4 data
8.		LCD_senddata(0x1F);      //Load row 5 data
9.		LCD_senddata(0x00);      //Load row 6 data
10.		LCD_senddata(0x04);      //Load row 7 data
11.		LCD_senddata(0x00);      //Load row 8 data
12.	}


Şu anda birçoğunuzun C ile program yazmanın asembly'den çok daha kolay olduğunu düşündüğünüzü biliyorum.  Yukarıdaki örnek, konuyu özetlemek amacıyla yazılmış basit bir kod parçasıydı ve pek te kullanışlı değildi. Şimdi aynı fonksiyonu, pointer ve dizi kullanarak daha kullanışlı bir hale getirelim :

1.	//Input:
2.	//     location: location where you want to store
3.	//               0,1,2,....7
4.	//     ptr: Pointer to pattern data
5.	//
6.	//Usage:
7.	//     pattern[8]={0x04,0x0E,0x0E,0x0E,0x1F,0x00,0x04,0x00};
8.	//     LCD_build(1,pattern);
9.	//
10.	//LCD Ports are same as discussed in previous sections
11.	 
12.	void LCD_build(unsigned char location, unsigned char *ptr){
13.	      unsigned char i;
14.	      if(location<8){
15.	          LCD_command(0x40+(location*8));
16.	          for(i=0;i<8;i++)
17.	             LCD_senddata(ptr[ i ]);
18.	     }
19.	 
20.	}



4 bit haberleşme moduna giriş :
Başlangıçtan buraya kadar konuştuğumuz her şey, LCD'nin 8 bitlik haberleşme (8 bit modu) ile bağlı olduğu duruma göre anlatıldı. Şimdiyse, LCD'nin 4 bit modda nasıl çalıştığını öğreneceğiz. LCD'nin bazen 8 bit yerine 4 bit ile haberleşmesinin birçok sebebi vardır. Bunlardan en önemlisi, LCD'yi bağladığımız MCU'daki 4 bacağı, başka amaçlarla kullanabilmek için boşa çıkartmaktır.
4 bit haberleşme modunda data, bir ascii karakteri oluşturan 8 bitlik byte'ın 4 + 4 şeklinde nibble'lara bölünmesiyle 2 aşamada gönderilir.  İlk aşamada üst nibble (byte'ın sol parçası), ardından da alt nibble (byte'ın sağ parçası) gönderilir.  LCD'ye kendisiyle 4 bit haberleşeceğimizi aşağıdaki adımları uygulayarak bildiririz. Aşağıdaki adımlar LCD reset olduktan sonra başlatılır.
•   20 ms kadar bekle,
•   İlk başlatma komutunu yolla (0x30),
•   10 ms kadar bekle,
•   İkinci başlatma komutunu yolla (0x30),
•   1 ms kadar bekle,
•   Üçüncü başlatma komutunu yolla (0x30),
•   1 ms kadar bekle,
•   Haberleşme modunu seç (8 bit için 0x30 ; 4 bit için 0x20),
•   1 ms daha bekle.
Meşgul bayrağı (BF) ancak bu aşamadan sonra okunabilir. 4 bit haberleşme modunda genellikle meşgul bayrağı (BF) kullanılmaz. Bunun yerine kodumuzu, LCD'ye gönderdiğimiz 2 nibble'ı geri okuyacak şeklinde yazarız. Yahutta daha basit olarak, her bir nibble yollama arasına 300 ila 600 us gecikme koyarız. Bu gecikmenin süresi kullandığımız LCD'ye göre değişiklik gösterir. Basitçe, LCD'yi sürerken problemle karşılaşırsanız, ilk olarak bu süreyi arttırmayı denemelisiniz. Süre arttırımı genellikle işe yarar. Bana göre 400 us mükemmel iş görmektedir.

4 bit haberleşme modunda LCD bağlantıları :



Yukarıdaki şekilde, LCD'nin 4 bit haberleşmesine ait bağlantı şeması görülüyor. Şemadan da açıkça görüldüğü gibi, LCD sadece 6 bacakla kontrol edilmektedir. Bunlardan D4, D5, D6, D7 bacakları LCD'nin data uçları; RS ve E uçlarıysa kontrol bacaklarıdır. Gene şemadan görüldüğü üzere RW ucunu kullanmıyoruz. Bu ucu LCD'yi yazma modunda tutmak amacıyla doğrudan GND'a bağlıyoruz. Eğer RW ucunu illa kullanmak isterseniz, bu ucu DND yerine MCU'nun bir portuna bağlamalısınız. Bu durumda MCU'dan bir bacak daha kullanmış olacaksınız ve programınız biraz daha karmaşık olacaktır. Fakat emin olun çok büyük bir fark göremeyeceksiniz. 4 bit haberleşme modunda, kullanılmayan D0...D3 bacakları da GND'a bağlanmalıdır.

4 bit haberleşme modunda LCD – MCU haberleşmesi :
Şimdi, LCD 4 bit haberleşme modundayken nasıl komut/data yollayacağımıza bakacağız. Önceden de söylediğimiz gibi, 4 modundayken MCU'dan LCD'ye gönderilen 1'er byte'lık bilgiler nibble nibble ikiye bölünerek gönderilir. İlk olarak üst nibble, ardından da alt nibble yollanır. Bunun anlamı, hem datalar, hem de komutlar nibble'lara bölünerek 2 aşamada yollanır. Bu işin adımları kabaca şöyledir:
•   Alt 4 biti maskele,
•   LCD portuna yolla,
•   Enable sinyalini yolla,
•   Üst 4 biti maskele,
•   LCD portuna yolla,
•   Enable sinyalini yolla,
İşin teori kısmı bu kadar. Bir sonraki bölümde, LCD'yi 4 bitle kontrol etmek için MCU'yu nasıl programlayacağımızı göreceğiz.

4 bit'le ilk çalışmaya hazırlama :
İlk çalışmaya hazırlama, reset işleminden sonra yapılabilir. Bunları zaten önceki bölümlerde konuşmuştuk.
Hadi şimdi programlama kısmına geçelim.
Her zamanki gibi öncelikle asembly :

1.	;In this whole 4-bit tutorial LCD is connected to
2.	;my controller in following way...
3.	;D4 - P3.0
4.	;D5 - P3.1
5.	;D6 - P3.2
6.	;D7 - P3.3
7.	;EN - P3.7
8.	;RS - P3.5
9.	 
10.		lcd_port equ P3         ;LCD connected to Port3
11.		en equ P3.7             ;Enable connected to P3.7
12.		rs equ P3.5             ;Register select to P3.5
13.		
14.	lcd_reset:                  ;LCD reset sequence
15.		mov lcd_port, #0FFH
16.		mov delay,#20           ;20mS delay
17.		acall delayms
18.		mov lcd_port, #83H      ;Data = 30H, EN = 1, First Init
19.		mov lcd_port, #03H      ;Data = 30H, EN = 0
20.		mov delay,#15           ;Delay 15mS
21.		acall delayms
22.		mov lcd_port, #83H      ;Second Init, Data = 30H, EN = 1
23.	 
24.		mov lcd_port, #03H      ;Data = 30H, EN = 0
25.		mov delay,#5            ;Delay 5mS
26.		acall delayms
27.		mov lcd_port, #83H      ;Third Init
28.	 
29.		mov lcd_port, #03H
30.		mov delay,#5            ;Delay 5mS
31.		acall delayms
32.		mov lcd_port, #82H      ;Select Data width (20H for 4bit)
33.	 
34.		mov lcd_port, #02H      ;Data = 20H, EN = 0
35.		mov delay,#5            ;Delay 5mS
36.		acall delayms
37.		ret
38.	 
39.	 
40.	lcd_init:
41.		acall lcd_reset         ;Call LCD Reset sequence
42.		mov a,#28H              ;4-bit, 2 line, 5x7 dots
43.	 
44.		acall lcd_cmd           ;Call LCD command
45.		mov a,#0CH              ;Display ON cursor OFF
46.		acall lcd_cmd           ;Call LCD command
47.		mov a,#06H              ;Set entry mode (Auto increment)
48.	 
49.		acall lcd_cmd           ;Call LCD command
50.		mov a,#80H              ;Bring cursor to line 1
51.		acall lcd_cmd           ;Call LCD command
52.		ret


Ve C eşdeğeri

1.	//The pins used are same as explained earlier
2.	#define lcd_port    P3
3.	 
4.	//LCD Registers addresses
5.	#define LCD_EN      0x80
6.	#define LCD_RS      0x20
7.	 
8.	void lcd_reset()
9.	{
10.		lcd_port = 0xFF;
11.		delayms(20);
12.		lcd_port = 0x03+LCD_EN;
13.		lcd_port = 0x03;
14.		delayms(10);
15.		lcd_port = 0x03+LCD_EN;
16.		lcd_port = 0x03;
17.		delayms(1);
18.		lcd_port = 0x03+LCD_EN;
19.		lcd_port = 0x03;
20.		delayms(1);
21.		lcd_port = 0x02+LCD_EN;
22.		lcd_port = 0x02;
23.		delayms(1);
24.	}
25.	 
26.	void lcd_init ()
27.	{
28.		lcd_reset();         // Call LCD reset
29.		lcd_cmd(0x28);       // 4-bit mode - 2 line - 5x7 font. 
30.		lcd_cmd(0x0C);       // Display no cursor - no blink.
31.		lcd_cmd(0x06);       // Automatic Increment - No Display shift.
32.		lcd_cmd(0x80);       // Address DDRAM with 0 offset 80h.
33.	 }


4 bit haberleşme modundayken LCD'ye komut/data yollama :

Assembly Program

1.	lcd_cmd:                  ;LCD command Routine
2.		mov temp,a            ;Save a copy of command to temp
3.		swap a                ;Swap to use higher nibble
4.		anl a,#0FH            ;Mask the first four bits
5.		add a,#80H            ;Enable = 1, RS = 0
6.		mov lcd_port,a        ;Move it to lcd port
7.		anl a,#0FH            ;Enable = 0, RS = 0
8.		mov lcd_port,a        ;Move to lcd port
9.	 
10.		mov a,temp            ;Reload the command from temp
11.		anl a,#0FH            ;Mask first four bits
12.		add a,#80H            ;Enable = 1
13.		mov lcd_port,a        ;Move to port
14.		anl a,#0FH            ;Enable = 0
15.		mov lcd_port,a        ;Move to lcd port
16.	 
17.		mov delay,#1          ;delay 1 ms
18.		acall delayms
19.		ret
20.	 
21.	lcd_dat:                  ;LCD data Routine
22.		mov temp,a            ;Keep copy of data in temp
23.		swap a                ;We need higher nibble
24.		anl a,#0FH            ;Mask first four bits
25.		add a,#0A0H           ;Enable = 1, RS = 1
26.		mov lcd_port,a        ;Move to lcd port
27.		nop
28.		clr en                ;Enable = 0
29.	 
30.		mov a,temp            ;Reload the data from temp
31.		anl a,#0FH            ;we need lower nibble now
32.		add a,#0A0H           ;Enable = 1, RS = 1
33.		mov lcd_port,a        ;Move to lcd port
34.		nop
35.		clr en                ;Enable = 0
36.	 
37.		mov delay,#1          ;Delay 1mS
38.		acall delayms
39.		ret


C eşdeğeri :

1.	void lcd_cmd (char cmd)
2.	{ 
3.		lcd_port = ((cmd >> 4) & 0x0F)|LCD_EN;
4.		lcd_port = ((cmd >> 4) & 0x0F);
5.	 
6.		lcd_port = (cmd & 0x0F)|LCD_EN;
7.		lcd_port = (cmd & 0x0F);
8.	 
9.		delayus(200);
10.		delayus(200);
11.	}
12.	 
13.	void lcd_data (unsigned char dat)
14.	{ 
15.		lcd_port = (((dat >> 4) & 0x0F)|LCD_EN|LCD_RS);
16.		lcd_port = (((dat >> 4) & 0x0F)|LCD_RS);
17.		
18.		lcd_port = ((dat & 0x0F)|LCD_EN|LCD_RS);
19.		lcd_port = ((dat & 0x0F)|LCD_RS);
20.	 
21.		delayus(200);
22.		delayus(200);
23.	}



Bitti.
Bu mektup icin hic agac kesmedim. Sadece elektronlari durtukledim.

kantirici

Bayağı uğraşmışsınız, teşekkürler.

Gökhan BEKEN

Güzel bir kaynak olmuş, teşekkür ederiz. Bende dün c18 ve xc8 dilleri için yazılım paylaşımı yapmıştım, konu açılmışken paylaşayım: http://gokhanbeken.com/lcd-kutuphanesic18-ve-xc8-icin
Özel mesaj okumuyorum, lütfen göndermeyin.

drozk

Yeni başlayan arkadaşlar için çok yararlı olacak bir kaynak olmuş.
Ellerinize sağlık.

Extreme

Çok emek verilmiş.
Güzel hazırlanmış bir kaynak olmuş.

Salih

Çok güzel bir çalışma olmuş.
Ellerine sağlık.

F.T

Hakk şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.