Mikrodenetleyici LED programımın durmasına neden olan nedir?


11

Yani, ben bir TAMAM ve programlama konusunda acemi oldum. Arduinos üzerinde bazı temel şeyler yaptım (kelimenin tam anlamıyla LED'leri değiştiriyor ve bir LCD'de bir şey gösteriyor) ve kendime C'de nasıl programlanacağını kendim öğretmeye çalışıyorum, ticaretle donanım mühendisiyim, ama beni herhangi bir firmware / yazılım tarafı yapın ve öğretmek için akşam kursları yoktur ve kariyer seçeneklerimi daha da ileriye taşımak istiyorum. Bu komutlardan bazılarının nasıl bir araya geldiğini ve neden işe yaramadığı konusunda kafamı bulamadığım bir sorunla karşılaştıklarını anlamaya çalışıyorum.

Yani, bir girdi ve çıktı var. Çıktım, bir LED'i açan bir FET'in kapısını açıyor. Giriş bir AND geçidinden geliyor. Yani, LED'im her zaman açık ve AND geçidinden bir giriş sinyali aldığımda (2 koşul karşılandı) Çıkışın (LED geçişi) DÜŞÜK (LED'i kapatmasını) istiyorum. Çıkış da bağlı olduğundan AND girişlerinden biri, bu giriş sinyalini DÜŞÜK duruma getirir.

Ne yapmak istiyorum: Sadece girişi 'koşullar karşılandı' olarak okumak ve LED'i kapatmak istiyorum. Daha sonra 1 saniye kapalı olmalı ve tekrar açılmalıdır. Giriş tekrar YÜKSEK ise işlem tekrarlanır. Diğer AND geçidi girişi olarak anahtar yapmak için basit bir itme kullanıyorum ve düğmeye basıldığında çıkışın (MCU girişi) yüksek olduğunu ölçtüm, ancak LED değiştirme (çıkış) kapanmayacak. Benim kod (sanırım) oldukça basit, ama açıkça işe yaramıyor gibi bir şey doğru anlamıyorum.

Yani bu kod kullanıyorum:

#include "mbed.h"

DigitalIn ip(D7);
DigitalOut op(D8);

int main() {
    if (ip == 1){
        op = 0;
        wait (1.0);
        op = 1;
    }else{
        op = 1;
    }
}

Bana göre bu mantıklı görünüyor. Normal durumda, çıktı YÜKSEK. Giriş sinyali AND geçidinden alırsa, LED 1 saniye boyunca söner ve sonra tekrar açılır.

Yanlış yaptığım şey, bunun mantıklı bir yolu gibi görünüyor ve bunun neden işe yaramadığını anlayamıyorum?

Yardımcı olursa, Nucleo F103RB kullanıyorum. 'Göz kırpma' kodunu kullandığımda ve LED'i bu şekilde açıp kapadığımda iyi çalışıyor, sadece 'if' ifadesini yanlış gittiğinde eklediğimde.

Bu basitleştirilmiş devredir:

şematik

bu devreyi simüle et - CircuitLab kullanılarak oluşturulan şematik

PS Şematikte onları eklemediğimi biliyorum, ancak AND kapılarının giriş ve çıkışta açılan dirençleri var.


"Koşulları" doğrudan IN'ye koyarsanız çalışır mı?
Transistör

O değil. Düğmeyi doğrudan
Meraklı

1
Giriş değişkenlerini geçici olarak işaretlemek iyi bir fikirdir veya derleyici, kodun dışından değiştirilmediğini varsayarak bazı garip optimizasyonlar yapabilir.
Dirk Bruere

3
@DirkBruere: DigitalInZaten içerdiği tanımın umarız volatile.
MSalters

3
Bir dahaki sefere bir ipucu: CPU'yu (veya mikro denetleyiciyi) açtığınızda (veya sıfırladığınızda) düğmeyi basılı tutmayı deneyin. Şimdi ne olacak?
CVn

Yanıtlar:


26

Kodunuzun etrafında bir döngüye ihtiyacınız olacağını düşünürdüm -

while(1)
{

    if (ip == 1){
       op = 0;
       wait (1.0);
       op = 1;}
    else {
       op = 1;}
}

Düğmeye basma şansınız olmadan önce kodunuz bitmiş ve çıkmış olacaktır. İf ifadesinin art arda çalışmasını sağlamak için zamana ihtiyacınız vardır.


Bunu benimkinden farklı kılan nedir? 'While'ı görebiliyorum ama bu ne yapıyor? Tüm sorular için özür dilerim ama gerçekten sıfır bilgi ile başlıyorum!
Meraklı

1
@curious Düğmeye basma şansınız olmadan önce kodunuz bitmiş ve çıkmış olacaktır. İf ifadesinin art arda çalışmasını sağlamak için zamana ihtiyacınız vardır. Programladığınız mikrodenetleyici hakkında farklı bir şey olmadığı sürece normalde durum böyledir.
HandyHowie

9
"Bunun neden işe yaradığını açıklayabilir misin?" - Durum sıfıra gelene kadar her şey döngü içinde tekrarlanır. Durum nedir, sorabilirsiniz; "while" anahtar sözcüğünden sonra parantez içindeki kısımdır ve gördüğünüz gibi durum 1 olarak ayarlanmıştır, bu yüzden asla sıfır değildir ve bu nedenle süresiz olarak tekrarlanır. While döngüsü olmadan kod yalnızca bir kez ve sonra yazılım sonlandırılır, ancak while döngüsü ile siz donanımı kapatıncaya kadar kod tekrar tekrar yürütülür.
Jurgy

14
Hatanız muhtemelen Arduino'ya gitmekten mbed'e kaynaklanmıştı. Arduino'da genellikle uygulama kodunuzu loop()girersiniz, ancak Arduino çerçevesi kabaca davranan kodu ekler int main() { setup(); while(1) { loop(); } }.
ris8_allo_zen0

1
@Sevgili Sevgiler işe yaradı. Ne yazık ki tam olarak bir kez, hemen açtığınızda koştu. Çalışması belki bir mikrosaniye sürdü ve hepsi bu kadar. Girdiyi kontrol etmeye ve çıkışı ayarlamaya devam etmek istiyorsanız, girmeye devam etmesini söylemeniz gerekir. "while (some_condition)", "some_condition" doğru olduğu sürece çalışır; bu, C dilinde sıfır olmayan anlamına gelir. Bu yüzden "while (1)", girişi sonsuza kadar veya en azından açık olduğu sürece kontrol etmeye devam eder.
Graham

21
#include "mbed.h"

DigitalIn ip(D7);
DigitalOut op(D8);

int main() {
    if (ip == 1){
        op = 0;
        wait (1.0);
        op = 1;
    }else{
        op = 1;
    }
    // and now the program ends? What to do?
}

İşlemci talimatları sırayla yürütür . Bu bir atlama ile başlar main()ait mBED kütüphane başlatma kodu içinde DigitalInve DigitalOut.
Sonra karşılaştırmayı gerçekleştirir, ip == 0talimatı içinde çalıştırır {}ve sonra main()biter ... daha fazla talimat yok ... Ne işe yarar?

Boş flash bellekte geçersiz işlenenler bulunması nedeniyle sıfırlanabilir. Veya bir hata işleyicisine asılabilir ve mbedlerin yaptığı gibi SOS'u yanıp sönebilir. Bu, bunun nasıl uygulandığına bağlıdır ve muhtemelen şu anda üzerinizden geçecektir.
Ancak merak ediyorsanız, ARM Fault Handling'i araştırabilir veya main()gerçekte nereden çağrıldığını öğrenebilirsiniz .

Şimdi, bunu nasıl düzeltebilirim?

int main() {
    // Add a while(1) infinite loop
    while(1){
        if (ip == 1){
            op = 0;
            wait (1.0);
            op = 1;
        }else{
            op = 1;
        }
    }
    // Program never gets here
}

Açıklama için çok teşekkür ederim. While döngüsü çalışmasını sağladı. Ne yazık ki benim temsilcisi çok düşük olduğu için henüz bir +1 veremem ama cevap ve açıklamayı çok takdir ediyorum
Meraklı

Aha! Sorumdaki üçüncü oylama cevabını oylamama izin verdi! Tekrar teşekkürler
Meraklı

