Bu uygulamamızda 5
tane kod dosyamız var. Daha doğrusu kodların okunurluğunu artırmak ve sizi olası hatalardan korumak maksadıyla kod dosyalarımızı ayrı ayrı dosyalarda oluşturduk. Bu daha profesyonel kod yazmanıza imkân sağlayacaktır.
“Delay.h” başlık dosyamız
//
16F877A için delay fonksiyonu tanımlaması
//
Bu ms_bekle 168877a 4 Mhz frekansı için ayarlanmış bir
fonksiyondur
typedef
unsigned short int uint16_t;
void
ms_delay(uint16_t milisaniye)
{
uint16_t
i,j;
for
(i = 0; i < milisaniye; i++)
{
//
Döngüde optimizasyon için bu asm komutu eklenmiştir.
for
(j=0; j < 46; j++)
__asm
nop __endasm;
}
}
//
Bu fonksiyon her döngüde 20 us (mikrosaniye) gecikme sağlar
void
us_delay_20(uint16_t usDegerx20)
{
uint16_t
i;
for
(i = 0; i < usDegerx20; i++) //her döngü adımı yaklaşık 20
us
{
//
Döngüde optimizasyon için bu asm komutu eklenmiştir.
__asm
nop __endasm;
}
}
“bizim_lcd.h” başlık dosyamız
/*
Durali Kiraz 2015
*
www.duralikiraz.blogspot.com
*
*
D4,D5,D6,D7 pinlerini kullanarak 4 bit iletişim kullanır.
*
Cursor kapalıdır.
*
RW kullanılmadığı için direk toprağa bağlanabilir.
*
2x16 LCD Kullanım Klavuzu
*
*
lcd_baslat(); ile LCD'nin ilk ayarlarını yap
*
lcd_ekranisil(); ile LCD'yi sil
*
lcd_yaz("deneme"); Şeklinde yazı yazdır.
*
veri_yolla('F'); Şeklinde tek ascii kodu yazdır.
*
lcd_konumlanxy(1,13); Şeklinde LCD'nin istenilen yerine git.
*
*
*/
#define rs
RC0 //Pin tanımlamaları
#define rw RC1
#define e
RC2
#define
lcd_port PORTB
/*
LCD'de kullanilan komutlarin tanimlamasi*/
#define
Sil 1 // Ekrani temizler
#define
BasaDon 2 // Imleci sol üst köseye getirir
#define
SolaYaz 4 // Imlecin belirttigi adres azalarak gider
#define
SagaYaz 6 // Imlecin belirttigi adres artarak gider
#define
ImlecGizle 12 // Göstergeyi ac, kursor görünmesin
#define
ImlecAltta 14 // Yanip sönen blok kursor
#define
ImlecYanSon 15 // Yanip sönen blok kursor
#define
ImleciGeri 16 // Kursoru bir karakter geri kaydır
#define
KaydirSaga 24 // Göstergeyi bir karakter sağa kaydır
#define
KaydirSola 28 // Göstergeyi bir karakter sola kaydır
#define
EkraniKapat 8 // Göstergeyi kapat (veriler silinmez)
#define
BirinciSatir 128 // LCD'nin ilk satir başlangıç adresi
//
(DDRAM adres)
#define
IkinciSatir 192 // İkinci satirin başlangıç adresi
#define
KarakUretAdres 64 // Karakter üreteci adresini belirle
//
(CGRAM adres)
/*
LCD'de Kullanilan Fonksiyon Seçimi */
#define
CiftSatir8Bit 56 // 8 bit ara birim, 2 satir, 5*7 piksel
#define
TekSatir8Bit 48 // 8 bit ara birim, 1 satir, 5*7 piksel
#define
CiftSatir4Bit 40 // 4 bit ara birim, 2 satir, 5*7 piksel
#define
TekSatir4Bit 32 // 4 bit ara birim, 1 satir, 5*7 piksel
extern
void veri_yolla(unsigned char);
extern
void lcd_ekranisil(void);
extern
void lcd_yaz(const char *s);
extern
void lcd_konumlanxy(unsigned char x, unsigned char y);
extern
void lcd_baslat(void);
extern
void lcd_komut(unsigned char c);
“bizim_lcd.c” kod dosyası
/*
Durali Kiraz 2015
*
www.duralikiraz.blogspot.com
*/
#include
<pic14regs.h> //mikrodenetleyici hazır tanımları alınıyor
#include
"bizim_lcd.h" // lcd.h dosyası tanımlanıp, değerler
alınıyor
#include
"delay.h" // Gecikme fonksiyonu tanımlanıyor
void
lcd_busy(void)
{
us_delay_20(12);
//DelayUs(250);
}
void
lcd_komut(unsigned char c) // Komut gönderme fonksiyonu
{
rw=0; //
LCD'ye yazma yapılacak
rs=0; //
LCD'ye komut gönderilecek
e=1; //
Düşen kenar tetikleme olduğu için E önce 1
lcd_port
= ( c & 0xF0 ); // Yüksek değerlikli bitler gönderiliyor
e=0; //
E, 0 yapılıyor
lcd_busy(); //Belirli
süre bekleniyor
e=1; //
E, 1 yapılıyor
lcd_port
= ( (c & 0x0F)<<4 ); // Düşük değerlikli bitler
gönderiliyor
e=0; //
E, 0 yapılıyor
lcd_busy(); //
Belirli bir süre bekleniyor
}
void
veri_yolla(unsigned char c)
{
rw=0;
rs=1; //
Komut yolladan tek farkı, RS'nin 1 olması
e=1;
lcd_port
= ( c & 0xF0 );
e=0;
lcd_busy();
e=1;
lcd_port
= ( (c & 0x0F)<<4 );
e=0;
lcd_busy();
}
void
lcd_ekranisil(void) // LCD siliniyor
{
lcd_komut(0x1);
ms_delay(2);
}
void
lcd_yaz(const char * s) // LCD'ye string ifade gönderiliyor
{
lcd_busy();
while(*s)
veri_yolla(*s++);
}
void
lcd_konumlanxy(unsigned char x,unsigned char y) //LCD'nin belli bir
//bölgesine gidiliyor
{
if(x==1)
lcd_komut(0x80+((y-1)%16));
else
lcd_komut(0xC0+((y-1)%16));
}
void lcd_baslat() // LCD ilk yükleme ayarları yapılıyor
{
rs = 0;
e = 0;
rw = 0;
ms_delay(15);
e=1;
lcd_komut(0x02);
ms_delay(2);
lcd_komut(CiftSatir4Bit);
lcd_komut(SagaYaz);
lcd_komut(ImlecGizle);
lcd_ekranisil();
lcd_komut(BirinciSatir);
}
void lcd_baslat() // LCD ilk yükleme ayarları yapılıyor
{
rs = 0;
e = 0;
rw = 0;
ms_delay(15);
e=1;
lcd_komut(0x02);
ms_delay(2);
lcd_komut(CiftSatir4Bit);
lcd_komut(SagaYaz);
lcd_komut(ImlecGizle);
lcd_ekranisil();
lcd_komut(BirinciSatir);
}
“lcdcalisma.c” ana dosyamız
//
Durali Kiraz 2015
//
PIC16F877A için hazırlanmıştır.
#include
"ayarlar.h"
#include
"bizim_lcd.h" // LCD kütüphanesi tanımlanıyor
void
main(void) // Ana fonksiyon alanı
{
TRISB=0x00; //
LCD'ye bağlı portlar çıkış yapılıyor
TRISC=0x00;
PORTB=0x00;
PORTC=0x00;
lcd_baslat(); //
LCD ilk ayarları yapılıyor
lcd_yaz("
DURALi KiRAZ"); // İlk satıra isim yazılıyor
lcd_konumlanxy(2,1); //
İkinci satıra geçiliyor
lcd_yaz("1234567890"); //
Rakamlar yazılıyor
for(;;); //Sonsuz
döngüye giriliyor
}
“ayarlar.h” dosyası
//
Copyright (C) 2015 Durali Kiraz
//
PIC16F877A için hazırlandı.
#include
<pic14regs.h>
typedef
unsigned short int uint16_t;
//sigorta
tanımlarımızı yapıyoruz.
__code
uint16_t __at _CONFIG __configword =
_PWRTE_OFF &&
_CP_OFF &&
_FOSC_XT
&&
_WDT_OFF
&&
_BOREN_OFF
&&
_LVP_OFF
;
Bu dersimizde
elektronik projelerimizin kısmen vazgeçilmezi sayılabilecek 16
sûtûn 2 satır Lcd display aygıtını nasıl sdcc ile
sürebileceğimizi öğrenmeye çalışacağız. Bilindiği gibi
devremizde oluşan bazı sonuçların gösterimi ve bazı verilen
girilmesi gerektiğinde Lcd display kullanmak büyük bir avantaj
sağlar. Ayrıca projelerimizin görselliğini de artırır.
Öncelikle lcd
mikrodenetleyiciden bağımsız bir harici aygıttır. Bu yüzden
şahsına münhasır bir kontrol mekanizması bulunmaktadır. Bu
aygıtın nasıl kontrol edileceği datasheet'i içerisinde geniş
bir şekilde açıklanmıştır. Dilerseniz kendi ihtiyacınıza
uygun “sürücü” yazabilirsiniz. Biz burada kod benzerliğinden
de istifade ederek Fırat Deveci'nin hazırlamış olduğu hitec c
e-kitabında hazırlamış olduğu lcd sürücünü çok az bir
değişiklikle burada kullanmak üzere kendimiz için hazırladık.
Bu lcd sürücü dosyası bundan sonraki projelerimizde
kullanacağımız lcd sürücü dosyamız olacaktır. Bu lcd sürücü
dosyaları aygıtın kontrolünde çok kolaylaştırmaktadır. Bu
dosyalarla ilgili daha fazla detayı kod üzerinde bulabilirsiniz.
Delay.h isimli
dosyamızda ise programımız için oluşturduğumuz yaklaşık
değerleri yakalayan bir gecikme fonksiyonlarını tanımladık.
Programımızda 4 Mhz frekans ve PIC16F877A işlemcimiz için bunları
kullanacağız. Anlayacağınız üzere sadece bu işlemci ve
frekansta yaklaşık doğru sonucu elde edebileceğimiz
fonksiyonlardır. us_delay_20
isimli
fonksiyon her döngüde 20~22 mikro saniye zaman beklemesi sağlayan
bir fonksiyondur. Açıkçası sadece bu projedeki geçici ihtiyacı
karşılayacaktır.
“ayarlar.c”
dosyamız
önceki derslerde ana dosya içerisinde tanımladığımız sigorta
ayarları vs. ek kodları tanımlayabileceğimiz bir dosyadır.
Bundan sonra PIC16F877A mikrodenetleyicisi için bir proje
oluşturacağımız zaman bu ayarları her seferinde tekrar yazmak
yerine sadece başlık dosyamızın ismini belirttiğimizde çok
kolaylık sağlamış olacağız.
“lcdcalisma.c”
isimli ana dosyamızı inceleyecek olursak
#include
"ayarlar.h"
#include
"bizim_lcd.h" // LCD kütüphanesi tanımlanıyor
satırlarıyla
kendimize özel oluşturduğumuz başlık dosyalarını projemize
dahil ediyoruz. Main fonksiyonu içinde
TRISB=0x00; //
LCD'ye bağlı portlar çıkış yapılıyor
TRISC=0x00;
PORTB=0x00;
PORTC=0x00;
satırları
B portunu çıkış olarak ayarlayıp diğer tüm portlara da sıfır
atamaktadır. Sonrasındaki
lcd_baslat(); //
LCD ilk ayarları yapılıyor
fonksiyonu
“bizim_lcd.c” sürücü dosyamızda gerçeklenmiş bir
fonksiyondur. Bununla lcd display'imiz çalışmak üzere bir takım
kodları çalıştırarak kendini karakterleri göstermeye hazırlar.
Daha doğrusu kullanıma hazırlar.
lcd_yaz("
DURALi KiRAZ"); // İlk satıra isim yazılıyor
satırında
ise lcd ye bir karakter serisini yazmasını söylüyoruz. Yine bu
fonksiyonun kodunuda incelediğinizde bir hafıza işaretçisini
parametre aldığını görebilirsiniz. Peki 2. satır 1. sutuna
konumlanmak istersek? Aşağıdaki satırda bu işi yapıyor.
lcd_konumlanxy(2,1); //
İkinci satıra geçiliyor
sonrasında
da
lcd_yaz("1234567890"); //
Rakamlar yazılıyor
for(;;); //Sonsuz
döngüye giriliyor
tekrar
lcd ye bir karakter serisini yazıdırıyoruz ve son olarak for
döngüsü ile programı sonsuz döngüye sokuyoruz. Diğer lcd
komutlarımızıda sürücü dosyasını inceleyerek kendiniz
uygulayabilirisiniz.
Dikkatinizi
çektiyse bu derste ilk defa bir aygıt için sürücü dosyası
kullandık. Normal şartlarda komut satırında derleme yapmaya
çalıştığımda aşağıdaki hata mesajlarını döndürerek kodun
object dosyasını oluşturduğunu fakat derlemeyi tamamlamadığını
gördüm.
sdcc
--use-non-free -mpic14 -p16f877a lcdcalisma.c
message:
using default linker script "/usr/share/gputils/lkr/16f877a.lkr"
error:
missing definition for symbol "_lcd_yaz", required by
"lcdcalisma.o"
error:
missing definition for symbol "_lcd_konumlanxy", required
by "lcdcalisma.o"
error:
missing definition for symbol "_lcd_baslat", required by
"lcdcalisma.o"
Bunun
sebebini araştırdığımda öncelikle harici sürücümüzün
object dosyasının derlenmesi, daha sonra ana dosyamızın object
dosyasının oluşturulup ikisinin birleştirme (linker) yapılmasının
gerektiğini öğrendim. Bu kısım çok önemli şayet aşağıda
anlatacağım adımları uygulayarak derleme işlemlerini
gerçekleştirmezseniz hex dosyasını oluşturamazsınız. İlk
olarak Linux üzerinde terminal/konsol penceresini, Windows
kullanıyorsanız cmd.exe yi çalıştırmalısınız. Ardından
sırayla şu iki satırı yazıp Enter lıyorsunuz. (Ben ubuntuya
göre yazıyorum burada.)
sdcc
--use-non-free -mpic14 -p16f877a -I path/to/pic14/includes -c
bizim_lcd.c
sdcc
--use-non-free -mpic14 -p16f877a -I path/to/pic14/includes -L
path/to/pic14/libraries -Wl, lcdcalisma.c bizim_lcd.o
-I
parametresi ; “Add to the include (*.h) path, as in -Ipath”
şeklinde bir açıklamaya sahiptir. Yani bu parametreden sonra
yazılan path parametresinde geçen başlık dosyaları derlemeye
dahil edilecektir.
-c
parametresi ; “--compile-only Compile and assemble, but do
not link” şeklinde bir açıklamaya sahiptir. Bu parametreden
sonra yazılan kod dosyası sadece derlensin ve linker (kod bağlama)
işlemi yapılmasın anlamını taşır.
Bu
şekilde ilk satır konsolda çalıştırıldığında normal
şartlarda hiçbir mesaj vermeden sadece derlemeyi yapacaktır. Eğer
hatalı kod durumu varsa elbette derleme hataları görüntülenecektir.
İkinci
satırı inceleyecek olursak ;
-L
parametresi; “Add the next field to the library search path”
açıklamasına sahiptir. Yani kütüphane arama yoluna sonraki
sahayıda ekle anlamına gelir. Önceki saha -I den sonra yazılan
path bilgisidir. Sonraki arama yolu ise -L parametresiden sonra
belirtilmiş path bilgisidir.
-W
parametresi “Pass through options to the pre-processor (p),
assembler (a) or linker (l)” açıklamasına sahiptir. Ön
işlemcinin assembler veya linker işlemini pas geçmesi şeklinde
yorumlanabilir.
-WI
şeklinde yazıldığında parametre -I ile dahil edilmiş include
dosyalarımızı linker işleminin pas geçilmesini sağlar.
Dolayısıyla
ikinci satırdaki komutumuz ilk satırda oluşturulmuş lcd sürücünün
object dosyası ile sonra oluşturulan ana dosyanın object
dosyasınıda linker işlemine dahil ederek derlemeyi tamamlar ve
*.hex dosyasını oluşturur. Bir sonraki dersimizde görüşmek
üzere hoşçakalın.
duralikiraz.blogspot.com
31
Temmuz 2015
“Muvaffakiyet
Allahtandır”
Kaynaklar
:
1
- Fırat Deveci Hi-tech C ile PIC programlama e-kitabı.
2-
http://sourceforge.net/p/sdcc/discussion/1865/thread/e8062c7b/
Hiç yorum yok:
Yorum Gönder