Тоқтатулар 1

  • Образовательные программы
  • docx
  • 22.10.2018
Публикация в СМИ для учителей

Публикация в СМИ для учителей

Бесплатное участие. Свидетельство СМИ сразу.
Мгновенные 10 документов в портфолио.

Arduino-да тоқтатуларды қолдану (басы) Arduino Interrupts төлтума мақаланы, аудару Көп ретте микроконтроллерде жобалармен жұмыс кезінде фондық функцияны бірдей аралықтағы уақыт сайын іске қосып тұру қажет. Бұл көп ретте тоқтатуларды болдыру үшін, таймер аппараттық құрылғысымен жүзеге асырылады. Бұл тоқтатулар, кезеңдік тоқтатуларды басқару үшін, тоқтатуларды өңдеу бағдарламасын іске қосады (Interrupt Service Routine, ISR). Осы мақалада мен, ATMega168 Arduino микроконтроллеріндегі тоқтатуларды өңдеуге арналған 8-биттік 2 таймерінің орнатылуын сипаттаймын. Мен, оның өзінің ішіндегі және тоқтатуларды өңдеу бағдарламасын орнатуға қажет болатын кезеңдер бойынша өтемін.
Иконка файла материала 8.1.3 Прерывания 03.docx
«Роботты техника». 5­ші деңгей. 9 сабақ. Сабақтың тақырыбы: Тоқтатулар 3. Сабақтың ұзақтығы: 2 сағ. Таймер2 ISR  Таймер 2 қайта толуы бойынша үзіліске арналған ISR төменде көрсетілген. #define TOGGLE_IO 9 //ISR таймері бойынша қайта қосу үшін Arduino  қорытындысы //Timer2 толып кету жөніндегі үзіліс векторының көрсеткіші ISR(TIMER2_OVF_vect) { //IO­қорытындысының басқа күйге қайта қосылуы. digitalWrite(TOGGLE_IO,!digitalRead(TOGGLE_IO)); //Таймердің ағымдағы мәнін қамту. Бұл қатенің көлемі //осы қызметтің үзілісін және жұмысын өңдеудің кідіруінің салдарынан  latency=TCNT2; //Таймердің қайта жүктелуі және кідіру жөніндегі түзету TCNT2=latency+timerLoadValue; } Бұл қызмет қысқа және оның негізгі міндеті ­ енгізу ­ шығару портын  ауыстырып қосу. Ауыстырып­қосқаннан кейін ол таймердің ағымдағы мәнін  қамтиды және оны таймерді қайта жүктеуге түзету үшін пайдаланады.  Кідіртудің мәні ғаламдық, оны жоғарыда аталған жүктеу өлшемдері үшін  басты бағдарлама қадағалайды. Бұл такттердің саны 2 МГЦ жиілігінде, ол  өзінің қызметтерін орындау үшін ISR алады. ISR қысқа болу керектігін естен шығармаңыз, себебі ол 50 кГц бапталған  таймер кезінде әр 20 мкс шақырылады. Сіз көп ISR жасай аласыз, бірақ сізге  үзілістің аралығы мен ISR орындалатын операциялардың санының арасында  теңгерімді табу қажет болады. Кідіртудің мәні төменде сипатталғандай  осыған көмектеседі.Менің сынақтарым шамамен 20 тактті құрайтын, орташа кідірісті көрсетті,  бұл процессорды жүктеудің 45% дейін құрайды. Бұл дегеніміз ISR үшін  бағдарламаның шамамен орта есеппен 45% баяу орындалатындығын білдіреді. Аса да қорқынышты жағдай емес, бірақ байқасаңыз, ISR орындалатын барлық  жұмыс енгізу­шығару портын ауыстырып­қосудан құралған. Бұл барлық  үдерістегі уақыттың шамамен жартысын құрады! Бұл көлем үзіліске қызмет  көрсетуге, сандық жазбаның рәсімін орындауға / сандық оқуға және таймердің қайта жүктелуінің толық үдерісіне кеткен уақыттан құралады. Егер портты тіркеудің көмегімен шығаруға тікелей әрекет жасағанда ISR  әлдеқайда тезірек болар еді. Бірақ жалпы кітапханалық қызметтерді  пайдалану әлдеқайда жеңіл болды, және егер маған шынымен енгізу­шығару  портының күйін ауыстырып­қосу ғана қажет болса, маған 45% жоғалуы  жеткілікті болар еді. Басты бағдарлама. Setup() функциясы Setup() қызметі бағдарламаны іске қосқан кезде бір рет Arduino жүйелік  бағдарламасының көмегімен шақырылады. Ол енгізу­шығару мен таймердің  порттарын жүктейді. Ол сондай­ақ ретті портқа бағдарламаның іске  асырылғандығын көрсететін шығаруды жүзеге асырады. void setup(void) { //ISR ауыстырып­қосу қажет портты шығарушы етіп орнатады. pinMode(TOGGLE_IO,OUTPUT); //Ретті портты іске қосады Serial.begin(9600); //Бағдарламаның іске қосылуы туралы хабарлама Serial.println("Timer2 Test"); //Таймерді іске қосады және таймердің жүктелетін мәнін алады. timerLoadValue=SetupTimer2(44100); //Таймердің жүктелетін мәнін шығарады Serial.print("Timer2 Load:");Serial.println(timerLoadValue,HEX); } Setup() ауыстырып ­ қосатын портты шығатын портқа орнатудан басталады,  сондықтан біз оны ISR ауыстырып қоса аламыз. Сосын ол ретті портты іске  қосады және бағдарламаның әрекет ететіндігін көрсету үшін жазбаша  хабарламаны шығарады. Одан әрі дыбыстың дискреттелуінің жалпы жиілігімен орнатылған 44100 Гц  жиілікпен қызметі шақырылады. Қайтарылатын мән ISR кейіннен қолдану  үшін ғаламдық ауыспалы timerLoadValue сақталады. Сонымен, Setup() timerLoadValue шығарады, сондықтан біз оның саналы шекте екендігіне көз жеткізе аламыз. Осы кезеңде таймер іске қосылған және біздің ISR рәсіміміз берілген  жиілікпен шақырылады. Егер осциллограф қоссақ, сіз таймер аралығының ½  тең шығудың ауыстырылып­қосылуын көресіз. ½ болатын себебі, біз ISR  біреуінің төменгі деңгейіне портты орнатамыз және оған екіншісінің жоғары  деңгейін жазамыз. Басты бағдарлама,  Loop() қызметі Кезеңнің қызметі бағдарлама іске қосылған кезде қайта­қайта шақырылады.  Кезеңнен қайтарылған әр кезде ол қайтадан шақырылады. Бағдарламаның  мәтіні күрделі болып көрінеді, бірақ шындығында, біздің жасағандарымыздың  барлығы ­ Таймер2 ISR кідірісінің көлемін орташа ландырамыз және 100  өлшемді алғаннан кейін өлшемнің нәтижесін шығарамыз. Кезеңнің қызметі енгізу­шығару желісін ауыстырып ­ қосуға қатысты  ешнәрсенің жасамауының қажеттілігін атап өтеміз. Бұның бәрі ISR  басқарылады, ол кезеңнің қызметіне басқа заттармен айналысуына мүмкіндік  береді, ISR болып жатқан үдерістерге назар аудармайды. Ретті порттың  кезеңінде сіз дайын болған кезде, UART келесі белгісінің жүктелуі туралы  қам жемеуіңіз керек. Сіз өз істеріңізбен айналысасыз, ал ретті порт фондық  режимде басқарылады. Бұл кідіріспен басқарылатын бағдарламаның  ерекшеліктерінің бірі. Қызметтер жағдайдың пайда болуы кезінде  шақырылады және сіздің қосалқы бағдарламаңыздан бөлек болып табылады.void loop(void) { //Әр 10 мс сайын ISR кідірісін жинайды. delay(10); // ISR кідірістің ағымдағы мәнін жинайды және есептегішті арттырады //the sample counter latencySum+=latency; sampleCount++; //10 өлшем жиналғаннан кейін есептейді және өлшемнің нәтижесін шығарады if(sampleCount>99) { float latencyAverage; float loadPercent; //Орташа кідірісті есептейді latencyAverage=latencySum/100.0; //сомманың мәнін нөлге теңестіреді sampleCount=0; latencySum=0; //Процессорды жүктеудің күтілетін пайызын есептейді loadPercent=latencyAverage/(float)timerLoadValue; loadPercent*=100; //Үлестерді пайызға ауыстырады; //Орташа кідірісті шығарады Serial.print("Latency Average:"); Serial.print((int)latencyAverage); Serial.print("."); latencyAverage­=(int)latencyAverage; Serial.print((int)(latencyAverage*100)); //Жүктеменің күтілетін пайызын шығарады Serial.print(" Load:"); Serial.print((int)loadPercent); Serial.println("%"); }} Кезеңнің қызметі 10 мс кідірісінен басталады. (Егер үздіксіз жоғары жиілікпен енгізу­шығарудың портын ауыстырып­қосу қажет болса мұндай кідірістерді  пайдалана алмайтындығымызды есте сақтаңыз). 10 мс кідірісі кідірістің  өлшемін және өлшемнің қорытындысын біздің қаншалықты жиі  жасайтындығымызды реттейді. Біз олардың әрқайсысы 10 мс алатын 100  өлшемді алғаннан кейін, нәтиже әр секунд сайын шығарылады. Одан әрі ISR кідірістің мәні latencySum ғаламдық ауыспалылығына жиналады. Біз кідірістің ағымдағы мәнін қамтимыз және оны жиналғандарға қосамыз.  Сонымен қатар, өлшемдердің жиналған санының есептегішін бірлікке  арттырамыз. Енді біз 100 өлшемнің жиналғандығын тексереміз. Егер болмаса, онда қалған  кодты қалдырамыз және қайтамыз. Егер 100 өлшем жиналса, онда  өлшемдердің санына жиналған кідірісті бөле отырып орташа мәнді аламыз  және latencyAverage нәтижесін сақтаймыз. Сосын барлығын қайта бастау үшін аккумуляторды және өлшемдердің есептегішін тазартамыз. Енді, кідірістің жақсы өлшемін ала отырып біз процессордың күтілетін  жүктелімін есептей аламыз. Бізге белгілісі таймер 0xFF дейін және кейін 0×00 дейін біздің қайта жүктелетін мәннен санап шыққанда таймердің толып  кететіндігі белгілі, бұл толып кетудің көрсеткіші. Жүктеу пайызы кідіріс/ ISR такті ретінде анықталатын болады. Бұл мәні есептеледі және өлшемнің  нәтижесі ретінде шығарылады, сондықтан біз ISR бағдарламасының әсерін  бағалай аламыз. Нәтижелер шығарылды, және кезеңнің қызметі қайтадан шақырылу үшін және  10 мс қайтарылады. Мен сіздің назарыңызды басты бағдарламаның портты  ауыстырып­қосу бойынша ешқандай жұмысты атқармайтындығына  аударамын. Ол кідірістерді пайдалануда шектелмеген, уақыттың өзінің  аралықтарымен шақырылады және оған оның тез орындалатындығы әсерін  тигізеді. Ол алатын уақыт ­ бұл барлық фондық ISR орындаудың, осы  таймердің ISR және үнемі белсенді басқаларының қалған уақыты, мысалы,  ретті порт пен Таймер 0.Бағдарламаның мысалында таймер он алты мәнді D4 немесе он мәнді 212  жүктелген. Ол дегеніміз, 44 тактті санағаннан кейін, ол үзіле беретін болады.  Біз білеміз, процессор ISR кодын орындап тұрғанда, таймер шамамен 20  шақты тактті санайды, яғни ол ISR қайтып оралғанға дейін барлығы шамамен  24 қалады. Бұл 24 такт ­ біздің басты бағдарлама орындауға алатын барлық  уақыт. Сондықтан жалпы уақыттан үзілістердің арасындағы 44 тактті біз 20  тактін ISR жұмсаймыз, қосалқы бағдарламаға шамамен 24 тактті қалдырамыз. Бұл ISR жіберілген процессордың шамамен 45% құрайды. Сонымен қатар, бізге белгілісі, ISR барлық орындалатын кодына шамамен 1  такт жұмсалады және кідірістің мәнінде өлшенбейді. Сондықтан жоғарыда  көрсетілген бағдарламада түзету үшін маған уақытша аралыққа бірлікті  қосуға тура келді. Нақты қосымшаға 44­тен тек 23 такт қана беріледі. Мен  қорытындының ауыстырып­қосуына пікір айтып сол бағдарламаны іске қосқан кезде, кідіріс орта есеппен шамамен 3 тактті немесе жүктеменің 6% құрады.  ISR қандай да бір пайдалы тапсырмаларсыз қызмет көрсетпей шамамен  қолжетімді ресурстардың шамамен 6% пайдаланады. Қалған уақытты сандық  оқудың қызметтері мен жазба жеп қояды. Түйіндеме Егер сіз осы орынға дейін оқып болсаңыз, онда сізде кідірістер туралы,  олардың неліктен өте маңызды екендігі туралы және олардың басты  бағдарламаға қалай әсер ететіндігі туралы түсінік қалыптасты. Сонымен  қатар, сізде өз жобаңызды құру үшін бірнеше мысал бар. ISR тез таймерімен  жұмыс жасаған уақытта өте мұқият болыңыз. Егер сіз жылдамдығы аз  таймерді іске қосаңыз, мәселелер, әрине, азаяды. Мен мұнда нені күтуге  болатындығы туралы түсінік беру үшін шектен тыс жағдайларды  қарастырдым.