Ці будзе гэта замена для таймера перапынення?

class Pseudo_Interrupt {
  //only cummulative time is important, exact interval is not
 //Class Member Variables
 //These are initialized at startup
  long OffTime = 1000;//milliseconds of off-time
 //These maintain the current state
  unsigned long previousMillis;//will store last time updated

  void Update() {
   //check to see if it's time for an Interrupt
    unsigned long currentMillis = millis();
    if ((currentMillis - previousMillis >= OffTime) {
      //Time to execute the one second code
    }
  }
}
1
Вы амаль там. Вы павінны ўсталяваць previousMillis ў currentMillis (унутры заяву, если-) для наступнага інтэрвалу. У previousMills і currentMillis <�б> павінен быць беззнаковыми доўга. «Offtime» можа быць знакавая цэлае, або падпісана даўно, але калі вы зробіце што непадпісаны доўга, а, значыць, усё непадпісаныя доўга што робіць код больш зразумелым і кампілятар не павінен пераўтварыць зменныя.
дададзена аўтар Standback, крыніца

5 адказы

Уся ідэя гуку, але я хацеў бы зрабіць некалькі змен:

  • as explained by Jot in a comment, you have to update previousMillis inside the if statement. You have two choices:
    • set it to currentMillis, then OffTime will be the minimum time between the pseudo-interrupts
    • increment it by a constant amount, which I would call period, then this will be the average time between pseudo-interrupts; this is more similar to how real timer interrupts work
  • add a constructor for:
    • making the period user-selectable
    • making the action of the timer user-selectable via a callback
    • initializing previousMillis

З улікам гэтых змяненняў, клас будзе выглядаць наступным чынам:

class Pseudo_Interrupt {
    unsigned long period;
    unsigned long previousMillis;
    void (*callback)();

public:
    Pseudo_Interrupt(void (*callback)(), unsigned long period)
        : period(period), previousMillis(millis()), callback(callback)
    { }

    void update()
    {  
        if (millis() - previousMillis >= period)
        {
            callback();
            previousMillis += period;
        }
    }
};
3
дададзена
Для стацыянарнага перыяду (прырашчэнне previousMillis з канстантай), ён можа стварыць выбух, напрыклад, калі ўстаноўка займае шмат часу. У гэтым выпадку я паставіў previousMillis да Millis ў канцы ўстаноўкі. Гэта прадухіляе выбух, калі эскіз пачынаецца і ўстаноўка займае шмат часу.
дададзена аўтар Standback, крыніца

Функцыя называецца вашай праграмай можна зрабіць некаторыя, але не ўсё, што робіць функцыя перапынення. Калі вы называеце гэта досыць часта, вы можаце атрымаць своечасовае выкананне Вашага «аднаго другога кода». Як часта вы павінны назваць гэта залежыць ад таго, як менавіта інтэрвалу выканання вам трэба. Гэта можа запатрабаваць код магістральнага марнаваць больш часу на апытанне таймер, чым вы можаце сабе дазволіць; гэта залежыць ад канкрэтных абставінаў.

Праўдзівая функцыя перапынення будзе выклікацца амаль адразу ж па наступе падзеі незалежна усталяваны, каб выклікаць яго. Да таго часу, няма часу, будзе ўзята з вашага кода магістральнага.

Незалежна ад таго, што гэта тое, што з'яўляецца эфектыўнай заменай залежыць ад канкрэтнай сітуацыі.

Вы паказалі код сінтаксічна ня правільна і ня кампілюецца. Укладзеныя функцыі не ўключаюць у C ці C ++, і ў «калі» заяву, дужкі з'яўляюцца незбалансаванымі.

1
дададзена
Незалежна ад таго, код ня кампіляваць ў Arduino IDE.
дададзена аўтар caryden, крыніца
Не, гэта не кампілятар канкрэтных; гэта стандарты спецыфічныя. Некаторыя кампілятары могуць рэалізаваць пашырэння мовы. Гэта не робіць іх часткай мовы.
дададзена аўтар caryden, крыніца
> Укладзеныя функцыі не ўключаюць у C ці C ++, ... гэта кампілятар спецыфічныя.
дададзена аўтар dannyf, крыніца
што да гэтага часу не робіць ваша першапачатковае заяву правільна
дададзена аўтар dannyf, крыніца

Так, калі вы загадзя папярэдні Миллис на 1000 разы, што параўнанне праўдзівае.

Ўстаноўка папярэдніх Миллис бягучай Millis няправільны падыход, паколькі ён будзе назапашваць памылкі сінхранізацыі.

рэдагаванне:

вось просты кавалак, які, спадзяюся, будзе рабіць тое, што вы спрабуеце зрабіць.

//pseudo timer isr
//return 1 if the timer overflows MYTMR_PR
uint8_t mytmr_ovf(void) {
    static uint32_t last_time=0;        //previous time
    uint32_t current_time;

    current_time = millis();            //take current time
    if (current_time - last_time >= MYTMR_PR) {
        last_time += MYTMR_PR;          //update last time
        return 1;                       //indicate overflow
    }
    return 0;                           //indicate no overflow
}

як я прапанаваў раней, код напісаны так, што таймер доўгатэрміновы дакладны.

Спадзяюся, што гэта дапамагае.

рэдагаваць 2: тут вышэй код працуе на PIC24F з MYTMR_PR роўным 100 (= 100 мс)

//user loop
void loop(void) {
    //looping around
    if (mytmr_ovf()) digitalWrite(LED, !digitalRead(LED));   //flip the led
}

enter image description here

1
дададзена
@dannyf, я толькі што прачытаў «толькі cummulative час важна, дакладны інтэрвал не з'яўляецца». Вы маеце рацыю, прыбаўка з пастаяннай будзе прымусіць яго працаваць з той жа дакладнасцю, што і крышталь мікракантролера/працэсара.
дададзена аўтар Standback, крыніца
Я мяркую, што вы ўвялі гэта на мабільны тэлефон ....
дададзена аўтар user18101, крыніца

Апошняя версія: 7/6/17

//--------------------------------------------------------
class Pseudo_Interrupt {

{  //These maintain the current state of the timer
public: 
volatile unsigned long previousMillis;  //will store last time updated   
volatile unsigned long lateMillis = 0;      //how late was it
volatile bool CallOneMinute = false; //facilitates while loops, 
}
// to prevent a callback set previousMillis = millis(); periodically within the 'period'
// to start the callback set previousMillis = millis() - period; lateMillis = 0;
volatile unsigned long currentMillis; 
static const unsigned long period = 1000;    //milliseconds of off-time delay
volatile unsigned long delta;
    void (*callback)();
public:
    Pseudo_Interrupt(void (*callback)(), unsigned long period)
        : period(period), previousMillis(millis()), callback(callback)
    { }

    void update()
    {       currentMillis = millis(); 
            CallOneMinute = false
            delta = currentMillis - previousMillis - period
        if (lateMillis + delta >= 0)                         
            lateMillis = delta;
            CallOneMinute = true             
        {
            callback();  //with correction to keep net correct cumulative time
            previousMillis += ( period - lateMillis ); 
    }
};
//----------------------------------------------------------
1
дададзена
Ваш тэст , калі (lateMillis + дэльта> = 0) заўсёды дакладна. <�Код> лятучы ключавое слова бескарысна тут.
дададзена аўтар Sprogz, крыніца

З таго часу я паставіў наступныя ў бесперапынным хуткім цыкле. Калі праграма атрымлівае да яго, ён выконвае. Адна другая трохі бязладным, але агульная назапашаная прыблізна дакладная.

long OffTime = 1000;    //milliseconds of off-time

// These maintain the current state of the timer
long previousMillis;  //will store last time updated   
long lateMillis;      //how late was it

//----------------------------------------------------------------------

currentMillis = millis();     //correct for millis() overflow
if (currentMillis - previousMillis < 0 )
    currentMillis = currentMillis + 32768;
{
    if (currentMillis - previousMillis >= OffTime - lateMillis )

       //Assume the difference is longer than 1000 milliseconds
       //because the sample time will be late but not by much
        lateMillis = currentMillis - previousMillis - OffTime;

       //Thus, cumulative time is essentially correct 
        //Time to execute the one second code here
        do some code
    else
        return;
    }
// ---------------------------------------------------- 
} // End Of Run Repeatedly
0
дададзена
Ваш зварот з Миллис() перапаўненне памылкова. Вы павінны проста дазволіць ёй перавярнуцца праз нуль, і зрабіць усё вашыя зменныя тэрміны без знака. На самай справе, як вы пазбегнуць таго, каб справіцца з гэтым у кодзе ад вашага пытання была правільнай.
дададзена аўтар Sprogz, крыніца