Bitirme projemiz kapsamında sensör girdilerini okumak ve motor sürmek için LM3S811 serisini kullanmaya karar verdik. Bu yazımızda uKeil üzerinde proje oluşturmayı ve kiti kullanmayı öğrenmek açısından bir kaç temel uygulama yazacağız.

Bu yazı kapsamında;

* uKeil ile yeni proje oluşturabilme,

* Led kontrol edebilme,

* LCD ekranı kontrol edebilme,

* UART üzerinden haberleşebilme uygulamalarını gerçekleştireceğiz.

 

 

 

 

GEREKLİ DÖKÜMANLAR

Stellaris üzerinde çalışabilmek için önce gerekli dökümanları ve programları indirmemiz gerekiyor.  Bu materyaller;

Derleme işlemlerini uKeil programı üzerinde yapacağız. O yüzden o programa ihtiyacımız var. Stellarisware dökümanı ise içinde kütüphanelerin ve örnek uygulamaların yer aldığı  geniş ve güzel bir dökümandır. Datasheet ve kullanıcı klavuzu da gerekiyordu. Bunun için kit dökümanlarını da indiriyoruz.

uKEIL  PROJE OLUŞTURMA

uKeil programını çalıştırdığımızda karşımıza çıkan pencerede öncelikle Project->New uvision Project seçeneğini seçiyoruz. ilk olarak karşımıza hangi cihazı kullanacağımızı soran bir ekran çıkıyor. LM3S811 seçeneğini seçiyoruz.

Ardından projeyi nereye kaydetmek istediğmizi soran bir ekran çıkıyor. Biz burada Masa üstünde yer alan stellaris klasörünün içerisinde bir hello klasörü oluşturup, o klasörün içinde bu işlemleri gerçekleştirdik.  Daha sonra kaydet butonuna bastığımızda bize startup.s dosyasını oluşturmak isteyip istemediğimizi soran bir pencere geliyor. Ve o pencereyi onaylıyoruz. Bu işlemlerden sonra projenin sol tarafında içerisinde Startup.s dosyasının bulunduğu projeyi görebiliriz.

Sol üst köşede yer alan new page seçeneğine bastığımızda yeni bir text dosyası açılıyor. İçerisine klasik main fonksiyonumuzu oluşturuyoruz ve kaydediyoruz.

Fakat bu işlemlerden sonra project  menüsünde main.c dosyasının eklenmediğini görüyoruz. Oluşturulmuş olan proje üzerine sağ tıkladığımızda Add Files to group.. seçeneğine basarak main.c dosyasını projemize dahil ediyoruz. Şimdi projemize gerekli kütüphaneleri ve header dosyalarını import edeceğiz. Bunun için öncelikle proje menüsünde sağ tıklayarak Add Group seçeneği ile lib isimli bir grup oluşturduk. Düzenli bir görünüm olması açısından bu işlemi yaptık. Ardından indirdiğimiz stellarisware dökümanının içinden driverlib.lib kütüphanesini ekliyoruz.  C:\StellarisWare\driverlib\rvmdk yolundan bulmak mümkün. Yine aynı şekilde LCD ekranın kaynak dosyalarını C:\StellarisWare\boards\ek-lm3s811\drivers yolu üzerinden projemize ekliyoruz.

Stellarisware üzerindeki header dosyalarını projemize tanıtmamız ve gerekli cihaz ayarlamalarını yapmamız gerekiyor. Bunun için Flash -> Configure Flash tools seçeneği altından bu ayarlara erişebiliriz. İlk olarak target sekemesi altında kristal hızını 6MHz olarak değiştiriyoruz. Eğer seçili değilse IROM1 ve IRAM2 seçeneklerini işaretliyoruz.

 Daha sonra C/C++ sekmesi altından Include Paths kısmına Stellarisware yolunu ekliyoruz. Kullanacağımız kütüphaneleri tanıtmak için gerekli olacaktır.

Linker sekmesi altında ise R/O Base ve R/W base seçeneklerinin şekildeki gibi olmasına dikkat ediyoruz.

Ardından Utilities kısmından Flash yüklemesi için kullanılacak programı Stellaris ICDI olarak değiştiriyoruz. Ve böylelikle ayarlarımız bitiyor.

Önemli bazı kütüphaneleri de main.c üzerine ekleyip BUILD seçeneğine tıkladığımızda hata almamamız gerekiyor. Ve sol taraftanda görebileceğimiz gibi stellarisware üzerindeki kütüphaneler projeye ekleniyor.

Proje oluşturma işlemimiz tamamlandı. Artık uygulamalarımızı yazmaya başlayabiliriz.

UYGULAMALAR

LCD EKRANI KULLANABİLME

Bu uygulama da temel olarak sistem saatini ayarlayacak, ekranı kullanacağımızı cihaza belirtecek ve ardından ekrana istediğimiz yazıyı yazdıracağız.

Sistem saatini belirlemek için; 

SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |SYSCTL_XTAL_6MHZ) fonksiyonunu kullanacağız.

SYSCTL_SYSDIV_1 parametresi için datasehhet üzerinde araştıma yaptığımızda hem ne anlama geldiğini hemde seçeneklerimizi görebiliriz.

SYSCTL_USE_OSC parametresi, sistem saatini osilatör  saati olarak belirlememize yarıyor. aksi halde çok hızlı olacağı için işlemler, yaptıklarımızı göremeyebiliriz.

SYSCTL_OSC_MAIN parametresi, osilatör kaynağımızın ana osilatör kaynağı olacağını belirliyor. Bir üstteki komut ana osilatör kaynağına göre çalışmaktadır.

SYSCTL_XTAL_6MHZ parametresi, kristalimizin hızını belirliyor. sysctl.h içerisinden diğer seçeneklerimizi de görmek mümkün.

Daha sonra LCD ekran fonksiyonlarını ekliyoruz;

Display96x16x1Init(false); // Bu fonksiyon OLED ekran icin I2C ara yuzunu tanimlamak icin kullanılıyor. Bir bakıma LCD ekranı kullanacağımızı cihaza belirtmiş oluyoruz.

Display96x16x1StringDraw(“Stellaris!”,0,0);// 0,0 noktasina stellaris yaz

Display96x16x1StringDraw(“MCU-TURKEY!”, 0, 1);// 0,1 noktasina yaz

Böylelikle kodumuz bitiyor. Ve çalıştırıyoruz.

#include "lm3s811.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "boards/ek-lm3s811/drivers/display96x16x1.h"
 
int main()
{
	SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |SYSCTL_XTAL_6MHZ);
	Display96x16x1Init(true);	/*Bu fonksiyon OLED ekran icin I2C ara yuzunu tanimlamak icin kullaniliyor*/	
 
	Display96x16x1StringDraw("Stellaris!",0,0);// 0,0 noktasina stellaris yaz
	Display96x16x1StringDraw("MCU-TURKEY!", 0, 1);// 0,1 noktasina yaz
 
	return 0;
}

LED KONTROL UYGULAMASI

Ekrana yazımızı yazdırdıktan sonra şimdi de stellaris üzerinde yer alan status ledini kullanacağız. Öncelkile Şematiklerden status ledin bağlı olduğu pini buluyoruz. PC5 adlı pin olduğunu bulduk.

PORTC üzerinde işlem yapacağımızı anladıktan sonra PORTC üzerindeki GPIO register larının neler olduğuna datasheet üzerinden bakıyoruz.

Daha sonra lm3s811.h üzerinde syntax larının nasıl olduğu kontrol edip kodumuzu yazmaya başlıyoruz. Temel olarak önce PORTC nin kullanılacağını belirtecek ardından PC5 numaralı pini çıkış olarak belirleyecek ve datamızı gireceğiz.

#include "lm3s811.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "boards/ek-lm3s811/drivers/display96x16x1.h"
 
int main()
{
	volatile unsigned long i= 0;
	SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |SYSCTL_XTAL_6MHZ);
	Display96x16x1Init(true);	/*Bu fonksiyon OLED ekran icin I2C ara yuzunu tanimlamak icin kullaniliyor*/	
 
	Display96x16x1StringDraw("Stellaris!",0,0);// 0,0 noktasina stellaris yaz
	Display96x16x1StringDraw("MCU-TURKEY!", 0, 1);// 0,1 noktasina yaz
 
	SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOC;	//PORTC nin kullanilacagini belirliyoruz
        i = SYSCTL_RCGC2_R;			// icindeki de[eri bir yere yazarak aktif hale getrmemiz gerekiyor
 
	GPIO_PORTC_DIR_R  = 0x20; // pc5 pinini output olarak ayarla
 
	for(;;)
	{
		GPIO_PORTC_DATA_R =0x20;
		for(i=0;i<100000;i++);
		GPIO_PORTC_DATA_R = ~0x20;
		for(i=0;i<100000;i++);
	}
	return 0;
}

Bu işlemlerden sonra butonumuz sürekli yanıp sönmeye başlayacaktır.

UART HABERLEŞMESİ

Bu uygulamada board üzerinden seri haberleşme yardımıyla bilgisayara veri göndermeyi gerçekleştireceğiz. Yine son yapmış olduğumuz kodu güncelleyerek bu işlemleri yapacağız.

Öncelikle temel algoritmasını çıkaralım;

  • UART ve GPIO çevresel aygıtlarını aktifleştir,
  • GPIO pinlerini UART için ayarla,
  • UART Rx İnterruptını aç,
  • Kullanıcının kullanabileceği adresleri belirle olarak tanımlayabiliriz.
Uygulamada iki adet GPIO pinine ihtiyacımız olacaktır. Birisi iletim(TX) diğeri ise alım(RX) olacaktır.  Aynı zamanda timer da kullanmamız gerekiyor timer lardan bir tanesi iletim tikini oluşturacak bir diğeri ise alım için tik oluşturacaktır. Bazı temel argümanları belirledikten sonra kullanacağımız fonksiyonları çıkarıyoruz.

SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);//UART0 kullanılacağını belirtiyoruz

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);//GPIOA kullanılacağını belirtiyoruz

IntMasterEnable();//Genel interruptları aktive et

UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT); //UART0 için interrupt aktive et

UARTConfigSetExpClk(

UART0_BASE, //UART0 için ayarla

SysCtlClockGet(), //sistem clock unu kullan

115200, //BAUD 115200

(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |UART_CONFIG_PAR_NONE)//8 bit data, 1 stop biti, parity yok

);

SysCtlDelay(SysCtlClockGet() / 12); //Gecikme

UARTCharsAvail(UART0_BASE)// Buffer tarafından kaç karakter alındığını bize döndürüyor.

UARTCharPutNonBlocking(UART0_BASE, UARTCharGetNonBlocking(UART0_BASE)); //Eğer uygun yer varsa buffer üzerine karakter iletmemizi sağlıyor. Eğer uygun yer yoksa hata kodu döndürüyor.

/*********************UART DATA GÖNDERME FONKSIYONU************************/
void UARTSend(const unsigned char *pucBuffer, unsigned long ulCount)//değişken olarak datayı ve gönderilen data sayısını al
{
 
    while(ulCount--)//goönderilen data sayısı bitene kadar gönder
    {
        UARTCharPutNonBlocking(UART0_BASE, *pucBuffer++);	//UART 0 üzeirnden pucbuufer içindeki datayı yaz bir sonraki dataya geç
    }
}
/**************************************************************************/

Veri gönderme fonksiyonumuz oldukça basit. Parametre olarak verimizi ve karakter sayımızı gönderiyoruz. Karakter sayımız bitene kadar verileri karakter karakter iletiyor.

#include "lm3s811.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "boards/ek-lm3s811/drivers/display96x16x1.h"
#include "driverlib/uart.h"
#include "driverlib/gpio.h"
/********Prototipler*********/
void UARTSend(const unsigned char *pucBuffer, unsigned long ulCount);
/****************************/
 
int main()
{
	volatile unsigned long i= 0;
	SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |SYSCTL_XTAL_6MHZ);
	Display96x16x1Init(false);	/*Bu fonksiyon OLED ekran icin I2C ara yuzunu tanimlamak icin kullaniliyor*/	
 
	Display96x16x1StringDraw("Stellaris!",0,0);// 0,0 noktasina stellaris yaz
	Display96x16x1StringDraw("MCU-TURKEY!", 0, 1);// 0,1 noktasina yaz
 
	SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOC;	//PORTC nin kullanilacagini belirliyoruz
    i = SYSCTL_RCGC2_R;						// icindeki de[eri bir yere yazarak aktif hale getrmemiz gerekiyor
	GPIO_PORTC_DIR_R  = 0x20; // pc5 pinini output olarak ayarla
 
	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);//UART0 kullanılacağını belirtiyoruz
 	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);//GPIOA kullanılacağını belirtiyoruz
 
	GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);//UART pinlerini A0 ve A1 üzerine set et
 
	/*********UART haberleşmesini ayarla********/
    UARTConfigSetExpClk(
		UART0_BASE,		 //UART0 için ayarla
		SysCtlClockGet(), //sistem clock unu kullan
	  	115200,			  //BAUD 115200
     	(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |UART_CONFIG_PAR_NONE)//8 bit data, 1 stop biti, parity yok
	 );
	/******************************************/
 
	for(;;)
	{
		SysCtlDelay(SysCtlClockGet() / 12); //Gecikme
        UARTSend("MCU-TURKEY  ",12);
		GPIO_PORTC_DATA_R =	 0x20;//ledi yak
		for(i=0;i<100000;i++);//delay
		GPIO_PORTC_DATA_R = ~0x20; //ledi söndür
		for(i=0;i<100000;i++);	 //delay
	}
	return 0;
}
/*********************UART DATA GÖNDERME FONKSIYONU************************/
void UARTSend(const unsigned char *pucBuffer, unsigned long ulCount)//değişken olarak datayı ve gönderilen data sayısını al
{
 
    while(ulCount--)//goönderilen data sayısı bitene kadar gönder
    {
        UARTCharPutNonBlocking(UART0_BASE, *pucBuffer++);	//UART 0 üzeirnden pucbuufer içindeki datayı yaz bir sonraki dataya geç
    }
}
/**************************************************************************/

Uygulamanın çalıştırılması kısmında windows 7 üzerinde Hyper terminal olmadığı için yine bu site üzerinde paylaşımı yapılmış olan seri port programını kullandık(link).

 

Böylelikle bazı temel uygulamaları çalıştırmış olduk. PWM,ADC ve sıcaklık sensörünü de paylaşacağız bir aksilik çıkmazsa.