Бұл Үзіліс таймерін ауыстырады ма?

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
Сіз бұл жерде дерлік. Келесі аралығындағы алдыңғыMillis файлын currentMillis (if-statement ішінде) етіп орнатуыңыз керек. PreviousMills және currentMililis міндетті түрде белгісі болмауы керек. 'Офсай уақыты' қолтаңбаланған бүтін сан болуы мүмкін немесе ұзағырақ қол қоя алады, бірақ егер сіз белгісіз ұзақ уақытты жасасаңыз, онда бәрі белгісіз болып табылады, бұл кодты неғұрлым анық етеді және компилятор айнымалыларды айналдыруға тура келмейді.
қосылды автор 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
қосылды
Тұрақты кезең үшін (алдыңғыMillis тұрақты мәнді ұлғайту), ол жарылыс жасай алады, мысалы орнату ұзақ уақыт алады. Бұл жағдайда орнатуды аяқтағаннан кейін алдыңғы Миллисті миллиске орнаттым. Эскиз басталған кезде, жарылыс алдын алады және орнату ұзақ уақыт алады.
қосылды автор Standback, көзі

Сіздің бағдарламаңызды шақыратын функция үзу функциясының қандай да бір әрекетін жасай алады, бірақ бәрі емес. Егер оны жиі жеткілікті деп санасаңыз, «бір екінші кодының» уақытында орындалуы мүмкін. Қанша рет қоңырау шалу керек, қаншалықты дәл орындау аралығы қажет екеніне байланысты. Мүмкін сіз негізгі кодты талап ете алмай, таймерді көп уақыт жұмсауды талап етуі мүмкін; бұл сіздің нақты жағдайларыңызға байланысты.

Шынайы үзіліс функциясы оны іске қосу үшін кез келген оқиғаның пайда болуына бірден дереу шақырылады. Осы уақытқа дейін негізгі кодтан ешқандай уақыт алынбайды.

Бұл тиімді ауыстыру сіздің нақты жағдайыңызға байланысты.

Сіз берген код синтаксистік түрде дұрыс емес және компиляцияланбайды. Кірістірілген функциялар C немесе C ++ ішіне кірмейді және 'if' сөзінде жақша теңдестірілмеген.

1
қосылды
Қарамастан, код Arduino IDE-де жасалмады.
қосылды автор caryden, көзі
Жоқ, компилятор нақты емес; бұл стандарттарға тән. Кейбір компиляторлар тілге кеңейтуді жүзеге асыра алады. Бұл олардың тілдің бір бөлігіне айналмайды.
қосылды автор caryden, көзі
> Енгізілген функциялар C немесе C ++ ішіне кірмейді, ол компиляторға тән.
қосылды автор dannyf, көзі
бұл сіздің түпнұсқа сөзіңізді әлі де дұрыс жасамайды
қосылды автор dannyf, көзі

Ия, салыстыру дұрыс болғанда, алдыңғы миллистің 1000-ға жетуі.

Алдыңғы миликті ағымдағы миллиске орнату - дұрыс емес тәсіл, себебі ол уақыт қателіктерін жинақтайды.

өңдеу:

міне, сіз жасауға тырысатын нәрсені жасайтын болар деп ойлаймын.

//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, мен жай ғана оқимын «тек жалпы уақыт өте маңызды, нақты аралық емес». Сіз дұрыс болып отырасыз, оны үнемі ұлғайта отырып, оны микроконтроллердің/процессордың кристалы сияқты бір дәлдікпен жұмыс жасай аласыз.
қосылды автор 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
қосылды
Сіздің тестіңіз if (lateMillis + delta> = 0) әрқашан дұрыс. volatile кілт сөзі мұнда пайдасыз.
қосылды автор 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
қосылды
millis() асып кетуін өңдеу дұрыс емес. Сіз оны тек нөл арқылы айналдыруға рұқсат етіңіз және барлық уақыт айнымалы мәндеріңізді қол қоюсыз жасаңыз. Шын мәнінде, сіздің кодыңызда бұл мәселені шешуден аулақ болғаныңыз дұрыс болды.
қосылды автор Sprogz, көзі