新手和无法编译的计时器模块

A newbie and the timer module that doesn't compile

本文关键字:计时器 模块 编译 新手      更新时间:2023-10-16

我对C/c++完全陌生。我做过一些高级语言,比如Java和c#,但这是我必须说的。我正试图为Arduino构建一个定时器模块,以便我可以轻松地排队工作,必须在一定时间后执行,而无需使用delay()。我希望尽可能直观地创建它,以便我可以轻松地重用它。

到目前为止,我已经尝试了很多不同的方法。我所做的主要是阅读关于如何在C/c++中实现某些事情的教程,并以此为基础创建了我的小项目。

主文件:

#include "Timer.h"
Timer timer;
void setup()
{
    // Init the timer
    timer.init();
    pinMode(13, OUTPUT);
    // Define the state
    int state = 1;
    // Create the action
    TimerAction action;
    action.create(1000, &timerElapsed, 1 -1);
    action.state = &state;
}
void loop()
{
    timer.run();
}
void timerElapsed(TimerAction action) {
    int *state = (int*)action.state;
    if (state == 0) {
        digitalWrite(13, HIGH);
        *state = 1;
    }
    else
    {
        digitalWrite(13, LOW);
        *state = 0;
    }
}

这很简单。我正试着用车载led作为概念验证。

Timer.h文件:

#ifndef _TIMER_h
#define _TIMER_h
#if defined(ARDUINO) && ARDUINO >= 100
    #include "arduino.h"
#else
    #include "WProgram.h"
#endif
struct Timer {
    TimerAction* actions;
    uint8_t size;
    void init();
    void queue(TimerAction action);
    void dequeue(TimerAction action);
    void dequeueIdx(int idx);
    void run();
};
struct TimerAction {
    // Sets whether to repeat the action
    uint8_t repetitive;
    // Sets how many times to repeat the action, -1 for infinite
    // Will only be used when repetitive == 1
    long finite;
    void (*callback)(TimerAction sender);
    void *state;
    unsigned long last;
    unsigned long interval;
    void create(long interval, void(*callback)(TimerAction sender), uint8_t repetitive = 0U, long finite = -1L);
};
#endif

Timer.ino文件:

#include "Timer.h"
void Timer::init() {
    size = 0;
    actions = new TimerAction[10];
}
void Timer::queue(TimerAction action) {
    action.last = millis();
    actions[size - 1] = action;
    size++;
}
void Timer::dequeue(TimerAction action) {
    for (int i = 0; i < size; i++)
        if (&(actions[i]) == &action) {
            memmove(actions + i, actions + i + 1, (size - (i + 1)) * sizeof(TimerAction));
            break;
        }
}
void Timer::dequeueIdx(int idx) {
    memmove(actions + idx, actions + idx + 1, (size - (idx + 1)) * sizeof(TimerAction));
}
void Timer::run() {
    for (int i = 0; i < size; i++)
        if ((actions[i].last + actions[i].interval) >= millis()) {
            TimerAction action = actions[i];
            action.callback(action);
            if (action.repetitive == 1) {
                if (action.finite > 0)
                    action.finite--;
                else
                    if (action.finite == 0)
                        dequeueIdx(i);
            }
            else
                dequeueIdx(i);
        }
}
void TimerAction::create(long _interval, void(*_callback)(TimerAction sender),
                         uint8_t _repetitive = 0U, long _finite = -1L) {
    interval = _interval;
    callback = _callback;
    repetitive = _repetitive;
    finite = _finite;
}

这些是编译器吐出的错误:

Arduino: 1.6.1 (Windows 8.1), Board: "Arduino Uno"
In file included from Stoplicht.ino:1:0:
Timer.h:13:2: error: 'TimerAction' does not name a type
  TimerAction* actions;
  ^
Timer.h:17:13: error: 'TimerAction' has not been declared
  void queue(TimerAction action);
             ^
Timer.h:18:15: error: 'TimerAction' has not been declared
  void dequeue(TimerAction action);
               ^
Timer.ino: In member function 'void Timer::init()':
Timer.ino:5:2: error: 'actions' was not declared in this scope
Timer.ino: At global scope:
Timer.ino:8:6: error: prototype for 'void Timer::queue(TimerAction)' does not match any in class 'Timer'
In file included from Stoplicht.ino:1:0:
Timer.h:17:7: error: candidate is: void Timer::queue(int)
  void queue(TimerAction action);
       ^
Timer.ino:15:6: error: prototype for 'void Timer::dequeue(TimerAction)' does not match any in class 'Timer'
In file included from Stoplicht.ino:1:0:
Timer.h:18:7: error: candidate is: void Timer::dequeue(int)
  void dequeue(TimerAction action);
       ^
Timer.ino: In member function 'void Timer::dequeueIdx(int)':
Timer.ino:24:10: error: 'actions' was not declared in this scope
Timer.ino: In member function 'void Timer::run()':
Timer.ino:29:8: error: 'actions' was not declared in this scope
Timer.ino: At global scope:
Timer.ino:45:52: error: default argument given for parameter 3 of 'void TimerAction::create(long int, void (*)(TimerAction), uint8_t, long int)' [-fpermissive]
In file included from Stoplicht.ino:1:0:
Timer.h:36:7: error: after previous specification in 'void TimerAction::create(long int, void (*)(TimerAction), uint8_t, long int)' [-fpermissive]
  void create(long interval, void(*callback)(TimerAction sender), uint8_t repetitive = 0U, long finite = -1L);
       ^
Timer.ino:45:52: error: default argument given for parameter 4 of 'void TimerAction::create(long int, void (*)(TimerAction), uint8_t, long int)' [-fpermissive]
In file included from Stoplicht.ino:1:0:
Timer.h:36:7: error: after previous specification in 'void TimerAction::create(long int, void (*)(TimerAction), uint8_t, long int)' [-fpermissive]
  void create(long interval, void(*callback)(TimerAction sender), uint8_t repetitive = 0U, long finite = -1L);
       ^

让我解释一下为什么我使用Array而不是std::vector。我的想法是这样的:Arduino很弱,actions将被访问很多。所以我认为最初实现它需要更多的工作,但它会确保计时器不会使用太多的Arduino资源。

我已经尝试了很多方法,但我真的不明白问题出在哪里。这就是为什么我要请专家来检查我的代码,也许能让我走上正确的道路。

在Timer.h中有:

TimerAction* actions;

在编译器看到这行代码时,它还没有看到TimerAction是什么。因此,它不知道类型是什么,并给您一个错误。你需要做的是在Timer之前前向声明TimerAction,这样编译器就知道它在做什么了。

#ifndef _TIMER_h
#define _TIMER_h
#if defined(ARDUINO) && ARDUINO >= 100
    #include "arduino.h"
#else
    #include "WProgram.h"
#endif
struct TimerAction;
struct Timer {
//...