Laboratorul 09 - Configurări

Cheatsheet

GPIO

Folosind GPIO (General-Purpose Input/Output) putem controla un pin al unui circuit integrat. De exemplu, putem aprinde un led folosind instrucțiuni AVR sau putem citi starea unui pin - LOW sau HIGH. Pinii ce suportă GPIO sunt grupați în porturi (grupuri de 8 pini logici numite A sau B) controlate de registre speciale (pe câte 8 biți):

  1. DDRx: Data Direction Register
    • un bit setat pe 0 indică faptul ca va fi folosit pentru 'citire'
    • un bit setat pe 1 indică 'scriere'
  2. PORTx: Data Register: (Stabilesc cum vreau să fie un pin)
    1. Dacă DDRx e setat ca ieșire ('scriere')
      • dacă un bit n este 0 atunci pinul respectiv va fi legat la LOW (GND)
      • dacă un bit n este 1 atunci pinul respectiv va fi legat la HIGH (VCC)
    2. Dacă DDRx e setat ca intrare ('citire')
  3. PINx: Data Input Register (Indică starea reală a unui pin)
    • daca un bit este 0 atunci pinul respectiv are valoarea LOW
    • daca un bit este 1 atunci pinul are valoare HIGH
  • Unde x poate fi A sau B

În memoria microcontrollerului de la 0x00 la 0x3F gasim I/O Space. Aici se află toate registrele de lucru cu periferice și, desigur, DDRx, PORTx și PINx. De exemplu registrul PORTA are adresa 0x02.

Pentru a scrie citi date din I/O Space putem folosi instrucțiunile LDS/STS, însă recomandat este să folosim instrucțiunile speciale pentru lucru de memoria I/O Space ce se execută mai rapid:

  • OUT A, Rr: Scrie (Store) în I/O Space la adresa A valoarea din registrul Rr
  • IN Rd, A : Citește (Load) din I/O Space de la adresa A și pune în registrul Rd

Pentru a modifica un singur bit dintr-un registru de configurare putem folosi instrucțiunile SBI/CBI.

TIMER

  • Un timer este un simplu numărător implementat în hardware
  • Orice timer trebuie să aibă:
    • O sursă de ceas
    • Un registru contor
      • Trei valori de referință: BOTTOM, MAX și TOP
  • PWM este o tehnică de generare a unui semnal analogic pornind de la unul digital
    • Semnalul analogic obtinut depinde de factorul de umplere al semnalului digital
  • Timerele de pe ATtiny20 conțin 3 registre importante: TCNT0, OCR0A/OCR0B, TCCR0A, TCCR0B
    • TCNT0 este registrul cu contor
    • OCR0A/OCR0B definesc valori de comparație iar OCR0A poate fi folosit la TOP
    • TCCR0A și TCCR0B sunt registre de control pentru modul de funcționare
  • Moduri de funcționare:
    • Normal
      • Timer-ul numără crescător de la 0 la 255, apoi se resetează la 0
    • CTC
      • Timer-ul numără crescător de la 0 la OCR0A, apoi se resetează la 0
    • Fast PWM
      • Timer-ul numără crescător de la 0 la 255 (sau OCR0A), apoi se resetează la 0
      • Starea pinilor OC0A/OC0B poate fi schimbată la comparaței și BOTTOM

INTRERUPERI

  • Întreruperile sunt eveniment asincrone execuției programului
  • Dacă apare o întrerupere, procesorul oprește execuția normală a programului după instrucțiunea curentă și execută o rutină de tratare
    • Tabela vectorilor de întreruperi conține câte o intrare pentru fiecare întrerupere care duce la rutina ei de tratare
    • În cadrul rutinei de tratare trebuie să dăm acknowledge la întrerupere
  • Întreruperile pot fi activate/dezactivate la nivel global și demascate/mascate la nivel individual
    • Excepție fac NMI
  • Pe AVR
    • Activarea/Dezactivarea la nivel global se face cu instrucțiunile SEI/CLI
    • Demascarea/Mascarea se face prin registrele de control
      • E.g. TIMSK
    • Tabela vectorilor de întreruperi se află la adresa 0
      • La intrarea într-o rutină de tratare întreruperile sunt dezactivate la nivel global
      • La ieșirea dintr-o rutină de tratare întreruperile sunt activate la nivel global
    • O întrerupere este tratată dacă
      • Întreruperile sunt activate la nivel global (bitul I din SREG este 1)
      • Întreruperea este demascată la nivel individual (masca ei este 1)
      • Întreruperea este activă (flag-ul ei este activ)

