计算信号时间

时间:2014-11-03 10:55:31

标签: c arduino microcontroller arduino-uno arduino-yun

所以我重写了我的代码。当我按下连接在引脚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);
}

1 个答案:

答案 0 :(得分: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()

由于我们在注册按钮后立即开始等待signalFlag ISR激活{{1}},因此我们不必过于担心在这种情况下去掉开关。

通常,您需要使用物理电路或软件计数器去抖动开关。查看this tutorial以开始使用软件,或查看here以获取有关构建去抖电路的信息。