マイクロコントローラーのLEDプログラムが機能しなくなるのはなぜですか?


11

だから、私は完全でプログラミングの初心者です。私はArduinosで基本的なことをいくつか行いました(文字通りLEDを切り替えてLCDに何かを表示します)Cでプログラミングする方法を独学しようとしています。私はハードウェアエンジニアであるが、ファームウェア/ソフトウェア側のいずれかを実行し、それを教えるための夜のコースはありません、そして私は私のキャリアオプションを促進したいと思います。これらのコマンドのいくつかがどのように連携するかを理解しようと努力していますが、なぜそれが機能しないのか頭を悩ませることができないという問題に遭遇しました。

したがって、入力と出力があります。私の出力は、LEDをオンにするFETのゲートを切り替えています。入力はANDゲートから来ています。だから、私のLEDは常にオンであり、ANDゲートから入力信号を取得するとき(2つの条件が満たされたとき)、出力(LEDトグル)をLOWにしたい(LEDをオフにします。 AND入力の1つである場合、これは入力信号をLOWにします。

やりたいこと:入力を「条件が満たされた」と読み、LEDをオフにしたいだけです。その後、1秒間オフになり、再びオンになります。入力が再びHIGHになると、プロセスが繰り返されます。単純なプッシュを使用して他のANDゲート入力としてスイッチを作成し、ボタンを押したときに出力(MCU入力)が高くなるが、LEDトグル(出力)がオフにならないことを測定しました。私のコードは(私は)非常に単純ですが、明らかに、それが機能していないので、正しく理解できません。

したがって、これは私が使用しているコードです:

#include "mbed.h"

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

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

そして私には、それは論理的に思えます。通常の状態では、出力はHIGHです。入力がANDゲートから信号を受け取ると、LEDは1秒間オフになり、再びオンになります。

それは論理的な方法のように見えますが、なぜそれがうまくいかないのか理解できないので、私は間違っていますか?

それが役立つ場合は、Nucleo F103RBを使用しています。「点滅」コードを使用し、そのようにLEDをオン/オフするだけで問題なく動作します。「if」ステートメントを追加したときに問題が発生します。

これは簡略化された回路です。

回路図

この回路のシミュレーションCircuitLabを使用して作成された回路

PS回路図には追加していませんが、ANDゲートの入力と出力にはプルダウン抵抗があります。


INに「満たされた条件」を直接入力すると機能しますか?
トランジスタ

ありません。ボタンを真っ直ぐにINに貼り付けても動作しませんでした
好奇心が

1
入力変数をvolatileとしてマークすることをお勧めします。そうしないと、コンパイラーはコードの外部から変更されていないと想定して、奇妙な最適化を行う場合があります。
ダークブルーア

3
@DirkBruere:の定義にDigitalIn既にincludeが含まれていることを望みますvolatile
–MSalters

3
次回のヒント:CPU(またはマイクロコントローラー)をオン(またはリセット)するときにボタンを押したままにしてください。さてどうなりますか?
CVn

回答:


26

私はあなたのコードの周りにループが必要になると思っていただろう-

while(1)
{

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

ボタンを押す前に、コードは終了して終了します。ifステートメントを繰り返し実行し続けるには、しばらく時間が必要です。


何が私のそれと違うのですか?私は「しばらく」を見ることができますが、それは何をしますか?すべての質問におApび申し上げますが、私は本当にゼロ知識から始めています!
好奇心が

1
@curiousボタンを押す機会がある前に、コードは終了して終了します。ifステートメントを繰り返し実行し続けるには、しばらく時間が必要です。これは通常、プログラミングしているマイクロコントローラーについて何か別のことがない限り当てはまります。
-HandyHowie

9
「なぜそれが機能したのか説明してください」-whileループのすべてが、条件がゼロになるまで繰り返されます。条件は何ですか、あなたは尋ねるかもしれません。これは、「while」キーワードの後の括弧内の部分です。ご覧のとおり、条件は1に設定されているため、ゼロになることはないため、無限に繰り返されます。whileループがないと、コードは一度だけ実行され、その後ソフトウェアは終了しますが、whileループでは、ハードウェアがオフになるまでコードが繰り返し実行されます。
ジャージー

14
あなたのエラーはおそらくArduinoからmbedに行くことに由来します。Arduinoでは通常アプリケーションコードを入れますloop()が、Arduinoフレームワークは大体のように振る舞うコードを追加しますint main() { setup(); while(1) { loop(); } }
ris8_allo_zen0

1
@Curious Yoursは機能しました。残念ながら、電源を入れるとすぐに1回実行されました。実行に1マイクロ秒かかる可能性があり、それだけでした。入力のチェックと出力の設定を続けたい場合は、入力を続けるように指示する必要があります。「while(some_condition)」は、「some_condition」がtrueである限り実行されます。これは、C言語ではゼロ以外を意味します。そのため、「while(1)」は入力を永遠に、または少なくとも電源がオンになっている限りはチェックし続けます。
グラハム

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?
}

プロセッサは命令を順次実行します。main()mbedライブラリ初期化コード内からへのジャンプで始まりDigitalInDigitalOutます。
次に、比較ip == 0を実行し、内部で命令を実行して{}からmain()終了します...これ以上の命令はありません...それは何をしますか?

空のフラッシュメモリで不正なオペランドが見つかったため、リセットされる可能性があります。または、障害ハンドラーでハングし、mbedsのようにSOSを点滅させる可能性があります。これは、これがどのように実装されているかに依存しており、おそらく今あなたを超えているでしょう。
しかし、好奇心が強い場合は、ARM Fault Handlingを調査するか、main()実際にどこから呼び出されているかを調べることができます。

さて、これを修正する方法は?

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
}