Exerciții

java -jar avrasm.jar input.txt output.txt

Task 01 (2p) Scrieți un program care setează portul A ca ieșire, portul B ca intrare, apoi, într-o buclă, citește valoarea de pe portul B și o scrie pe portul A. Folosiți tool-ul avrasm pentru a-l scrie în fișierul rom.v.

Task 02 (2p) Scrieți un program care scrie pe portul A următoarea secvență, folosind instrucțiunle SBI si CBI. Vom verifica secvența folosind simularea.

  t0   *------*
  t1   -*----*-
  t2   --*--*--
  t3   ---**---
  t4   ---**---
  t5   --*--*--
  t6   -*----*-
  t7   *------*
  
     - `-` înseamnă led stins
     - `*` înseamnă led aprins
     - (dacă am lega la pinii PAx leduri :-) )

Task 03 (3p) Scrieți și simulați un program în avrasm care:

  • Configurează timer-ul 0 in modul fast PWM, TOP == 0xFF
    • HINT: Ce biți controlează modul de operare al timer-ului? Ce valoare trebuie să aibă acei biți? În ce registre se află acei biți?
  • Setează ceasul timer-ului 0 la clkI/O (No prescaling)
    • HINT: Ce biți controlează sursa de ceas a timer-ului? Ce valoare trebuie să aibă acei biți? În ce registru se află acei biți?
  • Configurează timer-ul 0 să schimbe starea pinului OC0A astfel: Clear OC0A on Compare Match, set OC0A at BOTTOM (non-inverting mode)
    • HINT: Ce biți controlează pinul OC0A? Ce valoare trebuie să aibă acei biți? În ce registru se află acei biți?
  • Setează valoarea lui OCR0A la 63
  • Simulați pentru a vedea semnalul PWM

Task 04 (3p) Plecând de la următorul schelet de cod, creați un program care schimbă starea pinului PA0 folosindu-se de o întrerupere, cât timp bucla principală este într-o buclă infinită. Simulați programul.

task04_skel.asm
    DDRA        equ 0x01
    PORTA       equ 0x02
    TCCR0A      equ 0x19
    TCCR0B      equ 0x18
    TIMSK       equ 0x26
    OCR0A       equ 0x16
 
    rjmp        main            ; Adresa 0x0000
    reti                        ; Adresa 0x0001
    reti                        ; Adresa 0x0002
    reti                        ; Adresa 0x0003
    reti                        ; Adresa 0x0004
    reti                        ; Adresa 0x0005
    reti                        ; Adresa 0x0006
    reti                        ; Adresa 0x0007
    reti                        ; Adresa 0x0008
    rjmp        TIM0_COMPA_ISR  ; Adresa 0x0009
    reti                        ; Adresa 0x000A
    reti                        ; Adresa 0x000B
    reti                        ; Adresa 0x000C
    reti                        ; Adresa 0x000D
    reti                        ; Adresa 0x000E
    reti                        ; Adresa 0x000F
    reti                        ; Adresa 0x0010
 
TIM0_COMPA_ISR:
    ; TODO 4: Schimbați (toggle) starea pinului PA0.
 
main:
    ; TODO 4: Configurați pinul PA0 ca și ieșire.
 
    ; TODO 4: Porniți un timer care să genereze o întrerupere de comparație pe canalul A. Puneți
    ; valoarea 42 ca valoare de comparație pentru canalul A.
 
    ; TODO 4: Activați întreruperile global.
 
    ; Deși programul pare să stea într-o buclă infinită, ar trebui să vedem că totuși starea
    ; pinului PA0 se schimbă.
    loop:
        rjmp loop

Resurse

cn2/laboratoare/009.txt · Last modified: 2023/01/13 16:51 by cristina.buciu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0