This shows you the differences between two versions of the page.
pm:lab:lab1-2021 [2021/03/15 09:42] alexandru.predescu [4. Resurse] |
pm:lab:lab1-2021 [2021/03/18 14:39] (current) alexandru.predescu [4. Resurse] |
||
---|---|---|---|
Line 41: | Line 41: | ||
| 26 | 0032 | SPM_READY | Store Program Memory Ready | | | 26 | 0032 | SPM_READY | Store Program Memory Ready | | ||
- | După cum se observă din tabelul de mai sus, pe lângă întreruperile componentelor interne uC-ului (timer-e, interfețe seriale, convertor analog-digital), există și câteva linii pentru întreruperi de la periferice externe: INT0-INT1 și PCINT0-PCINT2. Diferența dintre aceste două tipuri de întreruperi externe este dată de capabilitățile suportate și de granularitatea lor. Semnalele pentru întreruperile INTn pot genera o întrerupere la tranziție (crescătoare, descrescătoare sau ambele) sau pe nivel 0, în funcție de configurarea întreruperii. Întreruperile PCINTn se declanșează la ambele tranziții (de unde și numele Pin Change INTerrupt) și câte 8 pini sunt multiplexați pe o singură întrerupere. Semnalele de întrerupere PCINT se pot activa individual, însă pentru a afla exact ce semnal a declanșat o anumită întrerupere trebuie verificat registrul PINn corespunzător. Dacă mai multe semnale se declanșează în același timp, ele nu vor putea fi deosebite. | + | /*După cum se observă din tabelul de mai sus, pe lângă întreruperile componentelor interne uC-ului (timer-e, interfețe seriale, convertor analog-digital), există și câteva linii pentru întreruperi de la periferice externe: INT0-INT1 și PCINT0-PCINT2. Diferența dintre aceste două tipuri de întreruperi externe este dată de capabilitățile suportate și de granularitatea lor. Semnalele pentru întreruperile INTn pot genera o întrerupere la tranziție (crescătoare, descrescătoare sau ambele) sau pe nivel 0, în funcție de configurarea întreruperii. Întreruperile PCINTn se declanșează la ambele tranziții (de unde și numele Pin Change INTerrupt) și câte 8 pini sunt multiplexați pe o singură întrerupere. Semnalele de întrerupere PCINT se pot activa individual, însă pentru a afla exact ce semnal a declanșat o anumită întrerupere trebuie verificat registrul PINn corespunzător. Dacă mai multe semnale se declanșează în același timp, ele nu vor putea fi deosebite. |
- | <note important>În cazul întreruperilor de tip pin change interrupt, a nu se confunda vectorul de tratare a întreruperilor e.g. PCINT0 cu întreruperea efectivă e.g. PCINT8 (PC0). Maparea dintre vector și întreruperi se poate găsi în secțiunea 30 pag. 278 din {{:pm:atmel-7810-automotive-microcontrollers-atmega328p_datasheet.pdf|datasheet}}</note> | + | <note important>În cazul întreruperilor de tip pin change interrupt, a nu se confunda vectorul de tratare a întreruperilor ex. PCINT0 cu întreruperea efectivă ex. PCINT8 (PC0). Maparea dintre vector și întreruperi se poate găsi în secțiunea 30 pag. 278 din {{:pm:atmel-7810-automotive-microcontrollers-atmega328p_datasheet.pdf|datasheet}}</note> */ |
<note tip>La apariția unei întreruperi, în afară de salvarea stării, procesorul dezactivează întreruperile, iar la revenirea din rutina de tratare le reactivează. Activarea lor poate fi realizată forțat și din handler-ul de întrerupere (de exemplu, suntem în handler-ul pt recepția unui frame pe interfața seriala, și dorim să activăm întreruperile unui timer).</note> | <note tip>La apariția unei întreruperi, în afară de salvarea stării, procesorul dezactivează întreruperile, iar la revenirea din rutina de tratare le reactivează. Activarea lor poate fi realizată forțat și din handler-ul de întrerupere (de exemplu, suntem în handler-ul pt recepția unui frame pe interfața seriala, și dorim să activăm întreruperile unui timer).</note> | ||
Line 67: | Line 67: | ||
<file c> | <file c> | ||
// exemplu de configurare pentru Timer 1 în mod CTC, care va genera întreruperi cu frecvența de 2Hz | // exemplu de configurare pentru Timer 1 în mod CTC, care va genera întreruperi cu frecvența de 2Hz | ||
- | OCR1A = 31250; // compare match register 16MHz/256/2Hz | + | OCR1A = 31249; // compare match register 16MHz/256/2Hz-1 |
TCCR1B |= (1 << WGM12); // CTC mode | TCCR1B |= (1 << WGM12); // CTC mode | ||
TCCR1B |= (1 << CS12); // 256 prescaler | TCCR1B |= (1 << CS12); // 256 prescaler | ||
- | TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt | ||
</file> | </file> | ||
| | ||
Line 104: | Line 103: | ||
* Datorită faptului că handler-ul întârzie orice altă activitate din main și inhibă execuția altor întreruperi, se dorește ca timpul de execuție să fie cât mai mic. | * Datorită faptului că handler-ul întârzie orice altă activitate din main și inhibă execuția altor întreruperi, se dorește ca timpul de execuție să fie cât mai mic. | ||
* La folosirea unor variabile comune în mai multe handler-e de întrerupere și/sau main trebuie avut în vedere accesul concurent la acestea (în special la variabilele de 16/32 biți a căror modificare necesită mai mulți cicli de procesor). | * La folosirea unor variabile comune în mai multe handler-e de întrerupere și/sau main trebuie avut în vedere accesul concurent la acestea (în special la variabilele de 16/32 biți a căror modificare necesită mai mulți cicli de procesor). | ||
- | * Variabilele comune trebuiesc marcate ca ''volatile'' pentru ca accesele la acestea să nu fie optimizate de către compilator | + | * Variabilele comune trebuie marcate ca ''volatile'' pentru ca accesele la acestea să nu fie optimizate de către compilator |
Line 157: | Line 156: | ||
^ Timer ^ Registre ^ Rol ^ | ^ Timer ^ Registre ^ Rol ^ | ||
- | | **Timer0** \\ \\ **8 biți** | ''TCNT0'' | Registrul contor al timer-ului 0 (//cel care numără//) | | + | | **Timer0** \\ \\ **8 biți** | ''TCNT0'' | Registrul contor al timer-ului 0 (cel care numără) | |
- | | ::: | ''TCCR0A'',''TCCR0B'' | Registre de control ale timer-ului 0 (//aici veți activa diverși biți pentru configurarea timer-ului//)| | + | | ::: | ''TCCR0A'', ''TCCR0B'' | Registre de control ale timer-ului 0 (diverși biți pentru configurarea timer-ului)| |
- | | ::: | ''OCR0A'',''OCR0B'' | Registre prag pentru timer-ul 0 (//prag al numărătorii la care se poate declansa intreruperea, în funcție de configurare//) | | + | | ::: | ''OCR0A'', ''OCR0B'' | Registre prag pentru timer-ul 0 (prag al numărătorii la care se poate declansa intreruperea, în funcție de configurare) | |
- | | ::: | ''TIMSK0'',''TIFR0'' | Registre cu biți de activare întreruperi timer 0 / flag-uri de activare (//aici activați întreruperile//) | | + | | ::: | ''TIMSK0'', ''TIFR0'' | Registre cu biți de activare întreruperi timer 0 / flag-uri de activare (activați întreruperile) | |
- | | **Timer1** \\ \\ **16 biți** | ''TCNT1H/L'' = \\ ''TCNT1H'' + ''TCNT1L'' | Registrul contor al timer-ului 1 (//la fel ca la timer0, doar că pe 16 biți//) | | + | | **Timer1** \\ \\ **16 biți** | ''TCNT1'' | Registrul contor al timer-ului 1 (la fel ca la timer0, doar că pe 16 biți) | |
- | | ::: | ''TCCR1A'' , ''TCCR1B'', ''TCCR1C'' | Registre control ale timer-ului 1 (//la fel ca la timer0//) | | + | | ::: | ''TCCR1A'' \\ ''TCCR1B'' \\ ''TCCR1C'' | Registre control ale timer-ului 1 (la fel ca la timer0) | |
- | | ::: | ''OCR1AH/L'' , ''OCR1BH/L'' | Registre prag pe 16 biți ale timer-ului 1 (//la fel ca la timer0//) | | + | | ::: | ''OCR1A'' , ''OCR1B'' | Registre prag pe 16 biți ale timer-ului 1 (la fel ca la timer0) | |
- | | ::: | ''TIMSK1'', ''TIFR1''| (//la fel ca la timer0//) | | + | | ::: | ''TIMSK1'', ''TIFR1''| (la fel ca la timer0) | |
- | | ::: | ''ICR1H/L'' | Registru folosit pentru a reține valoarea contorului la apariția unui eveniment extern pe pin-ul ''ICP'' sau ca prag pentru unul din modurile CTC| | + | | ::: | ''ICR1'' | Registru folosit pentru a reține valoarea contorului la apariția unui eveniment extern pe pin-ul ''ICP'' sau ca prag pentru unul din modurile CTC| |
| **Timer2** \\ \\ **8 biți** | aceleași registre ca la Timer0 | Diferența față de Timer-ul 0 este posibilitatea folosirii unui oscilator extern separat pentru Timer-ul 2, \\ pe pinii ''TOSC1'' și ''TOSC2'' | | | **Timer2** \\ \\ **8 biți** | aceleași registre ca la Timer0 | Diferența față de Timer-ul 0 este posibilitatea folosirii unui oscilator extern separat pentru Timer-ul 2, \\ pe pinii ''TOSC1'' și ''TOSC2'' | | ||
| ::: | ''ASSR'', ''GTCCR'' | Registre ce țin de funcționarea asicronă a acestui timer față de restul sistemului | | | ::: | ''ASSR'', ''GTCCR'' | Registre ce țin de funcționarea asicronă a acestui timer față de restul sistemului | | ||
Line 218: | Line 217: | ||
void configure_timer1() { | void configure_timer1() { | ||
- | // exemplu de configurare pentru Timer 1 în mod CTC, care va genera întreruperi cu frecvența de 2Hz | + | // exemplu de configurare pentru Timer 1 în mod CTC |
- | OCR1A = 31250; // compare match register 16MHz/256/2Hz | + | // care va genera întreruperi cu frecvența de 2Hz |
+ | OCR1A = 31249; // compare match register 16MHz/256/2Hz-1 | ||
TCCR1B |= (1 << WGM12); // CTC mode | TCCR1B |= (1 << WGM12); // CTC mode | ||
TCCR1B |= (1 << CS12); // 256 prescaler | TCCR1B |= (1 << CS12); // 256 prescaler | ||
- | TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt | ||
} | } | ||
void init_timer1() { | void init_timer1() { | ||
- | TIMSK1 |= (1 << OCIE1A); | + | TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt |
} | } | ||
Line 247: | Line 246: | ||
În general, pentru configurarea unui Timer, este necesară alegerea unui prescaler și a unei limite de numărare, în funcție de perioada dorită și de frecvența de lucru a procesorului (e.g. 16 MHz pentru Arduino UNO) și de modul de funcționare ales. Un exemplu de calcul este prezentat mai jos: | În general, pentru configurarea unui Timer, este necesară alegerea unui prescaler și a unei limite de numărare, în funcție de perioada dorită și de frecvența de lucru a procesorului (e.g. 16 MHz pentru Arduino UNO) și de modul de funcționare ales. Un exemplu de calcul este prezentat mai jos: | ||
- | <file> | + | - calcul frecvență întreruperi în funcție de frecvența ceasului și a pragului de numărare: \\ |
- | // calcul frecvență întreruperi în funcție de frecvența ceasului | + | |
- | f_int = f_clk / (prescaler * (tc + 1)) | + | ''f_int = f_clk / (prescaler * (tc + 1))'' \\ |
- | // calcul prag de numărare al timer-ului pentru a obține frecvența dorită | + | |
- | tc = f_clk / (prescaler * f_int) - 1 | + | - calcul prag de numărare al timer-ului pentru a obține frecvența dorită: \\ |
- | </file> | + | |
+ | ''tc = f_clk / (prescaler * f_int) - 1'' | ||
+ | |||
+ | Observăm că trebuie aleasă o valoare convenabilă pentru prescaler (din cele disponibile, ex. 8, 64, 256, 1024) și un prag de numărare (0-255 pentru timer-e pe 8 biți, 0-65535 pentru timer-e pe 16 biți) astfel încât să se obțină frecvența exactă. | ||
Există însă calculatoare care pot fi utile pentru determinarea rapidă a valorilor pentru registrele de configurare ale unui Timer precum: | Există însă calculatoare care pot fi utile pentru determinarea rapidă a valorilor pentru registrele de configurare ale unui Timer precum: | ||
Line 265: | Line 268: | ||
==== 3.1. Exerciții Tinkercad ==== | ==== 3.1. Exerciții Tinkercad ==== | ||
- | **Task 0** Configurați Timer 1 folosind registre și întreruperea TIMER1_COMPA pentru a aprinde un LED o dată pe secundă: | + | **Task 0** Configurați Timer 1 folosind registre și întreruperea ''TIMER1_COMPA'' pentru a aprinde un LED o dată pe secundă: |
<file> | <file> | ||
Line 283: | Line 286: | ||
TCNT1 = 0; | TCNT1 = 0; | ||
| | ||
- | OCR1A = 31250; // compare match register 16MHz/256/2Hz | + | OCR1A = 31249; // compare match register 16MHz/256/2Hz-1 |
TCCR1B |= (1 << WGM12); // CTC mode | TCCR1B |= (1 << WGM12); // CTC mode | ||
TCCR1B |= (1 << CS12); // 256 prescaler | TCCR1B |= (1 << CS12); // 256 prescaler | ||
Line 295: | Line 298: | ||
</file> | </file> | ||
+ | |||
+ | <hidden> | ||
+ | **Soluția** se găsește pe [[https://www.tinkercad.com/things/8ak1bNqH8kY-pm-lab1-timer-blink-led-with-interrupt/editel?sharecode=FHxu1dKVgJKS8jqUdFraMA_e-XKvoqEGVlG-9UfQmuw|Tinkercad Tinkercad blink led with interrupt]] | ||
+ | </hidden> | ||
**Task 1** Configurați Timer 1 folosind registre și întreruperea ''TIMER1_COMPA'' pentru a comanda un buzzer la o frecvență audibilă (e.g. un ton/notă muzicală între 440 și 880 Hz). Consultați acest [[https://www.intmath.com/trigonometric-graphs/music.php|link]] pentru frecvența notelor muzicale. | **Task 1** Configurați Timer 1 folosind registre și întreruperea ''TIMER1_COMPA'' pentru a comanda un buzzer la o frecvență audibilă (e.g. un ton/notă muzicală între 440 și 880 Hz). Consultați acest [[https://www.intmath.com/trigonometric-graphs/music.php|link]] pentru frecvența notelor muzicale. | ||
+ | <hidden> | ||
+ | **Soluția** se găsește pe [[https://www.tinkercad.com/things/h7t1IaSSFY2-pm-lab1-classic-tone-generator-with-interrupts/editel?sharecode=zRz6oXdPYDDqn7lZJ8836eovx3LYHD8B1TSjABJicz8|Tinkercad tone generator with interrupts]] | ||
+ | </hidden> | ||
**Task 2** Rulați programul de mai jos care configurează Timer 0 pentru a aprinde LED-ul periodic fără a folosi întreruperi: | **Task 2** Rulați programul de mai jos care configurează Timer 0 pentru a aprinde LED-ul periodic fără a folosi întreruperi: | ||
Line 326: | Line 336: | ||
</file> | </file> | ||
+ | <hidden> | ||
+ | **Soluția** se găsește pe | ||
+ | [[https://www.tinkercad.com/things/9zfCKNmXUCB-pm-lab1-timer-blink-led-no-interrupt/editel?sharecode=ByNv2zVUZcBmfh4ZMb4cDt3GjZeddiVvLR4IZsaOK0E|Tinkercad blink led without interrupt]] respectiv [[https://www.tinkercad.com/things/7FnyoP7uCT9-pm-lab1-arduino-tone-exemple/editel?sharecode=YajfkI_9Ui2nnsDfV4SdsKJyPDudPymnvPHjro8O-DM|Tinkercad tone generator without interrupts]] | ||
+ | </hidden> | ||
==== 3.2. Exerciții Arduino ==== | ==== 3.2. Exerciții Arduino ==== | ||
Line 331: | Line 345: | ||
{{:pm:lab:lab1:manage_libraries.jpeg?300|}} | {{:pm:lab:lab1:manage_libraries.jpeg?300|}} | ||
- | **Task 3** Configurați un Timer folosind biblioteca Arduino [[http://example.com|TimerOne]] astfel încât să aprindeți un LED o dată pe secundă | + | **Task 3** Configurați un Timer folosind biblioteca Arduino [[https://www.arduino.cc/reference/en/libraries/timerone/|TimerOne]] astfel încât să aprindeți un LED o dată pe secundă |
<note important>Biblioteca ''TimerOne'' nu vine preinstalată cu Arduino. Urmăriți modul de instalare a bibliotecilor externe.</note> | <note important>Biblioteca ''TimerOne'' nu vine preinstalată cu Arduino. Urmăriți modul de instalare a bibliotecilor externe.</note> | ||
Line 368: | Line 382: | ||
* {{:pm:atmel-7810-automotive-microcontrollers-atmega328p_datasheet.pdf|Datasheet Atmega 328p}} | * {{:pm:atmel-7810-automotive-microcontrollers-atmega328p_datasheet.pdf|Datasheet Atmega 328p}} | ||
+ | * Arduino UNO pinout | ||
+ | * {{:pm:lab:uno.jpg?200|pinout Arduino UNO}} | ||
* Responsabili: [[Adrian.Mocanu@gmail.com | Adrian Mocanu]] | * Responsabili: [[Adrian.Mocanu@gmail.com | Adrian Mocanu]] | ||
===== 5. Linkuri utile ===== | ===== 5. Linkuri utile ===== |