This is an old revision of the document!


Laboratorul 07 - GPIO 2: Intrări

Obiective

În acest laborator vom îmbunătăți implementarea noastră a modulului de GPIO adăugând posibilitatea pinilor de a funcționa și ca intrări.

1. Registrele de control al perifericelor și al porturilor I/O

În laboratorul trecut am învățat că dacă un pin are funcția de GPIO, atunci vom putea să îi controlăm direcția și valoarea în mod programatic prin scrieri și citiri în/din anumite registre.

Registrele care controlează comportamentul unui port sunt:

  • DDRx: Port x Data Direction Register (ie: DDRA și DDRB)
  • PORTx: Port x Data Register (ie: PORTA si PORTB)
  • PINx: Port x Data Input Register (ie: PINA și PINB)

Aceste registre sunt toate pe 8 biți iar fiecare bit controlează comportamentul unui pin al portului respectiv. Ca și în laboratorul trecut, ne vom limita la portul A al microcontroller-ului.

= PORTA (recapitulare) =

În laboratorul trecut am învățat ce efect avea schimbarea unui bit din registrul PORTA:

  • PORTAn: dacă bitul n este 0 atunci pinul respectiv va lua valoarea LOW, iar dacă bitul este 1 atunci pinul va lua valoarea HIGH.
DDRA

Registrul DDRA controleaza direcția pinilor din portul A astfel:

  • DDRAn: dacă bitul n este 1 atunci pinul va funcționa ca și ieșire (microcontroller-ul va putea impune o tensiune electrică pe acel pin), iar dacă bitul este 0 atunci pinul respectiv va funcționa ca și intrare (microcontroller-ul nu va impune nicio tensiune pe linie)
PINA

Din registrul PINA putem citi valoarea tensiunii de pe pinii portului A astfel:

  • PINAn: dacă bitul n este 0 atunci pinul respectiv are valoarea LOW, iar dacă bitul este 1 atunci pinul are valoare HIGH

2. Instrucțiunile SBI și CBI

Până acum am învațat că dacă schimbăm un bit din DDRA sau PORTA putem să influențăm comportamentul unui pin. Însă instrucțiunile in și out nu pot scrie decât valori pe 8 biți. Spre exemplu, dacă dorim să schimbăm doar bitul 5 din DDRA în 1 atunci pașii pe care trebuie sa îi urmăm sunt:

    ldi     R17, 0b00100000 ; încărcăm în R17 o mască ce are 1 pe bitul 5
    in      R16, DDRA       ; încărcăm în R16 valoarea din DDRA
    or      R16, R17        ; în urma operației sau între R16 și R17 în R16 bitul 5 va fi pus pe 1
    out     DDRA, R16       ; stocăm valoarea din R16 înapoi în DDRA

Pentru a pune bitul 5 din DDRA pe 1 a trebuit să folosim o mască de biți ce are 1 pe poziția 5.

Fiindcă acțiunea de a schimba un bit în 1 (set) sau în 0 (clear) este una întâlnită des în programele ce rulează pe arhitectura AVR aceasta include două instrucțiuni ce permit schimbarea unui bit dintr-un registru ce se află în primele 32 de adrese din I/O Space în 0 sau în 1: cbi (Clear Bit in Register) și sbi (Set Bit in Register). Ele primesc ca și argumente adresa registrului (în intervalul [0:31]) și numărul bitului (în intervalul [0:7]). Dacă rescriem codul folosind aceste înstrucțiuni el devine:

sbi DDRA, 5

Instrucțiunile cbi și sbi primesc ca și argument numărul bitului pe care dorim să-l schimbăm, nu o mască de biți.

3. TL;DR

Pentru a modifica valoarea unui registru I/O putem sa folosim:

  • instructiunea OUT cu masca de biti:
 LDI R16, 7 
 OUT 0x01, R16 ; DDRA = 00001111
  • instructiunile SBI si CBI pentru a modifica un singur bit
 LDI R16 0 
 OUT 0x01, R16 ; DDRA = 00000000
 SBI 0x01, 5   ; DDRA = 00100000
 SBI 0x01, 4   ; DDRA = 00110000
 CBI 0x01, 5   ; DDRA = 00010000

4. Exerciții

  1. Task 01 (4p) Extindeți modulul gpio astfel încât să suporte și intrări și ieșiri. Urmăriți comentariile marcate cu TODO 1 din gpio.v și cpu.v.
  2. Task 02 (2p) Decodificați instrucțiunile sbi și cbi și completați logica necesară execuției lor. Urmăriți comentariile marcate cu TODO 2 din signal_generation_unit.v, decode_unit.v și control_unit.v.
  3. Task 03 (1p) 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.
  4. Task 04 (1p) Urcați programul de la punctul precedent pe placa de dezvoltare. Portul A va fi mapat pe cele 8 led-uri astfel: PA0 - LED0, …, PA7 - LED7. Portul B va fi mapat pe cele 8 switch-uri astfel: PB0 - SW0, …, PB7 - SW7.
  5. Task 05 (2p) Scrieți un program care să aprindă led-urile în următoarea secvență folosind instructiunle SBI si CBI. Încărcați-l pe placa de dezvoltare:
  t0   *------*
  t1   -*----*-
  t2   --*--*--
  t3   ---**---
  t4   ---**---
  t5   --*--*--
  t6   -*----*-
  t7   *------*
  1. Task 06 (Bonus 2p) Modificați programul de la punctul 3 astfel încât acesta să citească valoarea de pe portul B și să folosească instrucțiunile sbi și cbi pentru a scrie valoarea pinului PB0 pe pinul PA0. Încărcați-l pe placa de dezvoltare.

5. Resurse

cn2/laboratoare/07.1573909716.txt.gz · Last modified: 2019/11/16 15:08 by mihaela.lungoci
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