I2C LCD kullanımı

Başlatan alien876, 18 Temmuz 2017, 21:17:15

alien876

Merhaba arkadaşlar birşey danışmak istiyorum arduinoda i2c lcd modulü bulunuyor bunu pbp de kullanan varmı varsa arkadaşlar nasıl kullanıldığını anlatabilirmi yabancı forumlarda var fakat ingilizce eksikliğinden olayı anlayamadım hem benim gibi ihtiyacı olan arkadaşlarada yardım olur herkese kolay gelsin

bu linkde kütüphaneside bulunuyor
http://support.melabs.com/forum/picbasic-pro-compiler-3-0-and-later/pbp3-picbasic-pro-3-0/773-i2c-pcf8574-20x4-lcd

ete

Orada bulunan bir I2C LCD modül değildir. PCF8574 I2C, Bus genişletici olarak adlandırılan standart bir I2C port çoğaltıcısı diyebiliriz. Asıl kullanım alanı seri datayı parelel'e çevirmek. Bu sistemdeki kullanım amacı da  Paralel çalışan bir LCD yi seri yolla (I2C mantığı ile) kontrol etmek olmuş.

Bu sistemi iyi anlamak için kullandılan LCD nin data sheet'ini iyi incelemek ve bu LCD yi en azından standart LCD komutlarını kullanmadan kontrol etmeyi başarmak gerekir. Zira işin temelinde bu yatmaktadır. Verdiğin linkteki mesajları okudum. Genel anlamda bir I2C kontrol edresi problemi yaşandığı açıklanmış. Her bir I2C elemanı mutlaka bir kontrol adresine sahip olması gerekir. PCF8574 ün data sheet'inde bu adres değeri $40 olarak verilmiş. Ancak sürekli yaşanan haberleşme problemlerinden bahsedilmektedir. Zira PCF8574'ün iki ayrı versiyonu olduğu belirtilmiş birisi (A) versiyonu diğeride (A olmayan) versiyonu. Bu ikisi kontrol adresi açısından farklılıklar gösteriyormuş. Birisinde adres $40 olurken diğerinde $70 oluyormuş.
Onun dışında normal LCD kontrol işlemi diyebiliriz. Tabiiki bir diğer sıkıntı da 8 bitlik data ve kontrol değerlerinin 4'er bitlik iki ayrı parça (nibble) şeklinde LCD ye verilmesi sorunu. Elbette işi bu kadar basite indirgememek gerekiyor. LCD komutları olmadan işin kontrolünü yapmak için bir araba kod yazmak gerekiyor. Linkteki bahsi geçen kontrol mekanizması tamamen PBP3 derleyici temeline dayanmakta ve bu derleyicinin yeteneklerinden birisi olan ARRAYWRITE komutuna dayanmaktadır.
Bu komut dahilinde parametre olarak verilen birden fazla elemanın bir komutla LCD ye yollanması mümkün olabilmektedir.
ARRAYWRITE LCD_Buff,[$FE,$40,$00,$04,$0A,$04,$0E,$15,$0A,$11] komut satırına bakarsanız 10 adet elemanın bir seferde LCD ye yollandığını görebilirsiniz. Bu işi normal PBP derleyici ile yapmak isterseniz işiniz zor gerçekten. Ne kadar zor olduğunu tespit etmek için bile bir inceleme yapmak gerek.
Ama PBP3 temelinde verilen kütüphanede işler kolaylaşmış gözüküyor. Örnekle açıklamak gerekir ise;
Normal LCD komutları ile ;
LCDOUT $FE,Line2,"Count = ",DEC LoopCount,"   " şeklinde bir yazdırma komutu

ARRAYWRITE LCD_Buff,[$FE,Line2,"Count = ",DEC LoopCount,"   "]
şeklinde yazdırılabiliyor. İki komut arasındaki farka bakarsanız LCDOUT kalkmış yerine ARRAYWRITE LCD_Buff komutu gelmiş oluyor.

Ete



hasanemmii

#2
5 yıldır konuya yazan olmamış ama 900 civarında bakılmış. I2C ile lcd kullanımı PBP da kolayca kulanılamıyor sanırım. Ben de 16f886 ile devre tasarımı yaptığımda sonradan bir pine daha ihtiyaç oldu ve sadece 4 bit bağlı LCD yi IC2 ile kullanırsam pin elde edebiliyorum. Çok araştırdım düzenli bir örnek bulamadım. LCDOUT komutunu kolayca kullandığımız gibi IC2 nin bir kullanım şekli yok mudur arkadaşlar?