説明ありがとうございます。whileループが機能するようになりました。残念ながら、私はまだ私の担当者が低すぎるとして、あなたに+1を与えることはできませんが、私は非常に多くの回答や説明に感謝
おさるの

あぁ!私の質問に対するその3番目の賛成票は、あなたの答えを投票させてくれました!再びありがとう
好奇心

1
@Curiousプログラマーであるあなたにこれをもっと明確にしたいならwhile(1 == 1)、単にの代わりにのようなものを書くことができますwhile(1)。後者は慣用的なCですが、前者は「常に真であると評価されます」として人間にとってより明白です。適切なコンパイラは、両方のバリアントに対して同じバイナリコードを生成する必要があります。
CVn

2
@MichaelKjörling人間にはもっと明白だとは思わないでしょう。脳が文字ではなく形で単語を読むように、経験豊富なプログラマーにとって、これらのイディオムは個々のステートメントが何をしているのかを解釈するのではなく、概念に直接変換します。慣用的な構造から離れることにより、理解に必要なレベルよりも低いレベルでコードを使用するように人々に強制します。大規模なコードベースを使用すると、多くの不必要なメンタルワークが必要になります。
チュウ

1
@Chuu「(経験豊富なプログラマーではない)人間による」
-user253751

2

他の人が正しく述べているように、ループを使用すると、コードを繰り返し実行できます。ただし、whileループを使用せずにArduinoに対してこれを行う組み込みの方法があります。これはloop関数によって行われます-問題への適用可能性は、Arduino IDEを使用するかどうかによって異なります。

次のようになります。

#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;
    }
}

これで、メイン関数は非表示になり、コンパイル時にのみプログラムに追加されます。これについての良い議論があります:http : //forum.arduino.cc/index.php?topic=379368.0


うん。私はもともとarduinoでこれを行いました。これには、核とmbed IDEに切り替えると、なぜ機能しないのか理解できませんでした!
好奇心が

1
この回答は、Arduinoシステムの使用に依存しています。mbedは異なるシステム/ライブラリのセットであり、Arduino のloop()およびsetup()関数はほとんどのシステムで使用されていません。参考のため、Arduinoのは、単純に定義しmain()、このような何かを:void setup(); void loop(); int main() { setup(); while (true) loop(); }
キャメロンTacklind

0

組み立てに精通している場合、これはあなたの快適ゾーンでももう少しかもしれません:

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
上記のアセンブリ言語ではgoto使用しないでください。
Jeroen3

私は恐れているアセンブリにまったく精通していません!
好奇心が

私はそれを知っていますが、それはそれについてです!
好奇心が

@ Jeroen3リンクする質問には、「gotoがいくつかの場所で適切である」、「gotoを適切に使用すれば何も問題はありません」、「goto自体に問題はありません」と回答されます。例外のある言語ではgotoは不要ですが、特にCではgotoが使用されることに同意します。
glglgl

@glglgl:Chuuが上で述べたように、コードは読みやすいはずです。goto**強く**は、おそらくここを除いて、「ここで起こっている魔法」を示唆していますgoto cleanup;。ここの例では、読者にはwhile(1) { }「ここで使用しなかった特別なことは何ですか?」という不可解な質問が残されます。
MSalters
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.