Elektronik / Mikrodenetleyici Projeleri/

ARM: Hello World

8051, PIC, ATMEL ve MSP derken sıra gömülü sistemlerin şahı ARM‘a geldi. ARM herkesin bildiği üzere bir core yani çekirdek. Çeşitli firmalarda bu çekirdeği alıp, yanına kendilerine göre çevre birimleri ekleyip ya piyasaya sunuyorlar ya da kendi cihazlarında kullanıyorlar. Örneğin benim telefonum Nokia N79’da ARM11 kullanılıyor.

ARM’ın bir diğer güzel özelliği ise güç tüketimi konusunda. Daha önce sitemde bahsettiğim MSP430 elbette güç tüketimi konusunda ARM’ı zorlayabilir fakat işlevlik sınıfında ARM’ın yanında sönük kalır.

Bunları gördükten sonra ben de artık ARM’a el atmanın zamanı geldi deyip, iki haftadır bana armağan edilen aşağıdaki kitle çalışmalarımı yavaş da olsa sürdürüyorum. Hatta müjdesini vermek isterim, ARM ile ilgili sağlam bir kitap hazırlıyorum.

arm-kit-LPC2368

Yukarıdaki kartın üzerinde NXP’nin LPC2368 ARM7 mikrodenetleyicisi mevcut. ARM7 artık düşük seviyeli bir ARM mikrodenetleyicisi olsa da üzerinde barındırdığı özellikler oldukça fazla: 72MHz’e kadar çalışabilme, 512kB Flash Memory, Ethernet, SD Kart, CAN, USB2.0 desteği ve RTC. Bu özelliklerin yanında ARM’ın 32 bit veri yoluna sahip olduğunu da söylemek isterim. Fiyatı ise tüm bunlara rağmen 12$ civarında. Bu fiyatın içine ARM programlayıcı da dahil. Dahil diyorum çünkü NXP’nin ürettiği neredeyse tüm ARM’lar seri porttan çok basit bir şekilde programlanabiliyor. Hem de PIC ya da Atmega gibi ayrı bir programlayıcıya ihtiyaç duymadan.*

ARM konusunda belki de en hoşuma giden durumlardan biri de datasheet, örnekler ve driver’lar konusunda. NXP’nin kendi sitesinde ilgili mikrodenetleyici ile ilgili bir çok driver ve örneğe kolayca ulaşabiliyorsunuz. Bir çok firma ARM için derleyici yazmış olsa da benim önereceğim Keil ve IAR ile çok kolay program yazıp, debug edebiliyorsunuz.** Özellikle bu kısımda register içeriklerini an be an görmek çok hoş oluyor. ARM ile ilgili bu kadar övgüyü bir kenara bırakıp ilk demo örneğimizi yapmaya başlayalım.

Çoğu ARM’ın içinde artık RTC birimi bütünleşik halde geliyor ve ARM çalışmasa dahi, aynı RTC entegrelerinde olduğu gibi bir pil ile saatin geri kalmaması sağlanıyor. Hatta ileri bir tarih ve saate alarm kurup, cihazın o an çalışması dahi sağlanabiliyor.
Öncelikle RTC’nin çalışması için 32.768kHz frekansında saat kaynağına ihtiyacımız var ve bu saat kaynağı ARM’ın ana saat kaynağından ya da RTC’den çekilebiliyor. Aşağıdaki resimde saat kaynağının PCLK seçilmesi durumunda bölücü değerinin nasıl hesaplanacağı görülebilir.

RTC_Pre

Yukarıdaki resimde görülen PREINT ve PREFRAC registerlerinin değerleri ise aşağıdaki denklemle hesaplanabilir.

PREINT=(int)(PCLK/32768)-1

PREFRAC=PCLK-((PREINT+1)x32768)

RTC biriminin saat kaynağı belirlendikten sonra saat ve tarih ayarlarının yapılması için aşağıdaki registerlere yazım yapılır ve yine bu registerlerden okuma yaparak ilgili tarih, saat bilgilerine ulaşılır:

SEC: Saniye bilgisi (0-59)
MIN: Dakika bilgisi (0-59)
HOUR: Saat bilgisi (0-23)
DOM: Gün bilgisi (1-31, 1-30, 1-28, 1-29)
DOW: Haftanın günü bilgisi, pazar gününde 0 olacak (0-6)
DOY: Yılın günü bilgisi (1-365, 1-366)
MONTH: Ay bilgisi (1-12)

YEAR: Yıl bilgisi (0-4095)

Ayrıca ARM içerisinde bulunan RTC biriminde alarm ile ilgili ayrı registerler de bulunur. Bu registerlerin neler olduğuna kullandığınız ARM’ın datasheetinden bakabilirsiniz.

Biz ilk örneğimizde RTC’yi yeni bir yıldan 10 saniye öncesine kuralım ve yeni yıla girişte kesme oluşturarak LCD ekrana ‘Yeni Yiliniz/Kutlu Olsun’ yazdıralım. Bu isteğimizi yerine getiren ilgili kod aşağıda görülebilir.

#include "LPC213x.h"
#include "lcd.h"

#define PCLK			12000000
#define RTC_CLK_SRC		1

typedef struct {
    char Sec;     // Saniye değeri 	- [0,59]
    char Min;     // Dakika değeri 	- [0,59]
    char Hour;    // Saat değeri 	- [0,23]
    char Day;     // Saat değeri 	- [1,31]
    char Mon;     // Ay değeri 		- [1,12]
    int  Year;    // Yıl değeri 	- [0,4095]
    char Dow;     // Haftanın günü değeri - [0,6]
} ARM_RTC;

const char DAYS[7][4]={{"PAZR"},{"PZRT"},{"SALI"},{"ÇARŞ"},{"PERŞ"},{"CUMA"},{"CMRT"}};
char yeni_yil_flag=0;

void RTC_isr(void) __irq
{
	if(ILR&0x01)	// Alarm kesmesi mi üretti
	{
		ILR=0x01;	// Kesme yazmacı temizleniyor
		yeni_yil_flag=1;
	}
	VICVectAddr=0;
}

void RTC_init(void)
{
	CCR=0x02;		// RTC değerleri sıfırlanıyor

	if(RTC_CLK_SRC)
	{
	CCR=0x11;
	}
	else
	{
		PREINT=(int)(PCLK/32768)-1;
		PREFRAC=PCLK-((PREINT+1)*32768);
		CCR=0x01;
	}
}

void set_RTC(char RTC_SEC,char RTC_MIN, char RTC_HOUR, char RTC_DOM, char RTC_MONTH, int RTC_YEAR, char RTC_DOW)
{
	DOW    = RTC_DOW;
	YEAR   = RTC_YEAR;
	MONTH  = RTC_MONTH;
	DOM    = RTC_DOM;
	HOUR   = RTC_HOUR;
	MIN    = RTC_MIN;
	SEC    = RTC_SEC;
}

void RTC_read(char *RTC_SEC,char *RTC_MIN, char *RTC_HOUR, char *RTC_DOM, char *RTC_MONTH, int *RTC_YEAR, char *RTC_DOW)
{
	*RTC_DOW	= DOW;
	*RTC_YEAR	= YEAR;
	*RTC_MONTH	= MONTH;
	*RTC_DOM	= DOM;
	*RTC_HOUR	= HOUR;
	*RTC_MIN	= MIN;
	*RTC_SEC	= SEC;
}