Hattuşa

proton plusda tek pinle 2x16,4x16 vb LCD ler kullanılabiliyor, PBP ve proton aynı sayılır, karmaşık bir kodunuz yoksa protona çevirip devam edebilirsiniz
https://etepic.com/index.php/topic,3469.msg44543.html#msg44543

hasanemmii

Bir ara çizgi izleyen robotla uğraşırken, pbp nin hesaplama eksikliğinden dolayı protonla çalışmıştım. Ben biraz daha uğraşacağım. Başaramazsam dediğiniz gibi protona bakayım.  Arduino ile bile çatır çatır Data ve Clock pinlerini kullanıp LCD ye hükmediyorlar. PBP ile nasıl kolayca yapılamıyor inanamıyorum. Cevap için teşekkürler.

ete

Daha önce açıklama yapmışım ama anlaşılmamış gözüküyor. Yeniden açıklayayım.
I2C bir seri haberleşme tekniğidir. Teknik komutlara dayanır. Komutun kullanım formatı aşağıdaki gibidir.
I2CREAD DataPin,ClockPin,Control,{Address,}[Var{,Var...}]{,Label}

Bu bir I2C okuma komutudur. Tek tek parametreleri açıklayacak olursak;
DataPin adı üzerinde Data bilgisinin verildiği yada alındığı işlemci yad I2C cihazının pini oluyor .
Aynı şekilde ClockPin de CLK pulsinin verildiği pin oluyor.
Control ise önemli bir parametre olup her bir I2C ile çalışan aletin bir Control adresi olmak zorunda. Bu sayede aynı Data ve Clok pinine bağlı birden fazla I2C cihazı olabiliyor. Kime yada kimden bilgi alınacağına verileceğine Control adresi ile karar veriliyor. Bu olmadan I2C haberleşmesi olamıyor maalesef.
Address, Cihaz içindeki hangi adrese ulaşılacağına işaret ediyor. Bir eprom düşünü onun hangi adresinden bilgi okuyacaksanız adres yerine o bilgiyi veriyorsunuz.
Ardından gelen Var lar değişkenleri ifade ediyor. Kaç bilgi okuyacaksanız o kadar da bilgi (değişken yada Var)olmalı.

I2CWRITE da aynı parametrelerle kullanılan yazma komutudur. Burada dikkat edilecek husus Control rakam değerinin sıfır nolu biti Okuma yada yazma yapılacağına işaret eder. Burada okuma yapılacağı zaman bu bit "1" yazma yapılacağı zaman ise "0" olmaktadır. Basic bu işi otomatik yapar. Sizin bit değiştirmeniz gerekmez. Siz hep aynı Control değerini kullanırsınız o derleme esnasında gereken biti 1 yada sıfır yapar. Buda önemli bir kolaylık.
I2C ile haberleşirken en çok yapılan hatalardan birisi genelde 7 bit olarak verilen Control byte değerinin yanlış olarak komuta yerleştirilmesi oluyor. 7 bit olarak verilen bilgi %xxxxxxx0 şeklinde veriliyor. Mesela diyorki Control =%1100100 dir. Bunun desimal karşılığı 100 dür.
BU sayıyı Control Byte değerine çevirmek için sonuna bir sıfır eklemeniz ve sonra sayıyı okumanız gerekiyor şöyle %11001000 bu sayının desimal değeri ise 200 oluyor. İşte şaşırtan kısım burası. Doğru değer 200 olmalıdır daima. Bu zyüden 7 bit olarak verilen Control değerlerine dikkat etmenizi öneririm.

Şimdi bu işin LCD ile olan alakasına tekrar bakalım. Normal LCD lerde 14 pin bulunur ve bu pinler sayesinde paralel haberleşme yapılır. LCD bir I2C cihazı değildir. Olması için ona bir chip eklenmeli. Chip I2C ile seri (2 pin) yoldan bilgi almalı ve bu bilgiyi paralel bilgiye çevirerek LCD pinlerine sanki İşlemci ile paralel haberleşiyormuş gibi vermelidir.
Bu şekilde hazırlanmış satılan Seri LCD ler mevcut bunu zaman zaman görüyorum. Ama nadiren kullanıldıkları için bulunması zor oluyor. Bir ara aramış bizim piyasada bulamamış idim. Şimdi varmıdır bilemiyorum. Bu durumda illa I2C ile LCD yi haberleştireceğim diye normal bir LCD yi I2C ile çalışacak hale getirmek çok mantıklı olmuyor. İşlemciyi değiştirip kullanmak daha ucuz ve mantıklı oluyor.
Olay bundan ibarettir.

