所以我重写了我的代码。当我按下连接在引脚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);
}
答案 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以获取有关构建去抖电路的信息。