首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LED闪烁序列

LED闪烁序列
EN

Stack Overflow用户
提问于 2018-11-30 21:51:00
回答 1查看 101关注 0票数 0

我有一个易失性的无符号字符数组LedState9变量,它在线程之间共享。数组中的每个索引表示一个状态。根据每种状态,LED将以不同的顺序闪烁。一个线程设置数组中的状态,另一个基于数组索引的线程将使LED闪烁。每个状态维护一组ontimer和offtimer数组。

unsigned long TimersForBlueLedOn[] = {100,200,500,1,0,0,100,200,500};

unsigned long TimersForBlueLedOff[] = {100,200,500,0,0,0,100,200,500};

在主线程中,我遍历数组中的每个状态,并检查状态是否打开。如果state为on,我会使LED闪烁,以获得与该状态对应的计时器值。

例如:状态2必须在500ms内打开,在ms内关闭。我们继续处于状态2,直到状态3被设置。状态3的ON定时器为1,没有OFF定时器,这意味着LED应始终亮起。

状态3是基本状态,也就是状态3之后的任何状态,应该根据定时器闪烁,并且应该返回到状态3。

例如,在状态3之后,Led蓝色被点亮,当状态6被设置时,Led应该闪烁100ms on和100ms OFF。leds应该闪烁,直到状态6关闭并返回到状态3。因此,基本上它是基于优先级的。如果状态7也是打开的,则在完成状态6之后,它应该闪烁状态7,直到状态7关闭,并且应该返回到状态3。

我的问题是,当状态3总是被设置时,闪烁看起来像闪烁。我需要进行无状态转换。我无法根据下一个状态关闭状态3。

代码语言:javascript
复制
    void TurnOnLed(ModemState state) {
    LEDState[state] = 1;
}

void TurnOffLed(ModemState state) {
    LEDState[state] = 0;
}

unsigned char CheckLedState(unsigned char state) {
    return LEDState[state];
}
void GetLedStateVar(LEDStateVar *pLS) {
    unsigned char state = pLS->State;
    pLS->LongflashCode = INVALID_VAL;
    switch(state) {
          case ModemTurnOn:
              pLS->LED = Blue;
              pLS->OnTimer  = TimersForBlueLedOn[state];
              pLS->OffTimer = TimersForBlueLedOff[state];
              break;
          case ModemInit:
              pLS->LED = Blue;
              pLS->OnTimer  = TimersForBlueLedOn[state];
              pLS->OffTimer = TimersForBlueLedOff[state];
              break;
          case GSMConnected:
              pLS->LED = Blue;
              pLS->OnTimer  = TimersForBlueLedOn[state];
              pLS->OffTimer = TimersForBlueLedOff[state];
              break;
          case GPRSOn:
              pLS->LED = Blue;
              pLS->OnTimer  = TimersForBlueLedOn[state];
              pLS->OffTimer = TimersForBlueLedOff[state];
              break;
         case ServerNotConnected:
              pLS->LED = Green;
              pLS->OnTimer = TimersForGreenLedOn[state];
              pLS->OffTimer = TimersForGreenLedOff[state];
              break;
         case SwUpdateDownload:
              pLS->LED = Blue;
              pLS->OnTimer = TimersForBlueLedOn[state];
              pLS->OffTimer = TimersForBlueLedOff[state];
              break;
         case SwUpdateRestart:
              pLS->LED = Blue;
              pLS->OnTimer = TimersForBlueLedOn[state];
              pLS->OffTimer = TimersForBlueLedOff[state];
              break;
         case SwUpdateNewVersion:
              pLS->LED = Blue;
              pLS->OnTimer = TimersForBlueLedOn[state];
              pLS->OffTimer = TimersForBlueLedOff[state];
              break;
}

void FlashBlueLed(LEDStateVar *pLSV) {

    if(pLSV->OnTimer == 1) {
              SetLEDBlue(1);          
      }else  {

          if(GetElapsedTime(&BlueFlashTimer) >  pLSV->OnTimer * MILLI_SECONDS) {
             if(!GetLEDBlue()) {
                 SetLEDBlue(1);
                 StartTimer(&BlueFlashTimer);
             }
          }

          if(GetElapsedTime(&BlueFlashTimer) > pLSV->OffTimer * MILLI_SECONDS) {
            if(GetLEDBlue()) {
                SetLEDBlue(0);
                StartTimer(&BlueFlashTimer);
             }
          }
    }
}   

 for(unsigned char i=0; i< FLASHSTATES; ++i) {
      LF.State = i;
      GetLedStateVar(&LF);

      //Flashcode not complete but the state has been reset
      if(i == LastBlueState || i == LastGreenState) {
          if(LF.LED == Blue) {  // BLUE LED
              FlashBlueLed(&LF);

          }else if(LF.LED == Green) {
              FlashGreenLed(&LF);
          }
      } else if(CheckLedState(i) && LF.OnTimer) {

          if(LF.LED == Blue) {  // BLUE LED
              if(LastBlueState == INVALID_VAL) {
                  FlashBlueLed(&LF);
              }
          } else if(LF.LED == Green) {  // GREEN LED
              if(LastGreenState == INVALID_VAL) {
                  FlashGreenLed(&LF);
              }
          } else if(LF.LED == Both) { //BOTH GREEN AND BLUE LED
              FlashBothLeds(&LF);
          }
      }
    }
EN

回答 1

Stack Overflow用户

发布于 2018-11-30 22:23:34

在这一点上,仍然缺少完整分析的信息,但目前可以提出这些改进建议。

1)通过将0值赋给LEDState变量,您将写入volatile

代码语言:javascript
复制
void TurnOffLed(ModemState state) {
    LEDState[state] = 0;
}

你不应该那样做。。无论如何,在您所描述的方法中,没有任何内容表明需要volatile。(除非您的硬件或应用程序外部的某些其他进程正在访问LEDState[i]。)

这个变量数组需要由程序中的各个线程进行更新,这一事实并不要求将其设为volatile。您的数组为每个线程都有一个专用元素就足够了,并且只要您严格限制对每个元素的访问仅限于其各自的线程,就可以使用此方法更新状态。但是这种方法不支持使用volatile

2)您声明数组中的每个索引表示一个状态。易失性数组只有5个状态的空间,但您在描述中提到了最多7个状态。(后来,在评论中,您说有9个州。)明确定义有多少个状态,然后更改数组以支持所有状态:(请注意,数组不是作为volatile创建的,也不需要是)。

代码语言:javascript
复制
#define MAX_STATES 9
unsigned char array LedState[MAX_STATES];

3)考虑对state machine使用switch()语句。

代码语言:javascript
复制
... 
switch(i)  {
    case LastBlueState:
    case LastGreenState:        
        // do something
        break;
    case <some other state>
        // do something
        break;
        ...
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53558845

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档