Ete

hasanemmii

#6
Erol hocam zaman ayırmışsınız teşekkürler. Yazınızı büyük bir dikkatle okudum. Yazınızda önceden öğrenmiş olduğum kısımlar da var, bilmediğim kısımlar da var. Her yeni bilgi beni bir adım daha ileriye götürüyor.
Paralel çalışan lcd için ek elemanlarla uğraşmak yerine hazır PCF8574 çipli seri paralel  dönüştürücüler bol miktarda ve 12 TL civarında bulunabiliyor. 
16F876 kullanırken belki 1 pin yetersizliğinden 16F877 ye geçmek pek mantıklı olmuyor. Fiyat farkı neredeyse iki katı. Daha uygun pic ler de vardır belki. Ama LCD için neredeyse B portunun tamamını kaybetmek de bana mantıksız geliyor. Ayrıca LCD yi 12F675 de niye kullanmayalım diye düşünüyorum?
Tüm bunlar bir araya gelince I2C desteğiyle LCD yi kontrol edebilmek büyük avantaj olacaktır.
Her şey bir tarafa, seri haberleşmeyle LCD kontrolünü yapabilmeyi istiyorum. Takıntı gibi bir şey. Aralık ayında WS2812b şerit ledine taktım. Hiç bir yerde açıklayıcı ve yardımcı olacak doğru düzgün bir kod bulamadım. Ama WS nin datasheet ini dikkatli inceleyince ve yeterli OSC frekansı kullanınca, İsis yardımıyla da mikrosaniye değerlerini gözlemleyince işi çödüm ve 14 bant toplam 280 ledli müzik analizörümü tamamladım. Yani söylemek istediğim takıntı işi bende biraz sıkıntılı hocam. İşime yarasın yaramasın çözmem lazım yoksa rüyamda satırlar dolusu komut yazıyorum.
Şu an bunu çözmeye ve anlamaya çalışıyorum. Sanırım dediğiniz gibi öncelikle LCD çipini çözmek gerekecek.  LCD nin 4 pinine gidecek data hangi sırayla gönderilecek. Datalar gönderilince LCD nin işleme alması için  Enable ne zaman gönderilecek RS nin fonksiyonu tam olarak nedir? Örneğin A karakteri veya bir değişkenin değeri için nasıl bir data, kaç bit şeklinde gönderilecek. Bu haberleşme protokolüne uzak olduğum sanırım ortada. Bu nedenle yardım istedim. Sanırım bu konuda yardım bekleyen çok insan vardır. Ben hazır kod peşinde olanlardan değilim. Algoritma mantığım da sizin kadar olmasa da iyi sayılır. Yol gösterilsin, parçaları birleştirebilirim. Her şey için teşekkürler.

cemilsivas

S. A. Herkese hayırlı akşamlar. Yeni konu açıp forum kirliliği olmasın diye buradan devam etmek istedim. Ben de 16f628a kullanarak i2c modülü üzerinde lcd 16x2 çalıştırmak istiyorum. i2cwrite komutu kullanarak birşeyler denedim. Ama sonuç alamadım. İçinizde deneme yapıp başarabilen arkadaşlar var mı? Ya da Ete hocam bir yol gösterme imkanınız var mı? Forumdaki cevapları okudum. Ama sanırım basit örnek olmadan yapamayacağım gibi. En azından bir parçasından tutabilirsem devamını getirebilirim diye düşünüyorum. Ya da hiç uğraşma, 7 pin kullanacağın bir pic ile devam et derseniz de öyle devam edeyim. Şimdiden cevaplarınız için teşekkür ederim. Hayırlı akşamlar.

istinaf duvarı

