5. derste neler yaptık?

5. derste yaptığımız mplab ve isis çalışmalarının son halini indirmek için >>Tıklayın.

İlk olarak Timer0 modülünün çalışma standartını anlayabilmek için aşağıdaki iki kodu yazıp karşılaştırdık.

char a=0;
 while(1){
 a++;
 PORTB=a;
 }
 while(1){
 PORTB=TMR0;
 }

TMR0 kaydedicisinin, donanımsal olarak,  kendiliğinden birer arttırdığını görmüş olduk. Başka kodlar yürütülürken dahi TMR0 kaydedicisinin kendiliğinden artacağını belirttik. Bu özelliğinden dolayı günlük yaşantımızda kol saati veya duvar saati veya güneş saati benzetimini yaptık. Günlük yaşantımızda zamanlayıcı aygıtlarımıza ne kadar ihtiyaç duyuyorsak bu modüle gömülü sistemde o derece ihtiyaç duyacağımızı vurguladık.

Timer0 modülünün kurulumu ile ilgili olan OPTION_REG özel kaydedicisinin bitlerinin anlamlarını açıkladık. TMR0 kaydedicisini bir su kabı gibi düşündük  Timer0 modülünü ise su akıtan musluğa benzettik. Musluktan akan suyun hızının prescaler “ps0, ps1, ps2” bitleri ile ayarlayabildiğimizi gördük. Musluktan akan suyun harici yada dahili besleyebileceğimizi ve bu seçimi yapabileceğimiz bit i gördük.

Timer0 tabanlı çalışan “zaman” kütüphanemi projelerimize dahil ettik.

zaman.c :

/************************************************************
* FileName: zaman.c
 * Dependencies: zaman.h , htc.h
 * Processor: PIC16F
 * Assembler/Compiler: HI-TECH ANSI C Compiler V9.71a
 * Linker: HI-TECH ANSI C Compiler V9.71a
 * Company: www.hasankara.info
*************************************************************/
#include "zaman.h"
#include <htc.h>

void zaman_init(void){
 TMR0=0; // TMR0=0 dan saymaya başlatılır
 T0CS=0; // 0 da, dahili osilatör
 PSA=0; // 0 da, Prescaler TMR0 için kullanılır
 PS2=1; // 1:256 bölüm değeri
 PS1=1;
 PS0=1;
 T0IF=0; // TMR0 kesme bayrağı temizleniyor
 T0IE=1; // TMR0 kesmesine izin veriliyor
 GIE=0; // Genel kesme izni verilmiyor
}// end
//_/__/___/____/_____/______/_______/________/_________/_____/
void zaman_sayac(void){
 unsigned char i;
 while(TMR0>40){ TMR0=TMR0-40;
 for(i=mmxreg;i>0;i--){
 if(rdelay_ms[i]>0)rdelay_ms[i]--;
 }// end for
 }// end while
}// end
//_/__/___/____/_____/______/_______/________/_________/_____/

zaman.h :

/************************************************************
 * FileName: zaman.h
 * Dependencies:
 * Processor: PIC16F
 * Assembler/Compiler: HI-TECH ANSI C Compiler V9.71a
 * Linker: HI-TECH ANSI C Compiler V9.71a
 * Company: www.hasankara.info
*************************************************************/
// prototypes

void zaman_init(void);
void zaman_sayac(void);
//_/__/___/____/_____/______/_______/________/_________/_____/

#define mmxreg 13

#define adc 1
#define lcd_bsy 2
#define veri 3
#define led4 4
#define led5 5
#define led6 6
#define led7 7
#define led8 8
#define hz1 9
#define bt0_bsy 10
#define bt1_bsy 11
//_/__/___/____/_____/______/_______/________/_________/_____/
unsigned int rdelay_ms[mmxreg];

