0

所以我重写了我的代码。当我按下连接在引脚 2 上的按钮时,它使引脚 13 变为高电平,并通过收发器向接收器发送信号(收发器的类型和接收器无关)。我将一根电线从接收器(引脚 13 使其变为高电平)连接到 arduino 上的引脚 7。我还将一个 LED 连接到引脚 8 以指示引脚 7 何时为高电平。

我的主要重点是计算从按下按钮到 Arduino 上的引脚 7 变为高电平所花费的时间。我正在使用 Arduino Leonardo(也是不相关的信息)。

这是我的代码:

int buttonState;
int buttonPin = 2;
int LbuttonState; // last button state
int pin13 = 13;
int pin7state;
int pin7 = 7;
int Lpin7state; // last pin 7 state
int pin8 = 8;
long startTimeKeeper;
long endTimeKeeper;
long elapsedTime;

void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT);
  pinMode(pin13, OUTPUT);
  pinMode(pin7, INPUT);
  pinMode(pin8, OUTPUT);
}

void loop() {
  buttonState = digitalRead(buttonPin);

  if(buttonState == HIGH && LbuttonState == LOW) {
    startTime(); // start the time
    digitalWrite(pin13, HIGH);
    LbuttonState = buttonState;
  } else if(buttonState == HIGH && LbuttonState == LOW) {
    digitalWrite(pin13, LOW);
  } else if(buttonState == LOW && LbuttonState == HIGH) {
    digitalWrite(pin13, LOW);
    LbuttonState = buttonState;
  } else//(buttonState == LOW && LbuttonState == LOW)
    digitalWrite(pin13, LOW);

  pin7state = digitalRead(pin7);

  if(pin7state == HIGH && Lpin7state == LOW) {
    stopTime(); // stop the time
    digitalWrite(pin8, HIGH);
    Lpin7state = pin7state;
  } else if(pin7state == HIGH && Lpin7state == HIGH) {
    digitalWrite(pin8, HIGH);
  } else if(pin7state == LOW && Lpin7state == HIGH) {
    digitalWrite(pin8, LOW);
    Lpin7state = pin7state;
  } else//(pin7state == LOW && Lpin7state == LOW)
    digitalWrite(pin8, LOW);
}

void startTime() {
  startTimeKeeper = millis();
}

void stopTime() {
  endTimeKeeper = millis();`enter code here`
  elapsedTime = endTimeKeeper - startTimeKeeper;
  Serial.print(elapsedTime);
}
4

1 回答 1

0

我建议使用interrupts,特别是因为 Leonardo 支持在您选择的两个引脚的状态更改时触发的中断。

如果我正确理解了问题的核心,您希望从按下引脚 2 的下降沿(高到低)到引脚 7 上的上升沿(低到高)之间经过的时间。如果我误解了这一点,而您的按钮实际上是高电平有效,只需将最终参数更改attachInterrupt(interrupt, ISR, mode)RISING

设置好这些之后,只要发生指定的状态或状态更改,就会调用我们指定的中断服务程序 (ISR) 函数。我们希望在这些 ISR 中做最少的工作,因为在运行时无法触发其他 ISR。记录开始或停止时间会很好。

但是,中断不能使用millis()micros()直接使用,因为这些函数本身使用中断。为了解决这个限制,我们将在每个 ISR 中切换一个我们自己的简单标志 - 以指示它已被触发 - 然后在主循环中轮询该标志值,我们将在其中执行计时器启动/停止行动。micros()由于按下按钮和接收到信号之间的时间应该很短(无论如何,绝不是几分钟),因此我进行了替换以获得更好的准确性。

#define ULONG_MAX 0xFFFFFFFFUL

unsigned long startTimeKeeper, stopTimeKeeper, elapsedTime;
volatile boolean buttonFlag = false, signalFlag = false;

void setup() {
  Serial.begin(9600);

  pinMode(2, INPUT);
  pinMode(7, INPUT);
  pinMode(13, OUTPUT);
  pinMode(8, OUTPUT);

  // Int.2 corresponds to pin 2
  attachInterrupt(2, buttonPressed, FALLING);
  // Int.4 corresponds to pin 7
  attachInterrupt(4, signalReceived, RISING);
}

void loop() {
  // Loop until the buttonPressed ISR sets this flag
  if (buttonFlag) {
    // Record the start time
    startTimeKeeper = micros();

    // Do nothing until the signal flag is set by the ISR
    while (!signalFlag);

    // Record the end time
    stopTimeKeeper = micros();

    // Normal case - stop time is apparently after start time
    if (stopTimeKeeper > startTimeKeeper)
      elapsedTime = stopTimeKeeper - startTimeKeeper;
    // Overflow case - stop time is apparently before start time
    else
      elapsedTime = stopTimeKeeper + (ULONG_MAX - startTimeKeeper);

    Serial.print(elapsedTime);

    signalFlag = buttonFlag = false;
  }
}

// Very lightweight ISRs
void buttonPressed() {
  buttonFlag = true;
}

void signalReceived() {
  signalFlag = true;
}

由于我们在注册按钮按下后立即开始等待signalReceived()ISR 激活signalFlag,因此在这种情况下我们不必太担心开关的去抖动。

通常,您需要使用物理电路或软件计数器来消除开关抖动。查看本教程以开始使用软件,或在此处查找有关构建去抖电路的信息。

于 2014-11-25T08:48:36.693 回答