#8
Alıntı yapılan: cemilsivas - 16 Aralık 2024, 23:18:18S. A. Herkese hayırlı akşamlar. Yeni konu açıp forum kirliliği olmasın diye buradan devam etmek istedim. Ben de 16f628a kullanarak i2c modülü üzerinde lcd 16x2 çalıştırmak istiyorum. i2cwrite komutu kullanarak birşeyler denedim. Ama sonuç alamadım. İçinizde deneme yapıp başarabilen arkadaşlar var mı? Ya da Ete hocam bir yol gösterme imkanınız var mı? Forumdaki cevapları okudum. Ama sanırım basit örnek olmadan yapamayacağım gibi. En azından bir parçasından tutabilirsem devamını getirebilirim diye düşünüyorum. Ya da hiç uğraşma, 7 pin kullanacağın bir pic ile devam et derseniz de öyle devam edeyim. Şimdiden cevaplarınız için teşekkür ederim. Hayırlı akşamlar.

Bunu kullanabilirsin. Kütüphaneyi çağırmadan  önce i2c ayarını yapıp, aşağıdaki gibi satır, sütun ve i2c slave adresini(8 bit olarak) belirtmelisin. Belirtmezsen varsayılan değerler aktif olur. (4x20 LCD, 0x4E adres) I2C pin isimlerini kullanacağınız pinlerle değiştirin.
 
#use i2c(Master,fast=100000,sda=PIN_B4,scl=PIN_B3, force_sw)
#define LCD_ADDR              0x4E        //I2C slave address for LCD module
#define lcd_total_rows        2           //Number of rows: 1,2,3 or 4
#define lcd_total_columns     16          //Number of columns: 1...20
#include <i2c_Flex_LCD.c>


