This shows you the differences between two versions of the page.
|
pm:lab:lab2-2023 [2024/03/17 09:55] florin.stancu |
pm:lab:lab2-2023 [2026/03/09 10:53] (current) jan.vaduva [2.4. Lucrul cu Timer-ul] |
||
|---|---|---|---|
| Line 362: | Line 362: | ||
| <file c > | <file c > | ||
| + | #include <avr/interrupt.h> | ||
| ISR(TIMER1_COMPA_vect) | ISR(TIMER1_COMPA_vect) | ||
| Line 370: | Line 371: | ||
| { | { | ||
| TIMSK1 |= (1 << OCIE1A); | TIMSK1 |= (1 << OCIE1A); | ||
| + | // ... | ||
| } | } | ||
| int main() | int main() | ||
| { | { | ||
| - | sei(); // activăm primirea întreruperilor | ||
| init_timer1(); // apelăm funcția de inițializare | init_timer1(); // apelăm funcția de inițializare | ||
| + | sei(); // activăm primirea întreruperilor | ||
| // ... | // ... | ||
| } | } | ||
| Line 418: | Line 420: | ||
| ===== 3. Exerciții ===== | ===== 3. Exerciții ===== | ||
| - | **Task 1.** | + | **Task 1. (2p)** |
| + | Implementați o funcție ''uptime_ms()'' care returnează numărul de milisecunde scurse de la pornirea microcontrolerului. | ||
| - | * Implementați o funcție asemănătoare cu ''millis()'' din biblioteca Arduino. Aceasta ar trebui să returneze intervalul de timp trecut de la pornirea (sau ultimul reset) al uC-ului. Configurați interfața USART0 cu aceeași parametri folosiți în laboratorul trecut și transmiteți către PC un mesaj ales de voi la intervale de 1 secundă. | ||
| - | HINTS: | + | * folosiți un timer și întreruperi pentru a genera un tick periodic de aproximativ 1 ms |
| + | |||
| + | * la fiecare întrerupere incrementați un contor global | ||
| + | |||
| + | * funcția ''uptime_ms()'' trebuie să returneze valoarea acestui contor | ||
| + | |||
| + | <note tip> | ||
| * Frecvența de ceas a uC-ului este de 12MHz. Folosiți formulele prezentate anterior pentru a obține valorile potrivite pentru prescaler și registrul de comparație ale timer-ului ales astfel încât întreruperile generate de acesta să se declanșeze la intervalul de timp dorit. | * Frecvența de ceas a uC-ului este de 12MHz. Folosiți formulele prezentate anterior pentru a obține valorile potrivite pentru prescaler și registrul de comparație ale timer-ului ales astfel încât întreruperile generate de acesta să se declanșeze la intervalul de timp dorit. | ||
| * Timer2 poate fi utilizat cu un număr mai mare de valori ale prescaler-ului. | * Timer2 poate fi utilizat cu un număr mai mare de valori ale prescaler-ului. | ||
| + | </note> | ||
| + | |||
| + | Configurați ''USART0'' cu aceiași parametri ca în laboratorul anterior și transmiteți către PC mesajul: | ||
| + | <code> | ||
| + | Uptime: <valoare> ms | ||
| + | </code> | ||
| + | |||
| + | Mesajul trebuie trimis la fiecare **1 secundă**. | ||
| + | |||
| + | |||
| + | |||
| + | <note> Funcția ''USART0_transmit(char data)'' este blocantă (blochează executia restul instrucțiunilor din main). Determinați limita minimă a intervalului de timp dintre mesaje pentru care acestea pot fi transmise corect, în funcție de BAUD rate și de numărul de caractere din mesaj. </note> | ||
| + | |||
| + | |||
| + | **Task 2.1 BTN Interrupt (2p)** | ||
| + | |||
| + | Configurați **pin change interrupt** pentru butonul BTN1 (PB2). | ||
| + | |||
| + | Implementați rutina de tratare a întreruperii ''ISR(PCINT<n>_vect)''. In ISR setați un flag atunci când butonul este apăsat. In ''main()'' detectați flag-ul și transmiteți pe USART mesajul: "**PRESS**". | ||
| + | |||
| + | **Task 2.2 Debouncing (1p)** | ||
| - | **Task 2.** | + | Când se apasă un buton, generați un eveniment "**PRESS**" o singură dată, chiar dacă contactul bounce-uiește. |
| + | Implementați debouncing cu o fereastră de 30–50 ms bazată pe ''uptime_ms()'' (din Task 1), dar fără să blocați execuția în main. | ||
| - | * Reluați exercițiul 3 din primul laborator și implementați-l folosind timer-e și întreruperi pentru citirea butoanelor și efectul de clipire al LED-urilor. | ||
| - | <spoiler **Reminder Ex. 3, lab 0**> | + | **Task 3. (3p)** |
| - | * La apăsarea succesivă a BTN1, LED-ul RGB trebuie să își schimbe culoarea (Red -> Green -> Blue -> Red) | + | |
| - | * BTN2 trebuie să controleze efectul de clipire al LED-ului aprins | + | |
| - | </spoiler> | + | |
| - | **Task 3.** | + | Folosiți buzzer-ul și butoanele: |
| - | * Folosiți butoanele ''PD6'' și ''PB2'' pentru a controla buzzer-ul: | + | |
| - | * Unul dintre butoane selectează frecvența sunetului generat de buzzer (dintre 3 valori, de ex. 100Hz, 200Hz, 300Hz) | + | |
| - | * Buzzer-ul funcționează doar când mențineți al doilea buton apăsat | + | |
| - | * Puteți folosi LED-ul RGB pentru a indica frecvența aleasă | + | |
| - | **Task 4. (BONUS)** | + | * BTN1 (''PB2'') schimbă frecvența sunetului generat de buzzer. Frecvența poate avea 3 valori diferite (200 Hz, 400 Hz, 800 Hz). |
| + | * BTN2 (''PD6'') este „gate”: buzzerul sună doar cât timp BTN2 este ținut apăsat. | ||
| - | * Funcția implementată la primul exercițiu va acumula o anumită eroare din cauza faptului că frecvența de ceas nu poate fi divizată perfect. | + | (generați semnalul pentru buzzer folosind un timer și întreruperi) |
| - | * Încercați să calculați după câte cicluri de funcționare a timer-ului eroarea devine semnificativă (peste 1 ms). | + | |
| - | * Propuneți o metodă prin care se poate reduce această eroare | + | |
| - | * Încercați implementarea metodei propuse | + | |
| + | **Task 4. Mini scheduler (2p)** | ||
| + | Folosiți funcția ''uptime_ms()'' pentru a implementa un mini-scheduler cooperativ care execută mai multe taskuri periodice. Implementați în bucla principală un mecanism care verifică periodic momentul curent (''now = uptime_ms()'') și execută următoarele taskuri: | ||
| + | * T1 – Heartbeat (periodă 1000 ms) - Comută starea LED-ului albastru. | ||
| + | * T2 – Logger (periodă 500 ms) - Transmite pe USART mesajul: **t=<uptime_ms> ms** | ||
| + | * T3 – Status (periodă 3000 ms) - Comută starea LED-ului roșu. | ||