int main(void)
{
	char i;
	ARM_RTC RTC;
	lcd_init();
	AMR=0x7F;		// Yil kesmesi aktif
	CIIR=0x80;		// Yil artış kesmesi aktif
	RTC_init();
	set_RTC(50,59,23,31,12,2010,6);

	VICVectAddr0=(unsigned)RTC_isr;	// Kesme vektör adresi
	VICVectCntl0=0x0000002D;		// RTC kesmesi
	VICIntEnable=0x00002000;		// RTC kesmesi aktif

	for(;;)
	{
		RTC_read(&RTC.Sec,&RTC.Min,&RTC.Hour,&RTC.Day,&RTC.Mon,&RTC.Year,&RTC.Dow);
		lcd_gotoxy(1,1);
		veri_yolla(RTC.Hour/10+48);
		veri_yolla(RTC.Hour%10+48);
		veri_yolla(':');
		veri_yolla(RTC.Min/10+48);
		veri_yolla(RTC.Min%10+48);
		veri_yolla(':');
		veri_yolla(RTC.Sec/10+48);
		veri_yolla(RTC.Sec%10+48);
		lcd_gotoxy(2,1);
		veri_yolla(RTC.Day/10+48);
		veri_yolla(RTC.Day%10+48);
		veri_yolla('/');
		veri_yolla(RTC.Mon/10+48);
		veri_yolla(RTC.Mon%10+48);
		veri_yolla('/');
		veri_yolla(RTC.Year/1000+48);
		veri_yolla((RTC.Year%1000)/100+48);
		veri_yolla((RTC.Year%100)/10+48);
		veri_yolla(RTC.Year%10+48);
		lcd_gotoxy(2,12);
		for(i=0;i<4;i++)
			veri_yolla(DAYS[RTC.Dow][i]);

		if(yeni_yil_flag)
		{
			yeni_yil_flag=0;
			lcd_clear();
			lcd_yaz("Yeni Yiliniz");
			lcd_gotoxy(2,1);
			lcd_yaz("Kutlu Olsun..");
			for(;;)
			{
				RTC_read(&RTC.Sec,&RTC.Min,&RTC.Hour,&RTC.Day,&RTC.Mon,&RTC.Year,&RTC.Dow);
				if(RTC.Sec==5)
				{
					lcd_clear();
					break;
				}
			}
		}
	}
}

Kodun çalışma anındaki resmi ise aşağıdan görülebilir.

arm-RTC

Yukarıdaki kodlar çok basit de olsa görüldüğü üzere ARM ve RTC ile çalışmak oldukça kolaydır.
Son olarak ARM ile çalışanlar pin görevlerini seçerken (genelde) 32bitlik iki seçim registeri (PINSELx) ile uğraşmak zorunda kalırlar. Çoğu pin için ayrılan 4 görevi seçmek için kullanılan bu bitlerle hesap yapmak bazen kafa karıştırdığından ben de aşağıda ekran görüntüsü görülebilecek programı yazdım.

PINSEL-arm-program

Programda öncelikle kullanacağınız ARM tipini seçtikten sonra, istediğiniz şekilde pin görevini atayarak çıkan rakamı kullanabilirsiniz.

Programların çalışabilmesi için sisteminizde Microsoft .NET Framework kurulu olması gerekmektedir. Microsoft .NET Framework kurulum dosyasına buradan ulaşabilirsiniz. Ayrıca programı istediğiniz şekilde paylaşıp, kullanabilirsiniz.

Sonuç itibariyle ARM dünyası koca bir okyanus ve uygulama yapmak, eğer uygun donanıma sahipseniz oldukça zevkli.
Herkese iyi çalışmalar dilerim.

* Bu işlem NXP ürünlerinin içinde dahili bootloader bulunmasından kaynaklanıyor. Elbette PIC ya da Atmega’ya da bootloader yükleyip, farklı bir araç olmadan programlayabilirsiniz.

** Debug özelliğini kullanmak için elinizde JTAG kartı bulunması gerektiğini unutmayın.

Program dosyaları: ARM: Hello World

Dosya indirme LINK listesi (TXT formatında) link-21499.zip şifre-pass: 320volt.com

  1. Tolga 2013/05/17
  2. Sarper 2013/05/17
  3. FxDev 2013/05/17
  4. ünal 2013/05/17

Yorum

Soru: