EEM 306 Mikroişlemciler ve Lab. Doç.Dr. Mehmet SAĞBAŞ
Örnek 1: Kara Şimsek (İki LED) Soru: MSP430 LaunchPad te buluna iki LED i birer saniye aralıklarla sırayla yakıp söndüren programı yazınız.
Kara Şimsek (İki LED) #include <msp430.h> void delay_ms(unsigned int ms) // delay_ms adlı gecikme fonksiyonu { while(ms--) delay_cycles(10000); } // oluşturuluyor int main(void) // ana program { WDTCTL = WDTPW WDTHOLD; // Stop watchdog timer BCSCTL1 = CALBC1_1MHZ; // Sistem saati 1MHz e ayarlanıyor DCOCTL = CALDCO_1MHZ; // Sistem saati 1MHz e ayarlanıyor P1DIR = 0x41; // P1.0 ve P1.6 pinleri çıkış olarak ayarlanıyor while(1) // sonsuz döngü { P1OUT = 0x01; // P1.0 pinine bağlı LED yakılıyor delay_ms(50); // gecikme P1OUT = 0x40; // P1.6 pinine bağlı LED yakılıyor delay_ms(50); // gecikme } }
Kara Şimsek (İki LED) Aşağıdaki değişiklikleri yapmak için programı nasıl değiştirmemiz gerekir. 1.
Örnek 2: Kara Şimsek (8 LED li) Soru: MSP430G2553 mikrokontrolörün P1 pinlerine (P1.0, P1.1,, P1.7) sekiz adet LED in bağlı olduğunu düşünelim. Sekiz LED i birer saniye aralıklarla sırayla yakıp söndüren programı yazınız.
Kara Şimşek (8 LED li) #include "msp430.h" void delay_ms(unsigned int ms) // delay_ms adlı gecikme fonksiyonu { while(ms--) delay_cycles(10000); } // oluşturuluyor void main( void ) { // ana program int a=1; WDTCTL = WDTPW WDTHOLD; BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; delay_cycles(100000); P1DIR = 0xFF; P1SEL = 0x00; while(1) { P1OUT = a; a<<=1; // bir sola kaydır delay_ms(50); if(a > 128) a=1; }}
Kara Şimşek (8 LED li) Aşağıdaki değişiklikleri yapmak için programı nasıl değiştirmemiz gerekir. 1. LED leri bir atlatarak (bir boşluk bırakarak) yakmak için programda nasıl bir değişiklik yapılmalı 2. 4 LED li kara şimşek yapınız 3. 16 LED li kara şimşek yapmak için programda nasıl bir değişiklik yapmamız gerekir açıklayınız.
Kara Şimşek (16 LED li) #include "msp430.h" void delay_ms(unsigned int ms) { while(ms--) delay_cycles(10000); } void main( void ) { int a=1,b=128; WDTCTL = WDTPW WDTHOLD; BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; delay_cycles(100000); P1DIR = 0xFF; P2DIR = 0xFF; P2SEL = 0x00; P2SEL2= 0x00; while(1) { P1OUT = a; a<<=1; P2OUT = b; b>>=1; delay_ms(50); if(a > 128 && b < 1) { a=1; b=128; } }}
Fibonacci Dizisi #include <msp430.h> int main(void) { int sayi0 = 0; int sayi1 = 1; int sayi; int i; WDTCTL = WDTPW WDTHOLD;// Stop watchdog timer BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; // P1DIR = 0x0F; for (i=2; i < =10; i++) { sayi = sayi0 + sayi1; sayi0 = sayi1; sayi1 = sayi; }}
Buton Uygulaması Şekilde görüldüğü gibi, MSP430 mikrodenetleyicisinin P1.0 ve P1.1 pinlerine iki adet push button ve P1.2, P1.3, P1.4, ve P1.5 pinlerine LED ler bağlanıyor. Bu devrede P1.0 pinine bağlı olan buttona basıldığında saat çalışmaya başlayacak ve P1.1 pinine bağlı buttona basıldığında saat duracaktır. İki butona basılma arasında geçen zaman saniye cinsinden hesaplanıp, sonuç ikili sayı tabanında LED lerde gösterilecektir.bu görevi yerine getirecek şekilde MSP430 mikrodenetleyicisini programlayacak C kodunu yazınız.
Buton Uygulaması (Devam) #include <msp430.h> volatile char sayac=0; void main(void) { WDTCTL = WDTPW WDTHOLD;// Stop watchdog timer P1DIR = BIT2 BIT3 BIT4 BIT5; P1REN = BIT0 BIT1; P1OUT = BIT0 BIT1; P1IE = BIT0 BIT1; BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; TACCTL0 = CCIE; TACCR0 = 10000; TACTL = TASSEL_2 + MC_1; interrupt_enable(); for(;;); } #pragma vector=timera0_vector interrupt void Timer_ISR() { sayac++;} #pragma vector=port1_vector interrupt void Button_ISR() { /*if(p1ifg==bit0) { TACTL = MC_1 CLR; P1IFG &= ~BIT0; } else if(p1ifg == BIT1){ volatile int zaman = sayac / 100; P1OUT = zaman; P1IFG &= ~BIT1; }*/ volatile char basla, sure; if(p1ifg==bit0) { basla = sayac; P1IFG &= ~BIT0; } else if(p1ifg == BIT1){ sure = (sayac - basla)/100; P1OUT = sure; P1IFG &= ~BIT1; }}
Seven Segment Display 7 segment display, 8 LEDden oluşmuş bir elemandır. Üzerinde sayıları ya da karakterleri göstermek için 7 parça, bir de sağ alt tarafındaki nokta için olmak üzere toplam 8 LED bulunur. Elemanın 10 tane bacağı bulunuyor. Bunlardan iki tanesi ortak (anot ya da katot), geri kalan 8 tanesi de her bir LED için ayrılmış bacaklar. Bu elemanlar ortak anotlu ve ortak katotlu olmak üzere ikiye ayrılıyor. Ortak anotlu olanda, tüm ledlerin anot (+) uçları birleşik. Bu durumda bu birleşik düğümden pozitif (yeterli seviyede) bir gerilim uygularsanız, ve yakmak istediğiniz led için ayrılmış diğer bacağı toprağa (ya da ledin yanması için üzerine düşmesi gereken gerilim dikkate alınarak daha düşük bir gerilim seviyesine) bağlarsanız, display üzerindeki o segment yanacaktır. MSP430 un bacakları direkt olarak displaye bağlayınız. P1IN dizilimimi; P1.0 pinini ortak anot olarak belirleyip sürekli lojik 1 de tutunuz. Diğer pinler, P1.1 => A, P1.2 => B, P1.3 => C olacak şekilde toplam 8 pin kullanılacaktır (1 pin ortak anot, 7 pin segmentler olmak üzere sağ alttaki noktayı kullanılmayacaktır) Pinlerin değerlerini belirlenmesi: P1.0 anot olduğu için, ortak olan ucum sürekli 1. Diğer pinler için de, yakmak istediğiniz segmente karşılık gelen pini 0 çekerek, o segment yakılacaktır. Bu durumda P1.7, yani G segmentine karşılık gelen bit en solda, P1.0 da en sağda olacak şekilde pinlerin durumlarını yazacak olursak; 0 => 10000001 => 0 81, 1 => 11110011 => 0xF3, 2 => 01001001 => 0 49,
#include "io430.h" // Fonksiyonların tanımlanması void kucuktenbuyuge(void); // Küçükten büyüğe sayar. void buyuktenkucuge(void); // Büyükten küçüğe sayar. void sayigoster(int); // O anki sayıyı displayde gösterir. void bekle(void); // Sayılar arası bekleme. void main( void ) { // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; P1DIR = 0xFF; // P1 çıkış olarak ayarlandı. P1OUT = 0x81; // 0 sayısı displaye basıldı. while(1) // Sonsuz döngü. { kucuktenbuyuge(); // Fonksiyonlar çağrılıyor. buyuktenkucuge(); }}
void kucuktenbuyuge(void) { int i; for (i = 0 ; i < 9 ; i++) // 0'dan 9'a kadar sayar. { sayigoster(i); // O anki sayıyı basması için fonksiyonu çağırır. bekle(); // Bir süre bekle. }} void buyuktenkucuge(void) { int i; for (i = 9 ; i > 0 ; i--) // 9'dan 0'a kadar sayar. { sayigoster(i); // Sayının basılması için fonksiyon çağırır. bekle(); // Bir süre bekle. }} void sayigoster(int sayi) { switch(sayi) // Gelen sayı kaç? {case 0 : P1OUT = 0x81; break; // Sayı 0 ise ilgili pinler ayarlanır. case 1 : P1OUT = 0xF3; break; // 1 case 2 : P1OUT = 0x49; break; // 2 case 3 : P1OUT = 0x61; break; // 3 case 4 : P1OUT = 0x33; break; // 4 case 5 : P1OUT = 0x25; break; // 5 case 6 : P1OUT = 0x05; break; // 6 case 7 : P1OUT = 0xF1; break; // 7 case 8 : P1OUT = 0x01; break; // 8 case 9 : P1OUT = 0x21; break; // 9 default : P1OUT = 0x0D; break; // Hata oluştu, displayde 'E' harfini göster. }} void bekle(void) { long int delay; for(delay = 0 ; delay < 100000 ; delay++); // Hiçbir işlem yapmadan bekle. }
MSP430 Launchpad Shift Register (74HC595 8BIT SHIFT REGISTER) http://processors.wiki.ti.com/index.php/msp4 30_Launchpad_Shift_Register
//******************************************* // MSP430 Driver for 74HC595 Shift Register // Description; Drives 8 LED's with 3 digital pins of the MSP430, via a shift register // MSP430x2xx //************************************ #include <msp430x20x2.h> //Define our pins #define DATA BIT0 // DS -> 1.0 #define CLOCK BIT4 // SH_CP -> 1.4 #define LATCH BIT5 // ST_CP -> 1.5 #define ENABLE BIT6 // OE -> 1.6 // The OE pin can be tied directly to ground, but controlling // it from the MCU lets you turn off the entire array without // zeroing the register // Declare functions void delay ( unsigned int ); void pulseclock ( void ); void shiftout ( unsigned char ); void enable ( void ); void disable ( void ); void init ( void ); void pinwrite ( unsigned int, unsigned char );
int main( void ) { // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; P1DIR = (DATA + CLOCK + LATCH + ENABLE); // Setup pins as outputs enable(); // Enable output (pull OE low) int i; //Do a "ping-pong" effect back and forth for(;;){ for ( i = 0 ; i < 8 ; i++ ) { shiftout(1 << i); delay(50); } for ( i = 7 ; i >= 0 ; i-- ) { shiftout(1 << i); delay(50); } } }
// Delays by the specified Milliseconds void delay(unsigned int ms) { while (ms ) { delay_cycles(1000); // set for 16Mhz change it to 1000 for 1 Mhz }} // Writes a value to the specified bitmask/pin. Use built in defines // when calling this, as the shiftout() function does. // All nonzero values are treated as "high" and zero is "low" void pinwrite( unsigned int bit, unsigned char val ) { if (val){ P1OUT = bit; } else { P1OUT &= ~bit; } } // Pulse the clock pin void pulseclock( void ) { P1OUT = CLOCK; P1OUT ^= CLOCK; }
// Take the given 8-bit value and shift it out, LSB to MSB void shiftout(unsigned char val) { //Set latch to low (should be already) P1OUT &= ~LATCH; char i; // Iterate over each bit, set data pin, and pulse the clock to send it // to the shift register for (i = 0; i < 8; i++) { pinwrite(data, (val & (1 << i))); pulseclock(); } // Pulse the latch pin to write the values into the storage register P1OUT = LATCH; P1OUT &= ~LATCH; } // These functions are just a shortcut to turn on and off the array of // LED's when you have the enable pin tied to the MCU. Entirely optional. void enable( void ) { P1OUT &= ~ENABLE; } void disable( void ) { P1OUT = ENABLE; }
LCD Uygulaması Bu uygulamada, ASCII formatta mesajı 16x2 bit LCD ye (HD44780-16x2bit LCD) göndereceğiz.
LCD Uygulaması: LCD-MSP430 Bağlantıları
LCD Uygulaması: Ana Program #include "msp430.h" #include "lcd_msp.h" //LCD kütüphanesi eklenecek. void main( void ) { WDTCTL = WDTPW + WDTHOLD; BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; delay_cycles(1000); lcd_init(); lcd_goto(1,2); // Satır ve sutun ayarlanıyor lcd_puts("eem306"); delay_ms(1000); lcd_goto(2,1); lcd_puts("mikroislemciler Dersi"); } bis_sr_register(lpm4_bits + GIE);
LCD Uygulaması: LCD Kütüphanesi // lcd_msp.h /*** MSP430 için 2x16 LCD Kütüphanesi ***/ #define delay_us(x) delay_cycles(x) #define delay_ms(x) delay_cycles((x * 1000L)) #define LCD_DATA P1OUT #define LCD_CONTROL P2OUT #define EN_ACKAPA() LCD_EN(1),LCD_EN(0) #define LCD_RS(x) ( (x)? (LCD_CONTROL = BIT7) : (LCD_CONTROL &= ~BIT7) ) #define LCD_EN(x) ( (x)? (LCD_CONTROL = BIT6) : (LCD_CONTROL &= ~BIT6) ) void lcd_komut(unsigned char); // LCD ye komut göndermeye yarar void lcd_temizle(void); // LCD ekranı temizler void lcd_puts(const char*); // LCD ye string ifade yazar void lcd_goto(char,char); // LCD de satır ve sutün olarak istenilen yere gider void lcd_init(void); // LCD başlangıç ayarları yapılır void lcd_putch(char); // LCD ye tek karakter yazmak için kullanılır.
LCD Uygulaması: LCD Kütüphane #include "msp430.h" #include "lcd_msp.h" void lcd_putch(char c) { LCD_RS(1); delay_us(200); LCD_DATA = (c & 0xF0); EN_ACKAPA(); LCD_DATA = ((c & 0x0F)<<4); EN_ACKAPA(); } fonksiyonları (1) void lcd_komut(unsigned char c) { LCD_RS(0); delay_us(200); LCD_DATA = (c & 0xF0); EN_ACKAPA(); LCD_DATA = ((c & 0x0F)<<4); EN_ACKAPA(); } void lcd_temizle(void) { lcd_komut(0x01); delay_ms(2); }
LCD Uygulaması: LCD Kütüphane void lcd_puts(const char* s) { while(*s) lcd_putch(*s++); } void lcd_goto(char x, char y) { if(x==1) lcd_komut(0x80+((y-1)%16)); else lcd_komut(0xc0+((y-1)%16)); } fonksiyonları (2) void lcd_init() { P1DIR = BIT4 + BIT5 + BIT6 + BIT7; P2DIR = BIT6 + BIT7; P2SEL = 0x00; P2SEL2 = 0x00; P1OUT = 0x00; P2OUT = 0x00; LCD_RS(0); LCD_EN(0); lcd_komut(0x28); // 4 Bit, Çift Satır LCD lcd_komut(0x0c); // İmleç Gizleniyor lcd_komut(0x06); // Sağa doğru yazma aktif lcd_komut(0x80); // LCD Birinci Satır Konumunda lcd_komut(0x28); // 4 Bit, Çift Satır LCD lcd_temizle(); // Ekran Temizleniyor }
Projeler 1. pulse oximeter: Parmaktan nabız ölçümü Pulse Oksimetre: hastanın kanında mevcut oksijeni ve beraberinde nabız hızını ölçen küçük bir cihazdır.pulse Oksimetre sürekli ve anlık arteriyal hemoglobin satürasyonunu verir. Kandaki bu oksijen oranı doktorların teşhislerinde önemli rol oynar. Dolayısıyla bu verilerin kolayca ve kesin olarak elde edilmesi gerekir. Bu verileri elde etmenin iki genel yöntemi vardır: Bunlardan birincisi, zor, acı veren ve gerekli netlikte sonuç vermeyen, klasik kan alma yöntemidir. Bu bildiğiniz gibi uygun iğnenin, doğru damara, doğru yerde batırılarak kan alınmasına dayanır. Aksi halde doğacak olumsuzlukları hepimiz biliriz. İkinci yöntem ise bir oksimetre kullanmaktır. Pulse oksimetreler çok çeşitli durumlarda kullanılabilir ama anestezi sırasında oksijenin ve nabız atışının gösteriminde kullanılması en önemli özelliklerindendir. Bunlar iyileşme safhalarında da oldukça kullanılır. Oksijen satürasyonu %95 in üstünde olmalıdır. Uzun süre yoğun bakımda kalan hastalarda, solunum hastalıkları olan hastalarda veya doğuştan kalp hastası olanlarda değerler daha düşüktür ve temelde yatan hastaların hastalık şiddetini yansıtır. Sonuç olarak Oksimetrenin anestezide ve cerrahi müdahelelerde hasta görüntülemedeki vazgeçilmezliği yıllarca sürecektir. Bu kadar karmaşık bir teknolojinin böyle küçük bir aletle kullanılabilmesi büyük avantaj sağlar.