//-----------------------------------------------------------------------------
	// Title:         i2c_Flex_LCD
	// Description:   Driver for common LCD with 1/2/3 or 4 rows by 1...20 columns
	//                using PCF8574T interface board with I2C protocol.
	// Date:          Nov-2013
	// Ver.Rev.:      1.1
	// Author:        Hugo Silva (sergio-hugo@bol.com.br) #Based on the routines of
	//                "20X4_LCD_I2C_DRIVER.h" from Pumrin S. and "lcd4_i2c.c" from XP8100
	//-----------------------------------------------------------------------------
	//
	// lcd_init() Must be called before any other function.
	//
	// lcd_putc(c) Will display c on the next position of the LCD.
	// 
	//     \f Clear LCD display
	//     \n Set write position on next lcd line
	//     \b LCD backspace
	//     lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1)
	//
	// lcd_backlight_led(ON)/lcd_backlight_led(OFF) = Turn ON/OFF LCD Backlight LED
	//
	//-----------------------------------------------------------------------------
	// LCD pins D0-D3 are not used.
	//-----------------------------------------------------------------------------
	//
	// Comment   : Control of a compatible LCD (1...4 rows by 1...4 columns) from
	//              a bus I2C with an EXPANDER of I/O with connection I2C.
	//              The tests of these routines have been programmed using the IC
	//              Phillips PCF8574T. I've used 4 bits mode programming.
	//              The 8 bits mode programming is possible if you use 2 x PCF8574T.
	//              RW Pin is not being used.
	//
	// As defined in the following structure the pin connection is as follows:
	//
	//  PCF8574P     LCD
	//  ========     ======
	//     P0        RS
	//     P1        RW    (Not used!)
	//     P2        Enable 
	//     P3        Led Backlight
	//     P4        D4
	//     P5        D5
	//     P6        D6
	//     P7        D7
	//
	//  The SCL and SDA pins should be pull-up resistor as shown below:
	//
	//             +5v
	//               |
	//               <
	//               > 4.7K       
	//               <         
	//To PIC         |          To i2c slave
	//pin xx ------------------ SDA pin 
	//(SDA)                     
	//              +5v
	//               |
	//               <
	//               > 4.7K       
	//               <         
	//To PIC         |          To i2c slave
	//pin xx ------------------ SCL pin 
	//(SCL)
	//
	//To PIC                    To i2c slave
	//Vss pin ----------------- Vss or ground pin 
	//                |
	//              -----
	//               ---  Ground
	//                - 
	// 
	// THIS DOCUMENT IS PROVIDED TO THE USER "AS IS"
	//-----------------------------------------------------------------------------
	#ifndef LCD_ADDR
	#define LCD_ADDR              0x4E        //Default I2C slave address for LCD module
	#endif
	#ifndef lcd_total_rows
	#define lcd_total_rows        4           //Default number of rows: 1,2,3 or 4
	#endif
	#ifndef lcd_total_columns
	#define lcd_total_columns     20          //Default number of columns: 1...20
	#endif    
	 
	#define RS                    0b00000001  //P0 - PCF8574T Pin connected to RS
	#define RW                    0b00000010  //P1 - PCF8574T Pin connected to RW
	#define ENABLE                0b00000100  //P2 - PCF8574T Pin connected to EN
	#define LCD_BACKLIGHT         0b00001000  //P3 - PCF8574T Pin connected to BACKLIGHT LED
	 
	#define addr_row_one          0x00        //LCD RAM address for row 1
	#define addr_row_two          0x40        //LCD RAM address for row 2
	#define addr_row_three        0x14        //LCD RAM address for row 3
	#define addr_row_four         0x54        //LCD RAM address for row 4
	 
	#define ON                    1
	#define OFF                   0
	#define NOT                   ~
	#define data_shifted          data<<4
	int8 new_row_request=1, BACKLIGHT_LED=LCD_BACKLIGHT;
	 
	void lcd_backlight_led(byte bl)
	{ 
	      If (bl) BACKLIGHT_LED=LCD_BACKLIGHT; else BACKLIGHT_LED=OFF;
	}
	 
	void i2c_send_nibble(byte data, byte type)
	{   
	   switch (type)
	   {     
	      case 0 :     
	      i2c_write(data_shifted | BACKLIGHT_LED);
	      delay_cycles(1);
	      i2c_write(data_shifted | ENABLE | BACKLIGHT_LED );
	      delay_us(2);
	      i2c_write(data_shifted & NOT ENABLE | BACKLIGHT_LED);
	      break;
	     
	      case 1 :
	      i2c_write(data_shifted | RS | BACKLIGHT_LED);
	      delay_cycles(1);
	      i2c_write(data_shifted | RS | ENABLE | BACKLIGHT_LED );
	      delay_us(2);
	     i2c_write(data_shifted | RS | BACKLIGHT_LED); //fix
	      break;
	   }
	} 
	   
	void lcd_send_byte(byte data, byte type)
	   {
	        i2c_start();
	        i2c_write(LCD_ADDR);
	        i2c_send_nibble(data >> 4 , type);
	        i2c_send_nibble(data & 0xf , type);
	        i2c_stop();       
	   }
	 
	void lcd_clear()
	{ 
	        lcd_send_byte(0x01,0);
	        delay_ms(2);
	        new_row_request=1;
	}
	 
	void lcd_init(void)
	{
	   byte i;
	   byte CONST lcd_type=2;  // 0=5x7, 1=5x10, 2=2 lines
	   byte CONST LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6}; // These bytes need to be sent to the LCD to start it up.
	 
	   disable_interrupts(GLOBAL);
	   delay_ms(50); //LCD power up delay
	   
	   i2c_start();
	   i2c_write(LCD_ADDR);
	      i2c_send_nibble(0x00,0);
	      delay_ms(15);
	   
	   for (i=1;i<=3;++i)   
	   {
	      i2c_send_nibble(0x03,0);
	      delay_ms(5);
	   }   
	      i2c_send_nibble(0x02,0);
	      delay_ms(5);
	   i2c_stop();
	   
	   for (i=0;i<=3;++i) {
	   lcd_send_byte(LCD_INIT_STRING[i],0);
	   delay_ms(5);
	   }
	   lcd_clear();  //Clear Display
	   enable_interrupts(GLOBAL);
	}
	 
	void lcd_gotoxy( byte x, byte y)
	{
	byte row,column,row_addr,lcd_address;
	static char data;
	 
	   if (y>lcd_total_rows) row=lcd_total_rows; else row=y;
	 
	   switch(row)
	   {
	      case 1:  row_addr=addr_row_one;     break;
	      case 2:  row_addr=addr_row_two;     break;
	      case 3:  row_addr=addr_row_three;   break;
	      case 4:  row_addr=addr_row_four;    break;
	      default: row_addr=addr_row_one;     break; 
	   } 
	   
	   if (x>lcd_total_columns) column=lcd_total_columns; else column=x; 
	   lcd_address=(row_addr+(column-1));
	   lcd_send_byte(0x80|lcd_address,0);
	}
	 
	//Display the character on LCD screen.
	void LCD_PUTC(char in_data)
	{   
	  switch(in_data)
	   { 
	     case '\f': lcd_clear();                       break;               
	     
	     case '\n':
	     new_row_request++;
	     if (new_row_request>lcd_total_rows) new_row_request=1;
	     lcd_gotoxy(1, new_row_request);
	     break;
	                 
	     case '\b': lcd_send_byte(0x10,0);             break;
	       
	     default: lcd_send_byte(in_data,1);            break;     
	     
	   }
	} 

