This shows you the differences between two versions of the page.
| fr:avr:timers [2010/03/25 11:10] – créée sdeniaud | fr:avr:timers [2020/07/20 12:00] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Compteurs/ | ||
| + | Les compteurs qui dans un certains sens peuvent s' | ||
| + | |||
| + | ===== Mode par défaut du compteur ===== | ||
| + | |||
| + | Dans le mode par défaut, un compteur ne fait rien plus que compter des nombres séquentiels tout le temps. Sa valeur peut, bien sûr, être lue et changée à partir du programme à tout moment. La seule fonction supplémentaire dans le mode par défaut permet de déclencher une interruption sur le dépassement de capacité du compteur. Le mode par défaut est typiquement utilisé pour exécuter une section du programme à certains intervalles. | ||
| + | |||
| + | <box 100% round # | ||
| + | |||
| + | Tâche: Réaliser l' | ||
| + | |||
| + | <code c> | ||
| + | #include < | ||
| + | |||
| + | ISR(TIMER0_OVF_vect) | ||
| + | { | ||
| + | // Give the counter such a value | ||
| + | // that the next overflow occurs in 10 ms. | ||
| + | // Formula: 256 - 8 MHz / 1024 / 100 Hz = 177,785 = ~178 | ||
| + | TCNT0 = 178; | ||
| + | } | ||
| + | |||
| + | int main() | ||
| + | { | ||
| + | // To make the first overflow interrupt fire in 10 ms as well, | ||
| + | // the counter needs to be initialized here. | ||
| + | TCNT0 = 178; | ||
| + | |||
| + | // Prescaler value 1024 | ||
| + | TCCR0 = 0x07; | ||
| + | |||
| + | // Allow overflow interrupts | ||
| + | TIMSK |= (1 << TOIE0); | ||
| + | |||
| + | // Allow interrupts globally | ||
| + | sei(); | ||
| + | |||
| + | // Endless loop | ||
| + | while (1) continue; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Le compteur de cet exemple ne génère pas l' | ||
| + | |||
| + | </ | ||
| + | |||
| + | ==== Compteur d' | ||
| + | |||
| + | Il est aussi possible d' | ||
| + | |||
| + | ==== Evénements chronométrés ==== | ||
| + | |||
| + | Depuis que les compteurs permettent les opérations chronométrées, | ||
| + | |||
| + | <box 100% round # | ||
| + | |||
| + | Tâche: Mesurer la fréquence d'un signal logique carré externe de 122 Hz - 100 kHz en utilisant un ATmega128 de 8 MHz. La mesure doit avoir une précision de 1 Hz. Le programme utilise un compteur de 16 bits avec une unité de capture d' | ||
| + | |||
| + | <code c> | ||
| + | #include < | ||
| + | |||
| + | unsigned long frequency; | ||
| + | |||
| + | // Interrupt for the event | ||
| + | ISR(TIMER1_CAPT_vect) | ||
| + | { | ||
| + | // Counter to 0 | ||
| + | TCNT1 = 0; | ||
| + | |||
| + | // The result is valid only if the counter | ||
| + | // has not overflown yet | ||
| + | if (!(TIFR & (1 << TOV1))) | ||
| + | { | ||
| + | // Calculating the frequency from the period | ||
| + | frequency = (unsigned long)8000000 / | ||
| + | (unsigned long)ICR1; | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | // Frequency is less than 122 Hz | ||
| + | frequency = 0; | ||
| + | |||
| + | // Set the counter' | ||
| + | TIFR &= ~(1 << TOV1); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | int main() | ||
| + | { | ||
| + | // Register a rising front, prescaler value 1 | ||
| + | TCCR1B = (1 << ICES1) | (1 << CS10); | ||
| + | |||
| + | // Allow event interrupts | ||
| + | TIMSK = (1 << TICIE1); | ||
| + | |||
| + | // Allow interrupts globally | ||
| + | sei(); | ||
| + | |||
| + | // Endless loop | ||
| + | while (1) continue; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Le programme exécute une interruption à chaque front montant du signal externe. Pendant l' | ||
| + | |||
| + | </ | ||
| + | |||
| + | La détection d' | ||
| + | |||
| + | ===== Génération du signal ===== | ||
| + | |||
| + | Des compteurs plus complexes peuvent générer un signal, en plus du chronométrage. Pour ce faire le compteur a une unité de comparaison de sortie et une unité de sortie de correspondance de comparaison. L' | ||
| + | |||
| + | Avec certains signaux produisant des modes, la valeur maximale du compteur peut être changée. La taille physique du compteur restera le même, mais un registre de comparaison est utilisé pour remettre le compteur à une valeur spécifique. Les exemples précédents pourraient aussi être résolus en utilisant cette méthode, mais la fonction sert plutôt à changer la période du signal. En plus de cela, un compteur peut être configuré dans un mode où il fonctionne aussi bien en croissance qu'en décroissance. | ||
| + | |||
| + | Les compteurs et le mode générant un signal sont l'un des modules de l'AVR les plus complexes. Toute écriture à ce propos prendrait énormément de temps et il n'est pas nécessaire de tout savoir pour pouvoir les utiliser. Le paragraphe suivant concerne les signaux PWM les plus courant en robotique. Le reste est à retrouver dans la documentation technique de l'AVR. | ||
| + | |||
| + | ==== Modulation de la largeur de l' | ||
| + | |||
| + | La modulation de la largeur de l' | ||
| + | |||
| + | <box 100% round # | ||
| + | |||
| + | Tâche: en utilisant un ATmega128 de 8 MHz, générer deux signaux de régulation de la vitesse du servo moteur. Utiliser la broche PB5 (OC1A) pour générer une impulsion de largeur de 1 ms et la broche PB6 (OC1B) pour générer une impulsion de largeur de 2 ms. | ||
| + | |||
| + | <code c> | ||
| + | #include < | ||
| + | |||
| + | int main() | ||
| + | { | ||
| + | // Set pins as outputs | ||
| + | DDRB |= (1 << PIN5) | (1 << PIN6); | ||
| + | |||
| + | // Set outputs A and B low for comparison, | ||
| + | // "Fast PWM" mode, prescaler value 8 | ||
| + | TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); | ||
| + | TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); | ||
| + | |||
| + | // Maximum value of the counter. Formula: | ||
| + | // TOP = 8 MHz / 8 / 50 Hz | ||
| + | ICR1 = 20000; | ||
| + | |||
| + | // Half-period of the first motor is 1 ms, and second 2 ms | ||
| + | OCR1A = 1000; | ||
| + | OCR1B = 2000; | ||
| + | |||
| + | // Endless loop | ||
| + | while (1) continue; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | </ | ||