C通过计时器触发任何功能作为单触发功能

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C通过计时器触发任何功能作为单触发功能相关的知识,希望对你有一定的参考价值。

我已经为轮式编带机构建了一个大型程序。我遇到某些功能的时间问题。

在某些方面,我不得不等待像气缸这样的东西。

它可以在某些点发生,即函数立即执行而不是在设置的间隔之后执行。它很少发生,但它可能是令人讨厌的。可能发生的是,车轮在录制之前意外地从机器中滚出。

最重要的是,我还为每个单拍功能使用了一个2字节的软件定时器,它可以更高效。

我现在在做什么:我触发一个在X时间后调用的函数

triggerOneshot(TWO,300);

void triggerOneshot(int C, int I)               // sets the interval for the one-shot timer and selects which function is to be fired.
{
    counter1[C] = counter;
    interval1[C] = I;
    oneshot_bool[C] = 1;
}

我不断打电话:

void updateTimers() 
{
    for(j=0;j<8;j++) {
        if(oneshot_bool[j] == 1) {
            if((counter - counter1[j]) >= interval1[j] ) {
                oneshot_bool[j] = 0;
                fireOneshot(j); } } } 
}

定时器ISR保持递增“计数器”。当时间到了,我做:

void fireOneshot(byte s)                                                                    // this function contains all one-shot timed events.
{
    switch(s) { // selector 
        case ONE:       oneshotFunction1(); break;          
        case TWO:   oneshotFunction2(); break;
        case THREE:   oneshotFunction3(); break;
        case FOUR:  oneshotFunction4(); break;      
        case FIVE:  oneshotFunction5(); break;
        case SIX:       oneshotFunction6(); break;          
        case SEVEN:  oneshotFunction7(); break;
        case EIGHT:  oneshotFunction8(); break; }   
}

所有这些单一功能的主体都包含一个独特的例程。

void oneshotFunction1()
{
    if(airPressureSensor == 1) {
        applicatorUp = 1;
        applicatorDown = 0;
        automatic = 1; 
        message_set = 0;
        setapos(1,15);clreol();// deletes error message
        stop_bool = 1;
        start_bool = 1; }
    else {
        lamp_bool = 1;
        automatic = IDLE; 
        greenLamp = 0;
        start_bool = 0;
        Estop_bool = 0;
        mainRelay = 0; }        
}

我可以同时使用这些单打,但我从来没有需要它。

我想要什么,不知道如何是以下。我想调用triggerOneshot并传递2个争论,时间和任何自定义函数而不是数字。现在我只能使用我为这些oneshot事件开发的特定函数(void oneshotFunction1())。但是我希望能够使用我拥有的每一个函数并将其解析为对于onehot事件的争论。我不知道如何实现这一点。

答案

首先是

void (*const fireOneshot[]) (void) = {
    oneshotFunction1, 
    oneshotFunction2,
    oneshotFunction3,
    oneshotFunction4,
    oneshotFunction5,
    oneshotFunction6,
    oneshotFunction7,
    oneshotFunction8,
};

你可以打电话给fireOneshot[j]()(到目前为止测试)。

(未在此处测试)

使用void (*const fireShot) (int i, char c);你可以用fireShot分配变量foo任意函数void foo(int, char)和签名fireshot = foo,并通过fireShot(7,3)调用它。

触发器可能是

typedef uint16_t WORD;

struct Trigger {
    void (*function)(int arg1, Foo * pointer);
    int fx_arg1;
    Foo * fx_arg2;
    WORD countdown;
} my_trigger;

struct Trigger * ptrigger;

然后可以通过设置这样的触发器

my_trigger.funtion = my_generic_shot;
my_trigger.fx_arg1 = 08;
my_trigger.fx_arg2 = p_current_foo;
my_trigger.countdown = 300;

当倒计时到期时,请致电

my_trigger.function(my_trigger.fx_arg1, my_trigger.fx_arg2);

或者

ptrigger->function(ptrigger->fx_arg1, ptrigger->fx_arg2);   

(测试会发现的错别字除外)。

另一答案

类似的答案,但让我提供另一个例子如下。

// oneshot event handler prototype; you can modify as you want
typedef int (*eventhandler_t)(uint32_t counter, void * context);
typedef struct {
  uint32_t timeout;
  eventhandler_t handler;
  void *context;
  bool triggered;
  //... even you can define further
} eventDS_t;

#define MAX_EVENTDS 10
eventDS_t _eventDS_list[MAX_EVENTDS];  // you can implement with linked list as well
unsigned int _eventDS_size = 0;
// You'd better implement this part with binary tree to search faster the handler with interval

int regHandler(uint32_t timeout, eventhandler_t func, void *context) {
  if (_eventDS_size < MAX_EVENTDS && func != NULL) {
    _eventDS_list[_eventDS_size].timeout = counter + timeout;
    _eventDS_list[_eventDS_size].handler = func;
    _eventDS_list[_eventDS_size].context = context;
    _eventDS_list[_eventDS_size].triggered = false;
    _eventDS_size++;
    return 0; // success
  }
  return -1;  // error
}

void updateTimer() {
  for (unsigned int i = 0; i < _eventDS_size; i++) {
    if (!_eventDS_list[i].triggered && 
        _eventDS_list[i].timeout >= counter) {
      _eventDS_list[i].handler(counter, _eventDS_list[i].context);
      _eventDS_list[i].triggered = true;
    }
  }
}

int fireOneshot(uint32_t counter, void * context) {
  //.... something else what you want 
  return 0;
}

int main(int argc, char *argv[]) {
  struct myData {
    int a, b;
  } data;
  // somewhere in your main codes, you can call regHandler() to register the hanlder
  regHandler(100, fireOneshot, (void*)&data);
  regHandler(200, fireTwoshot, (void*)&data);
  //.... as you want

  return 0;
}
另一答案

_eventDS_list[_eventDS_size].timeout = counter + timeout;_eventDS_list[i].timeout >= counter是一个严重的错误。

它没有考虑到qazxsw poi在232个单位时间内溢出。 (注意232毫秒= = 7个星期远离有缺陷的情况)。

以上是关于C通过计时器触发任何功能作为单触发功能的主要内容,如果未能解决你的问题,请参考以下文章

使 Azure Webjob 计时器触发器不作为单例运行

如何在Xamarian iOS应用程序中单击按钮后X秒触发事件?

使用js实现显示系统当前时间并实现倒计时功能并触发模态框(遮罩)功能

C#中定时器执行定时器触发任务是单线程还是多线程?

传奇定时器OnTimer功能详解(泡点时间触发任务活动)

单 Azure 函数多定时器触发