zaman.c içeriinde bulunan iki fonksiyonu ayrı ayrı gördük.

  • zaman_init() sonsuz döngüye girmeden evvel çağırarak Timer0 modülünde istediğimiz konfigürasyonu yaptığını gördük.
  • zaman_sayac() fonksiyonunu anadöngüde rutin olarak çağırdığımızda TMR0 kabını sürekli doluluk durumunu kontrol edeceğini gördük. TMR0 kabı belli bir seviyeye geldiğinde 1ms geçmiş olduğunu anladığını ve sonucunda rdelay_ms[] dizisinin, 0 olmayan her hücresinin birer azaltılmasında rol aldığını üst üste açıkladım. Daha sonra hücreleri istediğimiz senaryolarda planlı gecikme durumlarında kullanmak üzere sayılar yükleyip o hücrelerin 0 olup olmama durumlarını kontrol edeceğimizi vurguladım.

örnek olarak;

/************************************************************
 * FileName: main.c
 * Dependencies:htc.h user.h
 * Processor: PIC16F
 * Assembler/Compiler: HI-TECH ANSI C Compiler V9.71a
 * Linker: HI-TECH ANSI C Compiler V9.71a
 * Company: www.hasankara.info
*************************************************************/
// PORTB : 8 LED
// RD0 : BUTON 0
// RD1 : BUTON 1

#include <htc.h>
#include "user.h"
#include "zaman.h"
__CONFIG(0X3F3A);

main(){

TRISB=0b00000000; //
TRISD=0b01111111; //

PORTB=0;

zaman_init();

while(1){

if(rdelay_ms[1]==0){rdelay_ms[1]=500;

if(RB7) RB7=0; else RB7=1; }

if(rdelay_ms[2]==0){rdelay_ms[2]=505;

if(RB6) RB6=0; else RB6=1; }

zaman_sayac();

}// end while
}// end main

main.c içerisini bu şekilde düzenleyerek 1. ve 2. hücreleri farklı iki senaryo da kullandık. bu iki if döngüsü, kendi içlerinde, RB6 ve RB7 e bağladığımız ledleri, hücrelere yüklediğimiz sayılar kadar milisaniye sıklığında yakıp söndüren birbirinden bağımsız çalışan birer senaryo olduğunu belirttim.

Devamında zaman.h içerisindeki

#define adc 1
#define lcd_bsy 2
#define veri 3
#define led4 4
#define led5 5
#define led6 6
#define led7 7
#define led8 8
#define hz1 9
#define bt0_bsy 10
#define bt1_bsy 11

kısmında hücreleri, kullanacağımız senaryolara göre isimler tanımlayarak karışıklığı önleyebileceğimizden söz ettim. “rdelay_ms[led4]” şeklinde ki kullanımda, led4 için oluşturacağımız senaryoda 4. hücreyi kullanacağımızı program yazan kişi olarak bir kenarda kaydını tutmuş olduk.

isis_ders_5

Devamında 2×16 karakter lcd kullanımı için kolları sıvadık, lcd mizi paketinden çıkardık. Ardından tahtaya lcd nin pin isimlerini geniş geniş yazdım. Her pinin ayrı ayrı açıklamasını yaptım. Karakter lcd nin içerisinde kendi mikroişlemcisi olduğundan bahsettim.  Lcd nin içerisinde ASCİİ karakterlerin kayıtlı olduğunu ve biz sadece, şu satıra şu karakteri görüntüle diyerek kullanabileceğimizden bahsettim. ASCİİ karakterlerinin yanı sıra nokta nokta, lcd içerisinde 5×8 noktadan oluşan karakterler oluşturabileceğimizden ve karakter oluşturmak için R/W pinini 5 volt’a çekerek yaptığımızdan bahsettim. İlk uygulamada karakter tanımlaması yapmayacağımızdan dolayı bu pin i gnd bağlayarak normal kullanım modunda sabit kıldık.

Lcd kullanım için en az mikrodenetleyicimizin 6 pinini meşgul etmemiz gerektiği şemada görülüyor.  Lcd için kendi hazırlamış olduğum kütüphaneleri projemize dahil ettik.

lcd.c :

