CCS Ile Degisik Port ve Pinlerden LCD Kullanimi

Başlatan birumher, 20 Nisan 2004, 16:53:01

birumher

CCS e daha doğrusu C ile Pic programı geliştirmeye yeni başladım ancak bir türlü standart olmayan portlardan LCD ye veri gönderip yazdırmanın nasıl olacağını bulamadım. Compiler ın driver bölümünde lcd.c adlı dosyanın içinde aşağıdaki gibi commentler var. Buradan D portundan kullanacağımız ve pinlerin de 0,1,2 datalar için de 4,5,6,7 olduğunu görüyoruz ancak örneğin ben,
RS i D2
Enable ı D3
RW yi C1 yapacaksam neleri değiştirmem lazım? Bilen var mı?
Bana sanki Data yı ayrı porttan kontrolü ayrı porttan yapamazmışız gibi geldi buradaki kodlardan...

// As defined in the following structure the pin connection is as follows:
//     D0  enable
//     D1  rs
//     D2  rw
//     D4  D4
//     D5  D5
//     D6  D6
//     D7  D7
//
//   LCD pins D0-D3 are not used and PIC D3 is not used.

// Un-comment the following define to use port B
// #define use_portb_lcd TRUE


struct lcd_pin_map {                 // This structure is overlayed
          boolean enable;           // on to an I/O port to gain
          boolean rs;               // access to the LCD pins.
          boolean rw;               // The bits are allocated from
          boolean unused;           // low order up.  ENABLE will
          int     data : 4;         // be pin B0.
       } lcd;
Birkan.Herguner

Erkan Gench

driver'da lcdnin bağlı olduğu portu tanımlamak için bir structure kullanılmış. programın tüm mantığı lcd'nin bir tek porta bağlanması üzerine. yani portun birinde bir uç diğerinde başka uç kullanmak mevcut programla mümkün değil. ama isterseniz
// Un-comment the following define to use port B
// #define use_portb_lcd TRUE

satırlarında // #define use_portb_lcd TRUE'nin başındaki // işaretlerini kaldırarak lcd'yi b portunda kullana bilirsiniz.

yok ben illaki dediğim gibi olsunistiyorum diyorsanız programda lcd'nin herbir ucu için bir isim tanımlayıp (mesela enable ucu için #define enable port_c5 gibi) daha sonra kodda kullanılan lcd.enable=0 gibi ifadeler yerine enable=0 yazarak bunu yapabilirsiniz sanırım. tabi kullandığınız uçlar için trislerin ayarlanması falanda var. biraz uğraşmanız lazım yani.
Zorluklar, zamanında yapmamız gerekip de yapmadığımız kolay şeylerin birikmesiyle oluşur. Henry Ford ----------- Ya Rabbi Filistin'deki ve dünyanın her tarafındaki Müslüman kardeşlerime yardım et.

ise

struct lcd_pin_map {
boolean unused:1;             //d.0;
boolean unused1:1;           //d.1
boolean rs:1;                   //d.2
boolean enable:1;            //d.3
int data : 4;
} lcd;
#byte lcd=PORTD adresi

rw yi ayrı ayağa ayırman için lcd.rw yazan kısımlarıda lcd1.rw ile değiştirmen gerekir

struct lcd_pin_map1 {
boolean unused:1;             //c.0;
boolean rw:1;                   //c.1;
} lcd1;
#byte lcd1=PORTC adresi

birumher

sağolun en sonunda o kadar uğraşmaktansa kendi kodumu ve devre şemasını değiştirip yapmaya karar verdim hem böylece daha standart olur ...
Birkan.Herguner

ise

devreyi buna göre ayarlaman tabi iyi olmuş fakat bunlarda alıştırma olurdu

DumrulBey

Merhaba,

Thief dostum verdiğin bilgiler çok iyi olmuş. Arkadaş kendi çözümünü getirmiş olsa da benim gibi geriden yetişen programlayıcılar için güzel kodlar. Bir başka başlıkta tartışmaya açtığım 74HC595'li LCD kullanımı yapabilsem ne iyi olurdu.

Teşekkürler...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)

softheart