ete

Bu işin zor olduğunu en baştan söylemem gerek. Zorluk LCD üzerinde yer alan Chip'in kontrol mekanizmasından geliyor. Bu işi başarabilmenin yolu da bu Chip'in çalışma şeklini çözmekten geçiyor.
Açıkçası ben LCD nasıl çalışır diye daha önce pek uğraşmadım. ELimizde derleyicinin kendi içinde çözmüş olduğu LCD komutları bulunuyor ve onları kullanmayı tercih ettim daima.
Bu nedenle sana pek fazla bilgi verebileceğimi sanmıyorum. İşin detayları hakkıında biraz daha bilgi edinmek istersen aşağıdaki linkte yer alan LCD içindeki Chip'e ait data sheet'i incelemeni öneririrm.

https://www.sparkfun.com/datasheets/LCD/HD44780.pdf

Bütün iş burada. Register kontrollerine bakarsan ;
- Ekran nasıl temizlenir,
- Ekrana nasıl karekter yerleştirilir
- Karekter pozisyonları nasıl adreslenir
öğrenebilirsin. Bunları bilirsen gerisi 2 tane haberleşme pini kullanarak I2C ile LCD ye komut iletebilirsin. Oda komuta göre ne yapılacağına karar verip yapar.
Bir şey daha ekleyeyim. İşin blok şemasına da bakacak olursak, İşlemciden 2 pin ile çıkacaksın ve bir başka işlemciye gireceksin. Bu işlemci senin yolladığın I2C bilgisini (seri haberleşme bilgisi) alıp onu paralel bilgiye çevirecek ve bu bilgiyi LCD bacaklarına iletecek. Sonuçta bir I2C modülün olmalı bu modül gelen komutları paralel bilgiye çevirerek LCD ye vermeli hepsi bu söylemesi çok kolay ama uygulaması gerçekten zor olan bir iş.


Ete

istinaf duvarı

#10
Yukarıdaki kod için örnek deneme dosyası.
#include <16F628A.h>
#use delay(crystal=8000000)
#use i2c(Master,fast=100000,sda=PIN_B4,scl=PIN_B3, force_sw)
   #define LCD_ADDR              0x70        //I2C slave address for LCD module
   #define lcd_total_rows        2           //Number of rows: 1,2,3 or 4
   #define lcd_total_columns     16          //Number of columns: 1...20
   #include <i2c_Flex_LCD.c>

void main()
{
lcd_init();
delay_ms(100);
lcd_gotoxy(1,2);
lcd_putc("etepic.com");
int i=0;
   while(TRUE)
   {
   lcd_gotoxy(1,1);
lcd_putc("deneme    ");
 lcd_gotoxy(8,1);  
printf(lcd_putc,"%d",i);
delay_ms(200);
i++;
if (i==100) i=0;


      //TODO: User Code
   }

}


cemilsivas

Eyvallah hocam. Cevap için çok teşekkür ederim. Ama ben uzun yıllardır picbasic ile uğraşıyorum. Ufak tefek c ile de programlar yazdım ama programım sanırım yine pbasic olacak. Gönderdiğiniz kütüphaneyi inceleyim denemeler yapayım.

cemilsivas

@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _LVP_OFF & _CP_OFF
'DEFINE I2C_HOLD 1
DEFINE  OSC            4
DEFINE I2C_SLOW 1

OPTION_REG.7 = 0
SCL      VAR PORTB.1
SDA      var PORTB.0
LCD_Addr CON 78
'LCD_BuffSize    CON 30
'LCD_Buff        VAR BYTE[LCD_BuffSize]
'LCD_BuffAddr    CON EXT : @LCD_BuffAddr = _LCD_Buff
'LCD_BuffLen    VAR WORD        ; Length of data in buffer
LCD_Data        VAR BYTE        ; Data to Send to LCD
LCD_Byte        VAR BYTE        ; Nibbles to Send
LCD_RS          VAR LCD_Byte.0  ; Register Select bit
LCD_RW          VAR LCD_Byte.1  ; Read/Write bit
LCD_E          VAR LCD_Byte.2  ; Enable bit
LCD_BackLight  VAR LCD_Byte.3  ; Backlight 0=ON
LCD_WriteMode  VAR BYTE        ; 1=LowNibble, 2=HighNibble, 3=Both
LCD_CommandMode VAR BIT        ; Indicates next byte is a command
LCD_Byte2      VAR BYTE        ; Same nibble without E bit
LCD_Idx        VAR BYTE
testmode        var byte



;----[Initialize the LCD]-------------------------------------------------------
PAUSE 250            ; LCD Power-on delay
LCD_Backlight = 1    ; Backlight OFF
LCD_RW = 0            ; Write to LCD
LCD_RS = 0            ; Command Register

LCD_WriteMode = 1    ;-- Low Nibbles only
LCD_Data = 3          ; Reset 3 times
gosub LCD_Write_
PAUSEUS 6000
gosub LCD_Write_
PAUSEUS 1000
gosub LCD_Write_
PAUSEUS 1000

LCD_Data = 2          ; Start 4-bit mode
gosub LCD_Write_
PAUSEUS 1000

LCD_WriteMode = 3    ;-- Both Nibbles
LCD_Data = $28
gosub LCD_Write_      ; Function Set, 4-bit, 2-line, 5x7
LCD_Data = $0C
gosub LCD_Write_      ; Display ON
LCD_Data = $01
gosub LCD_Write_      ; Clear Screen
PAUSE 2
LCD_Data = $06 
gosub LCD_Write_      ; Entry Mode
                      
PAUSE 2              ; Let command finish
LCD_RS = 1  ' this is data
goto main

LCD_WRITE_:
  LCD_E = 1
  IF LCD_WriteMode.1 = 1 THEN                            ; Write High Nibble
    LCD_Byte = (LCD_Byte & $0F) | (LCD_Data  & $F0)
    LCD_Byte2 = LCD_Byte & $FB    
    I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte, LCD_Byte2]
  ENDIF
  
  IF LCD_WriteMode.0 = 1 THEN                            ; Write Low Nibble
    LCD_Byte = (LCD_Byte & $0F) | ((LCD_Data << 4 )& $F0)
    LCD_Byte2 = LCD_Byte & $FB
    I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte, LCD_Byte2]
  ENDIF
return

Main:
LCD_Backlight = 0
LCD_Data = "T"
gosub LCD_Write_: PAUSEUS 50
LCD_Data = "e" 
gosub LCD_Write_: PAUSEUS 50
LCD_Data = "s" 
gosub LCD_Write_: PAUSEUS 50 
LCD_Data = "t" 
gosub LCD_Write_: PAUSEUS 50 
pause 500
LCD_Backlight = 1
LCD_Data = "-" 
gosub LCD_Write_: PAUSEUS 50 
pause 500
goto main
Hayırlı geceler. Bu kodu yabancı bir siteden buldum. Ete hocamın dediği gibi lcd'deki registerleri tek tek ayarlamış ve harfler basmış. Yalnız anlamadığım taraf yazdırma bölümü oldu. Buradaki arkadaş harfleri teker teker bastırmış. İkinci olarak da
LCD_WRITE_:
  LCD_E = 1
  IF LCD_WriteMode.1 = 1 THEN                            ; Write High Nibble
    LCD_Byte = (LCD_Byte & $0F) | (LCD_Data  & $F0)
    LCD_Byte2 = LCD_Byte & $FB    
    I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte, LCD_Byte2]
  ENDIF
  
  IF LCD_WriteMode.0 = 1 THEN                            ; Write Low Nibble
    LCD_Byte = (LCD_Byte & $0F) | ((LCD_Data << 4 )& $F0)
    LCD_Byte2 = LCD_Byte & $FB
    I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte, LCD_Byte2]
  ENDIF
return
buradaki low nibble ve high nibble olayı oldu. Ekrana harf bastırmanın prosedürü böyle ise bayağı karışık söylediğiniz gibi. Eğer farklı bir durum varsa açıklayabilirseniz sevinirim.

onurinci

şu adreste bir basic örnek buldum, İnclude dosya ve örnek vermiş, ama ne yaptımsa text olarak alamadım , gelen text'in içinde HTML komut parçaları bulaşıyor


.

https://support.melabs.com/forum/picbasic-pro-compiler-3-0-and-later/working-code-examples/6763-example-code-i2c-lcd-character-displays

Pepe

#14
Proteus simulation in proton

Powered by EzPortal