#include <htc.h>
#include "zaman.h"
#include "lcd.h"

//_/__/___/____/_____/______/_______/________/_________/__________/
unsigned char lcd_busy(unsigned char k) {
static unsigned char mlt=0;

switch (mlt){

case 0: if(rdelay_ms[lcd_bsy]<1)rdelay_ms[lcd_bsy]=k; mlt=1; break;

case 1: if(rdelay_ms[lcd_bsy]<1)mlt=0; break;

default: mlt=0;}

return mlt; }
//_/__/___/____/_____/______/_______/________/_________/__________/
unsigned char lcd_komut( unsigned char c){
static unsigned char mlt=0,buff;

switch(mlt) {

case 0: buff=c;
 // rw=0; // LCD'ye yazma yapılacak
 rs=0; // LCD'ye komut gönderilecek
 e=1; // Düsen kenar tetikleme olduğu için E önce 1
 // Yüksek değerlikli bitler gönderiliyor
 db7 = bittest(buff,7); db6 = bittest(buff,6);
 db5 = bittest(buff,5); db4 = bittest(buff,4);
 e=0;mlt=1;break;

case 1: if(lcd_busy(2)==0)mlt=2; break;

case 2: e=1; rs=0;
 db7 = bittest(buff,3); db6 = bittest(buff,2);
 db5 = bittest(buff,1); db4 = bittest(buff,0);
 e=0; mlt=3;break;

case 3: if(lcd_busy(2)==0)mlt=4; break;

case 4: mlt=0; break;

default: mlt=0; break;} return mlt;}
//_/__/___/____/_____/______/_______/________/_________/__________/
unsigned char veri_yolla(unsigned char c){
static unsigned char mlt=0,buff;

switch (mlt){

case 0: buff=c; rs=1; e=1; //rw=0;
 db7 = bittest(buff,7); db6 = bittest(buff,6);
 db5 = bittest(buff,5); db4 = bittest(buff,4);
 e=0; mlt=1;break;

case 1: if(lcd_busy(2)==0){
 e=1; rs=1;
 db7 = bittest(buff,3); db6 = bittest(buff,2);
 db5 = bittest(buff,1); db4 = bittest(buff,0);
 e=0; mlt=3;
 } break;

case 3: if(lcd_busy(2)==0)mlt=4; break;

case 4: mlt=0; break;

default: mlt=0; break;} return mlt;}
//_/__/___/____/_____/______/_______/________/_________/__________/
unsigned char lcd_clear(void){
static unsigned char mlt=0;

switch (mlt){

case 0: if(lcd_komut(0x1)==0)mlt=1; break;

case 1: if(lcd_busy(2)==0)mlt=2; break;

case 2: mlt=0; break;

default: mlt=0; break; } return mlt;}
//_/__/___/____/_____/______/_______/________/_________/__________/
unsigned char lcd_yaz(const char * s){
static unsigned char mlt=0,buff=0,sayac=0;
unsigned int i;

switch(mlt){

case 0: mlt=1;sayac=0;buff=*s;

case 1: if(lcd_busy(2)==0)mlt=2; break;

case 2: if(buff){

if(veri_yolla(buff)==0){sayac++;
 for(i=0;i<sayac;i++)s++;buff=*s; }
 else break;}

 if(buff==0) {mlt=0;} break;

default: mlt=0; }
return mlt;}
//_/__/___/____/_____/______/_______/________/_________/__________/
unsigned char lcd_gotoxy(unsigned char k_x, unsigned char k_y){
static unsigned char mlt=0,buff=0;

switch(mlt){

 case 0: mlt=10;

case 10: if(k_x==1)buff=0x80; else buff=0xC0; mlt=11; break;

case 11: if(lcd_komut(buff+(k_y-1)%16)<1)mlt=20; break;

case 20: if(lcd_busy(2)<1)mlt=0; break;

default:mlt=0;
 }

return mlt;
}

