是什么导致我的微控制器LED程序停止工作?


11

所以,我是一个完全的编程新手。我已经在Arduinos上做了一些基本的工作(实际上是切换LED并在LCD上显示某些东西),我试图自学如何用C编程。做任何固件/软件方面的工作,而且没有夜校可以教它,我想进一步发展我的职业选择。我正在努力了解其中一些命令是如何结合使用的,并遇到了一个问题,我无法理解为什么它不起作用。

因此,我有一个输入和一个输出。我的输出是切换FET的栅极,从而使LED点亮。输入来自与门。因此,我的LED一直亮着,当我从AND门获得输入信号时(已满足2个条件),我希望输出(LED切换)变为低电平(关闭LED。因为输出也连接到“与”输入之一,这也将使输入信号变为低电平。

我想做什么:我只想读取输入内容为“满足条件”,然后关闭LED。然后应将其关闭1秒钟,然后重新打开。如果输入再次变为高电平,则重复该过程。我使用一个简单的推动将开关作为另一个“与”门输入,并测量了按下按钮时输出(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。如果输入从“与”门获得信号,则LED将关闭1秒钟,然后再次打开。

我做错了什么,因为这看起来像是合乎逻辑的方式,而我只是不明白为什么这不起作用?

如果有帮助,我正在使用Nucleo F103RB。当我使用“ blink”代码并像这样打开和关闭LED时,它可以正常工作,只是当我添加“ if”语句时,它才出错。

这是简化的电路:

原理图

模拟该电路 –使用CircuitLab创建的原理图

PS我知道我没有在原理图中添加它们,但是与门的输入和输出上确实具有下拉电阻。


如果您将“满足条件”直接输入IN,是否可行?
晶体管

它不是。我将按钮直接按到IN上却仍然无法正常工作
好奇

1
将输入变量标记为volatile是一个好主意,否则编译器可能会通过假设未从代码外部对其进行更改来进行一些奇怪的优化。
德克·布鲁尔(Birk Bruere)

3
@DirkBruere:您希望DigitalIn已经定义volatile
MSalters

3
下一次提示:在打开(或复位)CPU(或微控制器)时,请尝试按住按钮。现在会发生什么?
CVn

Answers:


26

我本以为您需要在代码周围循环-

while(1)
{

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

在您没有机会按下按钮之前,您的代码将完成并退出。您需要一段时间来保持if语句重复运行。


是什么让我与众不同?我可以看到“一会儿”,但那是什么呢?抱歉所有问题,但我真的是从零知识开始!
2017年

1
@curious在您有机会按下按钮之前,您的代码将完成并退出。您需要一段时间来保持if语句重复运行。通常是这种情况,除非所编程的微控制器有所不同。
HandyHowie

9
“您能解释一下为什么起作用吗”-重复执行while循环中的所有操作,直到条件恢复为零为止。您可能会问,条件是什么?您可以看到,条件是设置为1,所以它永远不会为零,因此会无限重复。如果不使用while循环,则代码仅执行一次,然后软件终止,而使用while循环,则重复执行代码,直到关闭硬件为止。
Jurgy

14
您的错误可能源于使用Arduino进行mbed。在Arduino中,通常会将您的应用程序代码放入其中loop(),但是Arduino框架会添加行为大致类似的代码int main() { setup(); while(1) { loop(); } }
ris8_allo_zen0

1
@好奇你的工作。不幸的是,它刚启动时就运行了一次。运行可能需要一微秒,仅此而已。如果希望它继续检查输入并设置输出,则需要告诉它继续执行。只要“ some_condition”为真,“ while(some_condition)”就会运行,这在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库初始化代码DigitalIn和中开始 DigitalOut
然后执行比较ip == 0,在中运行指令{},然后main()结束...不再有指令...它是做什么的?

由于在空的闪存中发现非法的操作数,它可能会复位。否则它将像mbeds一样挂在故障处理程序中并闪烁SOS。这取决于它的实现方式,现在可能会超出您的范围。
但是,如果您好奇,可以研究ARM故障处理,或者找出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,但我非常感谢您的答复和解释
Curious

啊哈!关于我的问题的第三次投票使我对你的答案投了赞成票!再次感谢
Curious

1
@Curious如果您想让程序员更清楚这些,则可以编写类似while(1 == 1)just的东西while(1)。后者是惯用的C,但是对于人类而言,前者更为明显,因为“将始终评估为真”。任何体面的编译器都应为两种变体产生相同的二进制代码。
CVn

2
@MichaelKjörling我不同意它对于人类来说更明显。就像您的大脑是通过单词的形状而不是字符来读取单词一样,对于一个经验丰富的程序员来说,这些习惯用法可以直接翻译为概念,而不是解释每个单独的语句在做什么。通过远离惯用的构造,您迫使人们使用代码的程度低于理解所需的水平。在庞大的代码库中,这增加了很多不必要的脑力劳动。
Chuu

1
@Chuu“由一个人[不是一个有经验的程序员]”
user253751 '17

2

正如其他人正确提到的那样,循环将允许您的代码重复运行。但是,有一种内置方法可以为Arduino执行此操作,而无需while循环。这是通过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(); }
Cameron Tacklind '17

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本身没有什么问题”。我同意在具有Exceptions的语言中goto是多余的,但是特别是在C语言中,它具有其用途。
glglgl

@glglgl:正如Chuu前面提到的,代码应该可读。goto**强烈**暗示“这里的魔术”,可能是的例外goto cleanup;。在此处的示例中,读者将遇到一个令人困惑的问题:“有什么特别之处,您在while(1) { }这里没有使用???”。
MSalters
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.