Светодиод мигает последовательность - PullRequest
0 голосов
/ 30 ноября 2018

У меня есть переменная LedState [9] с переменным массивом без знака, которая распределяется между потоками.Каждый индекс в массиве обозначает состояние.В соответствии с каждым состоянием светодиод будет мигать в различной последовательности.Один поток устанавливает состояние в массиве, а другой поток на основе индекса массива будет мигать светодиодами.Каждое государство поддерживает набор массивов 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};

В основном потоке я просматриваю каждое состояние в массиве и проверяю, включено ли это состояние или нет.Если состояние включено, я мигаю светодиодом для значений таймера, соответствующих состоянию.

Например: состояние 2 должно быть включено в течение 500 мс и отключено в течение мс.Мы продолжаем находиться в состоянии 2, пока не будет установлено состояние 3.Состояние 3 имеет таймер ВКЛ как 1 и таймер выключения отсутствует, что означает, что светодиод должен гореть постоянно.

Состояние 3 - это базовое состояние, то есть любое состояние после состояния 3, должно мигать в соответствии с таймером и возвращаться в состояние 3.
Например, светодиодный синий свет включается после состояния 3,Когда установлено состояние 6, светодиоды должны мигать в течение 100 мс ВКЛ и 100 мс ВЫКЛ.Светодиоды должны мигать, пока состояние 6 не будет выключено, и вернуться в состояние 3. Таким образом, в основном это основано на приоритете.Если состояние 7 также включено, после завершения состояния 6 оно должно мигать в состоянии 7, пока состояние 7 не будет выключено, и должно вернуться в состояние 3.

Моя проблема заключается в том, что мигание выглядит как мерцание, когда состояние 3всегда установлен.Мне нужен переход без гражданства.Я не могу отключить состояние 3 на основе следующего состояния.

    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);
          }
      }
    }

1 Ответ

0 голосов
/ 30 ноября 2018

На данный момент все еще отсутствует информация для полного анализа, но на данный момент, эти улучшения могут быть предложены.

1) Присваивая значение 0 переменной LEDState, выпишите на volatile:

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

Вы не должны этого делать. Они должны быть доступны только для чтения .И в любом случае в вашем описанном подходе нет ничего, что указывало бы на необходимость volatile.(Если только LEDState[i] не используется вашим оборудованием или каким-либо другим процессом вне вашего приложения.)
Тот факт, что этот массив переменных должен обновляться различными потоками в вашей программе не требуетчтобы это было сделано volatile.Достаточно того, что в вашем массиве есть выделенный элемент для каждого потока, и до тех пор, пока вы строго ограничиваете доступ к каждому элементу для соответствующего потока, обновление состояний с помощью этого метода будет работать.Но этот подход не поддерживает использование volatile.

Подробнее о volatile ЗДЕСЬ

2) Вы заявляете, что Каждый индекс в массиве обозначает состояние. VolatileВ массиве есть место только для 5 состояний, но вы упомянули в своем описании до 7 состояний.(Позже, в комментариях вы говорите, что есть 9 состояний.) Определите четко, сколько существует состояний, затем измените массив для поддержки всех ваших состояний: (обратите внимание, массив не создается как volatile, не должен это быть.)

#define MAX_STATES 9
unsigned char array LedState[MAX_STATES];

3) рассмотрите возможность использования оператора switch() для вашего state machine.

... 
switch(i)  {
    case LastBlueState:
    case LastGreenState:        
        // do something
        break;
    case <some other state>
        // do something
        break;
        ...
...