Dostum onu ben P16F84 lü devremde 4094 ile yaptım ve gayet sağlıklı çalışmıştı. ancak arkadaşlara önerim busy flag kontrolünü önemsemeleri. çünkü normal döngü süreleri her markada tutmuyor. ama komutları gönderme işleminde bussy flag kontrol edilince o problem ortadan kalkıyor.Ancak D7 pini ile şase arasına 10K atmayı unutmamalı busy flağı kullanırken.

Saygılar

jeopardy

arkadaslar bi devre yaptım. bu devre de programlama ile hallederiz hesabı ile lcd ye giden ayakların bazıları farklı portlarda benimkinde de. bende 18f8520 nini d portundan d0..d7 data lar, j0 a rs, rw yi e7 ye,  E yide e6 ya baglamışım. hazır lcd.c de 4 bitlik ve b portunda bılıyorsunuz. yukarda bahsedılen gıbı farklı struct lar altında dıger portlardaki ayakları girdim ama sonuc alamadım. bi compıle edebılseydım proteus da iyi olcaktı ama 8 bit için bifikriniz var mı? hazır dosyada degısmesı gerekenler neler ?neler eklemelıyım ayrıca? şimdiden sagolun.

Erkan Gench

Merhaba zamanında şu kodu yazıp kullanmıştım. Çok temiz bir kod değil ama çalışıyor.

#define enable	PIN_D7
#define rs		PIN_D5
#define rw		PIN_D6

#define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40    // LCD RAM address for the second line


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.


                             // The following are used for setting
                             // the I/O port direction register.

set_tris_b(0);
set_tris_d(0);

void lcd_send_nibble( BYTE n ) {
      output_b(n<<4);
      delay_cycles(1);
      output_high(enable);
      delay_us(2);
      output_low(enable);
}


void lcd_send_byte( BYTE address, BYTE n ) {

      output_low(rs);
      delay_us(10);
      if(address)
			output_high(rs);
		else
			output_low(rs);
      delay_cycles(1);
      output_low(rw);
      delay_cycles(1);
      output_low(enable);
      lcd_send_nibble(n >> 4);
      lcd_send_nibble(n & 0xf);
}


void lcd_init() {
    BYTE i;
    output_low(rs);
    output_low(rw);
    output_low(enable);
    delay_ms(15);
    for(i=1;i<=3;++i) {
       lcd_send_nibble(3);
       delay_ms(5);
    }
    lcd_send_nibble(2);
    for(i=0;i<=3;++i)
       lcd_send_byte(0,LCD_INIT_STRING[i]);
}


void lcd_gotoxy( BYTE x, BYTE y) {
   BYTE address;

   if(y!=1)
     address=lcd_line_two;
   else
     address=0;
   address+=x-1;
   lcd_send_byte(0,0x80|address);
}

void lcd_putc( char c) {
   switch (c) {
     case '\f'   : lcd_send_byte(0,1);
                   delay_ms(2);
                                           break;
     case '\n'   : lcd_gotoxy(1,2);        break;
     case '\b'   : lcd_send_byte(0,0x10);  break;
     default     : lcd_send_byte(1,c);     break;
   }
}


üstteki define'larla  hatların konumunu belirleyin kod içerisindeki output_b() komutu yerine bağladığınız portun ismini yazın. tabi kod içindeki tris'leride uygun şekilde değiştirmeniz lazım. aslında rw hattıda kullanılmıyor direk şaseye bağlasanızda olur.

kod 4 bite göre yazılmış 8 bite çevirmek için biraz uğraşmak lazım. peki ama neden 8 bit istiyorsuzki fazladan 4 hat kullanmaktan başka pek bir işe yaramıyor bence.
Zorluklar, zamanında yapmamız gerekip de yapmadığımız kolay şeylerin birikmesiyle oluşur. Henry Ford ----------- Ya Rabbi Filistin'deki ve dünyanın her tarafındaki Müslüman kardeşlerime yardım et.

Göktuğ

Devreyi ben tasarladım 8 bit baglantı  yapmıstım.Fakat yazılım kısmıyla ugrasmaya basladıktan sonra gordumki 4 bit yeterli imiş. Bu cok sorun değil bir dahaki sefere 4 bit baglayacagım.
Su an için durum 18f8520 ve glcd devrede bulunmakta. port d uzerinden data hatı baglı.
A portundan 5 adet kontrol biti kullandım.A0, cs1, (cs2yi kullanmamıstım sorun cıkarmı ?), CL, E, R/W. reset ucunuda J0 dan aldım.
baya dagınık oldu ama portlarda yer kalmamıstı.
glcdyi 4 bitte surebilirim ama diger kontrol bitlerinin tanıtılması gerekmekte.
Daha yeni basladıgımızdan programlama olaylarına zorlanıyoruz.glcdnin init fonksiyonu nasıl olacak? ve lcdnin pdfinde karakterler için tek tek tablo halinde kodlar vermiş.Yeni bir driver dosyası yazmamızmı gerekiyor?

Erkan Gench

Ortalık biraz karışmış. Şimdi elimizde bir goktug1217 var birde jeopardy var. Ayrıca işin içine glcd karışmış.

Şimdi konuları açıklığa kavuşturalım burada bahsettiğimiz LCD karakter LCD sizin bahsettiğiniz Grafik LCD ise durum tamamen farklı olur. Ayrıca jeopardy ve goktug1217 aynı kişimi?
Zorluklar, zamanında yapmamız gerekip de yapmadığımız kolay şeylerin birikmesiyle oluşur. Henry Ford ----------- Ya Rabbi Filistin'deki ve dünyanın her tarafındaki Müslüman kardeşlerime yardım et.

jeopardy

ben Ali. aynı şırkette calısıyoruz goktug la. pcb yi ve sema baglantılarını goktug a yaptırmıştık. fakat glcd yi tam incelememiş sanırım. o yuzden cs2 baglantısını devrede baglamamış. fakat uretılmış olmasına ragmen bız bunu bi şekilde baska bi port ayagından baglayabılırız lcd ye.

graphic lcd için aslında dün C18 e geçmeye karar verdik. hem ögrenıp hem yapmak işi biraz zorluyor dogal olarak. konuyu anlatırken saçma gelen tanımlamalar yapıyosak bu konudaki acemiligimizden kaynaklanıyor kusurumuza bakmayın.

baglantıları sayıyım tekrardan. lcd nin data ayakları D0...D7 pic in d portunu kaplamış durumda. Enable ucu E6 portuna, RW ucu E7 portuna, Reset ucu J0 portuna, CS1 ucu E4 portuna, CS2 ucu H7 portuna(sonradan duzeltıcem pcb de),A ucu(data/instruction input) E3 portuna baglı şu anda.

dünkü arastırmalarımda C18 de graphic lcd için bazı sonuclara yaklaştım ama font için bir hata verdi. bir sonraki mesajımda bunu gösterecegim ama CCS altında C18 yazmam ne kadar dogru olur bilmiyorum.bunun için baska bir topic te acabilirim daha sonra.

jeopardy

glcd.h

#include <p18f8520.h>
#include <delays.h>
#define LCD_TRIS      TRISD
#define LCD_DATA      PORTD
#define ENABLE        PORTEbits.RE6
#define RW            PORTEbits.RE7
#define DI            PORTEbits.RE3
#define RESET         PORTJbits.RJ0
#define CS1           PORTEbits.RE4
#define CS2           PORTHbits.RH7 
#define LEFT          0b01
#define RIGHT         0b10
#define BOTH          0b11
#define NONE          0b00
// internal function prototypes
// 
// you would not normally call these directly. but you can 
// if you like.

void _lcd_enable(void);
unsigned char _lcd_status(void);
void _lcd_reset(void);
void _lcd_waitbusy(void);
// public function prototypes
//
// call these all you want !
void lcd_screenon(unsigned char on);
void lcd_cls(void);
void lcd_setpage(unsigned char page);
void lcd_setyaddr(unsigned char y);
void lcd_selectside(unsigned char sides);
void lcd_write (unsigned char data);
unsigned char lcd_read (void);
void lcd_plotpixel(unsigned char rx, unsigned char ry);
void lcd_putchar(char c);
void lcd_puts(char *string);
void lcd_putrs(const rom char *string);

jeopardy

asagıdaki duzenlemeye çalıştıgım c18 ile yazılmış programda renkli yerde bir sorun var sanırım. font olarak istedigi şeyi nasıl gösterecegim o kısımda yardımcı olursanız sevinirim. fontla ilgili hazır linkler var.
http://www.geocities.com/dinceraydin/lcd/gfxhowto.htm

glcd.c

#include <p18f8520.h>
#include <glcd.h>

const rom char font[]= {[color=red]0,24,60,60,60,24,24,0,24,24,0,0[/color]};
void _lcd_enable(void)
{    
Delay10TCYx(1);    
ENABLE=1;    
Delay10TCYx(1);    
ENABLE=0;    
Delay10TCYx(1);
}
unsigned char _lcd_status(void)
{    
// returns the lcd status & maintains the TRIS state of the    
// lcd data port

unsigned char _lcd_tris, _status;

    // save the tris value    
_lcd_tris = LCD_TRIS;

    // read the status    
LCD_TRIS=0xFF; // all inputs
    DI=0; RW=1; // command/read

    _lcd_enable();    
_status = LCD_DATA;

    // restore the tris value    
LCD_TRIS = _lcd_tris;

        return _status;
}
void _lcd_reset(void)
{    
// reset the lcd module    
// datasheet says reset must be low for minimum of 1us
    // after Vdd clears 4.5v. 
    // from experimentation, this is bullshit. this seems to    
// work though.
    Delay10TCYx(250); // actually .5 ms    
RESET=1;    
Delay10TCYx(250); // actually .5 ms
    RESET=0;
    // check status, and wait if necessary    
while (_lcd_status() & 0b00010000)    
{        
Delay10TCYx(250); // .5 ms
    }
}
void lcd_screenon(unsigned char on)
{    
// turn the display on or off    
LCD_TRIS=0; // all outputs    
RW=0; DI=0;
    LATB = 0b00111110 | (on & 0b00000001); // main screen turn on!    
_lcd_enable();
}
void lcd_cls(void)
{    
unsigned char x,y;
    for (x=0; x<8; x++)    
{       
 // set the page (x)        
lcd_setpage(x);        
// set the y address to 0        
lcd_setyaddr(0);
        // setup for data        
LCD_DATA=0; RW=0; DI=1;
        // clear the row        
for (y=0; y<64; y++)        
{            
_lcd_enable();             
//Delay10TCYx(1);        
}    
}
}

void lcd_setpage(unsigned char page)
{    
_lcd_waitbusy();    
DI=0; RW=0;     
LCD_DATA = 0b10111000 | page;    
_lcd_enable();}

void lcd_setyaddr(unsigned char y)
{    
_lcd_waitbusy();
    DI=0; RW=0;
    LCD_DATA = 0b01000000 | (y & 0b00111111);    
_lcd_enable();
}

void _lcd_waitbusy(void)
{    
while (_lcd_status() & 0b10000000)
    {        
Delay10TCYx(250); // .5 ms    
}
}

void lcd_write (unsigned char data)
{    
_lcd_waitbusy();    
DI=1; RW=0;    
LCD_TRIS=0;     
LCD_DATA = data;    
_lcd_enable();
}

void lcd_selectside(unsigned char sides)
{    
// set a CS pin low to enable it    
if (sides & LEFT)        
CS1 = 0;    
else        
CS1 = 1;
    if (sides & RIGHT)        
CS2 = 0;    
else        
CS2 = 1;
}

unsigned char lcd_read (void)
{    
unsigned char _data;        
LCD_TRIS=0xFF;    
RW = 1; DI=1;

    _lcd_enable();    
_data = LCD_DATA;    
LCD_TRIS=0x00;
    return _data;
}
void lcd_plotpixel(unsigned char rx, unsigned char ry)
{    
unsigned char data;

    //lcd_waitbusy();
    // select the correct side    
if (rx & 64)        
lcd_selectside(RIGHT);    
else        
lcd_selectside(LEFT);

     lcd_setpage( ry >> 3);    
lcd_setyaddr( rx & 0b00111111);
    data = lcd_read(); // dummy read needed here    
data = lcd_read();

    lcd_setyaddr( rx & 0b00111111);     
lcd_write (data | (1 << (ry & 0b111)));
}

 void lcd_putchar(char c)
{    
int base;    
base = c - 32;    
base *= 3;

    lcd_write(font[base]);    
lcd_write(font[base + 1]);    
lcd_write(font[base + 2]);    
lcd_write(0);
}
void lcd_putrs(const rom char *string)
{    
char i=0;   
 while (string[i] != 0)       
 lcd_putchar(string[i++]);
} 
void lcd_puts(char *string)
{    
char i=0;
    while (string[i] != 0)       
 lcd_putchar(string[i++]);
}

aster