1
@Curious Bunun sizin için daha açık olmasını istiyorsanız, programcı, while(1 == 1)sadece yerine bir şey yazabilirsiniz while(1). İkincisi deyimsel C'dir, ancak birincisi "her zaman doğruyu değerlendirecek" gibi bir insan için daha açıktır. İyi bir derleyici her iki değişken için de aynı ikili kodu üretmelidir.
CVn

2
@ MichaelKjörling Bir insan için daha açık olduğunu kabul etmem. Tıpkı beyninizin kelimeleri karakter yerine şekline göre okuması gibi, deneyimli bir programcıya bu deyimler her bir ifadenin ne yaptığını yorumlamak yerine doğrudan kavramlara dönüşür. Deyimsel yapılardan uzaklaşarak insanları kodunuzla kavrayış için gerekenden daha düşük bir seviyeye girmeye zorlarsınız; hangi büyük bir kod tabanı üzerinde çok fazla gereksiz zihinsel çalışma ekler.
Chuu

1
@Chuu "[deneyimli bir programcı olmayan bir insan tarafından]"
user253751

2

Başkaları tarafından doğru şekilde belirtildiği gibi, bir döngü kodunuzun tekrar tekrar çalışmasına izin verir. Ancak, Arduino için bunu bir whiledöngüye gerek kalmadan yapmanın yerleşik bir yolu var . Bu loopfonksiyon tarafından yapılır - probleminize uygulanabilirliği Arduino IDE'yi kullanıp kullanmadığınıza bağlıdır.

Bunun gibi bir şeye benzemeli:

#include "mbed.h"

DigitalIn ip(D7);
DigitalOut op(D8);

void setup() {
    // any code before loop is run
}

void loop() {
    if (ip == 1){
        op = 0;
        wait (1.0);
        op = 1;
    }else{
        op = 1;
    }
}

Ana işleviniz artık gizlenmiştir ve programınıza yalnızca derlendiğinde eklenir. İşte bununla ilgili iyi bir tartışma: http://forum.arduino.cc/index.php?topic=379368.0


Evet. Başlangıçta bir arduino üzerinde bir şeyler yaptım, bu yüzden nükleo ve mbed IDE'ye geçerken neden işe yaramadığını anlayamadım!
Meraklı

1
Bu cevap Arduino sisteminin kullanımına dayanmaktadır. mBED kütüphanelerin farklı bir sistem / kümesidir ve loop()ve setup()Arduino işlevleri vardır değil birçok sistemde kullanılan. Referans için, Arduino sadece main()böyle bir şey tanımlar :void setup(); void loop(); int main() { setup(); while (true) loop(); }
Cameron Tacklind

0

Eğer montaj konusunda yandaşsanız, bu sizin konfor bölgenizde biraz daha olabilir:

int main () {

//A label or function similar to assembly

label:

    if (ip == 1){

        op = 0;

        wait (1.0);

        op = 1;

    }else{

        op = 1;

    }

// Goto used same as "jmp" in assembly

goto label;

// Program never gets here

}


3
Lütfen goto'yu montajın üzerinde herhangi bir dilde kullanmayın .
Jeroen3

Korkarım meclise hiç aşina değilim!
Meraklı

Biliyorum ama bu konuda!
Meraklı

@ Jeroen3 Bağlantı verdiğiniz soru "birkaç yerde goto'lar uygundur", "Düzgün kullanılırsa goto ile ilgili bir sorun yoktur" ve "Kendi içinde goto ile ilgili yanlış bir şey yoktur" şeklinde yanıtlanır. İstisnaları olan dillerde goto'nun gereksiz olduğunu, ancak özellikle C'de, kullanımlarının olduğunu kabul ediyorum.
glglgl

@glglgl: Chuu'nun yukarıda belirtildiği gibi, kod okunabilir olmalıdır. goto** kuvvetle ** muhtemelen "istisnasız" burada devam ediyor "önerir goto cleanup;. Buradaki örnekte, okuyucu " while(1) { }burada kullanmadığınız kadar özel olan ???" gibi şaşırtıcı bir soru ile kalacak .
MSalters
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.