LPC1769 ile 8 Temel Uygulama Bu uygulama notunun amacı, temel seviyede gömülü sistem bilgisi olan arkadaşlara 32 bit ARM Cortex-M3 tabanlı NXP firmasına ait olan LPC1769 hakkında bilgi vermek, temel seviyede 8 adet uygulama geliştirmek ve sıfırdan başlayacak arkadaşlara yardımcı olmaktır. Genel itibari ile Cortex-M3 mimarisi, donanım ve debugging özellikleri hakkında hakkında bilgiler verilecektir. ATAKAN CESİM tarafından hazırlanmıştır.
LPC 1769 ile 8 TEMEL UYGULAMA 2 BOARD ÖZELLİKLERİ 3 LPC1769 ÖZELLİKLERİ 4 LPCXpresso Kullanımı ve Proje Oluşturma 6 UYGULAMA-1 STANDART I/O KULLANIMI ve FLASHING LED 10 UYGALAMA-2 LPC1769 ve 7 SEGMENT UYGULAMASI 12 UYGULAMA-3 HARİCİ EINT1 I/O INTERRUPT VE REED RELAY 15 UYGULAMA-4 LM35 SICAKLIK SENSÖRÜ VE ADC UYGULAMASI 18 UYGULAMA-5 PWM ve MOTOR HIZ KONTROLÜ 21 UYGULAMA-6 LPC1769 ve RÖLE UYGULAMASI 27 UYGULAMA-7 LPC1769 ve RTC UYGULAMASI 29 UYGULAMA-8 LPC1769 ve 16*2 LCD UYGULAMASI 34
LPC 1769 ile 8 TEMEL UYGULAMA Bu uygulama notunun amacı, temel seviyede gömülü sistem bilgisi olan arkadaşlara 32 bit ARM Cortex-M3 tabanlı NXP firmasına ait olan LPC1769 hakkında bilgi vermek, temel seviyede 8 adet uygulama geliştirmek ve sıfırdan başlayacak arkadaşlara yardımcı olmaktır. Genel itibari ile Cortex-M3 mimarisi, donanım ve debugging özellikleri hakkında hakkında bilgiler verilecektir. Uygulamalar geliştirilirken LPC1769 tabanlı LPCXpresso Board u kullanacağız.bu döküman hazırlanırken üreticinin web sayfasından ve ürün datasheet inden faydalanılmıştır. Hali hazırda binlerce ARM tabanlı MCU kullanıcısı ve hızlı bir şekilde gelişen MCU teknolojisi ve pazarı bulunmaktadır. Pek çok firma Cortex-M3 tabanlı cihazlar üretmektedir. Cortex Microcontroller Software Interface Standart ı (CIMSIS) Cortex işlemcileri ve silikon üreticileri arasında code taşınabilirliği sağlamaktadır. LPCXpresso Board LPCXpresso board u Cortex-M3 ile hızlı bir şekilde uygulama geliştirmek için tasarlanmıştır. LPCXpresso board u ile birlikte ücretsiz olan Eclipse tabanlı Code Red IDE si kullanarak uygulamalarımızı geliştireceğiz.arm Cortex-M3 tabanlı LPC1769 board u NXP nin low-cost geliştirme kitidir.embedded Artists,Code Red ve NXP nin ortak çalışması ile geliştirilmiştir.end-to-end çözüm olarak üretim öncesi pek çok uygulama geliştirebileceğimiz bir kittir. Entegre JTAG Debugger ı var, harici emulatöre gerek yoktur. Ücretsiz Eclipse tabanlı IDE ve compiler (128K limitli)
Bildiğimiz pek çok üretici ARM Cortex-M3 core u kullanarak 32 bit mikrodenetleyiciler üretmektedir. Texas Instrument TMS470M,STMicroelectronics STM32 ve NXP firmasına ait LPC17xx serileri örnek olarak gösterilebilir ve bu firmalar ARM tabanlı işlemci dizaynı yapabilme lisansına sahiptirler. Cortex-M3 işlemcisi mikrokontrolör chip inin merkezi işlem birimidir (central processing unit CPU ). Chip üreticileri Cortex- M3 lisansını aldıktan sonra Cortex-M3 işlemcisini kendi silikon dizaynları içerisinde hafıza birimi, peripheral lar, I/O lar ve diğer özellikleri ekleyerek kullanabilmektedir. Bu chip lerin özellikleri ( hafıza, tip, peripheral v.b) üreticiden üreticiye farklılık göstermektedir. Cortex M3 tabanlı örnek chip BOARD ÖZELLİKLERİ Processor NXP's Cortex-M3 LPC1769 microcontroller in LQFP100 package Flash 512 kb Data Memory 64 kb Clock Crystals 12.000 MHz crystal for CPU Dimensions 35 x 140 mm Power 3.15V-3.3V external powering, or from USB via JTAG probe (LPC-LINK) Connectors All LPC1769 pins available on expansion connector (2x27 pin rows, 100 mil pitch, 900 mil between rows) Other Embedded JTAG (LPC-LINK) functionality via LPCXpresso toolchain LPC-LINK can be connected to external target processor after modifications to the LPCXpresso board LED on PIO0_7
LPC1769 ÖZELLİKLERİ Processor ARM Cortex-M3 core with speed up to 120 MHz Flash 512 kb RAM 64 kb Ethernet interface 10/100 Ethernet MAC USB interface USB 2.0 Host USB 2.0 Device USB 2.0 OTG Serial interfaces 2xCAN, 4xUART, 3xI2C, 2xSSP, 1xI2S Timers Four 32-bit counter/timers One Watchdog timer PWM/Motor controller PWM/timer block Motor control PWM with support for three-phase motor control Quadrature encoder interface ADC/DAC 12-bit ADC with input multiplexing among 8 pins Single 10-bit DAC output Other Serial Wire Debug and Serial Wire Trace Port Integrated PMU to minimize power consumption Three reduced power modes: Sleep, Deep-sleep, and Deep power-down Code Read Protection (CRP) with different security levels
LPC1769 ÖZELLİKLERİ
LPCXpresso IDE si ve Board u LPCXpresso Kullanımı ve Proje Oluşturma Bu bölümde kullanacağımız IDE hakkında bilgi verip, proje oluşturacağız. Daha sonraki uygulamalarımızı aynı şekilde gerçekleyeceğiz.öncelikle aşağıdaki linkten uygulamayı indirelim, kuralım ve aktivasyonunu yapalım. http://www.lpcware.com/lpcxpresso/download Aktivasyon işlemini yaparken öncelikle programı kurup Help menüsü altında sırayla; Help - Active LPCXpresso (Free Edition) - Create serial number and register Yukardaki işlemleri yaptıktan sonra bizim için oluşturulan seri numara ile yine aşağıdaki sayfadan kendimiz için aktivasyon kodu oluştururuz.oluşturulan kodu Help - Active LPCXpresso (Free Edition) Enter Activation Code kısmına gireriz. http://www.lpcware.com/lpcxpresso/activate Bu şekilde 128K limitli lisansımızı yapmış olduk.
LPCXpresso Aktivasyonu LPCExpresso uygulama perfektifidevelop ve debug olarak iki kısımdan oluşur aşağıda gösterildiği gibidirler. Project Explorer View :workspace içerisinde bulunan projeleri gösterir. Editor : Source code yazdığımız ve debug için breakpointleri kullandığımız kısım Console ve Problem Views : Compile ve debug hatalarını, program çıktılarını gördüğümüz kısım Quick Start View : Hızlı bir şekilde Projelerin build, dubug ve import işlemlerini yaptığımız kısımdır. LPCXpresso Develop Persfektifi
Peripheral View : Debug yapılırken peripheralların anlık durumu gösterilir Debug View : Step step yada full speed kod işlettiğimiz kısım Editor : Debug yapılırken execute edilen kodları gördüğümüz kısım Console View : Compile, debug, program output, memory ve peripheral register bilgilerini gördüğümüz kısım Quick Start View : Hızlı bir şekilde Projelerin build, dubug ve import işlemlerini yaptığımız kısımdır. LPCXpresso Debug Persfektifi The Cortex Microcontroller Software Interface Standard (CMSIS) ARM CortexM tabanlı sistemlerde developer ve vendorlar için yazılım paketlerini yeniden kullanılabilir yapar. CortexM serisi için üreticiden bağımsız şekilde kütüphanelerin kullanılabilir olmasını sağlar. Üreticiler için source code yazımı ve debug yapmayı standart haline getirmeyi amaçlamıştır.yani bir St ye ait Cortex serisi için kullandığımız CIMSIS kütüphanesini NXP firmasına ait bir Cortex serisi için de kullanabiliriz. Bizde projelerimizi oluştururken workspace CIMSIS kütüphanesini ekleyeceğiz. CIMSIS kütüphanesini workspace eklemek için Quick Start panelinden Import Project e tıklayalım.archive butonuna tıklayalım ve açılan pencereden NXP_LPCXpresso1769_MCB1700_2011-02-11.zip isimli sıkıştırılmış dosyayı seçelim(aşağıda gösterilmiştir) ve ileriye tıklayalım ve son olarak açılan pencereden sadece için CIMSISv2_LPC17xxseçelim.Bu sayede workspace CIMSIS eklenmiş oldu. Amacımız lpc17xx.h kütüphanesini kullanabilmek.
NXP_LPCXpresso1769_MCB1700_2011-02-11rar sıkıştırılmış dosyası Artık LPC1769 için bir proje oluşturabiliriz.bunun için sırası ile ; Quick Start panelinden New Project e tıklanır. LPC13/ LPC17/ LPC18/ seçilir, daha sonra LPC175x_6x seçilir ve en son C Project seçilir, devam edilir. Proje ismi girilir ve Use default location tıklanıp ileriye basılır ve Target seçilir. Target için LPC1769 seçilir ve ileriye tıklanır. LPCOpen Chip Library için CIMSISv2_LPC17xx seçilir ve ileriye tıklanır. Enable CRP in the target image kısmı nı işaretlemeyin ve Finish e tıklanarak projemiz oluşturulur. Proje oluşturulduktan sonra projeye sağ tıklayıp Properties den özelliklere girilerek Project References kısmından CIMSISv2_LPC17xx. Ayrıca yine Properties de Run/Debug settings de bizim projemizin gözükmesi gerekmektedir.artık main.c dosyamızda kodlarımızı yazabiliriz. LPCXpresso IDE ile birlikte gelen hazır projelerden bir tanesi işimizi kolaylaştıracağından Quick Start Panelinden Import Project ile hazır gelen projelerden herhangi birisini açıp source code üzerinde değişiklik yapabiliriz. Bu kısımda sıra ile 8 adet proje yapılacak ve LPC1769 un birimleri kullanılacaktır.
UYGULAMA-1 STANDART I/O KULLANIMI ve FLASHING LED Hello World uygulaması olarak kabul edeceğimiz bu uygulamada 4 adet led LPC1769 un P2 portuna bağlanarak (P2.0, P2.1, P2.2, P2.3 I/O ları) yakıp-söndürme işlemi yapılacaktır. P2.0-3 I/O larına bağlı ledler P2 portuna bağlı (0-4) I/O lar çıkış olarak atantı. LPC_GPIO2->DIR // I/O'ların giriş-çıkış yönlendirmesi yapılır. LPC_GPIO2->FIOSET //Çıkış olarak atanan I/O'ların lojik 1'e seviyesine çekilmesini LPC_GPIO2->FIOCLR // Çıkış olarak atanan I/O'ların lojik 0' seviyesine düşürülmesi Yukarde gösterildiği gibi şekilde belirtilen I/O lar çıkış olarak atandı.uygulamalar yapılmadan önce LPC17xx.h ile gösterilen kütüphanenin incelenmesi kafamızda oluşan soru işaretlerini giderecektir. Örnek olarak LPC_GPIO2 LPC_GPIO_TypeDef türünden bir struct olarak tanımlanmıştır. Bu bilgiler kütüphane içerisinde mevcut.uygulamada Position isminde bir fonksiyonumuz var ve lederin hangi sırayla ve bu fonksiton içerisinde ledlerin hangi şekilde yanması gerektiğini belirttik.yine Delayme süreleri bu fonksiyon içerisinde artırılıp azaltılıyor.
Uygulamaya ait video aşağıdaki linkte mevcuttur. http://www.youtube.com/watch?v=8kdukthc1uw void Delay(int sure); void Delay (int sure) int var,var1; for (var = 0; var < sure; ++var) for (var1 = 0; var1 < sure; ++var1) voidposition(int x); voidposition(int x) LPC_GPIO2->FIOSET = (0x00000000);Delay(x); LPC_GPIO2->FIOCLR = (0x0000000F);Delay(x); //P2.'ye ait tüm I/O'lar lojik 0 LPC_GPIO2->FIOSET = (0x00000001);Delay(x); //P2.0 (1.led) lojik 1 LPC_GPIO2->FIOCLR = (0x0000000F);Delay(x); LPC_GPIO2->FIOSET = (0x00000002);Delay(x); //P2.1 (2.led) lojik1 LPC_GPIO2->FIOCLR = (0x0000000F); Delay (x); LPC_GPIO2->FIOSET = (0x00000004); Delay (x); //3.Led LPC_GPIO2->FIOCLR = (0x0000000F); Delay (x); LPC_GPIO2->FIOSET = (0x00000008); Delay (x); //4.Led LPC_GPIO2->FIOCLR = (0x0000000F); Delay (x); LPC_GPIO2->FIOSET = (0x00000004); Delay (x); //1ve2.Led LPC_GPIO2->FIOCLR = (0x0000000F); Delay (x); LPC_GPIO2->FIOSET = (0x00000002); Delay (x); //1ve3.Led LPC_GPIO2->FIOCLR = (0x0000000F); Delay (x); LPC_GPIO2->FIOSET = (0x00000001); Delay (x); //1ve4.Led LPC_GPIO2->FIOCLR = (0x0000000F); Delay (x); LPC_GPIO2->FIOSET = (0x00000003); Delay (x); //2ve3.Led LPC_GPIO2->FIOCLR = (0x0000000F); Delay (x); LPC_GPIO2->FIOSET = (0x00000006); Delay (x); //2ve4.Led LPC_GPIO2->FIOCLR = (0x0000000F); Delay (x); LPC_GPIO2->FIOSET = (0x0000000C); Delay (x); //3ve4.Led LPC_GPIO2->FIOCLR = (0x0000000F); Delay (x); LPC_GPIO2->FIOSET = (0x00000006); Delay (x); //2ve4.Led LPC_GPIO2->FIOCLR = (0x0000000F); Delay (x); LPC_GPIO2->FIOSET = (0x00000003); Delay (x); //2ve3.Led LPC_GPIO2->FIOCLR = (0x0000000F); Delay (x); LPC_GPIO2->FIOSET = (0x00000007); Delay (x); //2ve3.Led LPC_GPIO2->FIOCLR = (0x0000000F); Delay (x); LPC_GPIO2->FIOSET = (0x0000000E); Delay (x); //2ve3.Led // Position fonksiyonun sonu.
UYGALAMA-2 LPC1769 ve 7 SEGMENT UYGULAMASI LPC1769 a ait olan P2.0-7 I/O ları kullanılarak 7 segment uygulaması yapılacaktır.bir adet 7 segment kullanılacak ve 0 dan 9 a kadar saydırma işleme yapılacaktır.sayım yapılırken Delayme süresi belirli miktara kadar artırılıp daha sonra sıfırlanıp sürekli belirlenen miktara kadar artırılacaktır.kullanılan 7 segment ortak katotludur ve bu yüzden yakmak istediğimiz segment lojik 1 yapılmalıdır.uygulamaya ait video aşağıdaki linkte mevcuttur. https://www.youtube.com/watch?v=ytfnig6vl8w Ortak katot 7 Segment 7 Segment ve LPC1769 bağlantısı
CRP Seçenekleri CRP donanım/yazılım etkileşimi
CRP constunsignedint CRP_WORD = CRP_NO_CRP ; /* Code Read Protection on-chip flash'a erişim seviyelerini belirlemek ve ISP(In system programming) kısıtlamak için kullanılır. Üç seçenek vardır CRP1,CRP2,CRP3 */ #include"lpc17xx.h" #include"type.h" void Delay(int delay); void Delay(int delay) int var,var1; for (var = 0; var < delay; ++var) for (var1 = 0; var1 < 1000; ++var1) char numbers[11]=0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x80; intmain (void) SystemClockUpdate(); //SystemFrequency güncelleniyor. LPC_GPIO2->FIODIR&= 0x00; LPC_GPIO2->FIODIR = 0xFF ; /* P2.xx ÇIKIŞ */ LPC_GPIO2->FIOCLR = 0xFF ; // 0 Volt LPC_GPIO2->FIOSET = 0xFF ; int counter=0; int delay=0; while(1) LPC_GPIO2->FIOCLR = 0xFF; LPC_GPIO2->FIOSET = numbers[counter]; Delay(delay); delay+=50; ++counter; if(delay>5000) delay=0; if(counter==10) counter=0; LPC_GPIO2->FIOCLR = 0xFF; LPC_GPIO2->FIOSET = numbers[10]; Delay(delay);
UYGULAMA-3 HARİCİ EINT1 I/O INTERRUPT VE REED RELAY Uygulama-2 deki konfigurasyona ek olarak P2.11 I/O su kullanılarak harici kesme oluşturulacaktır ( EINT1 external interrupt input 1 ). Herbir kesme sonrası 7 segmentteki değer 1 artırılıp 9 a geldikten sonra sıfırlanacaktır. Düşen kenarda yani lojik 1 den lojik 0 a geçişlerde kesme oluşturulacaktır. Reed röle ve mıknatıs kullanılarak gerçekleştirilecektir. 7 Segment, Reed Röle ve LPC1769 bağlantısı Yukardaki dizayndan görüldüğü gibi reed röle NO ( normal open ) durumunda ve P2.11 I/O su R1 üzerinden VCC yani lojik 1 seviyesini görür. Mıknatıs yaklaştırıldığında reed röle kısa devre durumuna geçer ve P2.11 I/O su lojik 0 seviyesini görür (düşen kenar kesmesi için gerekli durum) ve bu durumda EINT1 için kesme oluşturulup gerekli işlem yapılır. Uygulamaya ait video aşağıdaki linkte mevcuttur. https://www.youtube.com/watch?v=xluxejxs-ve İlk iki uygulamada kullandığımız tüm pin ler genel amaçlı input/output olarak kullanıldığı için giriş-çıkış atamaları (LPC_GPIO2->FIODIR, LPC_GPIO2->FIOSET, LPC_GPIO2- >FIOCLR ) dışında bir konfigurasyon yapılmadı. Bu uygulamamızda P2.11 giriş-çıkış kesme oluşturan dijital giriş ( EINT 1 ) olarak kullanılacağından ayrı konfigurasyonların yapılması gerekmektedir(um10360.pdf, sayfa 110). Ayrıca kullanacağımız pin fonksiyon register ı ile P2.11 in EINT1 olarak tanımlanması gerekmektedir. 23 bit 0 ve 22 bit 1 yapılarak EINT1 fonksiyonu P2.11 için aktif edilir.
Harici interrupt donanım yapısı Ayrıntılı bilgi için (UM10360.pdf, sayfa 23 ve sonrası okunabilir). Harici kesme register ları
CRP constunsignedint CRP_WORD = CRP_NO_CRP ; #include"lpc17xx.h" #include"type.h" voiddelay(int delay); voiddelay(int delay) int var,var1; for (var = 0; var < delay; ++var) for (var1 = 0; var1 < 1000; ++var1) char numbers[11]=0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x80; int counter=0; intmain (void) SystemClockUpdate(); LPC_GPIO2->FIODIR&= 0x00; LPC_GPIO2->FIODIR = 0xFF ; /* P2.xx ÇIKIŞ */ LPC_GPIO2->FIOCLR = 0xFF ; // 0 Volt LPC_GPIO2->FIOSET = 0xFF ; LPC_PINCON->PINSEL4 = 0x00400000; /* P2.11 => EINT1 */ LPC_GPIOINT->IO2IntEnF = 0x800; /* Düşen kenarda */ LPC_SC->EXTMODE = 0x00000002; /* INT1 kenar tetiklemeli */ LPC_SC->EXTPOLAR = 0; /* default olarak düşen kenarda INT1 */ NVIC_EnableIRQ(EINT1_IRQn); PC_GPIO2->FIOCLR = 0xFF ; LPC_GPIO2->FIOSET = numbers[0]; /* 7 Segmente 0 yazılıyor. */ while(1) voideint1_irqhandler(void) LPC_SC->EXTINT = 0x2; // EINT1 flag siliniyor. Her bir kesme de set edilerek sıfırlanıyor. ++counter; LPC_GPIO2->FIOSET = numbers[counter]; if(counter==10) counter=0; LPC_GPIO2->FIOCLR = 0xFF ; LPC_GPIO2->FIOSET = numbers[counter];
UYGULAMA-4 LM35 SICAKLIK SENSÖRÜ VE ADC UYGULAMASI Bu uygulamada LPC1769 un ADC birimi kullanılacaktır. AD05 kanalı kullanılacak ve LM35 in çıkışı okunup gerekli hesaplamalardan sonra ölçülen sıcaklığa göre uyarı ledi (P2.0 a bağlı led) yakılıp/söndürülecektir (21 dereceden fazla ise led yanacak).uygulamaya ait video aşağıdaki linkte mevcuttur. https://www.youtube.com/watch?v=-o16fyqmw0s LM35 pin isimleri LPC1769 ve LM35,LED bağlantısı Önceki uygulamalardan farklı olarak ADC birimi kullanılacaktır. ADC briminin AD05 kanalı kullanılacaktır.lpc1769 üzerinde 8 kanal 12 bit ADC bulunmaktadır.basit ADC konfigurasyonu için aşağıdaki adımlar incelenmelidir ve kodlarda uygulanmıştır,ayrıntılı bilgi için (UM10360.pdf, sayfa 574); AD05 fonksiyonu için gerekli pinselect regester ın 31. ve 30. bitleri lojik 1 olmalıdır.
PCONP(Power control peripheral register) register i üzerinde PCADC bit i (12.bit yani (1<<12) ) set edilerek ADC için power aktif edilmelidir.reset durumunda ADC disabled durumdadır, PCADC set edildikten sonra AD0CR içerisindeki PDN biti set edilmelidir. ADC yi disable duruma getirirken ilk olarak PDN biti ve daha sonra PCADC biti silinir. ADC pinlerini aktif etmek için gerekli PINSEL register ları üzerinde değişiklik yapılır. ADC kesmesi aktif edilir (main içerisinde). ADC çevrimi başlatılır. ADC çevrimi bittiğinde ADC_IRQHandler fonksiyonu çalıştırılır ve okunan değerler burda alınır işlemimize göre okunan değer işlenir.okuma sırasında ADC_IRQHandler içerisinde ADC çevrimi durdurulur.okunan değerler ADC nin GDR register ının 15-4. Bitleri arasındadır. 4 bit sağa kaydırıp 0xFFF ile and işlemine tabi tutulup değer okunur ve sonra gerekli işlemler yapılır.
CRP constunsignedint CRP_WORD = CRP_NO_CRP ; #include"lpc17xx.h" #include"type.h" voiddelay(int a,int b); voiddelay(int a,int b) int var,var1; for (var = 0; var < a; ++var) for (var1 = 0; var1 < b; ++var1) voidconverttemp(); voidconverttemp() LPC_SC->PCONP = (1<<12);// Power konfig registerindan ADC power enable edilir. LPC_ADC->CR =(1<<21); //PDN biti set edilir. (Bknz User Manual). LPC_ADC->CR =(1<< 5); //ADC0'ın 5inci kanalını kullanacağız. LPC_PINCON->PINSEL3&= ~(3<<30); //5inci kanal P1.31'de o yüzden konfig ediyoruz. LPC_PINCON->PINSEL3 = (3<<30); LPC_ADC->CR =(1<< 8); LPC_ADC->CR =(1<<24); voidadc_irqhandler(void) // Konfig P1.31 = AD0.5 // Çevirimi başlatıryoruz //Her çevirim tamamlanmasında kod ADC Kesmesine düşer yani buraya. LPC_ADC->CR&= ~(7<<24); // Çevirim durdurulur. float val = ((LPC_ADC->GDR>> 4) & 0xFFF); // Okunan değer ler 15-4 bitleri arasındadır,4bit sağa kaydırılır.(bknz User Manual). //Aşağıdaki işlemler LM35'in ve referans voltajı(3.3v) için hesaplanmıştır.35 dereceden fazla ise uyarı ledi yanmaktadır. float hvcc=0x00000fff; float Vcc=3.3; float measuredvoltagefromadc=((val/hvcc)*vcc); float measuredtemperaturefromlm35=measuredvoltagefromadc*100; if(measuredtemperaturefromlm35>=21) else LPC_GPIO2->FIOCLR = 0x01; intmain (void) SystemClockUpdate(); LPC_GPIO2->FIODIR&= 0x00; LPC_GPIO2->FIODIR = 0x01 ; /* P2.0 ÇIKIŞ */ LPC_GPIO2->FIOCLR = 0x01 ; // 0 Volt NVIC_EnableIRQ(ADC_IRQn); while(1) delay(1000,3000); converttemp(); LPC_GPIO2-IOSET = 0x01;
UYGULAMA-5 PWM ve MOTOR HIZ KONTROLÜ Bu uygulamada LPC1769 mikrodenetleyicisinin PWM ( Pulse width Modulation ) birimi kullanılacaktır ve LPC1769 üzerinde 6 tane PWM kanalı vardır. P2.0 ın bir diğer fonksiyonu PWM1.1 i gerçeklemesidir ve ADC uygulamamızda yaptığımız gibi gerekli pinselect register ına gerekli değerleri yazmamız gerekecektir. Uygulamada PWM1.1 kanalı single edge PWM olarak kullanılacaktır. Single edge PWM de output her bir periotta lojik 1 seviyesinden başlayacak ve belirlenen duty/cycle sonunda output lojik 0 olacaktır.iki tane match register i single edge PWM için kullanılır. 3 match regester i double edge PWM için kullanılır. M0 periyodunda M1 single edge, M2 ve M3 double edge için kullanıldı Yukardaki örnekte MR0 periyot süresini tutan register, MR1 single edge için doluluk oranını tutan register, MR2 ve MR3 double edge için doluluk oranının periyot içerisinde başlayacağı ve biteceği yeri tutan register. PWM belirli bir periyot ile salınım yapan kare dalganın duty/cycle yani doluluk ve boşluk oranları değiştirilerek toplam periyot içerisinde kare dalganın ortalamısının alınmasıdır ve ortalama bir dc volt elde etmiş oluruz. Aşağıdaki örnekte gösterilmiştir.uygulamaya ait video aşağıdaki linkte mevcuttur. http://www.youtube.com/watch?v=z6ipffo_elu Örnek duty/cycle gösterimi
Bu şekilde oluşturulan periyodik kare dalgaların ortalaması ortalama DC olur. Uygulamalarda kare duty/cycle oranları değiştirilerek istenilen işlemler yapılır. Bu uygulamada bir DC motorun dönme hızı periyodik olarak duty/cycle oranı artırılarak artırılacaktır. Uygulamada işlemcimizin dahili IRC osilatörü ( 4Mhz ) kullanılacaktır.bizim uygulamamızda pwm timer counter ı her bir 100000 clock ta yani 1/40 sn de 1 artacak ve 1 saniye içerisinde 40 a ulaştığında yeniden sıfırlanıp 40 a kadar artacak. Yani periyodumuz 1 saniye. Uygulamamızda sırası ile aşağıdaki duty/cycle oranları uygulanıp Delaymeler ile motor hızı yavaş yavaş artırılacaktır ve %100 duty/cycle dan sonra tekrar %0 duty cycle dan başlanacaktır. 0/40 = %0 5/40 = %12.5 10/40 = %25 15/40 = %37.5 20/40 = %50 25/40 = %62.5 30/40 = %75 35/40 = %87.5 40/40 = %100 Uygulamada bir adet LD293 motor sürücü kullanılmalıdır (H köprüsü).gerekli bağlantı şeması aşağıda gösterilmiştir. LD293 bağlantı şeması Yukardaki şemaya göre 1.pin enable ucu,pin 2 ve 7 yön belirlemedir. Örneğin pin1 lojik 1 pin 2 lojik 1 ve pin 7 de lojik 0 durumunda motor bir yöne dönecek ve diğer yöne döndermek için pin 2 lojik 0 ve pin 7 de lojik 1 yapılmalıdır. Pin1 yani enable pini lojik 0 olursa motor duracaktır.
LD293 ve LPC1769 bağlantısı Enable pini yani pin1 direk lojik1 e çekildi. MOTOR1 ve MOTOR2 dc motora giden uçlar.yön için P2.0 ve P2.1 kullanılacak ve LPC1769 ile bağlantısı yapılması gereken uçlardır. Basit PWM konfigurasyonu için aşağıdaki adımlar incelenmelidir ve kodlarda uygulanmıştır ve test edilmiştir, ayrıntılı bilgi için (UM10360.pdf, sayfa 509); PCONP register ı üzerinde PCPWM1 biti set edilmelidir. Mikrodenetleyici resetlenip yeniden başlatıldığında default olarak set durumundadır bu yüzden uygulamada bu adım direk geçilebilir(pcpwm=1). Gerekli PINSEL register ı (PINSEL4) üzerinde PWM1.1 için 0.bit 1 1.bit 0 yapılmaldır. PWM1.1 için 0.bit 1 1.bit 0 yapılmaldır. PWM birminin TCR register ı reset edilmelidir. Yani counter reset edilmelidir. (LPC_PWM1->TCR = TCR_RESET;)TCR (Timer Control Register ) Ve timer control fonksiyonun gerçeklerken dikkat edilecek prescale değeri girilmelidir. PR ( Prescale Register).TC (Timer Counter) peripheral clock un her bir PR+1 inde bir artar.
TC nin resetlenişi ve interrupt oluşumunun kontrolü için MCR nin(match Control Register) PWMMR0I biti yani 1.biti set edilmelidir (LPC_PWM1->MCR =(1<<0);) PWM cycle değerlerinin girilmesi (MR0 periyodu ve MR1 PWM1.1 için duty süresi) Örneğin MR0 = 40 ve MR1=20 ile %50 duty/cycle oranı elde edebiliriz. PWM Latch enable edilir ( LPC_PWM1->LER = (1<<0); ) PWM interrupt ı enable edilir ( NVIC_EnableIRQ(PWM1_IRQn);) Yukarda beliritlen konfigurasyon PWM init içindir. Uygulama esnasında duty/cycle oranı değiştirirken MR1 değeri değiştirilir. Single edge ve double edge PWM olarak iki şekilde uygulanabilir. Uygulamamızda single edge PWM yapılmıştır. Single ve double edge PWM ler
#include<cr_section_macros.h> #include<nxp/crp.h> CRP constunsignedint CRP_WORD = CRP_NO_CRP ; #include"lpc17xx.h" #include"type.h" volatileuint32_t match_counter0, match_counter1; voiddelay(int delay); uint32_tpwm_init( uint32_t channelnum, uint32_t cycle ); voidpwm_set( uint32_t channelnum, uint32_t cycle, uint32_t offset ); voidpwm_start( uint32_t channelnum ); voidpwm_stop( uint32_t channelnum ); voidpwm1_irqhandler (void) uint32_t regval; regval = LPC_PWM1->IR; if ( regval & (1<<0) ) match_counter1++; LPC_PWM1->IR = regval; return; uint32_tpwm_init( uint32_t ChannelNum, uint32_t cycle ) if ( ChannelNum == 1 ) match_counter1 = 0; LPC_PINCON->PINSEL4 = 0x00000001; LPC_PWM1->TCR = 0x01; /* Counter Reset */ LPC_PWM1->PR = 100000-1; LPC_PWM1->MCR =0x01; LPC_PWM1->MR0 = 40; /* PWM periyodu */ LPC_PWM1->MR1 =20; /* duty/cycle oranı */ LPC_PWM1->LER = (1<<0); /*PWM1.1 enable */ else return ( FALSE ); NVIC_EnableIRQ(PWM1_IRQn); return (TRUE); voidpwm_set( uint32_t ChannelNum, uint32_t cycle, uint32_t offset ) if ( ChannelNum == 1 ) LPC_PWM1->MR0 = 40; LPC_PWM1->MR1 =offset; LPC_PWM1->LER = (1<<0); return;
voidpwm_start( uint32_t channelnum ) if ( channelnum == 1 ) LPC_PWM1->PCR = 0x00 ; LPC_PWM1->TCR = 0x00000001 0x00000008;/*counter and PWM1.1 enable */ return; voidpwm_stop( uint32_t channelnum ) if ( channelnum == 1 ) LPC_PWM1->PCR = 0x00; LPC_PWM1->TCR = 0x00; /* Stop PWM1.1*/ return; voiddelay(int delay) int var,var1; for (var = 0; var < delay; ++var) for (var1 = 0; var1 < 1000; ++var1) intmain (void) uint32_t offset ; SystemClockUpdate(); if ( PWM_Init( 1, 0 )!= TRUE ) while( 1 ); offset=0; PWM_Set( 1, 40, offset ); PWM_Start( 1 ); while ( 1 ) offset+=5; DELAY(10000); if ( match_counter1!= 0 ) match_counter1 = 0; PWM_Set( 1, 40, offset ); if(offset==40) offset=0;
UYGULAMA-6 LPC1769 ve RÖLE UYGULAMASI Bu uygulamada bir adet röle kullanılıp anahtarlama yapıldı. P2.0 I/O su GPIO yani genel amaçlı input/output peripheral olarak kullanıldı. Uygulamaya ait video aşağıdaki linkte mevcuttur. http://www.youtube.com/watch?v=87j8qg5i0x4 Uygulamada birer adet transistör, diyot, röle ve led kullanılmıştır, bağlantı şeması aşağıdaki gibidir.
#include<cr_section_macros.h> #include<nxp/crp.h> CRPconstunsignedint CRP_WORD = CRP_NO_CRP ; #include"lpc17xx.h" #include"type.h" voiddelay(int delay); int counter=0; voiddelay(int delay) // Mikrodenetleyiciye 0 dan istenilen değere kadar saydırma yaptırılıyor. int var,var1; for (var = 0; var < delay; ++var) for (var1 = 0; var1 < 1000; ++var1) intmain (void) /* SystemClockUpdate() updates the SystemFrequency variable */ SystemClockUpdate(); LPC_GPIO2->FIODIR&= 0x00; LPC_GPIO2->FIODIR = 0x01 ; /* P2.0 ÇIKIŞ */ LPC_GPIO2->FIOCLR = 0x01 ; // lojik 0 yapıldı. while(1) LPC_GPIO2->FIOCLR = 0x01 ; // Röle bırakıyor. Led sönüyor. DELAY(10000); LPC_GPIO2->FIOSET = 0x01; ; // Led yanıyor. DELAY(10000);
UYGULAMA-7 LPC1769 ve RTC UYGULAMASI RTC (Real Time Clock), LPC1769 için 3 adet clock kaynağı mevcut. RTC donanımı doğrudan RTC osilatörünü kullanmaktadır. RTC bloğu 20 byte lık batarya beslemeli backup register ına sahiptir. Chip in enerji kaynağının kesilmesi durumunda sistem durumu bu registerlara aktarılabilir. Standart 3 V batarya kullanılabilir. Batarya voltajı 2.1 Volt un altına düşene kadar RTC çalışır.rtc interrupt u CPU yu herhangi bir power save moddan uyandırabilir. RTC nin belirli özellikleri aşağıda belirtilmiştir (UM10360.pdf, sayfa 558). Saniye,dakika,saat, ayın günü,yıl,haftanın günü ve yılın günü bilgilerini tutabilir. Batarya beslemeli çalışacağından çok düşük güç tüketimi vardır.batarya ile besleme de 1 ua den daha az tüketim. 32 khz ultra low power osilatör. RTC güç beslemesi chip in diğer kısımlarından izole edilmiştir. Belirlenen zamanalrda alarm interrupt ları oluşturulur. RTC 1 Hz dahili zaman referansı ile 32 khz lik bir osilatör kullanır. RTC donanım yapısı
RTC fonksiyonel blok şeması RTC biriminin ALARM register ları ile alarm bilgisi TIME register ları ile de zaman bilgisi tutulmaktadır. ALARM register ları ile zaman register ları birbirine eşit olduğu zaman interrupt oluşturulur. Ayrıca saniye,dakika,saat,ayın günü,haftanın günü,yılın günü,ay,yıl değişimlerinde de kesme oluşturulabilmektedir. ILR(Interrupt Location Register): RTCCIF(0.bit): Counter Increment Interrupt bloğu tarafından kesme oluşturulmuş ise bu bit set edilerek counter increment interrupt bayrağı silinir. voidrtc_irqhandler (void) LPC_RTC->ILR = 0x01; /* clear counter increment interrupt flag */ return; RTCALF(1.bit):Eğer alarm kesmesi oluşmuşsa bu bit set edilerekalarm interrupt bayrağı silinir. CCR(Clock Control Register): CLKEN(0.bit): RTCcounter ını aktif eder. 1 olduğunda counter aktif 0 olduğunda pasiftir.rtc nin başlaması için 1 olması gerekmektedir. /*--- Start RTC counters ---*/LPC_RTC->CCR = 0x01; CLKRST(1.bit):Counter ı resetlemeye yarar. Değeri 1 olduğunda counter resetlenir. /*--- Reset RTC counters ---*/ LPC_RTC->CCR = 0x02;
CIIR(Counter Increament Interrupt Register) Bu register sayesinde istenilen zaman dilimlerinde interrup oluşması sağlanabilir.bu register ın ilk 8 bitinden hangisi 1 yapılırsa o sürede 1 interrupt oluşur.örneğin 1.biti set edilerek her bir dakikada bir interrupt oluşturulur. LPC_RTC->CIIR = 0x01; CIIR register ve bitleri RTC_AUX(RTC_Auxililary Control Register) Bu registerın 4. biti RTC osilatörü fail durumunda ve RTC birimi ilk enerjilendiğinde 1 olur ve interrupt oluşturulur.interrupt durumunda 4.bit tekrar set edilerek interrupt bayrağı silinir. /* If RTC is stopped, clear STOP bit. */ if ( LPC_RTC->RTC_AUX& (0x1<<4) ) LPC_RTC->RTC_AUX = (0x1<<4); Diğer register lar için (UM10360.pdf, sayfa 558 den)itibaren inceleyiniz.
#include<cr_section_macros.h> #include<nxp/crp.h> // Variable to store CRP value in. Will be placed automatically // by the linker when "Enable Code Read Protect" selected. // See crp.h header for more information CRP constunsignedint CRP_WORD = CRP_NO_CRP ; #include"lpc17xx.h" #include"type.h" typedef struct uint32_t RTC_Sec; uint32_t RTC_Min; uint32_t RTC_Hour; uint32_t RTC_Mday; uint32_t RTC_Mon; uint32_t RTC_Year; uint32_t RTC_Wday; uint32_t RTC_Yday; RTCTime; /* Saniye*/ /* Dakika*/ /* Saat*/ /* Ayın gunu*/ /* Ay*/ /* Yıl*/ /* Haftanın gunu*/ /* Yılın gunu*/ void RTC_IRQHandler (void); void RTCInit( void ); void RTCStart( void ); void RTCStop( void ); void RTC_CTCReset( void ); void RTCSetTime( RTCTime ); RTCTime RTCGetTime( void ); RTCTime local_time; voidrtc_irqhandler (void) LPC_RTC->ILR = 0x01; /* interrupt bayrağını siliyoruz */ return; voidrtcinit( void ) LPC_SC->PCONP = (1 << 9);/* Enable RTC CLOCK */ if ( LPC_RTC->RTC_AUX& (0x1<<4) ) LPC_RTC->RTC_AUX = (0x1<<4); /* RTC durursa, stop biti sil. */ LPC_RTC->AMR = 0; //Alarm mask register LPC_RTC->CIIR = 0; //Counter Incremenet Interrupt register LPC_RTC->CCR = 0; //Clock Control Register return; voidrtcstart( void ) LPC_RTC->CCR = 0x01;/*--- RTC counter ı başlatıyoruz ---*/ LPC_RTC->ILR = 0x01; return; voidrtcstop( void ) LPC_RTC->CCR&= ~(0x01);/* counter ı durduruyoruz*/ return;
voidrtc_ctcreset( void ) /*--- Reset CTC ---*/ LPC_RTC->CCR = 0x02; return; voidrtcsettime( RTCTime Time ) LPC_RTC->SEC = Time.RTC_Sec; LPC_RTC->MIN = Time.RTC_Min; LPC_RTC->HOUR = Time.RTC_Hour; LPC_RTC->DOM = Time.RTC_Mday; LPC_RTC->DOW = Time.RTC_Wday; LPC_RTC->DOY = Time.RTC_Yday; LPC_RTC->MONTH = Time.RTC_Mon; LPC_RTC->YEAR = Time.RTC_Year; return; RTCTimeRTCGetTime( void ) RTCTime LocalTime; LocalTime.RTC_Sec = LPC_RTC->SEC; LocalTime.RTC_Min = LPC_RTC->MIN; LocalTime.RTC_Hour = LPC_RTC->HOUR; LocalTime.RTC_Mday = LPC_RTC->DOM; LocalTime.RTC_Wday = LPC_RTC->DOW; LocalTime.RTC_Yday = LPC_RTC->DOY; LocalTime.RTC_Mon = LPC_RTC->MONTH; LocalTime.RTC_Year = LPC_RTC->YEAR; return ( LocalTime ); intmain (void) /* SystemClockUpdate() updates the SystemFrequency variable */ SystemClockUpdate(); /* RTC modülü başlatıyoruz */ RTCInit(); local_time.rtc_sec = 0; local_time.rtc_min = 0; local_time.rtc_hour = 0; local_time.rtc_mday = 5; local_time.rtc_wday = 3; local_time.rtc_yday = 64; local_time.rtc_mon = 3; local_time.rtc_year = 2014; RTCSetTime( local_time ); /* Set local time */ NVIC_EnableIRQ(RTC_IRQn); LPC_RTC->CIIR = 0x02; /* Her bir dakikada interrupt oluşturulacak*/ RTCStart(); while (1) /*BU örnekte her bir dakikada interrupt oluşacak.interrupt durumunda yapmak istediğiniz işlemleri RTC_IRQHandler() interrupt fonksiyonu içerisinde yapabiliriz*/
UYGULAMA-8 LPC1769 ve 16*2 LCD UYGULAMASI 16x2 lcd uygulaması yapılmıştır.bu uygulamada sht11 sıcaklık ve nem sensöründen I2C üzerinden aktarılan bilgiler gerekli işlemlerden sonra lcd üzerinde gösterilmiştir.uygulamaya ait video aşağıdaki linkte mevcuttur. http://www.youtube.com/watch?v=avzonrmx4dk 16x2 LCD 4 bit bağlantı şeması CRP constunsignedint CRP_WORD = CRP_NO_CRP #include"lpc17xx.h" #include"core_cm3.h" #include<cr_section_macros.h> #include<nxp/crp.h> #include"stdio.h" #include<stdlib.h> #define RS_E (1<<5); //LCD Enable içinişlemciüzerinde GPIO 2.5 voidinitlcd(); voidwritetolcd(unsignedchar data,unsignedint instruction); voidwritetoscreen(unsignedchar data,unsignedint instruction); voidshifttowrite(); voidentertosecondline(); voidclearscreen(); voidlcd_gpio_configuration(void); volatileuint32_t timer0_counter; voidinit_timer( uint32_t timerinterval ); voiddelayms(uint32_t delayinms);
voidwritetolcd(unsignedchar data,unsignedint instruction) if(instruction==1) LPC_GPIO2->FIOSET =RS_E; else LPC_GPIO2->FIOCLR =RS_E; LPC_GPIO2->FIOCLR = 0x0000000F; LPC_GPIO2->FIOSET =data; LPC_GPIO2->FIOSET = (1<<4); delayms(200); LPC_GPIO2->FIOCLR = (1<<4); voidshifttowrite() writetoscreen(0x14,0); //BoşlukBırakıyorum... voidentertosecondline() writetoscreen(0xc0,0); //AltSatıraGeçiyorum... voidclearscreen() writetoscreen(0x01,0);//clearing Screen... voidwritetoscreen(unsignedchar data,unsignedint instruction) if(instruction==1) LPC_GPIO2->FIOSET =RS_E; else LPC_GPIO2->FIOCLR =RS_E; unsignedchar temp=data; LPC_GPIO2->FIOCLR = 0x0000000F; LPC_GPIO2->FIOSET =( temp >> 4 ); /*LCD 4 bit olarakçalıştırıldığıiçin data önce 4 bit sağa kaydırılıp en değerli 4 bit, daha sonra en değersiz 4 bit kullanılarak karakter yazdırılır.*/ LPC_GPIO2->FIOSET = (1<<4); delayms(200); LPC_GPIO2->FIOCLR = (1<<4); LPC_GPIO2->FIOCLR = 0x0000000F; LPC_GPIO2->FIOSET = (data & 0x0F) ; LPC_GPIO2->FIOSET = (1<<4); delayms(200); LPC_GPIO2->FIOCLR = (1<<4);
voidlcd_gpio_configuration(void) LPC_GPIO2->FIODIR&= 0x00000000; LPC_GPIO2->FIODIR = 0x000000FF; //GPIO2'nin 0..7 portları ÇIKIŞ olarakatandı. LPC_GPIO2->FIOCLR = 0x000000FF; //GPIO2'nin 0..7 portlarılojik - 0 yapıldı. voidinitlcd() delayms(200); writetolcd(0x03,0); delayms(50); writetolcd(0x03,0); delayms(10); writetolcd(0x03,0); delayms(10); writetolcd(0x02,0); delayms(10); writetolcd(0x02,0); delayms(10); writetolcd(0x08,0); delayms(10); writetolcd(0x00,0); delayms(10); writetolcd(0x08,0); delayms(10); writetolcd(0x00,0); delayms(10); writetolcd(0x0f,0); delayms(10); writetolcd(0x00,0); delayms(10); writetolcd(0x06,0); delayms(10); writetolcd(0x00,0); delayms(10); writetolcd(0x01,0); delayms(10); writetolcd(0x00,0); delayms(10); writetolcd(0x02,0); delayms(10);
voidinit_timer (uint32_t TimerInterval ) timer0_counter = 0; LPC_TIM0->MR0 = TimerInterval; LPC_TIM0->MCR = 3; MR0*/ NVIC_EnableIRQ(TIMER0_IRQn); /* Interrupt and Reset on voiddelayms(uint32_t delayinms) LPC_TIM0->TCR = 0x02; /* reset timer */ LPC_TIM0->PR = 0x00; /* set prescaler to zero */ LPC_TIM0->MR0 = delayinms * (9000000 / 1000-1); LPC_TIM0->IR = 0xff; /* reset all interrrupts */ LPC_TIM0->MCR = 0x04; /* stop timer on match */ LPC_TIM0->TCR = 0x01; /* start timer */ /* wait until delay time has elapsed */ while (LPC_TIM0->TCR& 0x01); return; intmain(void) int i; LCD_GPIO_Configuration(); //LCD için GPIO yönleriatandı. initlcd(); init_timer(10); delayms(1000); while(1) clearscreen(); unsignedchar waitcomment[16]="please WAIT..."; unsignedchar dotarray[16]="..."; for(i=0;i<16;++i) if(i==6) shifttowrite(); delayms(100); ++i; writetoscreen(waitcomment[i],1);//please WAIT yazdırılıyor delayms(100); entertosecondline(); for(i=0;i<16;++i) writetoscreen(dotarray[i],1);//ikinci satıra noktalar yazdırılıyor delayms(100); clearscreen();
1769 TABANLI KENDİ TASARIMIMIZ