Skip to content

non_blocking delays versus millis()

Iunie 19, 2013

UPDATE Jun 20, 2013: am detaliat modul de functionare la sfarsitul articolului. Deasemenea, pe forumul arduino.cc am deschis un topic de discutii.

Articolul original: Sau mai exact, timer0_isr_interval. Cei care programeaza microcontrolere Microchip folosind compilatorul JALv2 si setul de biblioteci jallib, stiu despre ce vorbesc.

Am deschis un nou „branch” (ramura) in repozitoriul SVN si am „clonat” actuala biblioteca sub denumirea de ATmegaCLib2, ca sa pot inlocui functia millis() si rescrie functiile pentru senzorii de temperatura Dallas fara sa afectez actualul cod. Am adaptat codul din bibliotecile jallib si functionarea este asemanatoare (pana la un punct, se pot folosi exemplele din jallib) – inlocuieste cu succes functia millis() si produce cod mai compact. Doar biblioteca din branch va fi dezvoltata pe mai departe…

Folosire non-blocking delays

In antetul atmegaclib2.h activati definitia ENABLE_NB_DELAYS, derulati fisierul mai jos si schimbati definitia DELAY_SLOTS ca sa reflecte numarul de delays (intarzieri) de care aveti nevoie. De exemplu, pentru programul urmator am avut nevoie de 3 delays  (n.a: mi se pare teribil sa incerc sa traduc in romaneste termeni tehnici englezesti consacrati, folositi in mod curent de toti cei care au de a face cu microcontrolere si programare, indiferent de natie – asta e.):

 #define DELAY_SLOTS  3 // the number of nb. delays

Urmatorul program clipeste simultan 3 LED-uri pe pinii RD5, RC6, RC7 ai microcontrolerului ATmega644P, la vitezele de 250, 500, 750 milisecunde.

#ifndef F_CPU
#define F_CPU 16000000U // required by Atmel Studio 6
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
//#include <util/delay.h>
#include <atmegaclib2.h>

void main(void) __attribute__((noreturn));
void main(void) {
	// setting (LED) pins as outputs
	sbi(DDRD, 5);
	sbi(DDRC, 6);
	sbi(DDRC, 7);
	// init the non_blocking delays
	timer0_isr_init();
	sei();
	// set delays in milliseconds for every LED
	set_delay(0, 250);
	set_delay(1, 500);
	set_delay(2, 750);
	while(1){
		if(check_delay(0)){
			tbi(PORTD, 5);
			set_delay(0, 250);
		}
		if(check_delay(1)){
			tbi(PORTC, 6);
			set_delay(1, 500);
		}
		if(check_delay(2)){
			tbi(PORTC, 7);
			set_delay(2, 750);
		}
	}
}

Definitia DELAY_SLOTS este folosita pentru a crea array-ul isr_countdowns[DELAY_SLOTS], unde vor fi stocate valorile in milisecunde ale intarzierilor de care avem nevoie. La fiecare milisecunda, aceste valori vor fi decrementate pana vor fi egale sau mai mici decat zero (uneori, se intampla sa decrementam cu doua milisecunde datorita partii zecimale acumulate si daca valoarea ramasa este 1 milisecunda, scazand-o cu 2, ajungem deja sub zero). Functia check_delay(slot) verifica daca valoarea de la slotul specificat a devenit mai mica sau egala cu zero, si asta inseamna ca intarzierea respectiva a expirat, si atunci intoarce valoarea TRUE – in felul asta stim ca intarzierea respectiva a expirat si actionam ca atare (in cazul nostru, stingem sau aprindem un LED), dupa care scriem din nou valoarea intarzierii in slotul din array folosind functia set_delay(slot, valoare_intarziere) (si ciclul se repeta).

La data scrierii articolului, functiile pentru senzorii de temperatura Dallas nu sunt finalizate,

Lasă un comentariu

Va rog, nu folositi limbaj de messenger. Multumesc!

Completează mai jos detaliile despre tine sau dă clic pe un icon pentru autentificare:

Logo WordPress.com

Comentezi folosind contul tău WordPress.com. Dezautentificare / Schimbă )

Poză Twitter

Comentezi folosind contul tău Twitter. Dezautentificare / Schimbă )

Fotografie Facebook

Comentezi folosind contul tău Facebook. Dezautentificare / Schimbă )

Fotografie Google+

Comentezi folosind contul tău Google+. Dezautentificare / Schimbă )

Conectare la %s

%d blogeri au apreciat asta: