Önceki eğitimimizde, PIC mikrodenetleyiciyi kullanarak bir LED'in yanıp sönmesini öğrendik ve aynı devreyi Perf kartına kurduk. Ardından programı Perf panomuza aktarmak için PICkit 3, ICSP ve MPLAB IPE'yi kullandık. Şimdi, bu eğitimde kendimizi PIC mikro denetleyicide daha fazla pin kullanmaya doğru ilerleteceğiz. 7 çıkış (LED) ve bir Giriş kullanacağız. Bu eğitim için eski Perf kartını (aşağıda gösterilmiştir) kullanacağız ve gerekli pimleri ikinci LED kartına çekmek için berg çubukları ekleyeceğiz. Bu eğitimin sonunda, PIC mikro denetleyici PIC16F877A'yı kullanarak bir Yanıp Sönen LED Dizisi Oluşturacağız ve birden çok giriş ve çıkışın nasıl kullanılacağını öğreneceğiz, 'for' döngüsü ve işlev çağrısı üzerine bazı temel bilgiler.
LED kartı, LED'leri akım sınırlayıcı bir Dirençle lehimleyeceğimiz başka bir mükemmel karttan başka bir şey değildir (aşağıda gösterilmiştir). Ayrıca LED'in yanıp sönmesini başlatmak için bir basma düğmesi ekleyeceğiz.
Devre şeması:
PIC Mikrodenetleyici PIC16F877A LED Yanıp Sönen Sıra Kodu ve Çalışma Açıklaması:
Tam Kod aşağıda verilmiştir (sonunda kontrol edin), burada onu satır satır alacağız. Bu kod, düğmeye basıldığında LED'leri sırayla yanmaya başlayacaktır. Sıraları anlamak için lütfen eğitimin sonundaki videoyu izleyin. Videoda gösterilen çıktıyı aşağıdaki kodla karşılaştırmanızı ve programı anlamaya çalışmanızı tavsiye ederim.
Kod satırına satır satır bakalım. İlk birkaç satır, önceki öğreticide açıklanan yapılandırma bitlerini ayarlamak içindir, bu yüzden şimdilik bunları atlıyorum. Herhangi bir programı anlamanın en iyi yolu main ( void main () ) işlevinden başlamaktır, öyleyse hadi yapalım
TRISB0 = 1; // MCU'ya PORTB pini 0'ın düğme girişi olarak kullanıldığını söyleyin. TRISD = 0x00; // MCU'ya tüm pinlerin PORTD = 0x00 çıkışı olduğunu bildir; // Tüm pinleri 0 olarak başlat
TRIS kelimesi, pin giriş / çıkış olarak kullanılıp kullanılmadığını tanımlamak için kullanılır ve PORT kelimesi bir pin High / Low yapmak için kullanılır. TRISB0 = 1 satırı, giriş olarak PORT B'nin 0. pinini yapacaktır. Bu bizim butonumuz olacak. TRISD = 0x00 satırları ; PORTD = 0x00; D portunun tüm pinlerini Çıkış olarak yapacak ve bu pinlere bir LOW başlangıç değeri atayacaktır.
Giriş olarak B0 kullanıldı dediğimiz için butonun bir ucunu B0 pinine diğer ucunu toprağa bağlayacağız. O zamana kadar düğmeye her bastığımızda, yukarıdaki bağlantı şemasında gösterildiği gibi pim toprağa tutulur. Ancak bunun gerçekleşmesi için, düğmeye basılmadığında pimin yüksek tutulması için yukarı çekme direnci kullanmalıyız. Yukarı çekme direnci böyle bir şeydir.
Ancak PIC MCU'muz, yazılımla etkinleştirilebilen dahili bir zayıf çekme direncine sahiptir ve bu şekilde çok fazla güçlükten tasarruf sağlar (daha fazla düğme bağlanacaksa).
Zayıf bir çekme direnci nedir?
İki tür yukarı çekme direnci vardır, biri Zayıf Yukarı Çekme ve diğeri Güçlü Yukarı Çekme. Zayıf yukarı çekme dirençleri yüksek değerdedir ve bu nedenle zayıf bir akımın geçmesine izin verir ve güçlü yukarı çekme dirençleri düşük değerdedir, bu nedenle güçlü bir akımın akmasına izin verir. Tüm MCU'lar çoğunlukla zayıf çekme dirençleri kullanır. Bunu PIC MCU'muzda etkinleştirmek için, aşağıdaki anlık görüntüde gösterildiği gibi OPTION_REG (seçenek kaydı) veri sayfamıza bakmalıyız.
Gösterildiği gibi bit 7, zayıf yukarı çekme direnci ile ilgilidir. Etkinleştirmek için sıfır yapılmalıdır. Bu OPTION_REG <7> = 0 ile yapılır . Bu özellikle bit 7 ile diğer bitleri varsayılan değerlerine bırakarak ilgilenir. Bununla, if (RB0 == 0) kullanarak düğmeye basılıp basılmadığını kontrol ettiği while döngümüze giriyoruz . Koşul sağlanırsa, fonksiyonumuzu 1, 3, 7 ve 15 parametreleriyle çağırırız.
sblink (1); // 1. parametre sblink (3) ile FUNCTION CALL 1; // 3. parametre sblink (7) ile FUNCTION CALL 3; // 7. parametre sblink (15) ile FUNCTION CALL 7; // FUNCTION CALL 4, parametre 15 ile
Neden fonksiyonları kullanıyoruz?
Kodumuzdaki satır sayısını azaltmak için fonksiyonlar kullanılır. Çoğumuzun bildiği şey buydu. Ancak, özellikle MCU programlaması söz konusu olduğunda, neden satır sayısını azaltmamız gerekiyor? Bunun nedeni, Program belleğimizdeki sınırlı alandır. Kodu düzgün şekilde optimize etmezsek bellek alanımız tükenebilir. Bu, uzun kod sayfaları yazdığımızda kullanışlı olacaktır.
Herhangi bir işlevin bir işlev tanımı (bizim durumumuzda sblink (int get) ) ve bir işlev Çağrısı (bizim durumumuzda sblink (1) ) olacaktır. Bir işlev bildirimine sahip olmak isteğe bağlıdır, bundan kaçınmak için işlev tanımımı işlevi ana işlevime çağırmadan önce yerleştirdim.
İşlev parametreleri, işlev çağrısından işlev tanımına geçirilecek değerdir. Bizim durumumuzda tamsayı değerleri (1, 3, 7, 15) fonksiyon çağrısından aktarılan parametrelerdir ve "get" değişkeni, parametrelerin değerini onları işlemek için fonksiyon tanımına alır. Bir işlevin birden fazla parametresi olabilir.
Fonksiyon çağrıldığında, fonksiyon tanımındaki aşağıdaki satırlar çalıştırılacaktır.
for (int i = 0; i <= 7 && RB0 == 0; i ++) {PORTD = get << i; // LED Sol Sırayı Hareket Ettir __delay_ms (50); } for (int i = 7; i> = 0 && RB0 == 0; i--) {PORTD = get << i; // LED Sol Sırayı Hareket Ettir __delay_ms (50); }
Şimdi bu satır tuhaf görünüyor: PORTD = get << i . Burada gerçekte ne olduğunu açıklayacağım.
"<<", tüm bitleri kendi sol konumuna kaydıran bir sola kaydırma operatörüdür. Şimdi sblink (int get) işlevini sblink (1) olarak '1' parametresi ile çağırdığımızda , 'get' değerini 1 olarak yapacaktır , bu ikili değerde 0b00000001'dir. Dolayısıyla bu satır PORTD = 0b00000001 << i gibi olacaktır.
"İ" nin değeri, (int i = 0; i <= 7 && RB0 == 0; i ++) için bir 'for döngüsü' kullandığımız için 0 ile 7 arasında değişecektir . 'İ' değerinin 0 ile 7 arasında olması sonucu aşağıdaki gibi değiştirecektir:
Gördüğünüz gibi, geri kalanını KAPALI tutarak bir seferde bir LED'i (soldan sağa) AÇIK konuma getirdik. (İnt i = 7; i> = 0 && RB0 == 0; i--) için bir sonraki 'for döngüsü' de aynı şeyi yapacak, ancak bu sefer LED sırayla sağdan sola AÇIK olacak, 7'den başlayıp 0'a inerken, LED'in AÇIK ve KAPALI olduğunu görselleştirmek için 200ms'lik bir gecikme kullandık.
Şimdi sblink (int get) fonksiyonunda 3 değerini geçtiğimizde, 'get' değerini 0b00000011 yapan sblink (3) fonksiyonu çalıştırılacak, dolayısıyla PORTD'deki sonuç şöyle olacaktır:
Şimdi bu sefer sblink (3) kullanılarak herhangi bir zamanda iki LED yanacaktır . Benzer şekilde sblink (7) ve sblink (15) için, sırayla üç ve dört LED AÇIK olacaktır. Bu tamamlandığında, tüm LED'in PORTD = 0xFF satırını kullanarak yanmasını sağlayacağız . Kontrol video tam Gösteri için aşağıya.
Umarım kodu anladınız ve böylece istediğiniz çıktıları elde etmek için 'for' ve 'while' döngüsünü nasıl kullanacağınızı öğrendiniz. Artık farklı LED yanıp sönme sıranızı elde etmek için kodun etrafında ince ayar yapabilirsiniz. Devam edin kodunuzu derleyin ve MCU'nuza aktarın ve çıktının keyfini çıkarın. Bir yere takılırsanız yorum bölümünü kullanabilirsiniz. Simülasyon ve program dosyalarını da buraya ekledim.
Şimdilik bu kadar sonraki eğitimimizde gecikme fonksiyonlarını kullanmak yerine PIC16F877A zamanlayıcıları nasıl kullanacağımızı öğreneceğiz. Tüm PIC mikro denetleyici öğreticilerine buradan göz atabilirsiniz.