//_/__/___/____/_____/______/_______/________/_________/__________/
unsigned char lcd_init() {
static unsigned char mlt=0;

switch(mlt){

case 0: rs=0; e=0; mlt=1; break; // rw=0;

case 1: if(lcd_busy(15)==0)mlt=2; break;

case 2: e=1; mlt=3;

case 3: if(lcd_komut(0x02)==0)mlt=4; break;

case 4: if(lcd_busy(1)==0)mlt=6; break;

case 6: if(lcd_komut(CiftSatir4Bit)==0)mlt=7; break;

case 7: if(lcd_komut(SagaYaz)==0)mlt=8; break;

case 8: if(lcd_komut(ImlecGizle)==0)mlt=9; break;

case 9: if(lcd_clear()==0)mlt=10; break;

case 10: if(lcd_komut(BirinciSatir)==0)mlt=11; break;

case 11: mlt=0; break;

default: mlt=0; break;} return mlt;}
//_/__/___/____/_____/______/_______/________/_________/__________/
unsigned char lcd_yaz_sayisal(long long ptr, unsigned char tbn, unsigned char bsm){
// lcd_yaz_sayisal(deger,taban,basamak);
static unsigned long buff,buff2,buff3,i;
static unsigned char mlt=0,bbsm;

switch (mlt){

case 0: if(ptr<0) { buff=(-1)*ptr; if(bsm>0)bsm--; mlt=14;}
 else {buff=ptr; mlt=15; } bbsm=bsm; break;

case 14: if(veri_yolla(*"-")==0)mlt=15; break;

case 15: for(buff2=1;buff>=buff2;buff2=buff2*tbn); mlt=16; break;

case 16: for(i=1;bbsm>0;bbsm--)i=i*tbn; mlt=17; break;

case 17: if(i>buff2){i=i/tbn; mlt=18;} else mlt=20; break;

case 18: if(veri_yolla('0')==0)mlt=17; break;

case 20: buff2=buff2/tbn; if(buff2>0)mlt=21; else mlt=100; break;

case 21: buff3=buff/buff2; buff=buff-buff2*buff3; mlt=22;

case 22: if(veri_yolla('0'+buff3)==0)mlt=20; break;

case 100: mlt=0; break;

default : mlt=0; break;} return mlt;}
//_/__/___/____/_____/______/_______/________/_________/__________/

lcd.h :


#define rs RD0 //Pin tanımlamaları
#define rw RD1
#define e RD2

#define db4 RD4
#define db5 RD5
#define db6 RD6
#define db7 RD7
/* 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 ImlecGeri 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 baGlangıç adresi
 // (DDRAM adres)
#define IkinciSatir 192 // Gkinci satirin baGlangıç 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
//_/__/___/____/_____/______/_______/__
#define bitset(var, bitno) ((var) |= 1UL << (bitno))
#define bitclr(var, bitno) ((var) &= ~(1UL << (bitno)))
#define bittest(var, bitno)(var&(0b00000001 << (bitno)) ? 1 :0 )
typedef union
{
 unsigned char all;
 struct{
 unsigned b0 :1;
 unsigned b1 :1;
 unsigned b2 :1;
 unsigned b3 :1;
 unsigned b4 :1;
 unsigned b5 :1;
 unsigned b6 :1;
 unsigned b7 :1;
 };
}bittype;
//_/__/___/____/_____/______/_______/__
extern unsigned char veri_yolla(unsigned char c);
extern unsigned char lcd_clear(void);
extern unsigned char lcd_yaz(const char * s);
extern unsigned char lcd_gotoxy(unsigned char x,unsigned char y);
extern unsigned char lcd_init();
extern unsigned char lcd_komut( unsigned char c);
extern unsigned char lcd_busy(unsigned char k);
extern unsigned char lcd_yaz_sayisal(long ptr, unsigned char tbn, unsigned char bsm);
//_/__/___/____/_____/______/_______/________/_________/__________/

lcd.h içerisinde mikrodenetleyicimize göre pin atamalarını yapmamız gereken bölümü belirttim. Bu pinlerin ayrekten çıkış olarak belirtmemiz gerektiğini belirttim.

2×16 karakter lcd kütüphanesini projemize dahil ettikten sonra main.c dosyasını aşağıdaki gibi düzenledik.

/************************************************************
 * FileName: main.c
 * Dependencies:htc.h user.h zaman.h lcd.h
 * Processor: PIC16F
 * Assembler/Compiler: HI-TECH ANSI C Compiler V9.71a
 * Linker: HI-TECH ANSI C Compiler V9.71a
 * Company: www.hasankara.info
*************************************************************/
#include <htc.h>
#include "user.h"
#include "zaman.h"
#include "lcd.h"

__CONFIG(0X3F3A);

main(){

TRISB=0b00000000; //
TRISD=0b00000000; //

PORTB=0;

zaman_init();

while(lcd_init()>0)zaman_sayac();
 while(1){
if(rdelay_ms[led1]==0){rdelay_ms[led1]=500;

if(RB7) RB7=0; else RB7=1; }

if(rdelay_ms[led2]==0){rdelay_ms[led2]=505;

if(RB6) RB6=0; else RB6=1; }
 veri_yolla('a');

zaman_sayac();
 }// end while
}// end main

Ana döngü içerisinde “while(lcd_init()>0)zaman_sayac();” satırının açıklamasını yaptım. lcd_init() fonksiyonunun multitask fonksiyon olduğunu ve bu fonksiyonu standart (ilkel) metot da kullanma şeklinin, while döngüsü içerisine alarak gerçekleştirdiğimizi gördük. Fonksiyon her geri dönüşte hangi aşamada olduğunu geri döndürüyor. 0 dan büyük olduğu sürece yani fonksiyon tamamlanmadığı sürece while içerisinden kurtulamayacak ve bitene kadar burda kalacak. lcd_init planlı gecikme barındırdığı için zaman_sayac() her döngüde kontrol etmesini istedik. Bu olmasa idi planlı gecikme kısımları hiç tamamlanmayacak ve while içinden hiç çıkamayacaktı.

veri_yolla(‘a’) satırının lcd e ‘a’ karakterini yollayan bir fonksiyon olduğunu ve başka bir lcd fonksiyonu kullanmadığımız için, multitask fonksiyonunu bu şekilde anadöngüde çağırmamızın bir sakıncası olmayacağını belirttim. Normalde bir switch case yapısı ile senaryo içerisinde kullanmamız gerekir. sadelik için şimdilik bu tek satır kodu yazdık ve uygulamada, lcd nin her karakterinde ‘ a’ gördük.

Sonrasında user.c kütüphanesinin içerisine


void lcd_kullan (void){
static unsigned char mlt=0;

switch(mlt){

case 0: mlt=1;

case 1: if(lcd_gotoxy(1,1)<1)mlt=2; break;

case 2: if(lcd_yaz("Merhaba Dunya")<1)mlt=0; break;
 }// end switch
}// end f

fonksiyonunu yazıp, user.h içinde tanıttık. main.c içindede veri_yolla(‘a’); satırını silerek yerine lcd_kullan(); satırını ekledik. Uygulamada case 0: satırını unuttuğumuzdan dolayı ekranda Merhaba Dunya yerine boş karakterler gördük. Çünkü İlk başta mlt=0; bulunduğundan dolayı ve case ler arasında 0 bulunmadığından dolayı işlem yapılmadan fonksiyondan direk çıkmasını istemiş olduk. case 0: satırını ekledikten sonra ben ekranda Merhaba Dunya yazısını görüntüleyebildim.

En üstteki indirme linkinde kayan yazılı haline getirerek projeyi kaydetmiştim. Programı Uygulamanızda görmeyi unutmayın. 5. ders ile ilk dönemimizi sonlandırmış olduk. Katılımlarınız için hepinize teşekkür eder, iyi çalışmalar dilerim.

Bir Cevap Yazın

Or

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir