Sunteți pe pagina 1din 805

Microcontrolere (si

microprocesoare)

Programarea in C pentru sisteme


incorporate (SI): microcontrolere,
microprocesoare

Medii de programare IDE (Integrated


Development Environment), GCC Toolchains
(Re)introducere in limbajul C, standard,
MISRA C
1
Structura tipică a unui mediu integrat de dezvoltare
(IDE-Integrated Development Environment) pentru
aplicaţiile software de tip sistem incorporat-SI
IDE Editor si utilitar Make (procesor batch)

Compilator ANSI C
(Macro) Asamblor

Biblioteci
ANSI C (RT)OS
Bibliotecar

Linker (Editor de legături) / Locator programe

.hex sau .srec sau .elf


Programator
Debugger (depanator) EPROM/FLASH
sau Emulator JTAG/ICE

Simulator Monitor rezident / depanator /


CPU+resurse Bootloader
pe maşina ţinta 2
IDE (Integrated Development Environment)

• Procesul de dezvoltare este similar oricărei alte aplicaţii software şi


presupune etapele:
– crearea unui proiect, cu selectarea unei anumite variante de MPU/MCU/DSP
precum şi cu configurarea componentelor (uneltelor) soft ce vor fi utilizate
– crearea şi editarea fişierelor sursă în C sau/si limbaj de asamblare
– generarea codului pentru aplicaţie (se foloseşte termenul de construire Build =
asamblare/compilare urmată de link editare/locatare) prin intermediul unui
manager de proiecte; se bazează pe existenta (transparenta sau nu pentru
utilizator) a unui fişier de tip make
– corectarea erorilor
– testarea aplicaţiei cu ajutorul simulatorului si/sau al sistemului de dezvoltare si
/sau a simulatorului de sistem si/sau pe sistemul final (real)
– Mediul integrat de dezvoltare a aplicaţiilor (IDE) permite si
automatizarea asamblării/compilării urmată de link editare (editarea de
legături intre modulele obiect) şi locatarea codului în memoria program.
• El oferă utilizatorului si o interfaţa grafică interactivă (GUI-Graphical User
Interface), uşurând mult operarea
• Corectarea interactivă a erorilor, cu setarea diverselor opţiuni, sunt alte
facilităţi oferite de un IDE
Mai prezintă interes si eventuala existenta/disponibilitate a unui sistem de operare
de tip RTOS – sistem de operare in timp real care sunt larg utilizate in dezvoltarea
aplicaţiilor de tip SI …vom reveni
3
Toolchains
• In software un lanţ de unelte (toolchain) este un set de
unelte de programare care sunt utilizate pentru crearea
unui produs (tipic un alt program sau sistem de
programe)
• Aceste unelte sunt folosite tipic înlănţuit, adică ieşirea
unei unelte devine intrare pentru următoarea, dar
termenul este până la urmă generic, desemnând un set
de unelte de dezvoltare care au legătură intre ele
• Un astfel de lanţ simplu de unelte am mentionat si in
slide-ul anterior: un compilator si un editor de legături
(linker) care să transforme codul sursă intr-un program
executabil, un set de biblioteci care să asigure interfaţa
cu un eventual sistem de operare, un depanator de
programe, etc.
• http://en.wikipedia.org/wiki/Toolchain
Modelul simplificat de compilare C
Cod sursă C

Pre-procesor

Tipic acest ansamblu este numit


Compilator compilator

Cod sursă in limbajul de asamblare al maşinii ţintă

Asamblor
Biblioteci Cod obiect
(cod obiect)
Editor de
Legături (linker) Acesta se încarcă in memoria
(de program) a maşinii ţintă si se
Cod binar executabil
va executa acolo

5
SI-IDE- compilatorul
Compilatorul C si asamblorul (“compilatorul”)
• Fişierele sursă create la nivelul IDE sunt transmise asamblorului
şi/sau compilatorului pentru a fi translatate in limbaj maşină.
– Acestea prelucrează fişierele sursă şi creează, în principiu, fişiere
obiect relocatabile.
• Compilatorul C este de regulă o implementare completă in sens
ANSI (Kernighan & Ritchie) a limbajului de programare C.
– In plus, există o serie de caracteristici speciale asociate implementării
pentru unui MPU/MCU/DSP particular.
• (Macro) asamblorul suportă setul complet de instrucţiuni pentru
MPU/MCU/DSP şi toate derivatele acestuia.
• Este posibilă şi generarea directă de fişiere obiect absolute, la care
informaţia legată de plasarea codului în memoria program este
stabilită în faza de asamblare.
• De cele mai multe ori folosim de fapt un crosscompiler care
rulează pe o mașină gazdă (host, gen stație de lucru PC), la fel ca
intreg IDE-ul, si generează cod pentru o altă mașină (alt CPU),
mașina țintă (target)
6
SI-IDE - Linker
Editorul de legături/ (re)locatorul ( Linker/ReLocator)
• Fişierele obiect (inclusiv cele provenite din biblioteci) sunt prelucrate/combinate de
linker, rezultând fişiere binare absolute.
• Un fişier (sau modul) binar absolut conţine cod care nu este relocatabil.
• Acesta poate exista si se va executa de la anumite adrese fixe (absolute) în memoria
de program a maşinii ţintă; el este obținut cu ajutorul (re)locatorului
• Pentru simularea/depanarea simbolică se utilizează formate evoluate de
reprezentare
ELF - Extended Linker Format
COFF - Common Object File Format
care conţin si informaţia suplimentară necesară simulării si depanării interactive (cum ar fi
numele simbolurilor)
• De regulă nu se utilizează direct binarul ci există o prelucrare suplimentară (gen
BIN2HEX) intr-un format standardizat: fişier Intel HEX (I8HEX, I16HEX, I32HEX)
sau fişier S(REC) (.s19) Freescale (ex.Motorola),de tip S-record
– Fişierele respective sunt fişiere ASCII (text) care conţin o modalitate convenţională de
reprezentare a datelor si a locului (adresei) unde vor fi încărcate in memoria de program a
maşinii ţintă
– Această categorie de cod poate fi utilizată direct pentru a programa memorii de tip EPROM,
FLASH, etc.
– Aceste formate sunt insa nepractice daca dimensiunea imaginii executabile (binarului) din
care sunt generate este foarte mare (> xMOctetilor)
• Modulele obiect absolute pot fi folosite de depanator (debugger) si/sau de un
emulator in-circuit pentru depanarea/testarea aplicaţiei.
7
Linker-ul
• In contextul unui linker similar cu cel utilizat împreuna cu
compilatoarele GNU (gcc) el realizează următoarele:
• Combină fișierele obiect prin fuzionarea diverselor secțiuni ale fișierelor
obiect
– Secțiuni de tip .text pentru cod (program)
– Secțiuni de tip .data pentru variabile globale inițializate
– Secțiuni de tip .bss pentru variabile globale neinițializate
• Rezolvă toate simbolurile nerezolvate pana in acest moment:
– Variabile externe
– Apeluri de funcții (eventual via biblioteci)
• Raportează erorile legate de simbolurile nerezolvate
• Adaugă un cod de start – startup code , dacă e cazul
• Furnizează informația necesara pentru depanarea simbolică
• Linker-ul in sine produce un fișier binar relocatabil
• Pentru un sistem de operare standard care utilizează un program de
incărcare dinamic (dynamic loader), procesul este acum finalizat
• Pentru un sistem incorporat este nevoie însă de fișiere binare absolute
acesta fiind rolul (re)locatorului
(Re)locatorul
• Relocatorul convertește un binar relocatabil intr-unul
absolut
• El este o componentă a linker-ului care este “dirijată” cu
ajutorul unui script al acestuia, care specifică cel puţin:
– Secțiunile logice de memorie utilizate pentru program si pentru
date
– Memoria pentru program si pentru date a mașinii țintă (eventual
si natura ei, ROM, RAM, etc.)
– Dimensiunea si amplasamentul stivei/stivelor
• (Re)locatorul produce deci un cod binar “executabil”
(uneori numită si imagine executabilă) care poate fi
utilizat direct pe mașina țintă sau de un simulator al
acesteia
• Observație un limbaj de tip script este un limbaj de nivel înalt care este
interpretat de un alt program in momentul in care acesta se execută (at
runtime); el nu este compilat de către procesor, cum se întâmplă tipic cu
limbajul C/C++
Codul de start - startup code
• Codul de start este un mic fragment de cod scris in limbaj de
asamblare pentru mașina respectivă (CPU-ul respectiv) care are
rolul de a pregăti mașina pentru execuția unui program scris intr-un
limbaj de nivel înalt; de exemplu:
– pentru C in Unix/Linux este apelat crt1.o (fișier obiect) sau crt0.S (in
asamblare)
– pentru un microcontrolere poate fi tipic un fișier obiect specificat prin
intermediul unui script al linker-ului
• Sarcinile uzuale ale acestui cod:
– Dezactivarea tuturor întreruperilor
– Inițializarea unor periferice critice pentru aplicație (dacă e cazul)
– Inițializarea indicatorilor de stivă pentru toate stivele software
– Inițializarea secțiunilor de tip idata (secţiuni de date iniţializate, alocate
global)
– Inițializarea tuturor zonelor de date neinițializate din memoria de date
(conform standardului ANSI)
– Apelarea programului principal si a unei bucle fără sfârșit de genul :
main(); goto loop ;
SI-IDE- bibliotecarul
Bibliotecarul (Librarian, Library Manger)
• Fişierele obiect create de asamblor sau compilator pot fi
folosite de bibliotecar pentru a crea biblioteci obiect
(object libraries).
• Acestea sunt colecţii de module obiect, special ordonate
şi formatate, pe care editorul de legături le poate folosi.
• Atunci când editorul de legături prelucrează o bibliotecă,
doar acele module obiect care sunt necesare vor fi
folosite pentru crearea codului executabil
• Tot prin intermediul bibliotecilor se realizează si interfaţa
cu un eventual sistem de operare

11
Aşa arată un fişier Intel HEX (.hex)
:1000000012C02BC02AC029C028C027C026C025C0C6
:1000100024C023C022C021C020C01FC01EC01DC0DC
:100020001CC01BC01AC011241FBECFEDCDBF10E0F5
:10003000A0E6B0E0E0ECF0E003C0C89531960D9288
:10004000A036B107D1F710E0A0E6B0E001C01D92E4
:10005000A036B107E1F704D032C0D2CF0000089536
:1000600081B3806781BB87B38F6187BB82B38067B1
:1000700082BB88B38F6188BB949A80E090E0A0E057
:10008000B0E000000196A11DB11D803A26E892075C
:1000900021E0A20720E0B207A1F7949880E090E069
:1000A000A0E0B0E000000196A11DB11D80342DE05C
:1000B000920723E0A20720E0B207A1F7DDCFFFCF30
:00000001FF

12
Aşa arată un fişier SREC (.s sau .srec)
Fișierele .hex sau .s sunt fișiere text(reprezentare ASCII)!

S00F000068656C6C6F202020202000003C
S11F00007C0802A6900100049421FFF07C6C1B787C8C23783C6000003863000026
S11F001C4BFFFFE5398000007D83637880010014382100107C0803A64E800020E9
S111003848656C6C6F20776F726C642E0A0042
S5030003F9
S9030000FC

Fişierele hex/S conţin (in reprezentare ASCII hexazecimal):


- Date: ce si cat (ca număr de octeţi) se încarcă
- Adrese: unde se încarcă
- Sumede control(checksum): o modalitate de a verifica integritatea
datelor/adreselor conținute in totalitatea fișierului, cat si pe fiecare
linie
Pentru detalii vezi wikipedia:
http://en.wikipedia.org/wiki/Intel_HEX
http://en.wikipedia.org/wiki/SREC

13
SI-IDE
Depanator, simulator, monitor rezident, bootloader-ul
• Depanatorul (debugger) este de regula un depanator simbolic, permiţând
depanarea interactivă a programelor la nivelul sursei.
• El include de fapt şi un simulator care implementează o maşină
MPU/MCU/DSP virtuală.
– Prin intermediul unei baze de date pentru resurse incorporate el permite o
configurare corespunzătoare variantei de MPU/MCU/DSP utilizate precum şi a
hardware-ului exterior acestuia (memorie externa).
• Monitorul rezident este tot un program de depanare dar care va fi rezident
(există şi rulează) în memoria de program a unei maşini ţintă
(MPU/MCU/DSP).
– El utilizează anumite resurse ale maşinii ţinta (memorie, anumite periferice) care
astfel nu mai sunt disponibile pentru aplicaţie!
– El comunică cu mediul IDE prin intermediul unui port serial (COM) al PC-ului,
unui port serial emulat USB sau al unei conexiuni Ethernet a acestuia
– Este astfel posibilă depanarea interactivă, la nivel de sursă, (cu anumite limitări)
a programelor ce rulează pe un sistem ţintă real.
• Bootloader-ul este in mod tipic tot un mic program rezident in memoria de
program a maşinii ţinta, care va încărca “adevăratul” program al aplicaţiei
folosind un port de comunicaţie
• De multe ori există o combinaţie de monitor rezident/depanator si
bootloader ca o entitate unică cu aceste funcţii

14
SI-IDE
• AVR Studio 4 este un
IDE freeware pentru
familia de microcontrolere
AVR 8 biti, dar care nu +
are decât un asamblor
• AVR Studio 4 +
compilatorul C WinAVR
este un IDE in sensul
celor prezentate anterior
• Pentru versiunile
ulterioare ale AVR Studio,
de exemplu Atmel
Studio 6/7 compilatorul
Win AVR este deja
integrat in IDE
15
GCC Toolchain, un exemplu
• Pentru ilustrare vom alege asa zisul GCC
Toolchain pentru familia de microprocesoare/
microcontrolere de 32 de biti ARM
• Este vorba de fapt de un set întreg de programe
care alcătuiesc un set de unelte GCC (GCC
Toolchain) pentru o anumită mașină țintă, in
cazul acestui exemplu, un CPU de tip ARM
(generic)
– Deși mai puțin vizibile pentru utilizatorul obișnuit AVR
Studio 4, o bună parte din cele prezentate sunt
adevărate si pentru compilatorul gcc WinAVR (AVR 8
biți)
Care este drumul de la un program scris in limbaj de
asamblare la imaginea executabilă a programului?
Fişier program
binare (.bin)

Fişier imagine
executabila (.elf,
Fişiere sursă Fişiere obiect .o, .so)
asamblare (.s) (.o)
ld
(linker-
editorul
as de
(asamblorul) legături)

Memory
layout

Fişier cu codul
Script Linker dezasamblat (.lst)
(.ld)

17
Care este drumul de la un program scris in limbaj C si in
asamblare la imaginea executabilă a programului?
Fișier sursa C Fişiere sursă in
(.c) asamblare(.s) Fişiere
as obiect (.o) Fişier program
(assembler)
binare (.bin)

gcc
(compiler)
Fişiere sursă in Fişiere obiect
Fişier imagine
asamblare(.s) (.o)
executabila
(.elf, .o, .so)
ld
(linker-
as editorul
(assembler) de
legături)

Fişiere obiect Configuraţie


biblioteci memorie
(.o, .so) Fişier cu
codul
Script Linker dezasamblat
(.ld) (.lst, .lss) 18
Care sunt numele fişierelor executabile din Toolchain-ul
(setul/lanţul de unelte) GNU C (GCC) pentru ARM?
• Pentru toate există un prefix “arm-none-eabi-” care identifică maşina ţintă;
– EABI = Embedded Application Binary Interface
• Prefixe similare există si pentru celelalte familii de microprocesoare
(maşini ţintă - targets) pentru care există portări ale GCC (powerpc,
mips, x86)!
• Asamblorul (as)
– arm-none-eabi-as
• Linker – editorul de legături (ld)
– arm-none-eabi-ld
• Generare binar program - Object copy (objcopy)
– arm-none-eabi-objcopy
• Dezasamblorul - Object dump (objdump)
– arm-none-eabi-objdump
• Compilatorul C (gcc)
– arm-none-eabi-gcc
• Compilatorul C++ (g++)
– arm-none-eabi-g++
19
Un exemplu de fişier Makefile

all:
arm-none-eabi-as -mcpu=cortex-m3 -mthumb example1.s -o example1.o
arm-none-eabi-ld -Ttext 0x0 -o example1.out example1.o
arm-none-eabi-objcopy -Obinary example1.out example1.bin
arm-none-eabi-objdump -S example1.out > example1.lst

• Nota
• Make este un program utilitar (provenit si larg utilizat in contextul
Unix/Linux) care construieşte in mod automat (asta face si un IDE)
programele executabile si bibliotecile prin utilizarea unor fişiere
numite Makefile care specifică cum anume se obţine imaginea
executabilă pentru maşina ţintă.
• Formatul ELF (Executable and Linkable Format) este un format
standardizat utilizat pentru fişierele obiect, executabile, biblioteci
partajate (shared libraries), fişiere de tip “core dump” (Linux),
– Extensiile acestui tip de fişiere pot fi diverse: .elf, .o, .so, .prx, .puff sau
fără nici o extensie !
20
Ce informaţii ne furnizează fişierul cu codul
dezasamblat?
all:
arm-none-eabi-as -mcpu=cortex-m3 -mthumb example1.s -o example1.o
arm-none-eabi-ld -Ttext 0x0 -o example1.out example1.o
arm-none-eabi-objcopy -Obinary example1.out example1.bin
arm-none-eabi-objdump -S example1.out > example1.lst

example1.out: file format elf32-littlearm


.equ STACK_TOP, 0x20000800
.text
.syntax unified Disassembly of section .text:
.thumb
.global _start 00000000 <_start>:
.type start, %function 0: 20000800 .word 0x20000800
4: 00000009 .word 0x00000009
_start:
.word STACK_TOP, start 00000008 <start>:
start: 8: 200a movs r0, #10
movs r0, #10 a: 2100 movs r1, #0
movs r1, #0
loop: 0000000c <loop>:
adds r1, r0 c: 1809 adds r1, r1, r0
subs r0, #1 e: 3801 subs r0, #1
bne loop 10: d1fc bne.n c <loop>
deadloop:
b deadloop 00000012 <deadloop>:
.end 12: e7fe b.n 12 <deadloop>

21
Cum poate fi citit conţinutul unui fişier obiect?

• $ readelf –a example.o

• Putem citi si afişa:


– Header (antetul) fişierului ELF
– Header program
– Header secţiuni
– Tabela de simboluri
– Atribute ale fişierelor

• Alte opţiuni
– -s afişează si simbolurile
– -S afişează header-ele secţiunilor

22
Ce conţine fişierul obiect?

$ readelf -S example1.o
There are 9 section headers, starting at offset 0xac:

Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000014 00 AX 0 0 1
[ 2] .rel.text REL 00000000 000300 000008 08 7 1 4
[ 3] .data PROGBITS 00000000 000048 000000 00 WA 0 0 1
[ 4] .bss NOBITS 00000000 000048 000000 00 WA 0 0 1
[ 5] .ARM.attributes ARM_ATTRIBUTES 00000000 000048 000021 00 0 0 1
[ 6] .shstrtab STRTAB 00000000 000069 000040 00 0 0 1
[ 7] .symtab SYMTAB 00000000 000214 0000c0 10 8 11 4
[ 8] .strtab STRTAB 00000000 0002d4 00002c 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)

23
Care este conţinutul unui script tipic pentru linker?
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(main)

MEMORY
{
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64k
}

SECTIONS
{
.text :
{
. = ALIGN(4);
*(.text*)
. = ALIGN(4);
_etext = .;
} >ram
}
end = .;

24
Ce conţine un fişier cu o imagine executabilă ?

• Segmentul .text
– Codul executabil
– Vectorul iniţial de reset (adresa de unde se
executa prima instructiune a programului)
• Segmentul .data (.rodata in ELF)
– Variabile statice (iniţializate)
• Segmentul .bss
– Variabile statice (neiniţializate)
– Iniţializat cu zero-uri de către sistemul de
operare sau bibliotecile C de runtime
– Denumirea provine de la: Block Started by
Symbol
• NU conţine stivă/stive sau zona de memorie
pentru alocare dinamică (heap) !
• Vezi si:
/usr/include/linux/elf.h 25
Cum poate fi citit conținutul unui fișier imagine
executabilă?

• Exact la fel ca un fişier obiect (adică cu readelf)!


• Aceleaşi opţiuni utile (câteva):
– -a afişează toata informaţia
– -s afişează simbolurile
– -S afişează header-ele secţiunilor
• OBSERVATIE Un fișier imagine executabilă poate avea
câteva zeci de octeți dacă este vorba de o aplicație
simplă pentru un microcontroler AVR de 8 biţi sau sute de
MOcteţi dacă este vorba de imaginea unui sistem de
operare Linux pentru un microprocesor ARM sau
similar…
26
Câteva exemple pentru fișierele aferente
Toolchain-ului GCC in cazul WinAVR

• Pentru proiectul BlinkyX acestea sunt


fișierele care se găsesc in sub-directorul
…/default
• *.eep, *.elf, *.hex sunt fișiere care se
utilizează pentru programarea
microcontrolerului (.elf sau .hex pentru
memoria Flash, .eep pentru memoria
EEPROM)
• *.lss este fișierul listing, in el găsim si codul
dezasamblat, in limbaj de asamblare
• Fișierele Makefile, • *.o este fișierul obiect, care va fi locatat
*.map, *.lss , *.hex, (plasat in memorie la locul potrivit) de
*.eep sunt fișiere text, linker; este un fișier binar
care se pot deschide cu • *.map este fișierul de raportare al linker-
orice editor de texte
ului, care arata si cum au fost plasate in
memorie diversele segmente
• Makefile este fișierul Make, care nu are nici 27
o extensie
Să începem cu un clasic “Hello
World”!
#include <stdio.h>
main()
{
printf(“hello, world\n”);
}

Pentru a compila si rula pe o maşina Linux/Unix (in linie de


comanda):
$ gcc –o helloworld helloworld.c
$ ./helloworld
hello, world
Fără un IDE pare ca e ceva mai greu de lucrat…dar folosind
Makefile-uri se poate.
Ca editoare de text pentru surse se pot folosi editoare freeware
orientate (si) pe limbajul C cum ar fi: Programmer Notepad,
PSPad, etc.
28
Programarea in C pentru
sisteme incorporate
Este pana la urma tot programare
in limbajul C..

29
C si Java/C++
C este un limbaj procedural:
– Nu există clase si obiecte
– Cărămida de bază este “funcția”

Filozofia limbajului C:
– Cât mai simplu posibil
– Un set minim de constructori pentru limbaj
– Permite ușor un acces la nivel scăzut la resursele
sistemului de calcul!
• Un lucru bun, pentru programatorul de sisteme incorporate
• Un lucru rău, deoarece se pot si scrie cu relativa ușurință viruși
(in Java e mult mai greu de scris viruși..)
– Se bazează masiv pe utilizarea bibliotecilor

Discutăm despre ANSI C (K&R): marea majoritate a


compilatoarelor C pentru MPU/MCU/DSP sunt conforme
acestui standard dar atenţie, pot avea si caracteristici
care nu sunt conforme (mai ales in cazul MPU/MCU de
8/16 biţi) 30
Funcţii in C
Sunt echivalentele metodelor din Java, sau a
funcţiilor/procedurilor din PASCAL:

TipReturnat NumeFunctie (
Tip NumeParametru1,
Tip NumeParametru2, …)
{
return expresie de TipReturnat;
}

31
..Funcţii
/* calculeaza media lui x si y */
int average(int x, int y)
{
int avg_value;
avg_value = (x + y) / 2;
return avg_value;
}

/* mai simplu */
int average2(int x, int y)
{
return (x + y)/2;
}

32
..Funcţii
Echivalentul unei proceduri din Pascal este
o funcţie cu tipul de valoare returnat “void”
/* o procedura/functie care apeleaza alte trei */
void do_tasks(int x, int y, int z)
{
do_task1();
do_task2(x, y);
do_task3(z);
}

33
..Funcţii
Funcţia “main”: este punctul de start (de intrare) al
oricărui program in C
int main(int argc, char *argv[])
{
int i;
for (i = 0; i < argc; i++)
fprintf(“parameter %d is %s\n”, i, argv[i]);
}
Alte forme
int main();
main();

ATENTIE: Tipic pentru unele aplicaţii de tip SI, mai poate exista o funcţie care se
execută înainte de main (), de genul start_up (), funcţie scrisă in cea mai mare
parte in limbaj de asamblare. Ea realizează iniţializarea unor resurse critice,
imediat după reset-ul MCU/MPU/DSP si apoi apelează pe main(). Vezi partea
introductivă!
34
Funcţii
Prototipul unei funcții: se declară mai întâi, dar se
defineşte mai târziu
int func_apelata(int x, int y); //este declarat prototipul
….

int func_apelanta()
{

avg = func_apelata (a, b); // aici e apelata

}
….
int func_apelata(int x, int y) // mai tarziu definita
{

}

35
Tipuri, variabile si constante
Variabile scalare Structuri si uniuni

int i, j, k; struct {
char c; int x, y;
float x, y; float weight;
}
double z;

union {
Tablouri (vectori) char ch_value;
int int_value;
float X[100];
float float_value;
float pixel[1024][768];
}

36
Tipuri, variabile si constante
Câteva reguli in ce priveşte denumirea variabilelor
Ce se foloseşte: A-Z, a-z, 0-9, _ (underscore)
Prima litera trebuie sa fie A-Z, a-z, sau _ underscore
Contează litera mică sau mare (este case sensitive): MyVariable si
myvariable sunt diferite!!
Lungime: poate avea oricate caractere, dar tipic numai primele 31 contează

Convenţional si ca regulă de bună practică trebuie să se folosească nume


semnificative/relevante:
int inaltime;
float suprafata;
int dimensiune_vector;
Un stil de notare de bună practică care ne dă si o informaţie despre tip este:
int nInaltime; //prefixul n spune tipul intreg
float fSuprafata; //prefixul f spune tipul flotant
int nDimensiune_vector;
int *pnValoare; /*prefixul p ne spune ca avem un
pointer, n catre Valoare de tipul intreg */

37
Tipuri, variabile si constante
Tipuri scalare (implicit cu semn, signed): întreg (sau virgulă fixă), caracter si
virgulă mobilă
Întregi:
int întreg normal, 2, 4 sau 8-octeti
short întreg scurt, 2-octeti (evitati-l !)
long întreg lung/ tipic dublu fata int, 4, 8
Caracter:
char un singur caracter, 1-octet/Byte
Virgulă mobilă (VM)-IEEE 754:
float simplă precizie, 4-octeti
double dublă precizie , 8-octeti

Dimensiunea tipului int/long este dependentă de arhitectura CPU (MPU/MCU/DSP) !!


Pentru Win AVR/AVR 8 biți dimensiunea tipului int este de 2 octeți, lucru obișnuit
pentru microcontolerele de 8 biti 38
Tipuri, variabile si constante
Modificatorul unsigned (fără semn)
unsigned short short_value;
unsigned int int_value;
unsigned char char_value;

1. Afectează/modifică domeniul de reprezentare; de exemplu,


dacă int are 2 octeţi:
unsigned int avem 0 … 65535; int avem -32 768 … +32 767.
2. Contează si atunci când variabilele sunt folosite in comparaţii,
condiţii

39
Tipuri, variabile si constante: număr
de octeți (bytes) si domeniul de
reprezentare!
Name Bytes Range
char 1 -128 to 127
unsigned 1 0 to 255
char
short 2 -32,768 to 32,767
int varies may be same as
short
long 4
float 4 7 significant digits
double 8 15 significant digits
* (pointer) width of range of memory
memory
Cunoașterea numărului de octeți si a domeniului de
reprezentare (range) pentru un anumit tip este de
esențială in programarea SI! 40
Tipuri, variabile si constante
Iniţializarea variabilelor, se face la declarare
sau la utilizare:
int n = 100; //facuta la declarare
float x = 20.5;
char ch = ‘X’;

int avg = average(n, m);// sau la utilizare


int m = n/2, k;

41
Tipuri, variabile si constante
Conversia de tip (type casting): conversia unei
valori de un tip intr-o valoare de un alt tip
Atenţie: poate avea ca efecte colaterale, trunchieri, rotunjiri,
modificări ale domeniului de reprezentare (vezi unsigned)
(tip) expresie

pi = (double) 3.1415926;

size = (int) (3.14 * radius * radius);

if ((unsigned) x > (unsigned) y) …

42
Tipuri, variabile si constante
• typedef permite introducerea de “sinonime” pentru tipuri care deja există
sau au fost declarate intr-un fel sau altul, mărind lizibilitatea codului
• De exemplu pentru compilatorul WinAVR (de fapt pentru toate
compilatoarele gcc) in fișierul header stdint.h găsim următoarele re-
definiri de tipuri (cu denumiri de tip mai sugestive decât cele standard
din C, incluzând si numărul de biti):

typedef signed char int8_t;

typedef unsigned char uint8_t;

typedef signed int int16_t;

typedef unsigned int uint16_t;

typedef signed long int int32_t;

typedef unsigned long int uint32_t;

43
Tipuri, variabile si constante
Cum se folosesc/definesc constantele?

Folosim macroinstrucţiuni (directive) de tip #define :

#define N 1024 // N=1024


...
int array[N];

Folosim variabile constante (există si aşa ceva..):

const double Pi = 3.1415926;// la declarare

44
O paranteză: pre-procesorul
• Modifică codul sursă înainte de al transfera
compilatorului
• Trei utilizări:
– directive,
– constante si
– macroinstrucţiuni
• Directivele sunt comenzi care spun pre-procesorului:
– să “sară” anumite porţiuni ale fişierului sursa,
– să includă un alt fisier,
– să definească (#define) constante sau macroinstrucţiuni
• Încep cu simbolul # si tipic utilizează numai litere mari,
pentru identificarea rolului lor special

45
Pre-procesorul: compilarea
condiţională
• Există un set larg de opţiuni (directive) care pot fi
utilizate pentru a determina dacă pre-procesorul va
înlătura anumite linii de cod înainte de trece mai departe
codul sursă compilatorului
• Acestea sunt: #if, #elif, #else, #ifdef, si #ifndef.
• Un bloc #if sau #if / #elif / #else sau un bloc #ifdef
sau #ifndef trebuie să fie terminat (închis) cu un
#endif.
• Directiva #if aşteaptă un argument numeric pe care-l
evaluează ca adevărat(TRUE) dacă este diferit de zero,
caz in care codul care urmează pana la directivele #else,
#elif, sau #endif, va fi păstrat.
• Dacă argumentul este evaluat ca fals (FALSE), egal cu
0, atunci codul care urmează, pană la directivele #else,
#elif, sau #endif, va fi eliminat.
46
Pre-procesorul: compilarea
condiţională
Un exemplu de cod care execută tipărirea unei informatii care e utilă doar in
faza de testare/depanare (debug) a aplicatiei:

#ifdef DEBUG
printf("debug:x = %d, y = %f\n", x, y);
...
#endif

Activarea presupune definirea anterioara a lui DEBUG


#define DEBUG 1
Sau e suficient ca DEBUG să fie doar definită:
#define DEBUG
Dezactivarea presupune:
#define DEBUG 0
Sau
#undef DEBUG//se inlatura definitia anterioara a lui DEBUG
47
Pre-procesorul: compilarea condiţională
# define TINY13 0
# define MEGA8 1
# define MEGA32 2

# define MyAVR MEGA8

#if MyAVR == TINY13
# define TXD 12
# define RXD 13
#elif MyAVR == MEGA8
# define TXD 1
# define RXD 2
#elif MyAVR == MEGA32
# define TXD 5
# define RXD 6
#else
# error “Nu avem o definitie pentru TxD si RxD”
#endif
Dacă ne-ar interesa o definire a poziţiilor pinilor TxD sau RxD (port serial AVR) funcţie de
ce varianta de AVR utilizăm
Directiva #error va afişa un mesaj la compilare, dacă definirea lipseşte in cod
48
Pre-procesorul: evitarea includerii multiple

• O problema comună care apare intr-un proiect care


utilizează mai multe fişiere header/sursă: un fişier
header poate fi necesar in mai multe alte fişiere header,
care la rândul lor vor fi incluse mai târziu intr-un fişier
sursă
• Variabile, constante, structuri sau funcţii pot apărea
definite de mai multe ori, cate odată pentru fiecare fişier
inclus
• Rezultatul: erori si dificultăţi in compilarea programului
• Prin folosirea directivei #ifndef, se poate include un bloc
de text doar dacă o expresie particulară nu este definită:
apoi in fişierul header dorit se defineşte această
expresie.
• Aceasta ne va asigura că un cod sursă corespunzător lui
#ifndef este inclus doar prima dată, când este încărcat
(inclus) fişierul 49
Pre-procesorul: evitarea includerii multiple

#ifndef _FILE_NAME_H_
#define _FILE_NAME_H_
/* aici urmeaza codul */
#endif // #ifndef _FILE_NAME_H_
• O modalitate similară poate fi utilizată pentru a evita
definirea multiplă a unor constante specifice, cum ar fi de
exemplu, constanta NULL:
Litere MARI
#ifndef NULL
#define NULL (void *)0
#endif // #ifndef NULL
50
Pre-procesorul:macroinstrucţiuni
• O macroinstrucțiune are uzual forma :
#define NUME_MACRO(arg1, arg2, ...) [codul sursa care va fi generat]
Exemple:
#define INCREMENT(x) x++
#define MULT(x, y) x * y
Instanțierea /utilizarea (nu este vorba de o apelare!) unei macroinstrucţiuni înseamnă
înlocuirea ei cu codul sursă descris in corpul ei si cu valorile invocate ale
parametrilor formali, ea nu implică o încărcare suplimentară a unității
centrale, ca in cazul apelării unei funcții.
In schimb, codul unei funcții apare o singură dată in codul programului, pe când
codul aferent macroinstrucțiunii apare de atâtea ori de câte ori este utilizată
Este deci eficienta ca timp de execuție dar ineficienta ca grad de ocupare a memoriei

Aşa am utiliza pe MULT:


int z = MULT(3 + 2, 4 + 2);
// asa se instantiaza in codul sursa
int z = 3 + 2 * 4 + 2; /* dar 2 * 4 va fi evaluat primul!*/

Modalitatea corectă de definire este:


#define MULT(x, y) (x) * (y)
/* acum MULT(3 + 2, 4 + 2) va genera (3 + 2) * (4 + 2) cea ce este 51
corect */
Pre-procesorul:macroinstrucţiuni, alte
exemple
/* Folosim un SAU-EXLUSIV pentru a permuta-swap-
cele 2 variabile */
#define SWAP(a, b) a ^= b; b ^= a; a ^= b;
//utilizare
int x = 10;
int y = 5;
SWAP(x, y);

• Definirea unei macroinstrucţiuni pe mai multe linii!!


#define SWAP(a, b)
{ \
a ^= b; \
b ^= a; \
a ^= b; \
}

52
Pre-procesorul:macroinstrucţiuni
(WinAVR)
• Un exemplu util, in contextul compilatorului WinAVR, sunt
macroinstrucțiunile utilizate pentru manipularea biților, din biblioteci
definite in diverse fișiere header (de ex. io.h, sfr_defs.h, s.a)

• Macroinstrucțiunea:
#define _BV( bit) (1 << (bit))
– convertește valoarea de bit intr-un octet: un octet doar cu un “1” pe
poziția “bit”, restul biților fiind “0”
• Macroinstrucțiunea:
#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr))
– Returnează valoarea octetului din registrul sfr; care la rândul ei folosește
_MMIO_BYTE si _SFR_ADDR prin care se face trecerea de la numele registrului
la adresa lui din memoria de date (zona I/O)

• Un exemplu de utilizare directă a lui _BV pentru setarea bitului 2 din portul
C ar fi:
PORTC |= _BV(PC2);
Pre-procesorul:macroinstrucţiuni
(WinAVR)
• Ea la rândul ei este utilizată de alte macroinstrucțiuni de manipulare explicită a biților:
– setare bit din sfr
#define bit_is_set(sfr, bit) (_SFR_BYTE(sfr) & _BV(bit))
– ștergere bit din sfr
#define bit_is_clear(sfr, bit) (!(_SFR_BYTE(sfr) & _BV(bit)))
– buclare pana bit-ul din sfr este 0
#define loop_until_bit_is_set(sfr, bit) do { } while
(bit_is_clear(sfr, bit))
– buclare pana bit din sfr este 1
#define loop_until_bit_is_clear(sfr, bit) do { } while
(bit_is_set(sfr, bit))

• Există si o formă mai veche a unor macroinstrucțiuni similare;


– Ștergere (clear) bit din sfr
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= -_BV(bit))
– setare bit din sfr
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
Tipuri, variabile si constante
Constante speciale: tipul enumerat (enum)
enum color_type {RED, YELLOW, BLUE};
enum color_type wall_color;

Echivalent cu
#define RED 0
#define YELLOW 1
#define BLUE 2

Asignarea automată a valorii constantelor unui enum se


face in ordinea enumerării, începând de la 0
55
Tipuri, variabile si constante
• Exemplu: definirea stărilor unei maşini
secvenţiale, definim un nou tip numit
STARI, de tip enumerat:
typedef enum {
STARE_1, STARE_2,
STARE_3, STARE_4,
STARE_5, STARE_6,
STARE_7, STARE_8
} STARI;

56
Tipuri, variabile si constante: baze
de numerație
Valori constante in C : întregi
zecimal 100
hex 0x64
octal 0144

Hex începe cu “0x”, octal începe cu “0”!


0144 este 10010

57
Tipuri, variabile si constante
Valori constante in C : caracterele
‘\0’ caracterul NULL (cod ASCII =00)
‘\n’ newline (LF)
‘\r’ return (CR)
‘a’ litera “a”
‘\t’ tab
‘\32’ caracterul al cărui cod ASCII este
3210 (spaţiu, space)
58
Tipuri, variabile si constante
Virgula mobilă (VM) = se utilizează un standard de
reprezentare numit IEEE 754
– Folosită mai puţin in aplicaţii de tip sistem incorporat
cu MPU/MCU “mici”, de 8 sau 16 biți
– Foarte “costisitoare” in termen de resurse utilizate in
comparaţie cu numerele întregi (in virgula fixă - VF) dacă nu
există suport hardware pentru ea
Simpla precizie utilizează pentru reprezentare 32-biti
(4 octeţi), iar dubla precizie 64-biti (8 octeţi)
Exemplu:
AVR(MCU 8 biţi): op VM vs. op VF (întregi), o adunare
pe 32 de biţi (4 octeţi):
Execuția durează 160 cicluri maşină vs. 3 cicluri maşină!
Evitaţi utilizarea VM pentru aplicaţiile AVR 8 biti

59
Tablouri (arrays) si pointeri
Tip NumeVariabila [Dimensiune];
Tip NumeVariabila [Dimensiune1][Dimensiune2];
Tip NumeVariabila [Dimensiune1][Dimensiune2] .. [DimensiuneN];

• O înşiruire a unei variabile specifice având acelaşi tip, memorată in memorie


• Un tablou poate fi undimensional, adica un vector, sau multidimensional
• In limbajul C sunt Zero-indexate: adică indexarea elementelor incepe 0 si se
termină la N-1 !

int vector[8];
int vector2[4][4];
int vector3[2][2][2];
int n,k,l;

vector[0] = 1; /* primul element */
n = vector[7]; /* ultimul element */
k = vector2[3][3];
l = vector3[1][1][1];
vector[8] = -1; /* ce se intampla?! */
60
Tablouri si pointeri
Atenţie la limite (graniţe) in C!
In C nu există un mecanism intrinsec de a
semnala/verifica accesul, la scriere sau citire,
dincolo de limitele unui tablou!
Scrierea dincolo de limitele unui tablou = un dezastru
potenţial! Acolo se pot afla alte date esențiale pentru
funcționarea corecta a programului!

Ce este exact un tablou?


Nu este un tip specific
Este de fapt un pointer la un bloc de memorie
Nu există un mecanism intrinsec pentru copierea
tablourilor (asignarea lor ca un tot)
61
Tablouri: atribuirea/asignarea lor se
face element cu element!

Exemple

/* Asa e bine */
nTestArray1[0] = nTestArray2[0];

/* Asa nu este bine, eroare la compilare


!!!!!!!!!*/
nTestArray1 = nTestArray2;

62
Pointeri
O variabilă este doar un bloc de (sau in) memorie,
caracterizat de:
– Adresă (adresa de început): Unde începe blocul in spaţiul de
adrese ?
– Dimensiune: Cât loc el ocupă in memorie, incepand de la
adresa de inceput?
– Tip: Cum trebuie interpretată valoarea/conținutul blocului?

Un pointer este o adresă de început a unui bloc de


memorie:
– Valoarea pointerului: adresa de (din, in) memorie
– Variabila de tip pointer: o variabilă care conţine o adresă de
memorie

63
Pointeri - dimensiunea lor
• Cât de “mare” este un pointer?
• Cât loc ocupă el in memorie?
• Răspunsul este că depinde de dimensiunea spaţiului
de adrese al mașinii țintă (MPU/MCU/DSP)
– In slide-ul anterior este vorba de o adresă exprimată pe 32 de
biţi (un spaţiu de adrese de 232 adică 4GB): un pointer va ocupa
4 octeţi
– Dacă spaţiul de adrese este de 64kB (adrese de 16 biți) el va
avea doar 2 octeţi
– Un pointer pentru compilatorul WinAVR are întotdeauna 16 biți!
• Un cuvânt de program AVR (unitatea adresabilă in memoria
FLASH) are întotdeauna dimensiunea de 16 biți/ 2 octeți
• Aceasta poate pune unele probleme pentru variantele la care
memoria de program implementată depășește limita de 64 de
kilocuvinte, dar acum Win AVR oferă acum mijloacele de a le
conturna
– Mai ales in acest caz, trebuie citită si documentaţia
compilatorului! 64
Pointeri
int nVal;
int *pnVal;
pnVal = &nVal;/* fie de ex. adresa 0x2000 */
nVal = 10;
pnVal este 0x2000 (adresa)
*pnVal este 10 (ce se afla la adresa)

*pnVal = 5;

pnVal este inca 0x2000


*pnVal este 5
nVal va fi si el 5
65
Pointeri- utilizare
Trei puncte cheie când utilizam pointerii:
1. Declararea pointerului
tip *pNume;
char *pChar;
long *pHistory;
2. Iniţializarea pointerului
Pentru a putea fi utilizat el trebui să indice ceva.
pChar = (char *) 0x00001800;
pHistory = &lValue;
Castingul (char *) spune compilatorului că este vorba de o adresă de
memorie de 32 de biţi (adresa unui char), nu de o valoare de 32 de biţi.
3. Accesarea pointerului (Read/Write)
Pentru a utiliza valoarea, trebuie utilizat un * in fata numelui.
n = *pChar & 0x80;
if( (*pHistory + 25) > TOL_HISTORY )
*pHistory = TOL_MINIMUM;

Pointerii trebuie iniţializaţi: un pointer neiniţializat= un potenţial dezastru!


66
Pointeri- utilizare 2
Declararea unui pointer: Tip *NumeVariabila;
char *pLED;
char *pSwitch;

Iniţializarea unei variabile pointer (memorie unificata)


pLED = 0x0f001000;//adresa locatie LED- iesire
pSwitch = 0x0f001004;//adresa locatie switch- intrare

Utilizarea (de-referirea) unei variabile pointer


*pLED = 0xff; /* stinge LED-urile, actualizeaza o
iesire */
ch = *pSwitch;/*citeste stare comutator – citeste o
intrare */

Înţelegerea si utilizarea pointerilor este esenţială pentru


un programator C! 67
Pointeri: void, NULL
• Un pointer de tipul void este un tip special de pointer si aceasta
arată ca el poate indica orice tip de dată.
int i;
float f;

void* variabila_pointer;
..
variabila_pointer =&i;/*ambele atribuiri, initializari sunt corecte*/
variabila_pointer=&f;
• Pointerii NULL pot fi pointeri pentru orice tip de dată, dar ei nu
indică nici o adresă de memorie sau referinţă validă
• Există mai multe modalităţi de a declara/iniţializa un pointer NULL:
– Prin utilizarea macroinstrucţiunii (constantei ) NULL:
void * NULL
int* exemplu_pointer;
exemplu_pointer =0; //forme echivalente
exemplu_pointer=NULL;
• Un pointer NULL este diferit de un pointer neiniţializat, el poate
fi folosit in operaţiile aritmetice sau de comparare, având valoarea 0
– Un exemplu: o funcţie care returnează un pointer, poate returna un
pointer NULL in cazul in care de fapt nu poate returna un pointer valid;
pointerul returnat poate fi testat dacă este == NULL înainte de utilizare68
Pointeri – implementarea memoriei
Unde indică sau ce indică de fapt un pointer corect iniţializat?
Depinde de sistem, dar nu întotdeauna in memoria RAM sau ROM
Există două tipuri de arhitecturi de bază, mai ales la MPU:
Memorie unificată – Freescale (Power PC dar si HC05)
Toate dispozitivele, RAM, ROM si I/O ocupă un spaţiu de
adresare unic
0x2000 poate fi o locaţie in RAM, ROM, un “LED” – o ieşire (O)
sau un “comutator” – o intrare (I)
Singura modalitate de a accesa I/O este prin intermediul
pointerilor
Memorie separată pentru I/O – Intel (80x86)
Adrese separate pentru I/O si memorie
Avem porturi de I/O, instrucţiuni distincte pentru lucrul cu ele
Dar la AVR 8 biti?
Are memorie de date (SRAM), de program (ROM) si registre I/O in
spaţiul memoriei de date si instrucţiuni separate pentru lucrul cu ele
69
Pointeri – implementarea memoriei
• Dacă citim o o locaţie din memoria RAM vom
obţine ultima valoare care a fost scrisă in acea
locaţie
• In cazul insă in care locaţia este asociată unui
dispozitiv de I/O aceasta se poate comporta la o
scriere si citire in mod specific, deoarece apare o
interacțiune cu ce se poate afla si in afara
sistemului de calcul.
– O operaţie de scriere a unui octet cu bitul 7 =1 poate
avea efecte diferite decât cea a unei scrieri cu bitul 7 =0
– Trebuie înţeles modelul programatorului pentru
acel dispozitiv I/O si/sau natura acelei interfeţe cu
mediul exterior
70
Pointeri - aritmetica
Aritmetica cu pointeri si compararea lor
– Se poate face adunare si scădere; pentru aceasta contează
dimensiunea (tipul) elementului adresat
– Se poate testa egalitatea sau inegalitatea
int *pInt = 0x0f000000;//un CPU la care int are 4 oct.
char *pChar = 0x0f000004;
*(pInt +1) indica 0x0f000004 (tipul int avand aici 4
octeti)
*(pChar+1) indica 0x0f000005 (tipul char avand 1 octet)
“pChar > pInt” este adevărat
“pChar == pInt + 1” este adevărat

Pointerii către tipuri diferite sunt diferiţi!


Nu există o conversie implicită de la un tip la altul, cum se
întâmplă la tipurile aritmetice!

71
Tablouri si Pointeri
O variabilă tablou are asociată o valoare de tip pointer;
int X[N];
int *pX = X;

Următoarele atribuiri sunt echivalente:


X[2] = 100;
*(X+2) = 100;
*(pX+2) = 100;
pX[2] = 100;

Un tablou nu este in realitate o variabilă!


X = 0xf0000000;/* eroare de compilare!!!!! */
Când este utilizat intr-o expresie el este de fapt un pointer la primul
element al tabloului !

72
Structuri (struct) si uniuni
Sunt utilizate pentru definirea unor
componente complexe:
struct point { //asa se defineste o structura
int x; //elementele nu este necesar sa fie de
int y; //toate acelasi tip!
char z;
};

struct point p1 = {10, 20};//ex. declarare cu initializare
struct point p2, p3; //declarare
p2.x = 10; //
p2.y = -p1.y; //asa se acceseaza elementele
p3 = p2; //asignare structuri

73
Structuri si uniuni
Structuri si pointeri la structuri

//fie structura p1 de tip point, declarat anterior


struct point p1 = {10, 20, 30};
//declararea pointerului la structura de tip point si
// initializarea lui se face astfel
struct point *ptr = &p1;

ptr->x = 20; //accesare elemente structura –elementul x
(*ptr).y = 50;//modalitate echivalenta - elementul y

OBSERVATIE
• Limbajul C nu permite definirea recursivă de structuri, adică o structură nu
poate conține ca element/ câmpuri tot o structură
• Si din acest motiv sunt utili pointerii la strucuturi

74
Structuri si uniuni

Structuri si tablouri
struct key {
char *word;
int count;
} keytab[NKEYS];//asa definim un tablou de structuri
//…
keytab[0].word = “auto”;
keytab[0].count = 5;
//asa se acceseaza elementele tabloului de structuri

75
Structuri si uniuni (union)
Uniunea: permite “fuzionarea” la nivelul memoriei
ocupat a spațiului ocupat mai multor componente
(ocupa de fapt același spațiu)
Permit o oarecare economie de memorie, dar utilizarea lor poate avea si
efecte secundare
union u_tag {
int ival;
float fval; //acest element are dimensiunea maxima
// si el va da dimensiunea pe care u_tag o va ocupa
char *sval;
}

Dimensiunea unei variabile de tip union este dimensiunea celei


mai mari componente ale sale.
Utile atunci când resursele de memorie RAM sunt limitate, de
exemplu la MCU de 8 biţi, dar încercați să evitați utilizarea lor76
Structuri si uniuni
O uniune se poate utiliza si intr-o structură:
Struct {
char *name;
int flags;
int utype;
union { //uniune membra a structuri symtab
int ival;
float fval;
char *sval;
}
} symtab[NSYM];
//avem un tablou de structuri cu NSYM elemente

77
Expresii in limbajul C
Operatori aritmetici:
* / % (modulo, rest)
+ -
Care este rezultatul (vezi si precedenţa
operatorilor precum si asociativitatea)?
10 % 4
10 % 3 / 2

78
Expresii C
Incrementarea si decrementarea,
exista in varianta post- si pre-
++ --
Exemple:
n++;//doar incr.
//asignare cu post incrementare, atribuim si apoi ++
x = n++;
//asignare cu pre incrementare, ++ si apoi atribuim
x = ++n;
for (i = 0; i < N; i++) …
for (i = N-1; i > 0; i--) …
79
Expresii C
In limbajul C nu există tipul de date boolean!
Există însă operatori relaționali (de comparatie)
pentru care daca rezultatul evaluării =0 el fi
interpretat ca FALSE-fals si daca este ≠0 va fi
interpretat ca TRUE- adevarat
- 0x01 sau 0x235E sunt amândouă valori, care daca rezulta in
urma unei astfel de comparări, vor fi interpretate ca FALSE
Operatorii relaționali: produc un rezultat =0
(FALSE) sau 1 (≠0) (TRUE), deci valori booleene
> >= < <= == !=
Care este rezultatul?
10 > 5
(unsigned) -1 > 1
Exemplu
if (ch != EOF)
80
Expresii C
Operatorii logici (booleeni): Tratează orice valoare ne
nulă (adica ≠0) ca TRUE si orice valoare nulă (=0) ca
FALSE
! (NOT) “NU”
&& (AND) “SI”
|| (OR) “SAU”
Care este rezultatul?
(10 > 5) && (-1 > -2)
(10 > 5) || (-1 > -2) && (2 > 1)

Un exemplu mai puţin obişnuit ?


if (10 && 20)

81
Expresii C
Operatorii logici sunt evaluaţi folosind ce s-ar numi evaluarea
“leneşului” (lazy evaluation).
Lazy evaluation – Odată ce a apărut o valoare care garantează
îndeplinirea unei condiții TRUE sau FALSE oprim evaluarea
OR(SAU) când oricare din condiții este identificată ca TRUE
AND (SI) când oricare din condiții este identificată ca FALSE
- De exemplu:
- in expresia: A OR B OR 1 OR C OR D ne oprim odată ce am ajuns la 1, fără sa
mai evaluam si pe C si D deoarece rezultatul va fi oricum 1 (TRUE)
- in expresia: A AND 0 AND B AND C ne oprim odată ce am ajuns la 0, fără sa mai
evaluam si pe B si C deoarece rezultatul va fi 0 (FALSE)

De ce este evaluarea “leneșului” importantă?


- Codul se execută mai rapid – se “sare” peste porțiunile de cod ne
necesare
- Odată ce o condiție este evaluată/îndeplinită nu mai are sens sa
evaluam si ceilalți termeni
- Se poate valorifica aceasta modalitate de evaluare pentru evitarea
unor condiții nedorite: verificând, de ex., dacă un pointer este NULL
înainte de a-l folosi

82
Expresii C
Instrucţiuni si expresii
expresie-instructiuni ::= expresie ;
Care din următoarele sunt instrucţiuni
valide?
10 + 20;
average(2, 3);
10;
a = b = c = 10;
a = 10, b = 20;
83
Expresii C
Operatorul de asignare (atribuire):
Asignarea este o formă a unei expresii
Exemple:
a = (b = (c = 10))
if ((ch = getchar()) == EOF)

84
Expresii C
L-valoare (L- value): o expresie care se referă la o
regiune(entitate) care are capacitatea de
memorare; doar L-valori pot fi folosite in partea
stânga (L vine de la Left) a operatorului “=”
De exemplu o memorie de tip RAM are capacitatea de memorare (in ea
se poate scrie), iar una de tip ROM (din ea se poate doar citi), in
acest context (la execuția programului), tipic nu are , in ea nu se
poate scrie ; deci daca “variabila” este in alocata într-o memorie
ROM ea nu poate fi o L-valoare
Sunt următoarele utilizări valide ale unei L-valori?
int a;
(float) a = 3.14;
* ((float*) &a) = 3.14;

85
Expresii C
Expresii condiționale: dacă expr1 nu este 0 (este
≠0) se evaluează expr2, altcumva (este =0) se
evaluează expr3
expr1 ? expr2 : expr3
Exemple
x_abs = (x >= 0) ? x : -x;

Evitați utilizarea acestei forme, care este foarte putin


lizibila!

Ea este echivalentă cu:


if (x >= 0) //o forma mult mai lizibila!!
x_abs = x;
else
x_abs = -x;

86
Precedenţa operatorilor
Cea mai mare
~ ! - (unari) ++ --
* / % aritmetici
+ -
<< >> deplasare biţi
< <= > >= relaţionali
== !=
& logici la nivel de bit
^
|
&& logici (booleeni)
||
87
Precedenţa operatorilor
Ce vrem sa facem: vrem sa realizăm un SI
(AND) la nivel de bit intre X si o mască (o
constantă cu dimensiunea lui X), apoi
verificăm dacă rezultatul este 0
Cum este corect?
if (X & MASK = = 0)
if ( (X & MASK) = = 0)

88
Precedenţa operatorilor
• Contează si asociativitatea (ordinea de
evaluare): de la stânga la dreapta sau de la
dreapta la stânga!
• Cu excepţia unor cazuri simple (ca la
aritmetica..), sunt destul de greu de ţinut minte;
nu încercaţi neapărat să le țineți minte: folosiţi
din belşug parantezele ( , )!

• Parantezele pot fi uneori derutante, dar mult mai


derutantă poate fi absenţa lor!
(10 % 3 ) / 2 sau
10 % (3 / 2) unde este mult mai clar ce dorim
de fapt
89
Operaţii la nivel de bit (bitwise)
O notaţie este doar o modalitate de reprezentare a unei
mărimi.
Programatorul trebuie să înţeleagă si să interpreteze
corect cum este reprezentată informaţia si cum să
procedeze cu o variabilă

Exemple:
Dacă ar fi să reprezentăm valoarea 50 utilizând 8 biţi
– Binar = 00110010
– Hex = 0x32
– Zecimal = 50
Poate reprezenta pur si simplu valoarea 50:
x = x + 50
Sau starea biţilor poate să însemne ceva:
Daca bitul 6 este 1, se face ceva..
Sau poate fi o combinaţie a celor două scenarii anterioare:
Daca bitul 6 este 1, x = x + 2 (cei 4 biţi inferiori din valoare) 90
Operaţii la nivel de bit (bitwise)
Operatori la nivel de bit: Manipularea biților este o componentă
cheie a programării sistemelor incorporate (in special pentru MCU!)
Majoritatea resurselor periferice pentru un microcontroler sunt accesibile
prin intermediul unor biți de stare (care prezinta interes in a fi citiți) si
control (care prezinta interes in a fi scriși), grupați sub forma unor
registre de stare si control
Prin utilizarea unor variabile de tip bit se mai câștigă eventual si spaţiu
de memorare – In loc să folosim 8 biţi pentru o singură valoare, ii folosim
ca o colecție (un set) de 8 valori booleene distincte
Dar atenție, in limbajul C nu exista un tip de date bit, așa ca este
responsabilitatea utilizatorului de a-l gestiona

Operaţiile sunt executate bit cu bit, la nivel de bit – bitwise

In mod tipic, si in această situație, se utilizează tot notația


hexazecimală care este de regulă mai practică decât cea binară, fiind
mai compactă:
0xFF este mai comod/compact decât 0b11111111 in binar
0x10 este mai comod/compact decât 0b00010000 in binar
Stăpâniți conversia binar hex si invers?

91
Operaţii la nivel de bit (bitwise)
Operatorul AND(SI) & – Tipic utilizat pentru ștergerea
si/sau testarea biților individuali
0 AND (SI) cu orice altceva ne dă întotdeauna 0
1 AND (SI) cu orice altceva ne dă aceiași valoare (0 sau 1) :

0x10 & 0x10 = 0x10


0x01 & 0x10 = 0x00
0xFF & 0x00 = 0x00

Pentru a șterge biți:


1. Se șterg biții pe care vrem să-i aducem in 0 (Șterge)
2. Toți ceilalți biți sunt in 1 (Păstrează)

92
Operaţii la nivel de bit (bitwise)
Exemplu AND: Șterge doar biții 2, 3 ai unui număr
reprezentat pe 8 biți (char)
Se utilizează o “mască” (o constanta) cu “0”-uri
doar in pozițiile pe care vrem să le ștergem:
1111 0011
0x F 3

byVal = byVal & 0xF3;


byVal & = 0xF3;/*forma echivalenta prin
combinarea operatorului bitwise cu cel de
asignare*/

93
Operaţii la nivel de bit (bitwise)
Operatorul OR (SAU) | – Tipic utilizat pentru
setarea (doar) a unor biţi individuali
1 OR (SAU) cu orice altceva ne dă întotdeauna 1:

0x10 | 0x10 = 0x10


0x01 | 0x10 = 0x11
0xFF | 0x00 = 0xFF

Pentru a seta biţi:


1. Se setează biții pe care vrem sa-i aducem in 1 (Setare)
2. Toți ceilalți biți sunt in 0 (Păstrează) 94
Operaţii la nivel de bit (bitwise)
Exemplu OR : Setează ( 1) biţii 7 si 5 ai unui
număr de 8 biți
Masca care are biții setați doar in pozițiile
dorite:
1010 0000
0x A 0

byVal = byVal | 0xA0;


byVal |= 0xA0; /*forma echivalenta prin
combinarea operatorului bitwise cu cel de
asignare*/
95
Operaţii la nivel de bit (bitwise)
Operatorul XOR (SAU EXCLUSIV) ^ – Tipic utilizat
pentru a comuta/toggle un bit (a-i schimba starea)

1 XOR cu orice altceva inversează /comută (toggle) bitul (dacă e 0 îl


face 1, dacă e 1 îl face 0)
nu-l confundaţi cu ridicarea la putere ()..

0x10 ^ 0x10 = 0x00


0x01 ^ 0x10 = 0x11
0xFF ^ 0x00 = 0xFF

Pentru a comuta biţi:


1. Biţii care vrem să comute se setează in 1 (Comută)
2. Toţi ceilalţi biţi sunt in 0 (Păstrează)

96
Operaţii la nivel de bit (bitwise)
Operatorul de inversare/complement față de 1 ~ , fiecare bit este
complementat/inversat
~(0x10) = 0xEF;
Atenție, nu exista si un complement fata de 2!

Operatorii de deplasare (binara)


Sunt utilizați pentru a deplasa (shift) un sir de biți la stânga sau la dreapta:
>> sau <<
Sintaxa este:
Variabila/Valoare << Numar de pozitii binare
sau
Variabila/Valoare >> Numar de pozitii binare
Fiind vorba de deplasare (nu rotire) prin stânga (<<) sau prin dreapta se introduce
valoarea 0 (un bit 0) la fiecare deplasare!

nVal = nVal >> 4; /* Deplaseaza nVal la dreapta cu 4 pozitii */


nVal >> = 4; /*forma echivalenta prin combinarea operatorului bitwise cu cel de
asignare*/
nVal = 1 << 4; /* nVal = 00..10000 */
De ce să-l utilizăm?
Am putea număra numărul de biţi in 1 din nVal
Intr-o buclă, vom putea itera ceva pentru fiecare bit al lui nVal
Putem, in anumite limite, rearanja biții
Putem realiza uşor si rapid înmulțiri (<<) sau împărțiri (>>) ale lui nVal cu puteri ale lui 2 97
Operaţii la nivel de bit (bitwise)
a: 1 0 1 0 1 0 1 0 0xAA
• & AND (SI) b: 0 0 0 0 1 1 1 1 0x0F
• | OR (SAU inclusiv)
a&b: 0 0 0 0 1 0 1 0 0x0A
• ^ XOR (SAU
a|b: 1 0 1 0 1 1 1 1 0xAF
exclusiv)
a^b: 1 0 1 0 0 1 0 1 0xA5
• << deplasare stânga
a<<1: 0 1 0 1 0 1 0 0 0x54
• >> deplasare dreapta
• ~ complement faţă b>>2: 0 0 0 0 0 0 1 1 0x03

de 1 ~b: 1 1 1 1 0 0 0 0 0xF0

From Stroustrup/Programming
98
Condiţiile si testarea lor
Compararea – Utilizarea de condiţii multiple
Condițiile sunt “legate” intre ele cu operatorii booleeni (logici):
&& AND (SI)
|| OR (SAU)
! NOT (complement/negare)
Argumentele si rezultatul poate fi doar TRUE (Adevărat) si FALSE
(Fals)
De fapt in limbajul C nu există tipul boolean sau conceptul de
variabilă booleană!
Se folosesc valori numerice, orice valoare diferită de 0 se evaluează
ca TRUE(adevarat), iar orice valoare = 0 se evaluează ca FALSE(fals)!

Astfel, if(a != 0) este de fapt același lucru cu if(a), dar este mult mai
lizibil ce se dorește!

Exemple de comparari:
if ((nVal > 0) && (nArea < 10))
if ((nVal < 3) || (nVal > 50))
if ( ! (nVal <= 10))
99
Condiţiile si testarea lor
Un exemplu in care se testează dacă, într-o
variabila, un singur bit este setat
- Se “șterg” (nedestructiv!) biții care nu ne interesează, se
testează dacă rezultatul este zero (FALSE) sau diferit de
zero (TRUE)

Verifică dacă bitul 7 al variabilei nVal, de tip char, este


setat:

if (nVal & 0x80){



}
100
Condiţiile si testarea lor
Un exemplu in care se testează dacă, într-o
variabila, oricare din biții doriti este setat:
– Se “șterg” biții care nu ne interesează, se testează
dacă rezultatul este zero

Verifică pentru variabila nVal, de tip char, dacă bitul 2 sau


bitul 3 este setat :
if (nVal & 0x0C) {

}

101
Condiţiile si testarea lor
Un exemplu in care se testează dacă, într-o
variabila, toţi biţii doriti sunt setaţi :
– Se “şterg” biţii care nu ne interesează, se
testează dacă rezultatul este identic cu masca

Verifică dacă biţii 2 si 3 sunt setaţi (egalitate cu


masca):

if ((nVal & 0x0C) == 0x0C) {



}
102
Controlul fluxului program (program
flow)
Este realizat cu instrucţiuni compuse si
constructori specifici
{
declaratii;
instructiuni;
}
Exemple:
if (n > 0) {
int count = 0, i;

}
103
Controlul fluxului program: constructori
Instructiunea If-Else
if (expresie)
instructiune1
else
instructiune2
Exemplu: Exemplu mai bun:
if (n > 0) if (n > 0) {
if (a > b) if (a > b)
z = a; z = a;
else else
z = b; z = b;
}
104
Controlul fluxului program: constructori
Stilul Else-If
if (expresie1)
instructiune1
else if (expresie2)
instructiune2
else if (expresie3)
instructiune3
else
instructiune4

105
Stilul Else-If

if (tasta== T1) PORTA=0x01;


else if (tasta== T2) PORTA=0x02;
else if (tasta== T3) PORTA=0x04;
else if (tasta== T4) PORTA=0x08;
else if (tasta== T5) PORTA=0x10;

T1 ..T5 sunt constante, tasta este o variabilă, PORTA este portul A


de la un AVR

Dacă prima expresie este evaluată adevărată celelalte linii nu se


mai execută, s.a.m.d
Else –ul final poate lipsi dacă in cazul in care toate evaluările sunt
false nu dorim să facem nimic altceva.
106
Controlul fluxului program: constructori
Instrucţiunea Switch
switch (expresie) {
case expr-const: instructiuni
case expr-const: instructiuni

default: instructiuni
}

107
Controlul fluxului program: switch
Exemplu Switch : numără spaţiile, caracterele “0” si “1”,
precum si restul caracterelor
- Contoarele (numărătoarele) , presupuse declarate si iniţializate anterior,
sunt: nspace (spatii), nbinary (“0” si “1”) si nother(restul).

switch (ch = getchar()) {


case ‘ ’: nspace++;
break;
case ‘0’:
case ‘1’: nbinary++;
break;
default: nother++;
}

108
Exemplu de Switch
switch (tasta){
case T1: PORTA=0x01;
break;
case T2: PORTA=0x02;
break;
case T3: PORTA=0x04;
break;
case T4: PORTA=0x08;
break;
case T5: PORTA=0x10;
break;
default:
}

Realizează același lucru ca exemplul de la else-if


109
Switch: o maşină secvenţială
//o masina secventiala cu 4 stari, switch-ul descrie tranzitia de stare
//tranzitia de stare nu depinde de intrari!!
typedef enum {STAREA1, STAREA2, STAREA3, STAREA4} stare;
stare stare_curenta; // definire variabila de stare

stare_curenta=STAREA1; //initializare stare




switch(stare_curenta) {
case STAREA1:
//..prelucrari aferente starii 1
stare_curenta =STAREA2;//starea urmatoare, tranzitia de stare
break;
case STAREA2:
//..prelucrari aferente starii 2...
stare_curenta =STAREA4;
break;
case STAREA3:
//..prelucrari aferente starii 3...
stare_curenta =STAREA1;
break;
case STAREA4:
//..prelucrari aferente starii 4..
stare_curenta =STAREA3;
break;
default:
break;
} 110
Controlul fluxului program:
constructori, while
Bucle While
while (expresie)
instructiune

Atâta timp cât expresie este adevărată se execută instrucțiunea sau blocul
de instrucțiuni
Expresia este evaluată înainte de instrucțiune, astfel încât dacă ea este
falsă instrucțiunea nu se va executa (niciodată)

Exemplu:
i = 0, count = 0;
while (i < N) {
if (X[i++] > 0)
count++;
}

//in programarea SI mai intalnim si bucle fara sfarsit


while (1) {
bla_bla();
}
111
Controlul fluxului program:
constructori, do-while
Bucle Do-While
do
instructiune
while (expresie)

Atâta timp cât expresie este adevărată se execută


instrucțiunea (sau blocul de instrucţiuni)
Dar expresia este evaluată după execuția instrucțiunii,
astfel încât dacă ea este falsă instrucțiunea se va
executa (cel puțin odată)

Exemplu:
i = 0, count = 0;
do {
if (X[i] > 0)
count ++;
} while (++i < N); 112
Controlul fluxului program:
constructori, for
Bucle For

for (expr1; expr2; expr3)


instructiune

Un constructor echivalent ar fi:


expr1; //initializare
while (expr2) { //expresie conditionala
instructiune
expr3; //controlul buclarii
}

Exemplu:
//in programarea SI intalnim bucle fara sfarsit
for ( ;; ) bla_bla(); //
113
Controlul fluxului program:
constructori, break, continue
Break: Ieşire imediată din buclă sau din switch
Continue: Începe următoarea iteraţie imediat

/* “sarim” peste valorile nule si ne oprim


daca intalnim valori negative */
for (i = 0; i < N; i ++) {
if (X[i] == 0)
continue;
if (X[i] < 0)
break;
… /* prelucreaza datele X[i] */
}
114
Controlul fluxului program:
constructori, goto
Etichetele(labels) si instrucţiunea Goto (din păcate ea există
si in ANSI C!)
Trebuie utilizate foarte rar sau si mai bine niciodată!
Orice standard decent de codare C interzice utilizarea lor
Exemplu(unde state_i: sunt etichetele):
state_0:
if ((ch = getchar()) == ‘a’)
goto state_1;
else
goto state_2;
state_1:

state_2:

115
Controlul fluxului program
O greșeală comună cu efecte interesante, ce se va întâmpla daca
scriem :

if (x = 0)
{

}

In loc de

if (x == 0);
{

}

Poate explicați si de ce …
116
Programarea in C pentru
sisteme incorporate
Memoria de date, funcţiile si stiva,
funcţii si biblioteci

117
Utilizarea memoriei
Secţiunile tipice ale memoriei din punct de vedere al
programului sunt (denumirile pot diferi):
– Cod(program, code): aici sunt memorate instrucţiunile (binare)
pentru toate funcţiile
– Date statice (static data): aici sunt memorate datele care sunt
accesibile tuturor funcţiilor (alocarea este făcută o singură data
si rămâne valabilă pe toată durata execuţiei)
– Stiva (stack): aici se memorează informaţia din timpul execuţiei,
care este proprie fiecărei funcţii
– Zona de alocare dinamică (Heap): aici se află un spaţiu de
memorie care se alocă dinamic (in cursul execuţiei programului,
când e nevoie de el), spaţiu de memorie neorganizat pus la
dispoziţia programului; tipic se alocă cu malloc ( ) si se de-
alocă (eliberează) cu free ( );
– Intrări/ieșiri (I/O): adresele dispozitivelor I/O (pentru
microprocesoarele cu spațiu de adrese unificat), aici de fapt nu e
memorat nimic
118
Utilizarea memoriei
Adrese superioare
static char[] greeting
Adrese I/O
=“Hello world!”;
Stiva
main() (creste in jos)
{ Aici se pot
“întâlni”!!
int i; Si nu este bine!
char bVal; Heap (creste in sus)

Date Statice
LCD_init();
LCD_PutString(greeting);

} Cod

Cat se poate aloca/utiliza din RAM depinde Adrese inferioare


de MPU/MCU si de hardware-ul aferent SI: pot fi 119
x10kocteti..x10MOcteti sau doar x10..x100 octeţi
“Vizibilitatea” variabilelor si
memorarea (alocarea) lor
Datele (variabilele) globale (deși in C nu exista cuvântul
cheie global !):
– Declarate in afara funcţiilor C
– Vizibile pentru toate funcţiile C, de tot “programul”!
– Ocupă permanent un loc in memorie, in segmentul de date
– Reprezintă o modalitatea utilizata extensiv de a transfera
informație intre secțiuni de cod care nu se afla in relația
apelat/apelant
• De aici pot apărea unele probleme legate de partajarea lor, de
protecție a accesului prin excluziune; ce se întâmpla atunci când o
secțiune de cod scrie in ea si o alta citește din ea?
– Utilizarea lor in exces poate epuiza încet dar sigur memoria
RAM disponibilă (mai ales pentru un sistem cu resurse de
memorie RAM modeste)

120
“Vizibilitatea” variabilelor si
memorarea lor
Variabile cu alocare statică (există cuvântul cheie static)
– Spaţiu de memorare alocat permanent in secţiunile de date statice, prin
contrast cu variabilele “automate” alocate in stiva de apelare si cu cele
alocate dinamic in heap
– Este ocupat odată cu încărcarea programului executabil in memorie, in
zona de date (statice) sau in segmentul numit .BSS (pentru unele
compilatoare parte a segmentului de date, inițializat cu 0)
– Durata lor de viaţă este de la începutul execuţiei programului pană la
sfârşitul execuţiei
– Pot exista variabile statice globale, “vizibile” de întreg programul sau
variabile static locale, “vizibile” doar la nivelul unei funcții
– O variabilă declarată static in afara funcțiilor C, este vizibilă doar la
nivelul unității de compilare (a fișierului .c respectiv)
– Dacă însă vrem ca ea să fie vizibilă la nivelul tuturor unităților de
compilare, ea trebuie declarată cu atributul extern
– Utilizarea lor in exces poate epuiza încet dar sigur memoria RAM
disponibilă (mai ales pentru un sistem cu resurse de memorie RAM
modeste)

121
“Vizibilitatea” variabilelor si memorarea lor

Variabile in stivă(stive):
– Variabilele locale pentru o funcție sunt memorate intr-
o stivă proprie funcției
– Ele sunt declarate in interiorul unei funcții si sunt
vizibile doar in interiorul acestei funcții
– Ele sunt alocate si respectiv de-alocate de fiecare
dată când o funcţie este apelată
– Durata lor de viață este de la alocare pană la de-
alocare (când nu mai este nevoie de ele, până când
se iese din funcția respectiva), dacă nu cumva li s-a
dat atributul static
122
“Vizibilitatea” variabilelor si memorarea lor

Unde este variabila “vizibilă”, care este


domeniul ei de vizibilitate? (variable
scope)

int m; //m global

int any_func()
{
int m; //m local, sunt variabile diferite!
m = n = 5;
}
123
“Vizibilitatea” variabilelor si memorarea lor

Avem variabile C globale (vizibile pentru toate fișierele programului):

int global_var;

Avem variabile C statice la nivel de fişier (vizibile doar in fişierul-


unitatea de compilare- unde au fost declarate):

static int static_var;

Avem variabile locale statice:

any_func()
{
static int static_var;

}

124
“Vizibilitatea” variabilelor si memorarea lor

Cum să definim si să utilizăm variabilele globale?

In fişierul header myvar.h :

extern int global_var;//vazuta din toate fiserele

In fişierul care conţine programul myvar.c :

#include “myvar.h”
int global_var;
… /* utilizare myvar */

125
O paranteză: fişierele header
• Reprezintă un loc convenabil in care putem să
grupăm cam tot ce ar apărea sau ar trebui
declarat înaintea funcţiei main ();
• Au sufixul .h si includerea lor de către pre-
procesor se face cu directive:
#include <antet1.h>
#include “antet2.h”
• Dacă declaraţia este de forma <..> pre-procesorul îl caută intr-o
locaţie pre definită, tipic un director numit ../include
• Dacă declaraţia este de forma “ ..” pre-procesorul îl caută in
directorul in care se găseşte fişierul sursă propriu-zis (.c)

126
const, volatile si register
• const si volatile nu sunt tipuri, ci mai degrabă calificatori
pentru un tip
• Nu există nici o legătură intre ele
• Pot fi adăugate oricărei declaraţii

volatile float i;

volatile int j;

const long q;

const volatile unsigned long int rt_clk;

struct{
const int li;
unsigned char sc; }
volatile vs; 127
const, volatile si register
• const înseamnă ceva care nu poate fi modificat,
astfel încât, o dată care este declarată cu acest
calificator pentru tipul său, nu îi poate fi atribuită
o valoare (cu excepția inițializării) pe durata
execuției unui program.
• Principalul motiv pentru utilizarea datelor având
acest calificator este ca ele să fie memorate in
memoria de tip ROM (împreună cu codul
programului) si să permită compilatorului să facă
si verificări de consistență suplimentare ale
programului (să verifice că nu este o L-valoare!)
128
const, volatile si register
• Principalul motiv pentru care exista calificatorul volatile are legătura cu
programarea sistemelor incorporate si programarea de timp real
• El este utilizat in faza de optimizare a programului de către compilator
• El ii spune compilatorului că data calificată astfel poate fi obiectul unor
modificări care nu pot fi prezise doar din analiza codului programului,
forţând ca orice referinţă la această dată să fie una adevărată
• Cu alte cuvinte, in urma optimizării, suportul real al acestei date (locații de
memorie sau registre) nu trebuie să “dispară” ca rezultat al optimizării in
sensul minimizării volumului de memorie de date utilizat

void wait (void)


{
asm volatile ("nop"::); /*in urma optimizarii codul
corespunzator instructiunii nop ar fi fost eliminat, pt
ca aparent nu face nimic util*/
}

129
const, volatile si register
In mod normal compilatorul este cel care determină care anume date (variabile)
trebui să fie memorate in registrele CPU si nu in memoria RAM, intr-un
anumit moment al execuţiei programului.
In limbajul C există calificatorul register astfel incat programatorul să poată
“sugera” compilatorului ca pentru anumite variabile ar trebui să aloce
registre ale CPU, nu memorie, dacă este posibil
Astfel variabilele calificate cu register permit, intr-o anumită măsură, controlul
eficienţei execuţiei unui program.
Variabilele care sunt utilizate in mod repetat sau pentru care timpul de
acces mic este critic sunt candidate naturale pentru acest calificator.

#include <stdio.h>
main() {
register int i = 0;
for( i = 0; i < 2; i++) {
printf("i = %d\n",i);
}
}
130
Cum este “ocupată” memoria de date
(variabile)
Dacă “memoria” este o colecţie de octeţi adresabili, cum
anume sunt memorate variabilele care au mai mult de 1
octet?

Este o problemă de aliniere: o variabilă scalară de n


octeţi trebuie să fie aliniată la o graniţă de n-octeţi

Exemple:
char: nici o restricţie deoarece are doar 1 octet
short: graniţe de 2 octeţi (adrese pare)
float: graniţe de 4 octeţi (adrese pare divizibile cu 4)

131
Cum este “ocupată” memoria de date
(variabile)
Exemplu:
Care este adresa fiecărei variabile din cele de mai
jos?
Să presupunem că prima variabila / tabloul a
începe la adresa 0x20000000 (o adresă de 32
de biţi).
char a[5];
short b;
int d;
double e;
short f;
char *g;

132
Cum este “ocupată” memoria de date
(variabile)?
Ordonarea octeților pentru o anumită arhitectură de
calcul (endianess): Big-endian vs. Little-endian

– Big-endian: Octetul 0 (de la cea mai mică adresă) al unei


variabile de n- octeți este cel mai semnificativ: Most
Significant Byte (MSB)

– Little-endian: Octetul 0 (de la cea mai mică adresă) al unei


variabile de n-octeti este cel mai puţin semnificativ:
Least Significant Byte (LSB)

Arhitectura CPU Power PC si AVR 32 biți sunt nativ Big-


endian, arhitectura Intel 80x86 este Little –endian la fel
si AVR 8 biți

133
134
Cum este “ocupată” memoria de
date (variabile): endianess
Un număr pe 32-biti 0xDEADBEEF adică 4 octeți (bytes) poate fi:
MSB LSB

Big Endian: MSB (partea mare a


numărului..) este memorat la cea mai
mică adresă +0, adresă care devine și
adresa structurii multi-octet

Little Endian: LSB (partea mică a


numărului…) este memorat la cea mai mică
adresă +0, adresă care devine și adresa
structurii multi-octet

135
Cum este “ocupată” memoria de date
(variabile)
Care sunt valorile memorate in variabila string
pentru cele două modalităti de reprezentare?

static char string[8];


* (int*) string = 0x41424344;
string[4] = ‘\0’;

Codul ASCII 0x41 este pentru litera ‘A’.


136
Cum este “ocupată” memoria de date
(variabile)- big endian
Adresa Conținut memorie
+0 +1 +2 +3 +4 +5 +6 +7
30001FF8 25 24 5B 1A AC 57 9C 8D
30002000 00 FE 25 24 5B 1A EE 05
30002008 AC AE 81 83 45 67 89 25
30002010 01 23 55 3F AC CB F0 8D

Care este dispunerea, alinierea si conținutul variabilelor pentru un MPU Power


PC (magistrala sa de adrese are 32 de biti)?
char a[5]; // char 1 octet
short b; // short are 16 de biti-2 octeti (Power PC)
int d; // int are 32 de biti-4 octeti pt Power PC
double e; //are 8 octeti
short f;
char *g; //pointer la char, adresa are 32 de biti-4
octeti
137
Cum este “ocupată” memoria de date
(variabile)- little endian
Adresa Conținut memorie
+0 +1 +2 +3 +4 +5 +6 +7
30001FF8 57 AC 1A 5B 24 25 8D 9C
30002000 24 25 FE 00 05 EE 1A 5B
30002008 25 89 67 45 83 81 AE AC
30002010 23 01 3F 55 8D F0 CB AC

Care este dispunerea, alinierea si conținutul variabilelor pentru un MPU ARM


sau 80x86 (magistrala sa de adrese are 32 de biti)?
char a[5]; // char 1 octet
short b; // short are 16 de biti-2 octeti (Power PC)
int d; // int are 32 de biti-4 octeti pt Power PC
double e; //are 8 octeti
short f;
char *g; //pointer la char, adresa are 32 de biti-4
octeti
138
Cum este “ocupată” memoria de date
(variabile)
Care este dimensiunea următoarei structuri?
– Fiecare componentă trebuie să fie aliniată
– Dimensiunea totală trebuie să fie un multiplu de 8

struct mystruct {
int a;
short b;
double c;
char d;
}

139
Funcţii si stivă
Stiva (Stack): este structură de tip LIFO (Last-in, First-out), ultimul
intrat, primul ieşit
– Vârful si baza sunt utilizate pentru a determina cum este folosită
– Operație de tip Push (împinge): se adaugă/se scrie un element in vârf si
se actualizează vârful
– Operaţie de tip Pop (extrage): se înlătură/ se citeste un element din vârf
si se actualizează vârful

Poate implementată fizic cu ajutorul unei memorii de tip RAM static


sau al unui set de registre

Este esențială pentru a se putea implementa un limbaj procedural:


face posibil apelul de proceduri/funcții, si întoarcerea din
proceduri/funcții, cu salvarea si restaurarea corespunzătoare a
cadrului/contextului de execuție (cel putin a adresei de
intoarcere )

Aceasta salvare a cadrului/contextului de execuție reprezintă un


efort suplimentar ca timp de execuție a programului (scrieri si
citiri in/din stivă) si ca spațiu de memorie SRAM necesar
(pentru stiva propriu-zisă)
140
Funcţii si stivă

Stiva convenţională creşte in jos


Adrese superioare

Vârful stivei
- indicatorul Creştere stiva
de stiva (SP)

Adrese inferioare

Exista si rare exemple de


arhitecturi de calcul la care stiva 141
creste in sus (ex. 8051)
Funcţii si stivă
Cadrul/contextul de execuţie (execution
framework) al unei funcţii: alocarea si de-
alocarea locală de memorie pentru o
funcţie
Exemplu: 1. A este apelată; 2. A apelează pe B; 3.
B apelează pe C; 4. ne întoarcem din C

Cu fiecare apel succesiv, stiva crește in jos, ocupând din ce in ce mai multa142
memorie!
Funcţii si stivă
De ce se utilizeaza o stivă?
– Organizarea de tip LIFO se potriveşte
perfect cu ordinea de apelare a funcţiilor si
întoarcerea din funcţie
– Permite o alocare/de-alocare automată
eficientă si comodă a memoriei

143
Funcţii si stivă
Determinarea dimensiunii cadrului de execuție a unei funcții
– Fiecare variabilă este aliniată
– Fiecare cadru trebuie să fie aliniat la o graniță de 8 octeți
Exemplu: Care este dimensiunea cadrului? ( Se vor adăuga 8 octeți pentru
adresa de întoarcere si identificare cadrului la editarea de legături – pt. link-
editor)

int myfunc()
{
char byVal;
long lVal;
char szName[10];
… /* instructiunile incep aici */
}

De ce ne-ar interesa: pentru ca ne spune câtă memorie se alocă si este necesară la


fiecare apel al funcției
La unele aplicații dimensiunea RAM-ului disponibil este limitată si s-ar putea să se
termine repede!
Un MPU de 32 biti poate avea si x 100 MOcteti de (SD)RAM
Un AVR ATMega 32 are 2048 octeţi (2kOcteti) de (S)RAM
Un AVR ATtiny 2313 are doar 128 octeţi de (S)RAM
Un ATtiny15 nu are de loc (S)RAM, doar cele 32 de registre!
144
Funcţii si stivă: apelul recursiv
• In principiu apelul recursiv al unei funcții este posibil
in limbajul C:
void functie_recursiva (int data)
{ int alta_data;
// facem cate ceva aici cu alta_data
functie_recursiva (alta_data)
//mai facem si altceva in continuare
}

Este un exemplu in care dimensiunea RAM-ului alocat si a stivei, creste la


fiecare apel de funcție, poate să ne scape repede de sub control cu
consecințe neprevăzute!

In concluzie încercați să NU folosiți apelul recursiv, mai ales când


programați pentru un microcontroler de 8/16 biţi, cu resurse relativ
limitate de memorie de date!

145
Funcţii si stivă: recursiv si re-
entrant
• Ideea de “re-entranţă“ (reentrancy), termen cam forţat in limba română,
pentru o funcţie apare atunci când o funcţie este apelată înainte ca să fi
avut loc întoarcerea din invocarea(apelarea) precedentă
• Există trei motive pentru care aceasta se poate întâmpla:
– Apelul recursiv: funcția se apelează pe ea însăşi
– Utilizarea programării concurente (multi-fir, multi-threading): mai multe “fire” de
execuție apelează aceiași funcţie
– Întreruperile: funcția este întreruptă de o cerere de întrerupere, fiind apoi apelată
din nou in rutina de tratare a întreruperii
• Cazul cel mai simplu este cel al apelului recursiv, deoarece aici este clar
unde/când se va re-intra in funcție, sincron cu evoluția programului
• Cazul programării concurente si al utilizării întreruperilor este mai complicat,
deoarece aici procesul de re-intrare in funcție are loc asincron cu evoluția
programului.
• In mod tipic aceste funcții nu trebuie să modifice date (variabile) globale
– Citirea variabilelor globale este posibilă
– Scrierea lor va fi posibilă numai dacă există si un mecanism adecvat de
protecție al secțiunilor critice ( dezactivare întreruperi, excluziune prin
semafoare, mutex,, etc.).

146
Funcţii si stivă
Pointeri de/la funcții: Cum funcționează?
– O funcție este translatată/tradusă (prin compilare,
asamblare) intr-un bloc de instrucțiuni mașină
care va fi memorat undeva in memorie
– Apelarea funcției presupune transferul controlului
programului la adresa de început a acestui bloc
memorat
• La nivel hardware asta presupune aducerea acestei valori de
adresa intr-un numărător de program (PC)
• In limbaj de asamblare asta înseamnă execuţia unei
instrucțiuni de salt (ramificare) la această adresă
– O variabilă de tip pointer de/la funcție memorează
de fapt adresa de început a acestui bloc de
instrucțiuni
147
Pointeri de(la) funcţii (function
pointers)
Pointeri de funcţii: exemplu de declarare si utilizare

int average(int x, int y)


{

}
….

int main()
{
int (*pFunc)(int x, int y) = average; /*aici se
declara pointerul la functia average*/

int a = (*pFunc) (10, 20);/*aici functia este


apelata, cu parametrii actuali 10 si 20*/
}

148
Pointeri de(la) funcții: declararea
corectă
• Să presupunem că avem o funcţie care returnează un int si
pentru care vrem să definim/utilizăm un pointer pentru ea:
int func(int a, char b);

• Din cauza precedentei operatorilor, dacă numele funcţiei nu


este pus in paranteze se va declara de fapt o funcţie care
returnează un pointer la un int !

/* aceasta este o functie care returneaza un


pointer la int */
int *func(int a, char b);

/* acesta este un pointer la o functie care


returneaza un int */
int (*func)(int a, char b);
149
Pointeri de(la) funcţii
• Una din aplicațiile interesante din punct de vedere al SI
este utilizarea unui pointer de funcție pentru alegerea
dinamică (contextuală) a unei funcții care trebuie să se
execute la un moment dat, ținând cont de apariția unor
evenimente externe
– Cu alte cuvinte atunci când de fapt nu știm a-priori care anume
funcție, dintr-un set de funcții, se va executa (trebuie sa se
execute) intr-un anume punct al programului !
• O astfel de aplicație tipică este la realizarea /
implementarea software a unor mașini secvențiale
• Un astfel de exemplu de mașină secvențială (in contextul
AVR 8 biți) găsim in codul sistemului de dezvoltare AVR
Butterfly, fiind utilizată la controlul meniurilor de afișare
prin intermediul joystick-ului
(http://www.atmel.com/tools/AVRBUTTERFLY.aspx)
150
Biblioteci de funcţii in C
In limbajul C foarte multe lucruri utile sunt realizate de
funcții care sunt conținute si grupate in
biblioteci(libraries) de funcții
– C este un limbaj simplu, dar tipic implementările lui au si
biblioteci bogate!
Biblioteci utilizate in mod obișnuit:
– Intrare/ieşire fișiere - File I/O (nu este vorba numai de
fișiere propriu-zise, ele includ intrările/ieşirile utilizator)
– Manipulare șiruri (strings)
– Funcții matematice in virgula fixa, funcții matematice in
virgula mobila
– Gestiunea proceselor
– Suport pentru periferice, pentru rețea, etc
Biblioteci utilizate se declara cu ajutorul unor
directive de tip #include
151
Biblioteci de funcţii in C, exemple (ANSI
C)
Fişiere de intrare/ieşire (standard file I/O):

/* incluziune fisier header pentru


biblioteca I/O */
#include <stdio.h>
main()
{
/* utilizarea functiei fprintf */
fprintf(stdout, “%s\n”, “Hello World\n”);
}

152
Biblioteci de funcţii in C, exemple (ANSI
C)
Formatarea ieşirii utilizator: printf, fprintf, sprintf si altele; utilizează
specificatori de conversie (format) cum ar fi:
%s şir
%d zecimal cu semn
%u zecimal fără semn
%x hexazecimal
%f virgulă mobilă (float sau double)

Cum “tipărim” următoarele variabile in formatul


“a = …, b =…, c = …, str = …” pe o singură linie?

int a;
float b;
int *c;
char str[10];
153
Biblioteci de funcţii in C, exemple (ANSI
C)

Formatarea intrării utilizator: scanf, fscanf, sscanf si altele


– Se folosesc specificatori de format (conversie) similari cu cei
pentru familia printf

Cum să “citim” (cu scanf) următoarele variabile in formatul


“a = …, b =…, c = …, str = …” intr-o singură linie?

int a, b;
float c;
char str[10];

154
Biblioteci de funcţii in C (ANSI C)
• Atenție la funcțiile clasice de intrare/ ieșire de/la “consola”:
printf, scanf, cin, cout, etc.
• De cele mai multe ori pentru un SI sau un MCU “consola/tastatura”
utilizator este de fapt un port serial (de natura unui UART) asincron:
– Printf sau cout “scrie”, adică trimite/emite caractere (sau octeți) printr-un
port serial nu la consola
– Scanf sau cin “citeşte” ce se primeşte/recepţionează (sau octeți) pe un
port serial, nu de la o tastatura
– Portul serial utilizat (adica perifericul de tip UART- Universal
Asynchronous Receiver Transmitter) mai trebuie si configurat/programat
inainte de utilizare: viteza de comunicaţie, număr de biţi de date,
paritate, etc.

• De foarte multe ori , pentru un MPU/MCU “mic” de 8/16 biți, este


mult mai avantajos să ne scriem propriile funcţii echivalente,
mai simple, de I/O (emisie/recepție caractere/octeți, echivalentul
lui cin sau cout): dimensiunea codului generat va fi mai mică si
se va executa mai repede
155
Biblioteci de funcţii in C (ANSI C)
Operaţii tipice cu şiruri de caractere: copiere,
comparare, analiza conţinut si altele

#include <string.h>
– strcpy: copiază un şir intr-altul
– strcmp: compară două şiruri (ce înseamnă a
compara 2 şiruri? ‘ABC’ cu ‘abc’ ?)
– strlen: calculează lungimea unui şir
– strstr: caută intr-un şir existenta unui alt sir (sub-
şir)

156
Strlen (din K&R)
int strLen(char s[])
{int i;
i = 0;
while(s[i] != '\0')
++i;
return i
}
Un şir este un tablou de caractere care se termină implicit cu caracterul
‘\0’ adică cu 0x00 (terminator şir); acest caracter ‘\0’ poate fi utilizat
pentru identificarea sfârșitului unui şir cu lungimea necunoscută
apriori

Funcția strlen returnează lungimea șirului (numărul de caractere) fără a


include in acest numar si terminatorul de şir

157
Biblioteci de funcţii in C (ANSI C)
Prelucrarea erorilor si raportarea lor: utilizarea funcţiei exit
#include <stdio.h>
#include <stdlib.h>
int main ()
{
...
void myfunc(int x)
{
if (x < 0) {
fprintf(stderr, “%s\n”,
“x este in afara domeniului”);
exit(-1);
}
}

}

Provoacă terminarea imediată a programului, valoarea este returnată lui main


(procesului)

Un program de tip SI nu ar trebui să se termine niciodată așa!


Un program main () de tip SI nu ar trebui să ajungă niciodată la instructiunea return () !
158
Biblioteci de funcţii in C, exemple (ANSI C)

Funcţii matematice (tipic in virgula mobilă):

#include <math.h>

n = round (x); /* functie de rotunjire a
rezultatului in virgula mobila */

Atunci când veţi utiliza compilatorul WinAVR, veţi
utiliza si cel puţin una una din bibliotecile
specifice numită AVR libc care conţine practic
toate funcţiile destinate acestei familii de
microcontrolere
159
Standarde pentru scrierea codului C
• Un standard pentru scrierea codului (coding standard)
este un set de reguli care ne spune cum ar trebui să arate si
să fie scris acel cod intr-un limbaj specific (C in cazul nostru)
– Tipic specifică reguli pentru denumiri si pentru indentarea textului
(decalarea textului la dreapta sau la stânga)
• Ex. Se utilizează numai macheta (layout-ul) “Stroustrup”
– Tipic specifică un subset (mai restrictiv) al limbajului
• Ex. Nu se vor utiliza funcţiile new si throw pentru a evita
problemele de predictibilitate
– Tipic specifică reguli pentru comentarii
• Fiecare funcție trebuie să aibă un comentariu in care se explică de
face
– Adesea impun utilizarea unor anumite biblioteci
• Ex., se utilizează <iostream.h> si NU <stdio.h>
• La nivel de organizație deseori se încearcă să se gestioneze
complexitatea prin utilizarea unor astfel de standarde
– Nu doar aceste standarde pot rezolva problema, uneori ele creează
mai multă complexitate decât sunt in stare să gestioneze
160
From Stroustrup/Programming
Standarde pentru scrierea codului
• Existența unui standard bun pentru scrierea codului este mai bună
decât absența lui
– Un proiect industrial de anvergură (cu mai mulți programatori, pe mai mulți
ani) este de neconceput fără existenta/utilizarea unor astfel de standarde
• Un standard prost de scriere a codului poate fi mai rău decât absența
unui standard
– Un standard pentru C++ care restrânge programarea in acest limbaj la
ceva ce seamănă cu un subset al C-ului, face mai mult rău decât bine
– Din păcate există exemple in acest sens!
• Programatorii nu iubesc nici un standard de scriere a codului, cei
care o să utilizeze acest cod au însă altă părere!
– Chiar si cei mai buni!
– Toți programatorii vor să scrie cod exact in propriul lor stil
• Un standard bun este in același timp si prescriptiv si restrictiv:
– “Așa se face bine acest lucru, se recomandă, aceasta e o regulă de bună
practică”
– “Este interzis să…””
• Un standard bun are justificări pentru reguli
– Precum si exemple!

161
From Stroustrup/Programming
Standarde pentru scrierea codului

• Scopurile comune ale acestor standarde


doresc ca să se obțină pentru codul produs:
– Fiabilitate si robustețe
– Testabilitate
– Lizibilitate (ușor de citit si înțeles)
– Mentenabilitate (ușor de întreținut )
– Portabilitate
– Reutilizare
– Extensibilitate, scalabilitate

From Stroustrup/Programming

162
Câteva reguli simple
• Nici o funcție nu trebuie să aibă mai mult de 300 de linii (poate
limita de 30 ar fi si mai bună..)
– Asta ar înseamnă cam 200 de linii (fără comentarii)
• Fiecare nouă instrucțiune trebuie sa inceapa pe o linie nouă
– Ex. int a = 7; x = a+7; f(x,9); // gresit!
• Nu utilizați macroinstrucțiuni decât pentru controlul surselor
– utilizarea #ifdef si #ifndef
• Identificatorii trebuie să aibă nume descriptive
– Pot conține abrevieri comune si acronime
– Atunci când sunt folosite in mod convențional, nume ca x, y, i, j, etc.,
sunt descriptive!
– Utilizați stilul de scriere numar_de_elemente mai degrabă decât stilul
numarDeElemente
– Numele de tipuri si constantele trebuie să înceapă cu litera MARE
• Ex., Device_driver si Pi
– Identificatorii nu trebuie să difere doar prin tipul de literă (mică/MARE)
• Ex., Head si head // gresit!!
From Stroustrup/Programming 163
Alte câteva reguli simple
• Identificatori cu un domeniu de vizibilitate internă (in jos) nu trebuie
să fie identici cu cei cu un domeniu de vizibilitate externă (in sus)
– Ex. int var = 9; { int var = 7; ++var; }/* gresit: var il poate ascunde pe var
*/
• Declarațiile trebuie făcute cu cel mai mic domeniu de vizibilitate
posibil
• Toate variabilele trebuie inițializate
– Ex. int var; // nu e bine: var nu este initializata
• Conversia de tip (typecast) trebuie folosită doar acolo unde este
esențială
• Codul nu trebuie să depindă de regulile de precedență, cu excepția
celui din expresiile aritmetice
E.g. x = a*b+c; // ok
if( a<b || c<=d) // gresit: trebuie paranteze pt (a<b) si (c<=d)
• Incrementarea si decrementarea nu trebuie folosite ca sub-expresii
– Ex., int x = v[++i]; // gresit ( incrementul poate sa nu aiba loc)

Stroustrup/Programming
164
Exemple de standarde pentru limbajul C:
MISRA C

• MISRA C este un standard pentru dezvoltarea aplicaţiilor scrise in


limbajul C, propus si realizat de MISRA (Motor Industry Software
Reliability Association).
• Scopul lui a fost de a îmbunătăţii fiabilitatea, portabilitatea si
securitatea codului in contextul sistemelor incorporate (embedded
systems) , in mod specific a acelor programate in ANSI/ISO C.
• Prima ediţie a standardului MISRA C, "Guidelines for the use of the C
language in vehicle based software", datează din 1998 si este
cunoscută ca MISRA-C:1998
• In 2004, a apărut o a doua ediţie "Guidelines for the use of the C
language in critical systems", sau MISRA-C:2004 cu multe modificări
substanţiale, inclusiv o renumerotare completă a regulilor
• Pe 18 Martie 2013, a fost anunţată varianta MISRA C:2012, cu
accentul pus din nou pe utilizarea sigură a codului C pentru toate
sistemele critice (critical systems), nu numai cele din industria
automobilului
Exemple de standarde pentru limbajul C:
MISRA C
• Exista multe unelte software care verifică pentru un cod produs
“conformitatea cu MISRA”, deşi nu există un proces de aşa zisa
certificare MISRA
• Marea majoritate a regulilor poate fi verificată cu unelte de analiză
statică a codului (static code analysis), fără să fie nevoie ca să se
execute codul, iar restul regulilor cu unelte de analiză dinamică a
codului (dynamic code analysis), care presupun si execuţia codului
– http://en.wikipedia.org/wiki/MISRA_C
• OBS. ISO/ANSI C este o familie de standarde succesive (publicate
de ANSI- American National Standards Institute si apoi adoptate de
ISO-International Organization for Standardization) utilizate pentru
definirea limbajului C, având ca scop, printre altele si îmbunătăţirea
portabilităţii codului intre diverse compilatoare C.
– Variantele generice sunt cunoscute ca C89, C90, C99 si actualmente
C11 (cifrele codifica anul adoptării)

Dacă va interesează subiectul puteți (încă) găsi gratis o copie a MISRA C


2004:
http://caxapa.ru/thumbs/468328/misra-c-2004.pdf
Despre statutul acestei copii vă las să-l găsiți singuri…☺
Microcontrolere (si
microprocesoare)
(Re)Introducere in arhitectura sistemelor de
calcul; microcontrolere, microprocesoare;
sisteme incorporate

1
• Mai întâi câteva cuvinte (o recapitulare)
despre arhitectura sistemelor de
calcul (computere, calculatoare) sau
arhitecturi de calcul
• Recapitularea are ca scop si o
stabilire a terminologiei specifice
(inclusiv cea in limba engleză,
esențială!)
• Apoi pe scurt despre microprocesoare
si microcontrolere
• Si sisteme incorporate..
2
Imaginea in mare a unui sistem de
calcul, a rămas aceiași de mult timp…

Unitate Centrală (CPU)


Intrări (I)
Control
Memorie “Lumea
Calcul
Externă”

Ieşiri (O)
Căi de date

Din 1946 la toate sistemele de calcul se


regăsesc aceste componente mari!!! 3
Arhitectura: funcţii si structură

• Ce înseamnă aici arhitectură?


Funcţii + Structură
– Funcţii funcţionarea componentelor
individuale ca părți ale unei ansamblu
– Structură cum aceste componente
sunt legate una de cealaltă

4
Funcţii
• TOATE funcţiile unui sistem de calcul
sunt:
– PRELUCARE (PROCESSING) Date =
Informaţie
– MEMORARE
– DEPLASARE(MUTARE)
Coordonează cum
– CONTROL anume este
utilizată informaţia

• NIMIC ALTCEVA!
5
Structura – Cutia neagra
Periferice este..
Sistem de
calcul

Intrări
Sistem de Ieşiri (I/O)
calcul Unitate centrala
(CPU)
Sisteme de
Înăuntru
interconectare
avem alte cutii negre! (magistrala
sistem)
Linii de comunicaţie
cu lumea externa Memorie

Cum
funcţionează?
6
Structura – unitatea centrala (CPU)

CPU

Sistem de Unitate
calcul Registre Aritmetica-
I/O
Logica
Magistrala CPU (ALU)
Sistem
Interconexiuni
Memorie interne CPU
(magistrale interne)

Unitate de
Control
Cum
funcţionează?
Se poate merge
si mai jos! 7
Structura – Unitatea de control
Unitate de control

Deja asta nu ne Logica


CPU
mai interesează secvenţiala
ALU aici! - automate
Bus Unitate
Intern Control
Registre interne
Registre si logica de
decodificare

Automate
control
memorie
Cum
funcţionează?
8
Cum funcționează ?
Unitate centrala (CPU)
Memorie Unitate de Control
(principală) 1
Preia (Fetch) Decodifică
2 Ciclu
R Instrucţiune
cpu
E
Încarcă (Load)
G
I
RAM/ROM S
T Ciclu
Execuţie
R Memorează (Store)
E 3 Execută
4

Unitate Aritmetică si Logică

9
Execuția unei instrucțiuni

• Înainte de a executa instrucțiuni, instrucțiunile programului si


datele de prelucrat trebuie plasate in memorie (numită generic
memoria principala) fiind aduse de la un dispozitiv de intrare sau
transferate dintr-o memorie externă auxiliară, procesul putând fi in
realitate mai complicat
• Odată ce datele si instrucțiunile sunt in memorie, unitatea centrală
realizează (in mare si simplist) următoarele operații:
– Unitatea de control preia (fetch) instrucțiunea din memorie.
– Unitatea de control decodifică instrucțiunea (decide ce înseamnă ea)
si dirijează datele necesare încărcate (load) din memorie si/sau
registre către unitatea aritmetică-logică (ALU); aceste două prime
etape alcătuiesc faza instrucțiune care are asociat un timp
instrucțiune
– Unitatea aritmetică –logica are controlul si execută operațiile
aritmetice si logice asupra datelor
– Unitatea aritmetică-logica memorează(store) rezultatul operațiilor in
memorie si/sau registre; ultimele doua etape alcătuiesc faza
execuție si au asociat un timp de execuție
10
Execuția unei instrucțiuni -2

• Unitatea de control dirijează eventual transferul


rezultatelor către un dispozitiv de ieșire sau către o
memorie externă auxiliară; combinația intre faza/timpul de
instrucțiune si cel de execuție alcătuiesc un ciclu
(perioadă) mașină cu un timp asociat
• Orice unitate centrală are un ceas intern care este utilizat
pentru sincronizarea oricărei operații interne si pe baza lui
se definește durata unui ciclu mașină si a componentelor
lui
– Toate microprocesoarele si microcontrolerele moderne
utilizează in sistemul de ceas bucle cu calare de faza (PLL)
sau de frecventa (FLL) pentru multiplicarea/divizarea frecvenței
unui oscilator de baza
• O unitate centrală este proiectată să “înțeleagă” un anume
grup specific de instrucțiuni numit set de instrucțiuni
11
Ce trebuie să descrie o
instrucţiune ?
• Ilustrarea de mai jos este realizata folosind mnemonice generice pentru
un limbaj de asamblare generic.

• Ce operație trebuie realizată: add R0, R1, R3


– Opcod (cod instrucțiune)/mnemonică: add, l(oa)d, br(anch), etc.
• Unde se găsesc operanzii: add r0, R1, R3
– Registrele CPU, locaţii de memorie, locaţii I/O (intrări) , sau ca parte din instrucțiune
• Unde se va memora rezultatul: add R0, R1, R3
– Registre CPU, locaţii de memorie, locaţii I/O (ieşiri)
• Unde se află următoarea instrucțiune care se va executa:
add R0, R1, R3
br endloop
– Implicit este locația de memorie (program) indicată de numărătorul program-PC =
următoarea instrucţiune din secvenţă
– Exista instrucțiuni care afectează ordinea de execuție: instrucțiuni de salt si/sau
ramificare – br(anch) precum si apeluri de subrutine (neilustrate mai sus)
• Exista uneori instrucțiuni / situații pentru care nu există nici un operand, sau nu
există un rezultat sau nu există următoarea instrucțiune care se va executa

12
Execuția unei instrucțiuni -
cicluri si faze
• Ciclu maşină (machine cycle)
– Faza/ciclu instrucţiune
– Faza/ciclu execuţie
• Faza instrucţiune (instruction)
– Etapa 1: Preluarea/extragerea/citirea din memorie
a instrucţiunii (Fetch)
– Etapa 2: Decodificarea (decode) instrucţiunii
• Faza execuţie (execution)
– Etapa 3: Execuţia (execute) instrucţiunii
– Etapa 4: Memorarea (store) rezultatelor
13
Timpul necesar pentru un ciclu
maşină
• Timpul necesar pentru un ciclu mașină, definit funcție de
ceasul sistem
– Timpul necesar pentru execuția unei instrucțiuni
• Exista mașini (CPU) lente
– Măsurat in microsecunde
• Exista mașini (CPU) rapide
– Măsurat in zeci de nanosecunde sau in nanosecunde
• Ce inseamna MIPS ?
– Este una din masurile (adimensionale) pentru viteza de
execuție: milioane de instrucțiuni pe secunda - Millions
of Instructions Per Second

14
Memoria sistemelor de calcul: ierarhizarea
sistemelor de memorie (viteză, cost)
Microcircuit - microprocesor
Memorie Viteza si costul
CPU Memorie Cache L2 descresc
Cache L1 Dimensiunea
creste
Control Memorie
auxiliară
Magistrale externa (HDD,
Memorie
externă SSD,
(RAM, FLASH USB,
ROM)
CDROM)

Registre
Memorie
Cele mai on-chip Cea mai
rapide dar si (internă) lentă dar
cele mai si cea mai
RAM, Costul este unul relativ, ieftină
scumpe
ROM exprimat per bit!
Ierarhizarea sistemelor de memorie – in
ordinea descrescătoare a vitezei
• Registrele (sunt tot o memorie internă)
Cele mai rapide, dar si cele mai costisitoare (ca preţ de realizare
la nivelul microcircuitului), un set de circuite bistabile
• Memoria Cache L1 (o categorie specială de memorie
internă)- Cache L2 este o memorie externă!
Întotdeauna de tip SRAM, mai lentă decât registrele, dar mai
mare, rapidă si pentru că este strâns “cuplată” cu CPU.
Gestionată de hardware/firmware si tipic invizibilă pentru
programatori
• Memorie internă (diverse tehnologii: SRAM si ROM /
FLASH / EEPROM)
De dimensiuni mai mari, accesul mai lent însă decât la Cache L1
Gestionată de software.
Viteza – este invers proporțională cu timpul de acces pentru un circuit de memorie
Memorie rapidă=memorie cu timp de acces mic
Ierarhizarea sistemelor de memorie -2
• Memoria externă (SRAM/DRAM si ROM/FLASH/EEPROM)
Mai lentă decât cea internă, fiind mai slab cuplată cu CPU (conectată prin intermediul unor
magistrale externe paralele relativ rapide), dar poate fi de dimensiuni mult mai mari si costuri
aferente mai mici
• Memorie externă auxiliară (HDD, SSD, DVD/CDROM, etc)
Mult mai lentă decât memoria externă (conectata prin intermediul unor magistrale externe relativ
lente, eventual seriale), dar de dimensiuni mult, mult mai mari si costuri per bit mult mai mici
Tipic este ne-volatilă la fel ca o memorie de tip ROM, adică datele vor mai exista/ se vor c

– Dimensiuni: de la x 10 Octeți la registre la x10 T Octeți la


memoriile externe auxiliare

– Viteza (timpul de acces): de ordinul x nsec la registre pana


la ordinul x 1(0) msec la memoriile externe auxiliare

17
Ierarhizarea sistemelor de memorie -3

eSRAM- embedded
SRAM RAM static
incorporat
(aici unității centrale)

Memoriile auxiliare pot fi


azi locale sau la distanță,
in Cloud.. (cloud storage)

18
Există două mari categorii de arhitecturi de
calcul: Von Neumann si Harvard

John von Neumann si calculatorul


IAS (Institute for Advanced Study),
Princeton, New Jersey, 1945; primul
calculator cu programul memorat O porțiune din Calculatorul Harvard
Mark 1, 1944 (cu relee
electromagnetice)
Arhitectura de calcul Von Neumann
(sau Princeton)
• Aceiași memorie este utilizată atât pentru program (instrucțiuni) cat
si pentru date (datele asupra cărora operează instrucțiunile)
• Vor exista semnale/magistrale comune intre CPU si memorie, pentru
instrucțiuni si pentru date, o singură magistrala de date, de adrese si
de control
• Principial nu se pot suprapune operațiile de preluare a instrucțiunii
cu cele de preluare a operanzilor din memorie, pentru că există un
singur set de magistrale ca suport fizic pentru acest transfer

Intrări (I) Memorie


Unitate centrală Intrari (I)
de
CPU
date SI
Ieșiri (O)
memorie de Iesiri (O)
Magistrale program
comune
Arhitectura de calcul Harvard
• Memorii diferite/separate pentru program (instrucțiuni) si pentru
date (datele asupra cărora operează instrucțiunile)
• Vor exista semnale/magistrale diferite intre CPU si memorii, pentru
instrucțiuni si pentru date, două magistrale de date, două de adrese
si două de control
• Se pot suprapune operațiile de preluare a instrucțiunii cu cele de
preluare a operanzilor din memorie de către CPU, pentru că există
magistrale diferite ca suport fizic pentru aceste transfer simultan

Intrări (I)

Intrari (I)
Memorie Memorie
Unitate centrala
de de
CPU
program date Iesiri (O)

Magistrale Magistrale
program date
Ieșiri (O)
Există si două mari concepte arhitecturale de
realizare a unei unități centrale (CPU) din punct
de vedere al setului de instrucțiuni:
CISC si RISC
• CISC (Complex Instruction Set Computers) –
unități centrale care au un set complex (in
sensul de numeroase si puternice ca
funcționalitate) de instrucțiuni
• RISC (Reduced Instruction Set Computer)-
unități centrale care au un set redus (in sensul
de puține ca număr si simple ca funcționalitate)
de instrucțiuni
• Ambele se întâlnesc in lumea
microprocesoarelor si microcontrolerelor
Caracteristici arhitecturale ale unității
centrale - CISC (Complex Instruction Set
Computer)
• Set de instrucțiuni CISC
– Aceasta înseamnă un set uzual de ordinul sutelor (x100)
instrucțiuni, cele mai multe din ele foarte puternice şi
specializate.
– De obicei multe din aceste instrucțiuni sunt foarte diferite între
ele: unele operează numai cu anumite spații de adrese sau
registre, altele permit numai anumite moduri de adresare, pot
avea lungimi mult diferite, se execută intr-un număr diferit de
cicluri / perioade de ceas, etc.
– Cu cât operațiile implementate sunt mai complexe cu atât
instrucțiunile devin mai complexe
– Unitatea centrală devine si ea din ce in ce mai complexă si
mai lentă datorita creșterii numărului de cicluri/perioade de
ceas per instrucțiune si al limitării frecvenței maxime de ceas
– O buna parte din membrii vechi ai familiei 80x86 (Intel) sunt
CISC
23
Caracteristici arhitecturale ale unității
centrale - RISC (Reduced Instruction Set
Computer)
• Principiul a fost de “sacrifica” totul pentru a obține o
viteza de calcul cat mai mare
– Reducerea numărului de instrucțiuni la ordinul zecilor (x10) face
ca unitatea centrală să fie mai simplă
– Eliminarea instrucțiunilor complexe care duc la încetinirea unității
centrale
– Utilizarea de moduri de adresare simple face ca mai puțin timp
să fie necesar pentru calculul adresei operanzilor
– Limitarea numărului de accese la memorie
– Dacă o anumită operație nu poate fi implementată intr-un singur
ciclu de ceas atunci ea nu va fi implementată într-o instrucțiune
– Utilizarea extensivă a unei arhitecturi de pipeline pentru a obține
o instrucțiune executat la fiecare ciclu de ceas
– AVR 8 biti (Microchip) si ARM sunt RISC
– Vezi si:
https://en.wikipedia.org/wiki/Reduced_instruction_set_computer
24
Caracteristici arhitecturale ale unității
centrale - RISC (Reduced Instruction Set
Computer) -2
• Setul de instrucțiuni RISC
– Prin implementarea unui set (relativ) redus de instrucțiuni care
se pot executa foarte rapid şi eficient, se obține o reducere a
complexității microcircuitului, suprafața disponibilizată putând fi
utilizată în alte scopuri.
– Printre caracteristicile asociate de obicei unui CPU RISC se pot
menționa:
• arhitectură Harvard modificată sau mai rar von Neumann
• viteză sporită de execuție prin implementarea a cel puţin unui nivel
de pipeline pentru instrucțiuni
• set de instrucțiuni ortogonal (simetric): orice instrucțiune operează
cu orice spaţiu de adrese (de memorie) sau orice registru,
instrucțiunile nu prezintă combinații speciale, excepții, restricții sau
efecte colaterale

25
RISC si CISC
Caracteristica RISC CISC
Tipul de instrucțiuni Simple Complexe
Numărul de instrucțiuni Redus (x10) Mare (x100)
Durata unei instrucțiuni Un singur ciclu de ceas Mai multe cicluri (4-120)
Formatul instrucțiunii Fix Variabil
Execuția instrucțiunii In paralel (pipeline) Secvențial
Modurile de adresare Simple Complexe
Instrucțiuni care Doar doua tipuri de baza: Aproape toate
accesează memoria Încarcă (Load) si
Memorează (Store)
Setul de registre Multiplu Unic
Complexitatea La nivelul compilatorului La nivelul CPU (in
microprogram)

26
Introducere, definiții: ce este un
microprocesor?

• Un microprocesor (MPU,uP- MicroProcessor Unit),


sau poate mai corect un microprocesor de uz
general, este o unitate centrală de prelucrare (CPU
- Central Processing Unit), unitate prezentă în orice
arhitectură de calcul, implementată însă la nivelul
unui singur circuit integrat numeric monolitic (un
singur cip de siliciu, microcircuit) – pe scurt cip.
• Cu alte cuvinte, un microprocesor este un circuit
integrat (monolitic) numeric complex care conţine
cel puţin un CPU.

27
MPU - microprocesor, o unitate
centrală (CPU) realizată pe un singur
microcircuit (cip)

Componentele externe
sunt conectate prin
magistrale externe:
adrese, date si control
Memorie, Dispozitive de intrare/iesire, Ceas, Alimentare28
28
Introducere, definiţii: ce este un
microcontroler?
• Plecând de la cerinţele generale pentru alcătuirea unui sistem de
calcul, precum şi de la o orientare pe anumite categorii de
aplicaţii (calculatoare sau staţii de lucru personale, staţii de lucru
profesionale, controlere industriale de proces, sisteme de
prelucrare numerică a semnalelor) a apărut în decursul timpului şi
o anumită specializare a microprocesoarelor rezultând două
categorii noi:
– microcontrolerele (microcontrollers) şi
– procesoarele numerice de semnal (DSP- Digital Signal Processors).

• Un microcontroler - MCU (deși semnificația inițială a


acestui acronim este Micro Computer Unit) este un cip care
incorporează o unitate centrală (CPU) şi cel puțin o
memorie, împreună cu resurse care-i permit
interacțiunea cu mediul exterior.

29
Ce este un microcontroler? -2
• Un microcontroler (MC, MCU) este alcătuit dintr-o unitate
centrală (CPU) căreia i s-a adăugat, pe același microcircuit
(on-chip), in primul rând memorie şi apoi o gamă din ce in
ce mai largă si diversificata de dispozitive periferice,
specializate/orientate si pe interfața/interacțiunea eficienta cu
mediul exterior.
– Un MCU poate constitui astfel un sistem de calcul de sine stătător, realizat
la un raport preț/performanţă optim, orientat pe controlul interacțiunii cu
lumea exterioară (controler industrial).
• Un microcontroler este o arhitectură de calcul orientată pe
control: el trebuie să "simtă" evenimentele externe şi să le
"răspundă" (în sensul de a controla) cât mai eficient, din punct
de vedere al timpului de calcul și al resurselor folosite.
• Această interacțiune este, de cele mai multe ori, bazată pe
utilizarea întreruperilor ca modalitate de tratare a intrărilor si
ieșirilor.
– Din acest motiv, toate microcontrolerele înglobează şi un sistem
de întreruperi performant si simplu de utilizat.

30
MCU – un microcontroler cu o
arhitectură internă Harvard

Totul sau aproape totul este/trebuie integrat împreună cu


CPU pe același microcircuit, in scopul de a avea un sistem
de calcul cat mai complet si pregătit de interacțiune cu 31
31
lumea externă
Ce este un microcontroler? -3
• Pe parcursul timpului a fost posibil ca la resursele minimale
să fie adăugate si integrate, la un preț de cost avantajos,
periferice cu caracteristici specifice sarcinii de control care
trebuie îndeplinite:
– sisteme de conversie analog numerică (una sau mai multe intrări
analogice)
– sisteme de conversie numeric analogic şi/sau ieșiri PWM (cu
modulare în durată)
– comparatoare analogice
– memorii de date nevolatile de tip EEPROM sau FRAM
– facilități suplimentare pentru sistemul de temporizare/numărare
(captare şi comparare)
– ceasuri de gardă (timer de tip watchdog) si ceasuri de timp real
(RTC)
– sisteme complexe si flexibile de generare a ceasului sistem
folosind bucle PLL si FLL, integrate cu facilități pentru optimizarea
consumului propriu
– circuite de comunicație, de la cele mai simple la cele mai complexe
– suport pentru sisteme de afișare LCD/LED
– Si altele… 32
32
Introducere, definiții: procesoarele
numerice de semnal (PNS/DSP)
• Un procesor numeric de semnal (DSP- Digital Signal Processor)
este caracterizat de existența unei unități centrale (CPU)
specializată pe operații de calcul intensiv şi foarte eficient, în
virgulă fixă sau virgulă mobilă, operații specifice algoritmilor
consacrați de prelucrare numerică a semnalului
• Arhitectura CPU este optimizată in acest caz pentru executarea într-
un timp minim a operațiilor de calcul necesare implementării unor
algoritmi de prelucrare numerică a semnalului.
• Majoritatea procesoarelor numerice de semnal au o arhitectură de
sistem de tip Harvard, cu spații de memorie separate pentru program
şi date.
• Se întâlnesc şi aici, din ce în ce mai des, caracteristici specifice
microcontrolerelor: prezența memoriei on-chip şi a unor dispozitive
periferice specializate.
• La ora actuală, granița dintre anumite categorii de
microcontrolere, microprocesoare şi multe din procesoarele
numerice de semnal este din ce în ce mai puțin distinctă, exista
multe exemple de unități centrale de microcontrolere care au
instrucțiuni similare DSP si DSP-uri care au periferice similare unui
microcontroler
• Dar oare ce înseamnă GPU, VPU sau TPU ? – vom reveni

33
Introducere, definiții: componente
hardware
Există cel puţin 5 componente cheie prezente la un CPU (deci si la un
microprocesor si la un microcontroler):
• unitatea aritmetică şi logică (ALU-Arithmetic Logic Unit)
responsabilă cu tot ce înseamnă operații de calcul aritmetic şi/sau logic
• registrele (registers) utilizate pentru memorarea temporară a
informației cu care lucrează ALU
• unitatea de control (Control Unit) responsabilă cu controlul operațiilor
efectuate de CPU pe baza decodificării instrucțiunilor
• un sistem de magistrale, cai de date (buses) interne şi externe, care
interconectează componentele interne și realizează conectarea cu
exteriorul
• un ceas (clock) la baza căruia stă ceasul sistem (system clock) cel
care realizează periodizarea tuturor operațiilor CPU
Alte resurse tipice prezente de obicei la un microprocesor sunt:
-un sistem de întreruperi(interrupts system) si
-un sistem de acces direct la memorie (DMA-Direct Memory
Acces).

Orice sistem de calcul va avea nevoie, în afară de microprocesor (CPU),


de memorie (memory) şi de modalităţi de conectare la dispozitivele
de intrare-ieşire (I/O devices) prin intermediul cărora se face legătura34
cu lumea exterioară.
Introducere, definiţii: ASI/ISA
• Unitățile centrale pentru microprocesoare si
microcontrolere, se pot diferenția sau clasifica si prin
intermediul :
– Arhitecturii Setului de Instrucțiuni ASI (ISA- Instruction Set
Architecture)
• Arhitectura setului de instrucțiuni va determina si cea ce uneori se
numește Modelul Programator (Programming Model)
– Dimensiunii cuvântului de date sau, cu alte cuvinte,
numărului de biți de date care pot fi prelucrați într-o
singură instrucțiune: 8,16, 32, 64 de biti, etc.
– Caracteristicilor arhitecturale: RISC sau CISC, Von
Neumann sau Harvard
– Vitezei de lucru sau frecvenței maxime a ceasului sistem
Atenție: acronimul ISA mai identifica si un tip de magistrala
utilizat prima oara la IBM PC: ISA = Industry Standard
Architecture
35
Introducere, definiții: ce înseamnă ASI ?
ASI:
• Modelul de memorie (memorie unificată sau nu, harta
memoriei, etc.)
• Registrele unității centrale (CPU)
• Tipurile native de date suportate
• Instrucțiunile si modurile de adresare ale operanzilor
ASI poate fi văzută si ca un fel de interfață intre hardware si
software

Program in Program in C
FORTRAN 90
program F90 compilat Program C compilat
intr-un program ISA intr-un program ISA
Software
Nivelul ISA
Hardware
Program ISA executat de hardware

Hardware
36
Introducere, definiții: alte componente
hardware
• Actualmente, datorita măririi spectaculare a gradului de
integrare ca urmare a progreselor tehnologice, unități
funcționale specifice, altădată implementate separat, cum
ar fi:
– unitatea de prelucrare în virgulă mobilă (FPU- Floating Point
Unit),
– unitatea de gestiune a memoriei (MMU- Memory Management
Unit) si/sau o unitate de protecție a memoriei (MPU- Memory
Protection Unit)
– memoria/memoriile cache L1 si/sau L2,
sunt şi ele integrate la nivelul aceluiași cip.
• Uneori termenii de microprocesor, procesor şi CPU
sunt (sau vor fi) folosiți alternativ pentru a desemna
aceiași entitate.
• Un microprocesor (uP, MPU) este de fapt un sistem de
calcul, implementat pe un singur microcircuit (cip), fără
memorie
– Pentru un uP memoria este întotdeauna implementată cu circuite
externe de tip RAM si/sau ROM
37
Microprocesoare, un exemplu mai mult
sau mai puțin generic
• O caracteristică esențială a microprocesorului (ca de altfel
a orice CPU) este faptul ca el este programabil de către
utilizatorul lui.
• Programarea unei aplicații folosind un microprocesor se
poate face, mai rar, la nivelul producătorului
microcircuitului sau, mult mai des si mai practic, la nivelul
utilizatorului final al sistemului de calcul
• Se va prezenta mai întâi (sumar si informativ doar ca
ilustrație la unele concepte) o familie generica de
microprocesoare (oarecum asemănătoare cu familia
numită generic x86 a firmei Intel Corp. )
• O arhitectură/familie reprezentativă de microprocesoare,
familia ARM, va face obiectul, unei alte prezentări
distincte, vezi prezentarea ..ARM_RO.pdf

38
Un exemplu de arhitectura de calcul /familie de
microprocesoare
• Microprocesorul (CPU - unitatea centrală) descris poate fi clasificat ca
fiind unul CISC având o arhitectură de Mașină Von Neumann (MVN).
• Un calculator (o mașină) Von Neumann are trei componente principale:
– unitatea centrală de prelucrare (CPU- Central Processing Unit),
– o memorie şi
– dispozitivele de intrare/ieşire (Input /Output Devices - I/O ports).

• Cele trei componente sunt


interconectate prin intermediul
magistralei de sistem
(system bus), care reprezintă
de fapt un set de mai multe
magistrale (căi de date),
grupate după criterii 39
funcționale
Un exemplu de familie de microprocesoare

• În cazul unei MVN toate acțiunile de prelucrare au


loc la nivelul unității centrale (CPU).
• Toate calculele se efectuează aici, datele şi
instrucțiunile mașină stau în același spațiu de
memorie până când unitatea centrală are nevoie
de ele.
• Pentru unitatea centrală dispozitivele I/O sunt
similare memoriei pentru că ea poate memora (scrie)
date pe un dispozitiv de ieșire sau poate citi date de
pe un dispozitiv de intrare.
• Singura diferență aparentă este asocierea acestora
cu ceea ce există în exteriorul sistemului (interfața cu
lumea exterioară): datele sunt trimise (scrise) către
lumea exterioară sau sunt primite (citite) din lumea
exterioară; memoria este “lumea interioară”
40
Arhitectura Setului de Instrucțiuni:
Modelul de memorie
• Modelul de memorie: cum arată memoria
pentru CPU (dar si pentru programator)?
• Ce ne interesează (pe noi ca programatori si pe
CPU…):
– Dimensiunea “celulei” sau “celulelor” adresabile: 1 bit,
4 biti, 8 biți, 16 biți, etc.
– Spațiul de adresa(re): de unde (adresa de început ?)
pană unde (adresa de sfârșit memorie?), cum si de
cine este ocupat (tip memorie: registre,RAM, ROM, I/O
etc.); cu alte cuvinte, care este harta memoriei
(memory map) ?
– Care este alinierea in memorie a datelor (a structurilor
de date multi-octet) in memorie
– Ordonarea in memorie a octeților dintr-o structură
multi-octet (Endianness): Little Endian sau Big
Endian

41
Arhitectura Setului de Instrucțiuni: registrele (registers)
.. pe care trebuie sa le cunoască programatorul (in
limbaj de asamblare..)
• La modul general sunt de 2 feluri:
– De uz general (general purpose)
• Utilizate pentru memorarea temporara a unor rezultate,
etc.
– Dedicate, de uz special (special purpose), de
exemplu (denumirile in engleza pot varia funcție
de familie/fabricant!).
• Numărător de program (Program Counter -PC), asociat
CPU
• Indicator de stivă (Stack pointer -SP), asociat CPU
• Registru de stare (Status Register) , asociat CPU
• De intrare/ieşire (Input/Output Registers) asociate
dispozitivelor periferice: 42
Arhitectura Setului de Instrucțiuni:
tipurile (native) de date
• Date Numerice:
– Numere întregi (integers) cu dimensiuni diferite: 8, 16, 32, 64 biţi
• Posibil cu semn sau fără semn, denumire alternativă numere in
virgula fixă (fixed point)
– Numere in virgula mobilă (Floating point numbers): 32 biţi (simpla
precizie) sau 64 biţi (dubla precizie)
– Numere zecimale in codificare binară (BCD - Binary Coded
Decimal)
• Date Non-numerice:
– Booleene/logice (0 înseamnă Fals/False, ≠0 înseamnă
Adevărat/True) – memorate pe un byte (octet) sau cuvânt
– Bit-map, bit field (o colecţie de booleene, de exemplu 8 intr-un
octet, fiecare bit reprezentând o data booleana)
– Caractere (ASCII, UTF-8, Unicode)
– Pointeri (adrese de memorie)

43
Arhitectura Setului de Instrucțiuni: Tipuri de
date (continuare)
• Este vorba de tipurile de date “native”, cele pe care le
înțelege “direct” hardware-ul CPU!
– De exemplu, pentru arhitectura IA32, x86 Intel de 32 de biți,
vom avea:
Tip data 8 biţi 16 biţi 32 biţi 64 biţi 128 biţi
Întreg cu semn
Întreg fara semn
Întreg BCD
Virgula mobila

– Dar pentru pentru un microcontroler Microchip AVR de 8 biți


avem:
Tip data 8 biţi 16 biţi 32 biţi 64 biţi 128 biţi
Întreg cu semn
Întreg fara semn
Întreg BCD
Virgula mobila

44
Arhitectura Setului de Instrucțiuni :
instrucțiunile propriu-zise
• Setul de instructiuni reprezintă, împreună cu
modurile de adresare pentru operanzi, principala
caracteristică a ASI
• Instrucțiunile includ ca funcționalitate tipuri precum:
– Încărcare/memorare (Load/Store) – încărcă date in/ din
memorie
– Copiere (Move) – de copiere date, tipic intre registre (de
fapt nu mută= nu “move” datele!)
– Aritmetice – adunare, scădere, înmulțire, împărțire
– Logice – Operații booleene (NOT, AND, OR, XOR)
– De ramificare/salt/apel de subrutine
(Branching/Jumping/Calling) – stabilesc care va fi
următoarea instrucțiune ce va fi executata

45
Magistralele (buses, vezi curs
Electronica digitala…)

• Din punct de vedere electric, nivelele logice


implicate pentru componentele tipice conectate la
aceste magistrale sunt compatibile TTL sau LVTTL
(dacă se utilizează şi tensiuni de alimentare mai mici
de 5V).
• La procesoarele noi sau relativ noi pentru anumite
magistrale foarte rapide se utilizează o nouă
interfaţă electrică, care nu este compatibilă
TTL/LVTL, în variantele: GTL (Gunning Transceiver
Logic), GTL+ sau AGTL (Assisted Gunning
Transceiver Logic).
– Multe din aceste standarde utilizează o semnalizare
diferenţiala si nu asimetrica

46
Magistrala de sistem (System Bus)

• Magistrala de sistem conectează între ele


componentele unei MVN.
• Un microprocesor cu o arhitectura de tip MVN are
drept componente trei magistrale majore :
– de adrese,
– de date
– de control.
• Aceste magistrale sunt în general diferite de la o
varianta de procesor la altul, ele fiind clasificate după
natura informaţiei vehiculate.
– De exemplu chiar daca implementarea magistralelor de date
este diferită, in toate cazurile se vehiculează date între
unitatea centrala, memorie şi dispozitivele I/O.

47
Magistrala de date (Data Bus)
• Dimensiunea (numărul de linii de semnal) al acestei
magistrale este diferită funcție de familia de
microprocesoare ea definind într-un fel şi "mărimea"
procesorului.
• Magistrala de date poate avea, tipic, 8,16,32 sau 64
de biţi si respectiv un număr similar de linii de date.
• Dar atenție, nu neapărat numărul de linii de date
(numărul de semnale fizice) este egal cu numărul de
biți, datele fiind multiplexate in timp pentru a reduce
numărul interconexiunilor
– Magistrale cu 8 linii/semnale de date pot avea un numar
dublu de biti, adica 16

48
Magistrala de date (Data Bus) -2
• Existenţa unei magistrale de date de 8 biţi nu
înseamnă că un procesor este limitat doar la un
singur tip de date de 8 biţi (la un octet sau Byte).
– Înseamnă de fapt că procesorul poate accesa doar un octet
într-un ciclu de memorie (în cazul MVN).
• Astfel cei 8 biţi ai magistralei de date pot transmite
doar jumătate din informație în unitatea de timp (un
ciclu de memorie) comparativ cu o magistrala de date
de 16 biţi.
• Acesta este motivul pentru care procesoarele cu o
magistrală de date de 16 biţi sunt în mod natural mai
rapide decât cele cu o magistrală de 8 biţi, ş.a.m.d..
• Dimensiunea magistralei de date afectează
performanțele sistemului mai mult decât
dimensiunea oricărei alte magistrale.

49
Magistrala de date (Data Bus)-3
• Legat tot de "mărimea" procesorului (8,16, 32 sau 64 de biți) una din
modalitățile de definire consideră că ea este dată de dimensiunea celui
mai mare registru întreg (virgula fixa) de uz general al unității
centrale.
– Astfel, au existat si exista procesoare care au o magistrală de date de 8 biţi dar
sunt de fapt procesoare de 16 biţi, sau procesoare cu o magistrală de date de 64
de biți care sunt de fapt procesoare de 32 de biţi.
• Deși este evident posibil să prelucrăm şi date pe 12 biți, formatul preferat
este cel de 8, 16, 32 sau 64 de biţi deoarece oricum procesorul preia și
manipulează date în grupe de 8 biţi .
• Astfel manipularea datelor în formate multiplu de 8 biţi este întotdeauna
cea mai eficientă în acest caz.
• Microprocesoare cu magistrale de date de 16, 32 sau 64 de biţi pot
accesa date cu dimensiuni până la acelea ale magistralei, dar este
evident ca ele pot accesa și unități mai mici, de 8, 16 sau 32 de biți.
– In același timp orice ce se poate face cu o magistrală mai mare, ca număr de biți,
se poate face, mai complicat si mai lent și cu una mai mica diferind doar timpul
(mai mare) in care se accesează/ transferă datele respective; de exemplu un
transfer de 32 de biti poate fi “spart” in 2 transferuri de 16 biti, etc.
• OBSERVATIE Distincția referitoare la registru întreg (virgulă fixă) este
făcută pentru a nu lua în considerare registrele unității de prelucrare în
virgula mobilă (FPU), atunci când ea există, registre care pot avea o
dimensiune mai mare decât cele in virgula fixa
50
Magistrala de adrese (Address Bus)
• Magistrala de adrese este cea prin intermediul căreia
se diferențiază locațiile de memorie (si/sau
dispozitivele I/O daca e cazul) în cazul unui transfer
de date, asociindu-le acestora o adresă unică (în
mod tipic).
• Când se dorește să acceseze o locație particulară de
memorie sau un anumit dispozitiv I/O, procesorul
plasează pe magistrala de adrese o valoare (o
adresă);
– circuitele asociate memoriei sau dispozitivelor I/O recunosc
această adresă şi fac ca acestea să citească informația de
pe magistrala de date sau să plaseze (scrie) informația pe
aceiaşi magistrală.
• Folosind n linii de adresă (magistrala de adresă de n
biţi) procesorul poate gestiona/furniza 2n valori
distincte ale adresei.
51
Magistrala de control (Control Bus)

• Magistrala de control reprezintă un set variat de


semnale prin care procesorul comunică cu restul
sistemului.
• În primul rând trebuie să existe semnale care să
stabilească sensul transferului de date:
– de la CPU/procesor (scriere - Write, WR) către memorie sau
I/O sau
– către CPU/procesor (citire - Read, RD) de la memorie sau I/O.
– astfel există cel puțin două linii generice de semnal Read şi
Write care stabilesc sensul transferului de date.
• În afară de acestea mai există ceasuri de sistem, linii de
întrerupere, linii de stare, ş.a.m.d.
• Componența exactă a acestei magistrale este diferită
funcție de familie sau chiar în cadrul familiei, dar anumite
linii de control sunt comune și vor fi menționate în
continuare. 52
Exemplu de arhitectură de calcul (simplificată), orientată pe
magistrale externe (external busses) - oarecum similară unui
PC x86 (un sistem de calcul de uz general - SCUG)
/MWTC – scriere memorie; /MRDC – citire memorie;
/IOWC – scriere I/O; /IORCC – citire I/O;

Control
bus

I/O-
Intrari/Iesiri
Memorie
53
Dar ce ne interesează in primul rând sunt
sistemele incorporate (embedded systems) !

• Un sistem incorporat (SI) este un sistem de calcul


programat să realizeze numai o anumită sarcină
sau categorie îngustă de sarcini.
– Nu este relevant cât de complexă este această sarcină.
• Spre deosebire de un calculator personal care şi el
execută anumite sarcini, un sistem incorporat
execută mereu această sarcină, din momentul pornirii
până în momentul opririi, tipic fără intervenția
operatorului uman
– Intervenția operatorului uman si programarea SI nu poate fi
realizată decât în sensul în care proiectantul aplicației l-a
prevăzut și permis.
• Un sistem incorporat nu este altceva decât o
componentă a unui sistem mai mare, la fel ca o
poartă logică sau o altă componentă electronică, care
nu are de îndeplinit decât o singură sarcină. 54
Sisteme incorporate (embedded systems) -2
• Un SI este un sistem de calcul programat să execute
această singură sarcină, care poate fi de la una foarte
complexă pană la una foarte simplă.
• Deoarece el nu este decât o componentă, la rândul său
poate fi utilizat drept componentă a altui sistem
incorporat.
• Gradul de complexitate hardware al sistemului
incorporat în sine, puterea sa de calcul şi eventual
dimensiunile fizice sunt legate firesc de complexitatea
sarcinii pe care trebuie să o îndeplinească şi pot varia
de la:
– complexitatea hardware a unui circuit cu 8 pini care
îndeplinește funcțiile câtorva porți logice, care aprinde si stinge
un LED până la
– complexitatea hardware cel puțin echivalentă a unui calculator
personal (sau pe aproape) foarte performant (echivalentul a
sute de milioane de porți logice), care poate controla o
instalație complexa 55
Sisteme incorporate (embedded systems) -3
In practica de toate zilele există nenumărate exemple de sisteme
(sau aplicații) care au in componenţă şi care sunt controlate prin
intermediul unuia sau mai multor astfel de sisteme incorporate :
– industria automobilului (control motor, control frânare, etc.)
– industria aerospațială
– electronică de consum (aparatura audio, video, camere, etc.)
– aparatură electrocasnică (frigidere, maşini de spălat, cuptoare cu
microunde, etc.)
– aparatură de comunicații (telefonie mobila, routere, switch-uri, etc)
– roboți industriali şi roboți mobili
– aparatură medicală
– aparatură pentru automatizarea şi climatizarea spaţiilor de locuit sau
de lucru
– aparatură pentru măsurare şi control în industrie
– periferice pentru calculatoare (imprimante, scanere, etc.)

De fapt e foarte greu de găsit un domeniu in care sa nu fie utilizate


sisteme incorporate!
56
Sisteme incorporate (embedded systems) -4
Toate aceste aplicații menționate denotă drept caracteristici comune:
– realizarea unei sarcini bine definite pentru produsul, echipamentul sau
sistemul în care sunt integrate
– ele nu permit interacțiunea cu utilizatorul decât în măsura în care această
interacțiune face parte din sarcina pe care o are de îndeplinit (ele sunt
programabile doar in sensul conceput de proiectant)
– ele pot fi considerate doar o parte a unui produs, echipament sau sistem
– exista cerințe stricte legate de viteză de calcul si dimensiunea memoriei,
consum de energie cât mai mic, preț de cost cât mai mic posibil
• Complexitatea unui sistem incorporat este dată de atât de componenta
hardware, deja menționată, cat si de cea software.
• Prin intermediul software-ului este determinată funcționalitatea
sistemului incorporat.
• Complexitatea software poate varia de la echivalentul unui cod, de
sine stătător, cu dimensiunea de câteva zeci de octeţi (Bytes) si cateva
zeci de linii de cod, până la complexitatea unei aplicații de pană la zeci
de megaOcteţi (MBytes), cu zeci de mii de linii de cod, care la rândul
său rulează sub un sistem de operare, eventual unul de timp real.

• OBSERVAŢIE Din acest punct de vedere, am putea acum redefini


varietatea de microprocesor pe care am numit-o microcontroler ca
fiind un circuit destinat realizării unui sistem incorporat cu ajutorul
unui număr minim de circuite (ideal numai unul!).
57
Sistemele incorporate – o paradigmă deja
învechită..
• Din păcate, acum in 2019, lucrurile nu mai sunt atât de clare si
simple :) cum păreau acum 10 ani..
• Paradigma “embedded systems”, la fel ca si cea a sistemelor
informatice in general, s-a modificat si suferă evoluții importante odată
cu dezvoltarea conectivității lor, dezvoltare bazata tehnologiile numite
generic “Internet”
• Termenul cheie este Internet of Things(IoT), un ansamblu de sisteme
incorporate, caracterizate prin identificatori unici, asociate unor
sisteme fizice diferite- sunt cele enumerate la aplicatiile sistemelor
incorporate si capabile să transfere date (cu scopuri diferite) într-o
rețea, fără intervenția unui operator uman
– sistemele de operare pentru de tip Windows Embedded de la Microsoft sunt
acum numite Windows IoT…

58
Sisteme incorporate – o paradigmă deja
învechită.. 2
• Internet of Things(IoT) are o definiție care a evoluat datorită convergentei
mai multor tehnologii din care doar una este cea a sistemelor incorporate:
am putea spune si ca IoT a “înghițit” si tehnologia sistemelor incorporate
• Datele vehiculate de IoT vor fi fi transferate cu scopul de a ajunge, pentru
prelucrare, utilizare si/sau stocare la alte sisteme similare sau in Cloud..
• Cloud computing – o tehnologie care presupune utilizarea unor servere
informatice la distanta, conectate (in rețea) prin intermediul Internet-ului,
pentru stocarea si prelucrarea datelor
• Edge computing- înseamnă analiza si prelucrarea datelor realizate de a
lungul “marginii unei retele”, cel mai aproape de punctul de
colectare/generare astfel datele devenind utile si utilizabile in timp real, fără
întârzierile asociate prelucrării in cloud
Din păcate există si un preț imediat
plătit pentru IoT..
Dacă si înainte existau preocupări
legate de securitatea (security)
datelor si de intimitatea (privacy)
utilizatorilor pentru unele sisteme
incorporate, odată cu dezvoltarea IoT
si stocarea in Cloud aceste probleme
au devenit critice si blocante!
Se fac mari eforturi ca ele să fie
rezolvate de o manieră acceptabilă si
verificabilă pentru orice utilizator 59
privat
sau industrie .
Sisteme incorporate – o paradigmă deja
învechită.. 3
Datorita Cloud computing si Edge computing, IoT este acum asociat din ce in ce
mai mult cu alte tehnologii care alta data nu prea aveau legătură cu sistemele
incorporate, cum ar fi si:
- Big data (analytics)- analiza volumelor mari de date
- Artificial intelligence (AI) – tehnici de inteligență artificială
- Machine Learning (ML), Deep Learning (DL) – învățare automată, profundă
utilizată la recunoașterea formelor; fac parte din tehnicile de inteligența
artificială

60
Microcontrolere (si
microprocesoare)
Microprocesoare multi-core
Aplicații: sisteme de calcul de uz “general” (SCUG)-
arhitecturi de calcul de tip calculator personal (PC), calculatoare
centrale, supercalculatoare
Alt fel de sisteme incorporate: circuite numerice complexe, COTS,
SOC, ASSP, ASIC, SiP, SoM
Controlere incorporate
Funcții si subsisteme, ETX, COM, PC-104

1
Microprocesoare multi-core
• Un core este un ansamblu de circuite (o unitate de calcul- CPU),
capabile să execute programe in mod autonom. Toate funcționalitățile
necesare execuției unui program la nivel de CPU sunt prezente intr-un
core: registre, unitate aritmetico –logica, numărător program, unitate de
control, sistem de ceas. Memoriile de tip cache sunt definite pentru
fiecare core sau sunt partajate intre ele.
• Un microprocesor multi-core are cel puțin 2 core - 2 unități de calcul-
implementate pe același microcircuit (die). Există si implementări multi-
core in care mai multe microcircuite (die), fiecare o unitate de calcul,
sunt încapsulate in aceiași capsulă(package).
• https://en.wikipedia.org/wiki/Multi-core_processor

Quad-core
AMD Opteron

2
Microprocesoare multi-core
• Un microprocesor multi-core este un exemplu de multiprelucrare
(multiprocessing) realizat la nivelul unei singure capsule de circuit.
• Comunicarea intre-core este esențială in paralelizarea execuției, si se
face prin intermediul de mesaje sau prin partajare de memorie,
existând diverse topologii de interconectare a lor. Ele pot fi cuplate
strâns (tightly) – la nivel de magistrale procesor sau slab (loosely)-
utilizând o legătură seriala de mare viteza, gen Gigabit Ethernet.
• Exista multi-core omogene – toate core-urile sunt identice (exemplu
majoritatea multi-core de la Intel si AMD) si multi-core eterogene
unde există cel puțin două tipuri de core (exemplu Xilinx Zynq
UltraScale+ MPSoC are, pe lângă circuitul FPGA, un quad-core ARM
Cortex-A53 si un dual-core ARM Cortex-R5).
• Îmbunătățirea performantelor prin utilizarea de unități centrale multi-
core depinde foarte mult de algoritmii software utilizați si de
implementarea lor.
• Primul procesor multi-core a fost introdus de IBM in 2001, POWER4.,
fiind urmat de Sun si HP.
3
• Intel si AMD introduc variantele lor începând cu 2005.
Microprocesoare multi-core
• Actualmente aplicațiile de uz general ale microprocesoarelor multi-core sunt:
calculatoare desktop (PC), stații de lucru, servere, calculatoare centrale
(mainframes) si supercalculatoare.
• Si aplicațiile de tip sistem incorporat utilizează unități centrale multi-core, existând
de exemplu si procesoare numerice de semnal (DSP) multi-core.
• Cazul unităților de prelucrare grafica (GPU- Graphic Processing Unit) este un caz
particular de prelucrare numerica a semnalului, cu aplicații nu numai la
prelucrarea grafica, si va fi prezentat separat.
• State of the art -2017 (actorii principali):
AMD
• Ryzen, quad-, 6, 8, 12, 16, 24, 32-core desktop processors.
• Epyc, 8, 16, 24-, 32-core server processors.
IBM
• POWER8, a 12-core PowerPC processor, 2013
• z14, 10-core z/Architecture, 2017
• POWER9 12, 24 cores 2017
INTEL
• Familia Core i3, Core i5, Core i7 si Core i9 : dual, quad, 6, 8, 10, 12, 16, 18-core
desktop processors
• Xeon dual, quad, 6, 8, 10, 12, 14, 15, 16, 18, 22 , 24 core server processors
4
• Xeon Phi 57- 61, 64-72 – Intel x86 manycores
Aplicații: sisteme de calcul de uz
general
• Avem mai multe categorii de sisteme de calcul, cu performanțe
(viteza, resurse memorie) in ordine crescătoare:
– Calculatoare personale desktop sau portabile (PC)
– Stații de lucru (workstations)
– Servere
– Calculatoare centrale (mainframes)
– Super calculatoare
• Categoriile de sisteme de mai sus sunt mai mult sau mai puțin
specializate pe categorii de aplicații
• Cele mai răspândite sunt, evident, calculatoarele personale, care
sunt si cel mai puțin specializate (cu mici excepții, cum ar fi
configurații particulare optimizate pentru practicarea jocurilor –
gaming PC - care ca performanțe se pot apropia de stațiile de
lucru )
• Există însă si categorie aparte de sisteme de calcul specializate,
care nu poate fi descrisa ca de uz general, destinate unor aplicații
cum ar fi inteligența artificiala si/sau învățarea automata sau
mineritul criptomonedelor / criptovalutei (cryptocurrency mining)
• Aceste sisteme utilizează unități centrale particulare:
– GPU- Graphic Processing Units (Nvidia, AMD si nu numai), prelucrare
grafica, minerit criptomonede,
– TPU – Tensor Processing Units (Google), aplicații de inteligența
artificiala 5
– Vom reveni asupra acestor unități centrale
Calculatoare personale – un sistem de
calcul de uz general bazat pe magistrale
În figura următoare este prezentată arhitectura de sistem pentru
un calculator PC relativ modern (desktop PC).
- Este de fapt o reprezentare sistemică valabilă pentru aproape orice
placă de bază (motherboard) utilizată într-un PC (aproape) modern.

6
Calculatoare personale- un exemplu de
sisteme de calcul de uz general
• Vom începe cu exemplu atotprezent de aplicație a
microprocesoarelor – calculatoarele zise personale, in primul
rând in versiunile desktop si portabile
– vom vedea însă că exista si o legătură a acestor arhitecturi de
calcul cu sistemele incorporate..
• Placa de bază este construită în jurul unui set de circuite (un
chipset), care, la ora actuală, este alcătuit din doar două
circuite sau mai degrabă grupe de funcționalități principale
numite North(ern) Bridge şi South(ern) Bridge.
– Actualmente (2019) denumirea de chipset e puțin demodata, fiind
vorba de un singur circuit fizic!
• Denumirea North (Nord) sau South (Sud) se referă la poziţia
lor, în schema bloc, faţă de magistrala PCI: deasupra (Nord)
sau dedesubt (Sud).
• Termenul de Bridge (punte, legătură) vine de la faptul că ele
leagă împreună mai multe magistrale.
– Astfel North Bridge- Controlerul de sistem leagă magistrala
procesor (FSB-Front Side Bus) cu magistrala AGP, cu magistrala de
memorie, cu magistrala PCI şi cu South Bridge - Controlerul de
magistrale pentru periferice.
7
Un exemplu de
chipset.. vechi
(VIA, 2007)

8
Tot un exemplu de chipset.. ceva mai nou, Intel
X99 (2014) realizat cu un singur circuit fizic

9
Calculatoare personale
• Pentru proiectantul de sistem toate componentele
pentru care viteza de transfer a datelor este critică
sunt conectate la North Bridge.
• South Bridge are rolul de a integra, prin intermediul unor
magistrale corespunzătoare, perifericele mai lente,
pentru care viteza de transfer nu este un parametru critic.
• Controlerul de sistem - North Bridge incorporează
funcţiile de controler de memorie SDRAM şi, eventual,
controler pentru memoria cache L2.
• Începând de la Pentium Pro şi Pentium II funcţia de
controler al memoriei cache L2 este îndeplinită de
procesor.
• Deoarece înglobează controlerul de memorie şi
vehiculează un trafic masiv de date, performanţele
circuitului North Bridge sunt cele care de fapt
dictează performanţele chipset-ului respectiv. 10
Calculatoare personale-
magistrale
• Magistrala PCI (Peripheral Component Interconnect), în jurul căreia
se poate considera că este realizat sistemul prezentat, este o
tehnologie relativ nouă, destinată interconectării dispozitivelor
periferice interne, fiind introdusă pe piaţă de Intel în 1992 odată cu
primele chipset-uri pentru procesoarele Pentium.
• La origine PCI este la bază o magistrală internă performantă (la
timpul ei.. ), pentru periferice alimentate la 5V, cu un ceas sistem de
33MHz, cu o sub-magistrală de date de 32 de biţi şi o viteză
teoretică de transfer de 133MBytes /sec.
• De-a lungul timpului au apărut dezvoltări ale acesteia (care pot
apărea în orice combinaţie) cum ar fi:
– extensie la 64 de biţi
– extensii la 66MHz si apoi la 133MHz
– tensiune de alimentare de 3.3V, cu un conector diferit
– "Small PCI" pentru laptop-uri sau sisteme unde spaţiul este critic
– PCI-X (eXtended)
• Extensiile pentru magistrala de date sau ceasul de sistem PCI au
dus la o creștere corespunzătoare a vitezei de transfer (cu factorul
corespunzător de multiplicare).
• Diversele variante PCI sunt/vor fi înlocuite practic cu PCI-Express, o
varianta seriala de foarte mare viteza 11
Calculatoare personale - factori de
formă pentru plăcile de bază
Factor de formă = Lungime x lăţime (x înălţime)

12
PCI-slots
PCI 32 biti, 66MHz

PCI 64biti, 66MHz

PCI-X 2.0 64biti, 266MHz 13


PCI- cards

14
PCI Express

15
Calculatoare personale - magistrale
• Magistrala AGP (Accelerated Graphics Port) este o
magistrală dedicată exclusiv interfeţei cu
subsistemul video.
• Ea a fost destinată pentru a elimina traficul masiv de
date al subsistemului video pe magistrala PCI şi a oferi,
simultan, o lăţime mai mare de bandă pentru traficul de
date între procesor şi subsistemul video.
• Prin intermediul magistralei PCI se accesează doar
porturile I/O prezente pe subsistemul video.
• Există mai multe specificaţii, funcţie de viteza maximă
de transfer: AGP2X, AGP4X şi AGP8X.
– Ultima specificație, AGP8X, asigură a o viteză de transfer mai
mare de 2GBytes/sec !
– Tendința este însă sa fie înlocuită cu PCI Express!

16
AGP

17
Calculatoare personale – magistrale mai
vechi sau mai noi
• Magistrala ISA (Industry Standard Architecture) este o magistrală apărută
odată cu primele calculatoare IBM-PC.
• Este o magistrală lentă (viteza maximă de transfer este de cca 8MBytes/sec
– frecventa ceasului de referință este de cca. 8MHz), dar adecvată pentru o
gamă largă de periferice cu viteze de transfer compatibile.
• La majoritatea PC-urilor actuale magistrala ISA nu mai este disponibilă
ca atare (nu mai există sloturi ISA în care să se poată introduce interfeţe
compatibile).
• Ea continua însă sa fie utilizata pentru controlere, ca atare sau sub forma
PC-104 sau PISA
• Din considerente de compatibilitate ISA, periferice cu ar fi porturile seriale
(COM), porturile paralele (LPT), portul de jocuri, porturi PS/2 pentru mouse
şi tastatură precum şi controlerul de floppy disk sunt integrate la nivelul unui
singur circuit, numit tipic Super I/O, care se conectează la South Bridge.
• Tot pentru compatibilitate ISA la nivelul South Bridge mai sunt integrate un
timer compatibil Intel 8254, două controlere de întreruperi Intel 8259A, două
controlere de DMA compatibile Intel 8237 şi un ceas de timp real (RTC-Real
Time Clock).
• Aceste periferice sunt conectate printr-un înlocuitor al magistralei ISA
numita LPC (Low Pin Count) care permite transferul informației folosind un
număr minim de 7 fire (din care o magistrala de date de 4 biți) dar cu
frecvența de 33MHz 18
ISA

ISA 16 biti
ISA 8 biti

Aşa nu o sa mai găsim..

Dar aşa da… 19


Calculatoare personale - magistrale
• (E)IDE ( Extended Integrated Drive Electronics) este de fapt cea mai
comună şi ieftină interfaţă pentru conectarea unor dispozitive
externe de stocarea a datelor: hard disk-uri, CD-ROM, DVD-ROM,
etc.
• Specificaţia oficială pentru interfaţa IDE poartă numele de ATA (AT
Attachement).
• Împreună cu această siglă apare un număr care indică viteza
maximă de transfer.
– Exemple de astfel de specificaţie (care apare atât pentru chipset cât şi
pentru dispozitivul de stocare) sunt ATA/33 cu 33MB/sec, ATA/66,
ATA/100 sau ultima apărută ATA/133.
• Odată cu apariţia SATA, se mai numeşte si PATA, Parallel ATA
pentru ca exista acum si SATA (Serial ATA)
• Pe cale de dispariţie (2009) in calculatoarele personale obişnuite
dar utilizata in controlere clasice sau la calculatoarele personale
având un hard-disk FLASH/CompactFLASH
• vezi SATA
20
EIDE -PATA

Cablu /conector
ATA 133

21
SATA

22
Calculatoare personale – magistrale
externe paralele
• Prin intermediul unei magistrale (interfeţe) SCSI se
obţine o variantă superioară de interconectare a
dispozitivelor de stocare externe (şi nu numai, există şi
scannere care se pot conecta la o magistrală SCSI ).
• Un sistem SCSI (Small Computer System Interface) este
construit în jurul unui controler SCSI (host - gazda),
controler conectat la magistrala PCI.
• La acest controler se pot conecta prin intermediul
magistralei externe un număr de 7 sau 15 dispozitive
externe (mai mare ca la EIDE).
• Un controler SCSI posedă putere de calcul proprie,
putând implementa algoritmi inteligenţi, fără a consuma
putere de calcul a unităţii centrale.
• De regulă, datorită costurilor mari implicate, se utilizează
în sisteme PC de performanţă (high-end), servere sau
staţii de lucru. 23
SCSI (se pronunţa scazii)

24
Calculatoare personale –
magistrale externe seriale
• Magistrala USB (Universal Serial Bus) este o magistrală serială externă,
destinată conectării simple a unei categorii largi de periferice externe.
– Cu anumite limitări (maxim 500mA la 5V per port USB), dispozitivele periferice
respective se pot şi alimenta prin intermediul acestei magistrale.
• Apărută inițial cu specificația numită USB1.x, a fost destinată înlocuirii
conexiunilor cu periferice externe prin intermediul porturilor seriale (COM)
sau paralele (LPT).
• Viteza maximă de transfer pentru USB1.x este de 12Mbiţi/sec.
• Odată cu apariția specificației USB2.x viteza maximă a crescut la
480Mbiţi/sec, concurând direct cu o magistrală serială similară numită IEEE
1394 ("FireWire"), magistrală introdusă anterior de firma Apple.
• Au devenit astfel accesibile şi alte categorii de periferice (camere de
videoconferință, controlere de rețea -LAN, etc.).
• Circuitele moderne South Bridge incorporează unul sau două controlere
USB, ajungându-se până la 6 porturi USB disponibile.
• Actualmente specificația USB 3.0 asigura o viteza maximă teoretica de
4.8Gigabiţi/sec (obținută prin adăugarea de fire suplimentare)
• Thunderbolt este o magistrala similară USB 3.0, dezvoltată de Intel si
Apple, actualmente si ea la specificația Thunderbolt 3
25
USB..Firewire

26
Există însă si alte SCUG decât calculatoarele
personale - calculatoarele centrale
• Calculatoarele centrale (mainframe, „big iron”) - calculatoare construite
pentru si utilizate de marile organizații/companii/corporatii, cu o putere de
prelucrare mai mare decât ce înseamnă calculatoare personale, stații de
lucru (workstations) sau servere
• Realizează tipic sarcini critice precum: tranzacții informatice, realizarea de
statistici si recensăminte, prelucrarea datelor brute, gestiunea integrata a
întreprinderii
• Sunt arhitecturi de calcul multiprocesor (utilizează mai multe
microprocesoare multi-core) optimizate pe prelucrarea tranzacțiilor
informatice: viteza lor de prelucrare este exprimata in număr de tranzacții
per secunda

IBM este cel mai mare producător


de astfel de sisteme de calcul

https://en.wikipedia.org/wiki/Mainframe_computer

27
Si supercalculatoarele..
• Supercalculator (supercomputer) – un calculator conceput să obțină cele mai înalte performante
posibile cu mijloacele tehnice disponibile in momentul proiectării sale si in particular să obțină cea
mai mare viteza de calcul posibilă
• Știința supercalculatoarelor –calculul de înaltă performantă: HPC : High-Performance Computing
• Viteza lor de calcul este exprimata in număr de operații in virgula mobila per secunda FLOPS
(FLoating-point OPerations per Second): actualmente vorbim de mii si zeci de mii de TFLOPS
(TerraFlops = 1012 ) adica de PetaFlops (Peta = 1015)
• Toate utilizează arhitecturi de calcul paralel masiv (massively parallel designs) implementat
hardware cu mai multe unități centrale (cores), de fapt microprocesoare multi-core
• Exista un Top 500 al supercalculatoarelor, iar Europa nu este in Top 10!
• Toate utilizează sistemul de operare de tip Linux, de fapt adaptări ale acestuia pentru calcul
paralel eficient
• Ele stau azi la baza științei computaționale fiind esențiale pentru calcule din domenii ca:
simulările fizice inclusiv prognoze meteo si modificări climatice, modelare moleculara (esențială in
industria farmaceutica), mecanica cuantica, exploatarea zăcămintelor de hidrocarburi si minerale,
criptografie, studiul fuziunii nucleare, proiectarea armelor nucleare, etc.
Ran Site System Cores Rmax Rpeak Power
k (TFlop/s) (TFlop/s) (kW)
500 Swiss National EPFL Blue 65,536 715.6 838.9 329
Supercomputing Brain IV -
Centre (CSCS) BlueGene/Q,
Switzerland Power BQC
16C
1.600GHz,
Custom
Interconnect
IBM

28
Top 500 supercalculatoare..
Ran Site System Cores Rmax Rpeak Power
k (TFlop/s) (TFlop/s) (kW)
2 National Sunway 10,649,6 93,014.6 125,435.9 15,371
Supercomputing TaihuLight - 00
Center in Wuxi Sunway MPP,
China Sunway
SW26010 260C
1.45GHz,
Sunway
NRCPC
1 DOE/SC/Oak Summit - IBM 2,282,54 122,300.0 187,659.3 8,806
Ridge National Power System 4
Laboratory AC922, IBM
United States POWER9 22C
3.07GHz,
NVIDIA Volta
GV100, Dual-
rail Mellanox
EDR Infiniband
IBM

14 Commissariat a Tera-1000-2 - 561,408 11,965.5 23,396.4 3,178


l'Energie Bull Sequana
Atomique (CEA) X1000, Intel
France Xeon Phi 7250
68C 1.4GHz,
Bull BXI 1.2
Bull, Atos
Group

29
Sisteme incorporate si SOC (System on Chip)
• Actualmente conceptul de sistem incorporat este din ce in
ce mai strâns legat de cel de SOC
• Un SOC este un circuit integrat monolitic complex care
înglobează (aproape) toate funcțiile si sub-sistemele
unui sistem de calcul complet sau a unui sistem
electronic specific, pe un singur microcircuit (cip)
– Funcții diverse si complexe, numerice, analogice, de semnal mixt
sau de radiofrecvență au fost implementate pe un singur
microcircuit
• Ca grad de integrare s-ar putea spune că este
următorul pas după microcontroler, dar in același timp
exista exemple in care majoritatea componentelor unui
calculator PC sunt integrate pe un singur cip
• De fapt termenul este mai mult o hiperbolă indicând o
direcție tehnică si nu neapărat o realitate: creșterea
gradului de integrare cu scopul micșorării costurilor de
producție si al miniaturizării sistemelor
• http://en.wikipedia.org/wiki/System_on_a_chip
30
SOC - System On a Chip
Au făcut posibila realizarea de
controlere la un raport performanță –
preț foarte bun!

Un exemplu (destul de vechi) este Intel


Atom CE4100, un SOC descris ca un
media processor: pentru set-top box,
DVD players si HD media players, dar
nu numai !
Alt exemplu este AMD GEODE LX,
un SOC descris ca având ca țintă
reducerea puterii consumate si a
prețului de cost
• proiectul One Laptop per Child
a folosit Geode LX ! 31
PC si SOC - System On a Chip
• Rockchip RK3288 - a fost primul SoC care a avut ca
unitate centrală un Quad-core ARM Cortex-A17
• Procesor grafic 3D GPU
• Primul SoC cu un decodificator video 4kx2k
• Si multe, multe altele..
• Utilizat la realizarea unui Chromebit (Asus Chromebit),
aflați si singuri ce este un Chromebit dacă nu știți incă..

32
SOC - System On a Chip
..un exemplu si mai nou
Succesul sistemelor Raspberry PI este indisolubil legat de
circuitele SoC ale firmei Broadcom
• Raspberry Pi 4 Model B BCM2711
• Raspberry Pi 3+ BCM2837B0
• Raspberry Pi 3 BCM2837
• Raspberry Pi 2 BCM2836
• Raspberry Pi 1 BCM2835

33
O paranteză: circuite numerice complexe
• Circuite numerice complexe, cu structură complexă si o funcționalitate
(cel puțin potențial) foarte complexă stau la baza realizării sistemelor
incorporate actuale ele fiind:
– Microprocesoarele si microcontrolerele (cu una sau mai multe unități centrale-CPU
cores)
– Circuitele FPGA (Field Programmable Gate Arrays), care fac parte din categoria
circuitelor logice programabile ce pot fi folosite pentru implementarea a una sau mai
multe unități centrale, de la cel simple la cele complexe (funcție si de complexitatea
circuitului FPGA)
– Circuitele de tip ASIC (Application-Specific Integrated Circuit).
– Circuite de tip ASSP (Application Specific Standard Product)
– Circuitele de tip SoC (System on Chip)
• Astfel de circuite sunt cele care ating astăzi o complexitate echivalentă de
peste 100 de milioane de porți
• Există si legături si zone de suprapunere intre categoriile de circuite
menționate mai sus : FPGA, ASIC, ASSP si SoC
• In 1979 a apărut cartea Introduction to VLSI Systems, scrisă de
Carver Mead (cel care a încetățenit termenul de legea lui Moore..) si Lynn
Conway, bazata pe materialul unui curs omonim de la MIT
(Massachusetts Institute of Technology)
• Momentul respectiv este descris in industria circuitelor integrate numerice
complexe ca fiind revoluția Mead & Conway (Mead & Conway revolution),
revoluție care a dus la modificarea radicală a modului in care se predă si
se învață in universități această meserie, a modului cum funcționează
actualmente aceasta industrie, bazată in mare parte pe utilizarea unor 34
unelte software care permit automatizarea procesului de proiectare si
producție
Circuite numerice complexe: despre o revoluție si
despre altele..
• Revoluția Mead & Conway a permis o organizare mult mai
eficientă a activității, si funcție de competente astfel că astăzi
există mai multe categorii de actori/firme/companii in domeniu:
– Fabless – principalele activități sunt cele de proiectare si vânzare a
circuitelor, nu au capacitate de producție sau capacitatea este
nesemnificativă, alții se ocupă de producție aceasta fiind sub-
contractata; exemple Qualcomm, Apple, AMD, NVidia
– Fab sau Foundry sau Pure-Play Semiconductor Foundry –
principala activitate este cea de producție a circuitelor (ca sub-
contractant), capacitatea de proiectare a lor este nesemnificativă;
exemple: TSMC (Taiwan Semiconductor Manufacturing Company),
GlobalFoundries, UMC (United Microelectronics Corporation)
– Integrated device manufacturer (cu fabricație integrată) – care are
capacitatea de a proiecta, a fabrica si de a vinde circuitele fabricate;
exemple: Intel, Texas Instruments, NXP, STMicroelectronics
• Distincția intre cele 3 categorii are însă tendința de a deveni mai
vagă, apărând numeroase suprapuneri de activități
• Ca să avem o idee de importanța domeniului Foundry, firma
TSMC (principala activitate localizată in Taiwan) a fost fondata in
1987 si are (cca. 2017) o cifră de afaceri de cca. 1000 de
miliarde USD, cu cca 50 000 de angajați, la o capitalizare
bursiera de cca 70 de miliarde USD
– GDP-ul Romaniei in 2017 este estimat, in cele 2 variante de calcul, la
cca 200 de miliarde USD sau 500 de miliarde USD 35
Circuite numerice complexe – scară/densitate de
integrare, ce înseamnă …xum, x nm?
• Este o măsură de performanță a procesului de fabricație (CMOS),
măsura care descrie dimensiunea caracteristică (feature width)
minimă optenabilă pentru componentele majore ale microcircuitului
– Vorbim deci de un proces (tehnologic) caracterizat de o anumită dimensiune
minimă a tranzistorului (care nu include detalii cum ar fi grosimea izolatorului de
grila)
– Dimensiunea minimă are legătura cu lungimea de undă a luminii care poate fi
utilizata in procesul fotolitografic!
• Cu cât dimensiunea este mai mică cu atât numărul de “tranzistoare” pe
unitatea de suprafață si respectiv pe întregul microcircuit este mai mare

• 10 µm – 1971, Intel 4004, câteva mii de tranzistoare, procesul era de fapt


PMOS
• 6 µm – 1974, Intel 8080
• 3 µm – 1977, Intel 8086 folosea un proces de 3.2 µm
• 1.5 µm – 1982
• 1 µm – 1985 , Intel 80386
• 800 nm – 1989, Intel 80486
• 600 nm – 1994, Intel Pentium, IBM/Motorola Power PC601
• 350 nm – 1995
• 250 nm – 1997, Intel Pentium II si III, ca lungime de unda suntem deja in Ultra
Violet!
• 180 nm – 1999, Intel Celeron 36
Circuite numerice complexe – scară/densitate de
integrare, ce înseamnă … x nm?

• 130 nm – 2001
• 90 nm – 2004, Intel Pentium 4, Elpida SDRAM DDR2, deja
încep sa fie folosite tehnologii speciale de fotolitografie
• 65 nm – 2006, Intel Xeon, un tranzistor are deja dimensiuni
de x100 de atomi, izolator de grila 1.2nm!
• 45 nm – 2008, Intel Atom, TI OMAP 3 si 4, IBM POWER 7,
Intel Core i7
• 32 nm – 2010, Samsung SDRAM DDR4
• 22 nm – 2012, Micron NAND FLASH, IBM POWER8
• 14 nm – 2014, Apple A9, IBM POWER9
• 10 nm – 2017, “10 nm class” înseamnă circuite intre
10nm si 20nm; IBM POWER 10, Apple A11 - are 4.3
miliarde de tranzistoare pe un die de 87.66 mm2
• 7 nm – ~2019
• 5 nm – ~2021
• Vezi
https://en.wikipedia.org/wiki/Semiconductor_device_fabricatio
n
37
Circuite numerice complexe: ASIC
• ASIC (Application-Specific Integrated Circuit).
• ASIC este un circuit integrat numeric complex dedicat implementării unei
aplicații particulare, mai degrabă decât unei utilizări generale.
– De exemplu circuitele de memorie sunt circuite numerice destinate unei utilizări
generale, in multe aplicații
• Un circuit ASIC este proiectat de o anumită companie (care poate fi si una
fabless – adică să nu aibă si producție de circuite) şi este de regulă produs
pentru un singur beneficiar (client) de către un fabricant de circuite
integrate numerice.
• Exista ASIC:
– Full-custom – totul este particularizat
– Semi-custom- partial particularizat, bazate pe celule standard (standard-cells), sau pe
arii de porți (gate arrays), sau programabile (folosesc circuite logice programabile,
inclusiv FPGA!)
• Un circuit ASIC prezintă la un moment dat multe asemănări cu un circuit
FPGA, dar, spre deosebire de FPGA, circuitele ASIC:
– Sunt mai rapide
– Consuma mai puțin
– Pot costa mai puțin
– Pot face mai multe
– Sunt mai dificil de “copiat” (reverse engineering)
• Una din aplicațiile circuitelor FPGA este de realiza si valida prototipuri pentru
viitoarele circuite ASIC

38
Circuite numerice complexe: ASIC
• Utilizatorul/clientul este cel care stabilește/definește
specificațiile (incluzând performanțele dorite) după care
circuitul va fi proiectat si apoi realizat
– Exemple tipice:
• Circuite utilizate in comunicațiile de date, cum ar fi un switch/router Ethernet proiectat
pentru un anumit client (sa zicem CISCO..) ca să îndeplinească anumite cerințe de
performanta si consum
• O bună parte din circuitele utilizate in telefoanele sau ceasurile Apple..
• Ca o alternativă la utilizarea GPU (Graphical Processing Unit) există acum si circuite
ASIC realizate pentru minarea de criptovalută (cryptocurrency mining ASIC), de
exemplu un ASIC Bitcoin Miner folosește mai multe astfel de circuite

39
Circuite numerice complexe : ASSP
• ASSP (Application Specific Standard Product) este tot un circuit integrat similar
ASIC prin faptul ca e dedicat unei anume categorii de aplicații, dar este destinat
mai multor utilizatori/aplicaţii (de aici şi "standard"), nu numai unui singur client
• Reprezintă de fapt o etapă intermediară intre ASIC si circuitele standardizate
(cum ar fi seriile standardizate 74 sau mai degrabă circuitele de memorie)
• Circuitele de tip ASSP sunt destinate mai multor clienți pentru că sunt de uz
general, dar aplicația este una specifică.
• Exemple tipice:
– controlere Ethernet (MAC si PHT), controlere/module Bluetooth, controlere sisteme de
afișare grafice de tip LCD, controlere de tip on-screen display(OSD), controlere/module
USB

40
Circuite numerice complexe: SoC
• Un circuit ASIC poate include, de exemplu, un microprocesor de 32
de biți împreună cu memorie şi periferice complexe (video,
comunicații, sunet, etc.), deci practic aproape un PC complet..
• Atunci avem de a face cu un SoC (System on Chip) prin care se
înțelege un sistem de calcul realizat pe un singur microcircuit.
– Un SoC propriu-zis include in mod obligatoriu un procesor, o unitate centrala
de natura unui microprocesor sau microcontroler
• ASIC/ASSP + Procesor=SoC
• ASIC/ASSP - Procesor=non-SoC
• Există însă si circuite MPSoC (Multiprocessor SoC) care înglobează
mai multe unități centrale (multi-core)
• Tehnologia digitală si tehnica de calcul contemporană incluzând
sistemele de calcul din categoria “la purtător” (wearable
computers) sau IoT (Internet of the Things) se bazează masiv pe
conceptul SoC!

Apple
A4=ASIC + Procesor=SoC

Raspberry Pi este bazat pe un


SoC de la Broadcom
41
Circuite numerice complexe: SoC
• SoC este în realitate o noțiune mai largă, ținând cont că, pe același
microcircuit (pastila de Si) sau nu, se pot integra si senzori de tip
MEMS - Micro-Electro-Mechanical Systems (bazați pe micro sau
nano tehnologii mecanice) cum ar fi accelerometre si/sau
giroscoape (gyro)
– Eventual SoC-ul este asociat si cu o încapsulare de tip SiP (System in a
Package)
– Circuite ASIC/SoC găsim si in: smartphones, tablets, wearable devices
• Circuitele FPGA complexe sunt si pot fi utilizate pentru a realiza
prototipuri parțiale sau totale pentru circuite de tip ASIC/SOC
• Mai mult, exista si SoC FPGA, PSoC FPGA, MSoC FPGA= unul
sau mai multe core-uri ARM + FPGA; exemplu Intel FPGA (Altera)
SOC sau Xilinx Zynq 7000

Inside Apple Watch


42
Sisteme incorporate si SiP (System-in-a -
Package)
• Reprezintă un ansamblu de circuite integrate , mai mult sau mai puțin
complexe, toate încapsulate într-o singură capsulă (package) de tip “purtător
de cipuri” (chip carrier) – el ar putea fi descris ca un cip format din mai multe
cipuri
• Un SiP este realizat in ideea de a implementa cât mai multe dintre funcțiile
unui sistem electronic complex, si in particular ale unui sistem incorporat
• Circuitele integrate componente sunt la nivel de die (pastilele de siliciu) si sunt
conectate intre ele printr-un substrat comun sau cu ajutorul unor fire in
interiorul capsulei
• Soluțiile de tip SiP presupun stăpânirea si utilizarea unor tehnologii complexe
de încapsulare (flip chip, wire bonding, wafer-level packaging)
• SiP face posibila si eliminarea unor constrângeri legate de dimensiuni si de
realizarea unor cablaje imprimate pentru circuite de mare viteza, lucru care
înseamnă până la urma reducerea costurilor de producție

De exemplu circuitele SAMA5D2 SiP


de la Microchip incorporează un
procesor de 32 de biți ARM Cortex A5
si o memorie SDRAM DDR2 (de până
la 1Gbit), împreună cu multe periferice
destinate conectivității, toate într-o
capsulă BGA
43
Sisteme incorporate si SOM (System-On-a -
Module)
• Reprezintă un ansamblu de circuite integrate, mai mult sau mai
puțin complexe, asamblate , împreună cu alte componente ale
sistemului, pe un cablaj imprimat miniaturizat care este încapsulat
într-o capsula (package) asemănătoare celei pentru circuite
integrate monolitice
• Si un SOM este realizat in ideea de a include cât mai multe (daca
se poate chiar toate) dintre funcțiile unui sistem electronic complex,
si in particular ale unui sistem incorporat
• SOM poate fi reutilizat cu ușurință in mai multe proiecte de tip
sistem incorporat ducând la reducerea costurilor de producție

44
Arhitectura hardware a unui sistem incorporat:
funcții si subsisteme, implementarea cu MPU
Funcțiile si
Microcontroler (MPU) subsistemele
sunt realizate
Temporizare/ de perifericele
Memorie
numărare
Intrări Ieşiri microcontrolerului
numerice numerice
Sistem
Senzori/ întreruperi Elemente
traductoare de execuţie
CAN CNA
Intrari Sisteme CPU Iesiri
analogice analogice
comunicaţie

Interfaţa Dispozitive Sisteme


Om diagnoza si auxiliare:
Maşina testare alimentare,
răcire
Mediul
exterior: proces, 45
instalaţie
Arhitectura hardware a unui sistem incorporat: funcții
si subsisteme, implementarea cu un controler COTS
Funcțiile si
subsistemele
Sisteme
Controler auxiliare:
sunt realizate
de module (plăci)
alimentare,
Temporizare/ răcire
conectate cu ajutorul
numărare Memorie unor magistrale
Intrări Ieşiri externe (de tip fund
numerice numerice de sertar-backplane)
Sistem
Senzori/ întreruperi
Elemente
traductoare CAN CNA de execuţie
Intrari Sisteme CPU Iesiri
analogice analogice
comunicaţie

Interfaţa Dispozitive
Om diagnoza si
Chiar si unitatea
Maşina testare
centrală CPU este tot
Mediul un modul
exterior: proces,
46
instalaţie
Ce este însă un controler?
• Pană să ajungem la microcontrolere să discutăm puțin despre
controlere..
• Controler ("controller" - un termen de origine anglo-saxonă, cu un
domeniu de cuprindere foarte larg) este, actualmente, o structură
electronică numerică destinată controlului (destul de evident!) unui
proces sau, mai general, unei interacțiuni caracteristice cu mediul
exterior, fără să fie necesară intervenția operatorului uman.
• Cronologic, primele controlere au existat in variante de implementare
mecanică (de acum sute de ani..), electromecanică, analogică si apoi
numerică, cu relee, tuburi electronice si apoi cu componente discrete
semiconductoare si/sau cu circuite integrate din serii standardizate
• Microcontrolerele si microprocesoarele au permis însă realizarea
de sisteme incorporate care implementează, in tehnologie numerică,
cele mai performante controlere ce stau la baza civilizației
tehnologice actuale
– Așa cum vom vedea in continuare este posibila realizarea de controlere
folosind si sisteme de calcul de uz general (daca tot sunt de uz general..)

47
Ce este un controler?

Tot un controler este (a fost..), dar unul pur mecanic!

48
Sisteme incorporate si controlere:
soluția COTS
Controlerele sunt sisteme incorporate construite însă cu
un hardware(HW) de uz general (general purpose
hardware), eventual utilizat si la realizarea de
calculatoare personale, si/sau cu cat mai puțin
hardware dedicat (adică construit special pentru o
anumita aplicație).
– Efortul de proiectare HW este minimizat pentru lansarea rapidă
pe piață, minimizarea timpului de apariție pe piața (Time to
Market)
– Suportul hardware de dezvoltare este si el cumpărat: tot pentru
minimizarea timpului de apariție pe piața
– Efortul este orientat spre dezvoltarea funcțiilor în SW, cele
care diferențiază produsul de altele similare
– Hardware: COTS – Components Of The Shelf sau Commercial
Off-The-Shelf, componente care deja există, in comerț, la “raft”
– Software: si aici există COTS – biblioteci, module deja
existente pe piață, dezvoltate pentru alte aplicații, dar care pot
fi reutilizate
– Vezi si http://en.wikipedia.org/wiki/Commercial_off-the-shelf
49
Controlerele – un altfel de sisteme
incorporate ..
• Majoritatea controlerelor realizează diverse sarcini care presupun interacțiunea
în timp real cu mediul înconjurător.
• Termenul mai corect si complet ar fi controlere industriale
• Implementarea lor se face ca sisteme de calcul de sine stătătoare bazate tipic pe
procesoare de 32 de biți, cu capacități de extindere limitate, fiind de regulă
orientate pe o anumită aplicație de control.
• O caracteristică, des întâlnită la aceste sisteme, este absența unui sistem
extern de stocare a informației de tip hard disk electromecanic (HDD
clasic).
– Această caracteristică provine de regulă, de la anumite cerințe legate de mediul de utilizare al
controlerului (șocuri şi vibrații excesive, praf, condiții extreme de temperatură): fără piese in
mișcare
– Fără piese in mișcare înseamnă si fără ventilator de răcire – fanless, răcirea circuitelor
făcând-se prin convecție naturala, folosind doar radiatoare!
• Se utilizează un tip special de hard disk numit generic Flash Disk, fără piese în
mișcare, realizat pe baza tehnologiei NAND FLASH .
• Majoritatea utilizează, memorate pe Flash Disk alaturi de aplicatie, mai mult
sau mai puţin vizibil pentru utilizator, sisteme de operare:
– variante speciale (zise embedded - incorporate) ale sistemelor de operare
cunoscute, utilizabile pentru astfel de cazuri, cum ar fi ROM-DOS, Windows CE,
variante de Embedded Windows actualmente devenit Windows IoT, Embedded
Linux, etc. sau
– sisteme de operare in timp real (RTOS): VxWorks, QNX, eCOS, etc. 50
NAND FLASH (Disk) – SSD si restul..

SSD, e.MMC, UFS =?


Puteți găsi si singuri
răspunsul..
Nu toate sunt însă
adecvate pentru 51
aplicații industriale!
O paranteza: NAND FLASH vs. NOR
FLASH
• Tehnologia NAND FLASH este o tehnologie de acces
la memorie de tip secvențial, care a fost destinată
încă de la început înlocuirii hard-diskurilor (HDD)
clasice
• Un NAND FLASH este utilizat prin intermediul unui
sistem de fișiere!
• Un NAND FLASH nu poate fi utilizat direct ca o
memorie de program nevolatilă, pentru nici un sistem
de calcul, deoarece aceasta utilizare ar presupune un
acces aleator la informația din memorie
• Singurele circuite FLASH care pot fi utilizate in acest
scop, ca memorie de program, sunt cele in
tehnologia numită NOR FLASH, la care accesul la
citire e similar circuitelor RAM

52
Controlere: memorii, periferice si magistrale
• În situaţia în care programul trebuie să aibă un suport nevolatil
(ROM, EPROM sau FLASH) dar viteza de execuţie este critică,
codul respectiv poate fi copiat într-o memorie RAM dedicată, cu
un timp de acces oricum mai mic decât cel al suportului nevolatil.
• Variabilele sau subrutinele utilizate mai des ( cum ar fi rutinele de
tratare a întreruperilor şi stivele lor aferente) pot fi plasate
permanent în memoria cache internă, ducând la un spor de
performanţă remarcabil.
• Tipic, sistemele de tip controler au necesităţi de memorie mai mici
ca alte aplicaţii, iar aplicaţiile în sine pot avea o componentă
importantă scrisă în limbaj de asamblare, putând interacţiona direct
cu dispozitivele I/O şi memoria.
• Perifericele dedicate (sisteme de conversie analog - numerică sau
numeric analogică, intrări/ ieşiri numerice, sisteme de temporizare-
numărare, etc.) sunt conectate prin intermediul unor magistrale de
sistem.
• Variantele de magistrale utilizate sunt alese funcţie de viteza de
transfer necesară: ISA mai rar (sau mai des in varianta PC-104)
precum şi PCI (sau varianta PC-104 Plus)

53
Controlere: nu arată ca un desktop
PC..

Si variante care se conectează intr-un


“fund de sertar” activ (active backplane)
http://en.wikipedia.org/wiki/Backplane
Exista variante de
sine stătătoare..

54
Controlere: COM
• Conceptul COM (Computer On Module): un sistem de calcul pe un singur
modul (placă): unitate centrală, controlere de memorie, interfață video si
interfețe de comunicație
– http://en.wikipedia.org/wiki/Computer-on-module
• A devenit posibil, la un preț accesibil, numai datorită dezvoltării explozive a
tehnologiilor SOC (Sistem On a Chip)
• Denumiri/concepte alternative/similare: SBC (Single Board Computer), SOM
(System On Module)
• Pe o singură placă, pe lângă CPU va exista memorie (SDRAM, FLASH)
precum si setul specific de periferice pentru un SCUG (de fapt o bună parte
din ele si pentru un desktop PC)
– Periferice specifice unui controler, cum sistemele de conversie analog-numerice
sau numeric-analogice sunt disponibile ca module separate
• In mod tipic modulul se utilizează pe o placă “purtătoare” (carrier board,
base board) care permite accesul la resursele periferice si acces la
magistrale de sistem(conectori, socluri, etc.)
• Utilizarea lor oferă soluții compacte dimensional pentru implementarea
hardware/software a unui sistem incorporat
– Pe lângă sistemele fără ventilator (fan-less) exista însă si sisteme care folosesc o
răcire forțată dar la care nu exista o legătură intre circuitul intern de aer/lichid si
mediul extern (mult mai scumpe!)
55
Controlere: COM, ETX

• ETX (Embedded Technology eXtended), este un


factor de forma standardizat destul de compact (95 x
125 mm) utilizat la realizarea COM
– http://en.wikipedia.org/wiki/ETX_%28form_factor%29
• Există si ETX Express de fapt, mai corect COM
Express, pentru că nu are nici o legătură cu ETX
• Factorii de formă pentru COM Express sunt:
– 110mm ×155mm (extins),
– 95 mm × 125 mm (baza) si
– 95 mm x 95 mm (compact)

56
Controlere: COM, ETX

57
Controlere, factor de formă ultra-
compact: nano-ETX, DIMM-PC
Nano-ETX (55mm x 84mm)

Exemplu de “placă
purtătoare” (carrier board)

DIMM-PC (68mm x 40mm)


Utilizează acelaşi conector ca
un modul de memorie DIMM
58
59
Controlere: PISA (PCISA – încă se mai
utilizează antica magistrală PC de tip ISA !)
Un astfel de controler este bazat pe un fund
de sertar (passive backplane)
Este o construcţie pasivă:
- doar conectori ISA si PCI
- capacitori, rezistori, eventual si elemente
de protectie

In afară de module, din care cel


puţin un CPU, mai avem nevoie si
de o sursă de alimentare.

Module de tip unitate centrală (CPU) care se montează


60
in fundul de sertar
Controlere: magistrala PC-104(+)
• Magistrala PC/104 reprezintă o modificare, a factor de formă, a vechii
magistrale sincrone ISA (Industry Standard Architecture) IBM, fiind
destinată numai unor aplicații din domeniul industrial.
• PC/104 are câteva de semnale suplimentare și diferă esențial de ISA
din punct de vedere mecanic, având un factor de forma foarte
compact, pentru a permite interconectarea prin suprapunere (stacking)
a mai multor module PC/104
• Practic, conectorii sunt astfel realizați, pe partea cu piesele (component
side) si respectiv pe cea cu sudurile (solder side), încât plăcile se “înfig”
una in alta
• Din modulele conectate prin suprapunere cel puţin unul conţine o
unitate centrală (este modul de tip CPU).
• Astfel pentru magistrala PC/104 există două tipuri de module: CPU şi
respectiv alte module (diverse categorii de periferice, controlere,
memorie, etc).
• Semnalele sunt grupate în conectori astfel încât să se poată realiza
complet o interfaţă de 8 biţi folosind numai un conector (numit şi XT)
sau o interfaţă completă de 16 biţi folosind ambii conectori (cel de-al
doilea conector mai este numit şi AT)
• Evident, o astfel de stivă (stack) PC-104 mai trebuie si alimentată!
• OBS PC-104 Plus (+) utilizează o adaptare a magistralei PCI care nu 61
are nici o legătură cu magistrala ISA!
Controlere: PC-104, PC-104+

O stivă
PC-104
PC-104 stack

PC-104+ (PCI)
120pini

In stivă există cel puţin


PC-104 (ISA) un modul CPU
104 pini
Cei 2 conectori: XT si AT 62
Controlere: PC-104, PC-104+
http://en.wikipedia.org/wiki/PC/104

PC-104

PC-104+

63
Aici, la “baza” stivei este o sursa de alimentare
Arhitecturi software: o comparație SI cu
SCUG
Aplicaţii sau
Aplicaţii
aplicaţie

Middleware: Middleware:
biblioteci, API .. biblioteci, API, BSP..

Sistem de operare: Sistem de operare:


Windows, Linux, un RTOS, Linux sau Windows
MacOS embedded
Firmware si
Firmware: Firmware: aplicaţie
BIOS, drivere,.. Bootloader, BSP
Start_up

Hardware Hardware
Hardware

PC/SCUG SI complex/ controler SI simplu


Sisteme de Calcul de Uz General Sisteme incorporate 64
Ce ar trebui să însemne firmware?
• Un program, tipic de dimensiuni relativ mici(denumit uneori si
microprogram – a nu îl confunda cu microprogramarea!), cu
funcţii de control direct al hardware-ului, care este
instalat/programat in faza de producţie / fabricaţie intr-o
memorie de tip nevolatil (ROM, PROM, EPROM, EEPROM,
FLASH) a unui dispozitiv informatic.
– Acest cod cuprinde un ansamblu ordonat de instrucţiuni si date memorate
de o manieră care se doreşte, din punct de vedere funcţional, cât mai
independentă de arhitectura memoriei sistemului de calcul
• Tipic, actualizarea lui se face mai rar, si este mai complicată
procedural decât actualizarea unei aplicații software obișnuite
• Un exemplu de firmware este si ROM BIOS-ul întâlnit la
calculatoarele personale (SCUG)
• Mai există si termenul de middleware, un program care
furnizează servicii aplicațiilor, servicii care, din diverse motive,
nu sunt oferite de sistemul de operare; in general middleware
este orientat pe comunicații si operații de intrare - ieșire

65
Controlere: arhitectura software
• In mod tipic aplicațiile de tip sistem incorporat care sunt dezvoltate pentru
astfel de controlere utilizează un sistem de operare incorporat (sistem clasic
sau sistem de timp real)
• Unitățile centrale din această categorie sunt livrate de producător si împreună
cu cea ce se numește un pachet software suport BSP - Board Support
Package; practic toți furnizorii de sisteme de operare de timp real (RTOS) oferă
BSP specifice livrate pentru un anumit hardware
• Un BSP reprezintă un pachet software suport pentru o anumită “placă”/CPU,
pentru un anumit sistem de operare (de ex. Linux, Windows IoT, VxWorks,
etc.)
• El asigură încărcarea sistemului de operare precum si driverele necesare
pentru utilizarea unei game largi de periferice/interfețe
– El este un exemplu de software dependent de hardware si deci poate fi încadrat la categoria
firmware si parțial la middleware
• De exemplu fac parte din BSP:
– Bootloader-ul, pentru sistemele complexe este responsabil cu încărcarea si
lansarea in execuție a sistemului de operare
– Pentru sistemele incoprorate simple, bootloader-ul este cel care realizează
programarea aplicației in memoria de program (vezi bootloader AVR de la Arduino)
– Porțiunile de cod care realizează diverse inițializări ale perifericelor, ale memoriei,
ale sistemului de întreruperi, etc.
– Vezi: http://en.wikipedia.org/wiki/Board_support_package (un articol incomplet..)
66
Microcontrolere (si
microprocesoare)
Microcontrolere: introducere, o
prezentare generală, aplicații,
caracteristici, familii reprezentative,
limbaje de programare, testarea si
depanarea aplicațiilor, criterii de alegere
a unui microcontroler

1
Controler?
• Controler ("controller" - un termen de origine anglo-saxonă, cu un
domeniu de cuprindere foarte larg) este, in ziua de azi, o structură
electronică numerică destinată controlului (destul de evident!)
unui proces sau, mai general, unei interacțiuni caracteristice cu
mediul exterior, fără să fie necesară intervenția operatorului
uman.
– Nu in ultimul rând astăzi un controler este aproape sinonim cu un sistem
incorporat si deci cu o aplicație a microcontrolerelor
• Microcontrolerele si microprocesoarele au permis realizarea
celor mai performante controlere, in tehnologie numerică, care stau
la baza civilizației tehnologice actuale
• Trebuie menționat că actualmente diferențele hardware intre
microprocesoare, microcontrolere si procesoarele numerice
de semnal devin din ce in ce mai vagi, astfel că putem vorbi (si
vom vorbi) mai mult sau mai puțin generic despre aceste categorii,
care nu mai sunt atât de specializate cum erau pe vremuri.
• Mai trebuie spus si că in afară de soluțiile COTS de care am amintit
anterior, există si alte soluții cvasi standardizate ca hardware si
software pentru a realiza un controler (de care nu ne ocupam aici),
cum ar controlerele logice programabile – PLC Programmable
Logic Controller
2
De ce am utiliza un microcontroler?
• Utilizarea unui microcontroler constituie o soluție prin care se pot reduce
dramatic:
– numărul componentelor electronice
– costurile de proiectare şi dezvoltare ale unui produs de natura unui sistem incorporat.

• Un efect secundar benefic este si creșterea fiabilității aplicației/sistemului


prin:
– reducerea numărului de componente si interconexiuni externe (conectori, cablaje, etc.)
– reducerea puterii consumate si aferent a disipației termice

• OBSERVAŢIE IMPORTANTA
Utilizarea unui microcontroler, oricât de evoluat, in industrie, NU elimină si NU va
elimina prea curând unele componente ale interfeței cu mediul exterior,
componente care nu pot fi integrate la costuri decente (atunci când ele sunt
chiar necesare):
- anumite subsisteme de prelucrare analogică de precizie (amplificare, redresare,
filtrare, protecție-limitare)
- elemente pentru realizarea izolării galvanice (optocuploare, transformatoare),
- elemente de comutație de putere (tranzistoare de putere, relee electromecanice
sau statice)
- anumite componente de radiofrecvență

3
Unde sunt utilizate microcontrolerele?

Zeci si zeci de microcontrolere!


4
Unde sunt utilizate microcontrolerele?

Cel puțin un microcontroler per entitate! 5


Unde sunt utilizate microcontrolerele?

6
Zeci de microcontrolere!
Clasificări și variante constructive de
microcontrolere
• Există la ora actuală un număr extrem de mare de tipuri constructive
de microcontrolere.
• Un criteriu de clasificare este lungimea (dimensiunea) cuvântului de
date.
• Funcție de puterea de calcul dorită şi de alte caracteristici se pot alege
variante având dimensiunea cuvântului de date de 4, 8,16 32 sau 64 de
biţi!
– Nu este obligatoriu ca dimensiunea cuvântului de date să fie egală cu dimensiunea unui
cuvânt mașină (cuvânt program).
• Mai există şi variante zise dedicate, neprogramabile de utilizator la
nivel de cod maşină, strict specializate pe o anumită aplicație, prin
intermediul codului preprogramat şi al resurselor hardware, utilizate
pentru comunicații, controlul tastaturilor, controlul aparaturii audio/video,
prelucrarea numerică a semnalului, etc.

7
Tehnologiile de fabricație utilizate:
procese tehnologice CMOS
• Practic, toate microcontrolerele se realizează la ora actuală în tehnologie CMOS (tehnologii
moderne, similare celor utilizate la seriile standard CMOS de circuite numerice: HC, AC, ALV, etc.).
• Se pot realiza astfel structuri cu o densitate mare de integrare, cu un consum redus (care va
depinde totuși de frecvența de lucru), permițând eventual alimentarea de la surse independente
(baterie).
– Logica internă este statică (total sau în cea mai mare parte) permițând astfel, în anumite condiții, micșorarea
frecvenței de ceas sau chiar oprirea ceasului în ideea optimizării consumului.
• Tehnologiile curente sunt caracterizate şi de o imunitate mai mare la perturbații, sensibilitate
mai mică la fenomenul de zăvorâre (latch-up) esențială într-un mare număr de aplicații specifice.
• Se realizează si variante cu tensiunea de alimentare nominală (sau extinsă) in plaja 0.9V … 6V
• Pe lângă variantele uzuale cu domeniu zis comercial al temperaturii de lucru de la 0 ..+70 oC, se
realizează variante pentru domenii specifice de utilizare, zise domeniu extins (extended range)
al temperaturii de funcționare, de exemplu: industrial - 40 ..+85 oC, automotive -40 ..+125 o C
• Există si microcontrolere din familii cunoscute care sunt special construite (cu procese CMOS
SOS sau SOI) si certificate pentru a funcționa corect in medii cu radiație ionizanta: atmosfera
superioară, spațiul cosmic, industria nucleară – circuite zise radHard (radiation hardened) –
rezistente la radiațiile ionizante (game, X, neutroni, alfa)

8
Tehnologiile de fabricație utilizate:
încapsularea (packaging)
• Există foarte multe variante de încapsulare (capsule –packages- de
plastic şi mai rar de ceramică), multe din ele destinate montării pe
suprafață (SMT/SMD): SOIC, PLCC, PQFP, TQFP, BGA (x100 ..x1000
pini), etc., dar şi variante clasice cu pini, tip DIP/DIL (tipic de la 6 la 68
pini).
– Capsulele clasice DIP/DIL destinate montării pin-through sunt din ce in ce mai puțin
disponibile pe piață!

9
Aspecte legate de implementarea
memoriei microcontrolerelor
• În afară de memoria locală de tip RAM, de dimensiuni relativ reduse (de la
x10 octeţi la x1k), implementată ca atare sau existentă sub forma unui set
de registre şi destinată memorării datelor (variabilelor), mai există o serie
de aspecte specifice, marea majoritate a acestora fiind legată de
implementarea fizică a memoriei de program (şi eventual a unei părţi a
memoriei de date) cu ajutorul unor memorii nevolatile.
• In mod clasic, memoria de program era implementată într-o variantă de
tip ROM: EPROM pentru dezvoltare şi producție pe scară mică/medie sau
mask-ROM pentru producția de masă.
• Principalele concepte noi apărute de-a lungul timpului în legătură cu
implementarea memoriei de program si/sau date sunt legate in primul rând
dezvoltarea tehnologiilor NOR FLASH si EEPROM si sunt prezentate în
continuare

10
Implementarea memoriei –
memoria de program
• OTP – mai există încă producători care oferă variante de
microcontrolere la care memoria locală de program este de tip OTP
(One Time Programmable), practic o memorie PROM identică
intern cu una EPROM, dar fără fereastra de cuarț pentru ștergere
(deci şi mai ieftine); memoria se poate programa o singura data ca
o memorie EPROM, dar nu mai poate fi ștearsă/reprogramata ne
mai putând fi expusa la radiație UV
– aceste variante pot fi utilizate ca o alternativă pentru o producție
limitată, până în momentul testării și validării finale a codului, moment
în care pot fi comandate variantele (mask) ROM propriu-zise, cele mai
economice pentru o producție de masă
– conceptul OTP este utilizat, mai recent, si pentru a asigura securizarea
aplicației
• (NOR) FLASH EPROM – este practic soluția care a înlocuit
EPROM-ul propriu-zis care poate asigura azi un volum foarte mare
de memorie de program (nevolatilă) interna;
– Mai rapidă şi cu un număr garantat suficient de mare ( cca. 10000) de
cicluri de programare (de ștergere/scriere), este caracterizată şi prin
modalități mai flexibile de (auto)programare ;
– La ora actuală NOR FLASH este soluția standard pentru
implementarea memoriei de program.

11
Implementarea memoriei –
memoria de program
• EEPROM - multe microcontrolere au și o memorie de acest tip,
de dimensiune limitată (de la x10 octeți la x K octeți), destinată
memorării unui număr limitat de parametrii (ca memorie de
date constante/nevolatile) care eventual trebuie modificați din
timp în timp;
– Este o memorie mai scumpă, relativ lentă (la scriere), dar cu un număr
de cicluri de ștergere/scriere mai mare ca FLASH-ul (de la 100 000 la
1000 000).
– Actualmente este soluția standard pentru implementarea unei memorii
nevolatile de date
• FRAM (RAM feroelectric)- există la ora actuală putine familii
care utilizează acest tip de memorie nevolatila, relativ scumpă,
dar cu un număr practic nelimitat de cicluri de scriere
• NOVRAM (RAM nevolatil) - realizat prin alimentarea locală
(baterie sau acumulator cu Li) a unui masiv RAM CMOS atunci
când este necesar un volum mare de memorie de program și
date nevolatilă;
– Mult mai scumpă, dar mult mai rapidă decât toate celelalte tipuri și fără
limitări ca număr de cicluri.
12
Implementarea memoriei de program
- ISP
• Programarea "In Sistem" (ISP- In System Programming)
– folosirea unor memorii nevolatile de tip FLASH face posibilă şi
"programarea" unui astfel de microcontroler fără a-l scoate din sistemul în
care este încorporat (programare on-line, In System Programming);
– programarea ISP se face de regulă prin intermediul unei interfețe seriale
dedicate de tip ISP (poate avea nume diferite) sau a unei interfețe standard
JTAG.
– Există microcontrolere la care această programare ISP se poate face prin
intermediul portului serial asincron sau al unei interfețe seriale CAN
(Controller Area Network) dar cu ajutorul unui program bootloader (vezi
paragraful următor).
– Este posibilă astfel modificarea/actualizarea cu relativă cu ușurință a codului
programului sau a unor constante de lucru (local sau de la distanță - remote
update).
• Un lucru foarte important este că la anumite familii interfaţa prin intermediul
căreia se face programarea ISP poate fi utilizată şi la testarea şi depanarea
aplicației (soft), permiţând realizarea simplă, cu un preţ de cost minim, a unor
mijloace de testare şi depanare(emulatoare).
– De exemplu, în acest caz interfața JTAG este specificată ca fiind JTAG/ICE (In Circuit
Emulation) pentru a arăta că poate fi folosită şi pentru emularea în circuit.

13
Programarea in sistem ( In – Circuit)
Utilizată pentru memoria internă de tip FLASH a
microcontrolerelor
- circuitul rămâne conectat in sistem, programarea se face printr-o
modalitate/conexiune serială, cu ajutorul unui număr minim de interconexiuni/fire
Programatorul (aici el este de fapt este un emulator ICE-JTAG)
in-circuit (conectat la PC-ul gazdă)
Cablu/conector
Circuitul de programat programare

14
Programarea in afara sistemului (Off-System), cu utilizarea
programatoarelor (universale) pentru programarea memoriei
microcontrolerelor: EPROM (si OTP), NOR FLASH, EEPROM
- tipic doar pentru circuite cu capsula DIL
- interfața cu sistemul gazdă -Host (tipic un PC): de tip USB
- utilizează un soclu ZIF (Zero Insertion Force) de 40 de pini
- pentru alte tipuri de capsule (SMT, SMD) se utilizează
adaptoare DIL -> …. (f. scumpe in general!)

Pentru microcontrolere reprezintă deja o metodă învechită, 15


care este (va fi) total înlocuită de programarea ISP!
Implementarea memoriei -bootloader
• Programul de încărcare rezident:
Bootloader
– Multe din microcontrolerele recente la care
memoria de program este de tip NOR FLASH
au şi facilitatea (au de fapt au instrucțiuni
dedicate acestui scop) de a putea şi scrie în
această memorie de program fără a utiliza
un circuit de programare extern.
– Aceasta se întâmpla însă in secțiuni/ blocuri
diferite (cu proprietăți diferite) ale acestei
memorii, secțiuni denumite de bootloader (o
secțiune de mici dimensiuni) si de aplicații
(restul memoriei)!
– Codul care se execută in secțiunea de
bootloader va scrie in secțiunea de aplicații!
– Altcumva nu se poate scrie in aceiași secțiune
(bloc) de memorie din care se citește si se
execută cod!
– Astfel în microcontroler poate exista permanent
(rezident) un program/cod de mici dimensiuni
(denumit şi bootloader), la reset, poate încărca
prin intermediul portului serial standard (de
exemplu) codul utilizator si/sau constantele pe
care acesta vrea eventual să le actualizeze.
– Bootloader-ul este şi cel care lansează în
execuție programul utilizator după
încărcarea/programarea acestuia. 16
Implementarea memoriei – considerente
legate de securitatea aplicației
• Protejarea codului program (care este o formă a proprietății intelectuale
- IP)
• Protejarea codului program dintr-o memorie locală nevolatilă împotriva
accesului neautorizat este oferită ca o opțiune (ea mai trebuie şi folosită!)
la toate variantele de memorii interne de tip FLASH, EPROM sau OTP.
– Codul poate protejat atât la citire cât şi la scriere (practic circuitul va trebui
şters, înainte de a se mai putea scrie ceva în el).
– Este eliminată astfel si posibilitatea de a se realiza, în acest caz, de patch-uri
(alterări cu un anumit scop) ale codului original.
– La variantele mask-ROM propriu-zis protecția este de cele mai multe ori
implicită (nu mai exista mecanism de acces extern la secțiunile respective de
memorie); din păcate exista căi (dificile) pentru a accesa intr-un fel sau altul si
o astfel de memorie!
• Integritatea codului program – este tipic verificată cu ajutorul unei sume
de control (checksum) calculată pentru întreg codul si programată într-o
locație prestabilită; verificarea se face prin recalcularea sumei cu același
algoritm (de exemplu CRC 16 sau CRC32) si compararea cu valoarea
programată, odată cu programarea codului in memoria de program si
eventual înainte de lansarea in execuție
• Aceasta modalitate simplă de verificare a integrității nu garantează însă si
autenticitatea codului care trebuie programat! 17
Implementarea memoriei de
program si date – memoria externa
• Utilizarea de memorie externă de program sau date
– Marea majoritate a familiilor de microcontrolere permit principial si
utilizarea de memorie externă de program (tipic ROM) sau date (tipic
RAM).
– Fizic aceasta presupune existenta si utilizarea unor magistrale
externe de adrese, date si control.
– Conexiunile externe necesare pentru aceste magistrale sunt
disponibile ca funcţii alternative ale pinilor de intrare/iesire.
– Din păcate, dacă utilizăm magistrale externe, numărul de conexiuni
exterioare disponibile pentru interfața cu exteriorul se reduce
dramatic, reducând mult din versatilitatea si utilitatea
microcontrolerului.
– La variantele constructive cu un număr mic de pini (de conexiuni
externe) nu este posibilă utilizarea de memorie externă, decât,
eventual, într-o variantă cu interfață serială (memorii SRAM,
FLASH sau EEPROM cu interfață I2C, SPI, etc.) si numai ca
memorie de date.

18
Implementarea memoriei de program – alte
considerente legate de securitate
• Cum știe microcontrolerul daca un cod care trebuie
programat in memoria lui de program (firmware-ul) este unul
autentic si nemodificat?
– Este o întrebare autentica si importanta in contextul actual al
cibersecurității care a devenit din ce in ce mai important si in domeniul
sistemelor incorporate
– Vezi: https://en.wikipedia.org/wiki/Automotive_hacking,
https://en.wikipedia.org/wiki/Stuxnet
– Actualmente se folosește un sistem de chei criptografice publice si
private care permite autentificarea
– Dezvoltatorul are acces la o cheie privată cu ajutorul căreia “semnează”
codul criptat
– Microcontrolerul are acces la o cheie publică care este programată intr-
un circuit dedicat si care nu poate fi modificată (există mai mulți
producători de astfel de circuite, de exemplu Dallas sau Microchip,
circuite care sunt conectate la microcontroler printr-o interfață seriala
I2C sau SPI) si folosește aceasta cheie la decriptare
– Hash-ul criptografic care este realizat de un circuit dedicat- un
accelerator criptografic- cu o încărcare suplimentară minimă pentru
unitatea centrală a microcontrolerului, este cel va detecta orice
eventuală modificare a codului ce se vrea programat, intenționată sau
nu
Vezi prezentarea Securitate & IoT. 19
20
Controlul puterii consumate şi
alimentarea la tensiuni reduse
• Tensiunea de alimentare standard pentru microcontrolere a fost mult timp, din
considerente şi istorice (vezi circuitele TTL clasice/moderne), de Vcc = 5V (cu o anumită
toleranță).
• La fel ca si in cazul circuitelor integrate numerice standardizate si aici avem de face cu o
migrație către tensiuni de alimentare mai mici de 5V
– Circuite cu Vcc =5 V mai exista datorita unui (singur) avantaj al acestei tensiuni de alimentare: o margine
de zgomot mai mare si (potențial) o imunitate la zgomot mai mare
• La ora actuală se oferă, pentru majoritatea familiilor reprezentative de microcontrolere,
variante cu tensiune de alimentare redusă (LV- Low Voltage) cu Vcc = 0.9 .. 1.2 ..1.8 ..
2.5 .. 3.3V, destinate eventual si unor aplicații unde consumul este un parametru critic.
• Există variante care folosesc 2 tensiuni (si 2 borne) de alimentare: una redusă pentru
unitatea centrală si perifericele interne (un VCC core) si una mai mare, tipic 5V pentru
interfețele numerice cu exteriorul (un Vcc IO)
• Există si variante cu plajă mare a tensiunii de alimentare, de exemplu Vcc = 2..6V
• Pentru că avem totuși de a face cu circuite CMOS, funcționarea la limita inferioară a
tensiunii de alimentare implica însă o micșorare a frecvenței maxime de ceas sistem.

21
Controlul puterii consumate şi
alimentarea la tensiuni reduse
• Majoritatea microcontrolerelor pot fi trecute sub control soft în stări
speciale cum ar fi: în aşteptare (STAND-BY), inactiv ("IDLE") sau oprit
("HALT", "POWER DOWN"), denumirile acestor stări diferind şi funcție
de fabricant.
• În aceste moduri starea CPU, conținutul RAM-ului intern, starea I/O-
urilor poate fi conservată în condițiile unei tensiuni de alimentare
reduse (faţă de cea nominală) şi deci al unui consum mult redus.
• Fiind vorba de circuite CMOS flexibilitatea acestui sistem este strâns
legată de facilitățile si programabilitatea sistemului de generare a
ceasului de lucru (sistem si periferice)
• Se mai oferă uneori ca facilitate o protecție la scăderea accidentală (în
anumite limite) a tensiunii de alimentare ("brownout protection").
– La scăderea tensiunii de alimentare sub o anumită limită ("brownout
voltage") microcontrolerul este inițializat (resetat) şi ţinut în această stare
atâta timp cât condiția respectivă persistă.

22
Sistemul de generare a ceasului
• Orice microcontroler este caracterizat cel puțin de existenta circuitelor electronice
aferente oscilatorului care generează ceasul de sistem.
• Astfel este posibilă implementarea simplă a oscilatorului doar prin adăugarea, în
exterior, a unui rezonator extern (cuarț sau piezoceramic) pentru stabilizarea
frecvenței si eventual a unor capacitori.
• Dacă stabilitatea si precizia frecvenței nu este o cerință importantă, la anumite
microcontrolere se poate utiliza doar un circuit RC extern sau există un circuit RC
intern, care determină frecvența de oscilație.
• Există microcontrolere la care configurația oscilatorului este programabilă prin
intermediul unor „fuzibile”-fuses FLASH (se programează similar memoriei de
program): rezonator extern şi tipul acestuia, varianta RC intern sau extern, gama de
frecvenţă, etc.
• La familiile evoluate/moderne de microcontrolere există si circuite de tip PLL (Phase
Locked Loop)-bucle cu calare de faza si/sau FLL (Frequency Locked Loop) – bucle
cu calare de frecvență care permit multiplicarea cu ușurință a frecvenței de bază (cea
a rezonatorului extern).
– Astfel plecând, de exemplu de la o frecvenţă de 32.768KHz se pot obține frecvenţe de lucru
până la ordinul MHz sau zecilor de MHz.
• La astfel de microcontrolere sistemul de ceas este programabil prin intermediul unor
registre speciale oferind un maxim de flexibilitate în sensul putinței de a controla
compromisul între puterea consumată şi viteza maximă de lucru.

23
Interfața externă (sistemul de intrări şi
ieșiri- porturi I/O)
• Toate microcontrolerele au cel puțin un număr oarecare de intrări -
Inputs (I) si/sau ieşiri numerice - Outputs (O)
• De la x1 la x10 (depind de încapsulare), sunt organizate sub forma
unor porturi I/O (I/O ports);
• Sunt bidirecționale (intrare sau ieșire) sau, mai rar, unidirecționale
• Pot fi multifuncționale (se oferă mai multe funcții alternative,
exclusive insa, pe același pin),
• Pot avea o capacitate sporită de a absorbi si/sau debita curent (de
exemplu pentru comanda directă a unui LED sau optocuplor, cu IOL
max. = 20mA, IOH max. = - 20mA)
• În afară de acest set de intrări/ieşiri de uz general, pentru interfața cu
mediul exterior se oferă o serie de alte facilități importante de
intrare/ieşire

24
Sistemul de intrări şi ieşiri -
comunicatii seriale asincrone
Așa zisele porturi seriale, destinate vehicularii informației in forma seriala (bit cu bit) sunt tot
o forma de intrări-ieșiri numerice

Porturi seriale asincrone (denumiri generice) - nu folosesc un semnal de ceas explicit


• UART (Universal Asynchronous Receiver Transmitter) este un port serial bidirecțional
destinat implementării unui protocol asincron( fără utilizarea unui semnal de ceas explicit)
de comunicație seriala;
• USART (Universal Synchronous Asynchronous Receiver Transmitter) este un port similar,
dar care in plus permite implementarea şi a unui protocol sincron de comunicație seriala,
cu obținerea eventual a unor viteze mai mari de comunicație
• SCI (Serial Communications Interface) este un circuit de tip UART îmbunătățit, definit
inițial şi utilizat de firma NXP (ex Freescale, ex Motorola).
OBS. Pentru familiile moderne de microcontrolere, UART-ul poate implementa si o condiție
de Break (utilizând un caracter special de 13 timpi de bit), făcând astfel posibila utilizarea lui
pentru o magistrala LIN (larg utilizata in industria auto)

25
Sistemul de intrări şi ieşiri - comunicatii
seriale sincrone
• Porturi seriale sincrone dedicate - sunt destinate transferului serial de
date de mare viteză cu unele periferice specializate (sisteme de afișare,
convertoare analog-numerice, etc.) sau care permit conectarea într-o rețea
de comunicație
– Presupun existenta, împreuna cu datele de intrare si iesire, a unui semnal de ceas
explicit pentru sincronizarea acestora.
• Implică şi implementarea unor protocoale mai mult sau mai puțin complexe
de transfer al informației, fiind de fapt vorba de magistrale seriale.
• Există câteva implementări răspândite:
– SPI (Serial Peripheral Interface) este un port serial sincron definit de firma
Freescale (ex Motorola)
– I2C (Inter Integrated Circuits bus) este o interfață si o magistrală serială
sincrona bidirecțională (pe numai 2 fire), dezvoltată de NXP (ex Philips
Semiconductors), destinată aplicațiilor de 8 biţi; există şi multe circuite
"periferice" care sunt prevăzute cu o astfel de interfață; mai este cunoscută şi
sub denumirea TWI (Two Wire Interface) la Atmel/Microchip
– Microwire / Microwire Plus este o interfață serială bidirecțională sincronă
definită şi utilizată de firma National Semiconductors (ulterior cumpărată de
Texas instruments..); este oarecum similara SPI (a fost predecesoarea lui)
– I2S (Inter -IC Sound bus) o interfață serială sincronă cu 3 fire, dezvoltată tot de
NXP (ex Philips), optimizata pentru transmisia informației audio stereofonice in
formă digitală; in ciuda similitudinii numelui, este diferită de I2C

26
Sistemul de intrări şi ieșiri -comunicatii seriale
sincrone in industria automobilului
• CAN si LIN sunt standarde (care definesc o magistrală/ o interfata
electrica şi un protocol de acces) de comunicație serială sincronă
sau asincrona utilizate în industria de automobile, permițând
interconectarea într-o rețea a diverselor componente inteligente (senzori,
elemente de execuție, indicatoare, etc.) omniprezente într-un automobil
modern.
• CAN (Controller Area Network) este proprietate intelectuală a firmei
Bosch, e foarte utilizat în Europa şi Japonia, si este oarecum similar ca
funcționalitate lui SAE J1850 care este utilizat în America de Nord (SAE -
Society of Automotive Engineers),
– In ultimul timp magistrala CAN (CAN bus) a început să fie utilizată şi în alte domenii
decât industria de automobile (automatizări industriale, robotică, acționări electrice).
• LIN (Local Interconnect Network) reprezintă o implementare particulară a
unui protocol de comunicație asincron (care presupune disponibilitatea
caracterului Break – un caracter cu toți biții = 0, dar cu o lungime mai
mare decât a celorlalte caractere, 13 biti actualmente), utilizată în
industria de automobile ca o alternativă de mică viteză dar si cu un preț
de cost mai scăzut față de magistrala şi protocolul CAN..

27
CAN & LIN si nu numai..
MOST (Media Oriented Systems
Transport) - reţea bazată pe fibra
optică pentru vehicularea
informaţiei multimedia

Magistrala IDB-1394
este o variantă pentru
industria
automobilului a lui
IEEE 1394 - Firewire

Flex-Ray este o varianta de mare viteză de magistrală serială


mai rapidă (x10) si mai sigură decât CAN 28
Sistemul de intrări şi ieșiri -
conectivitate Ethernet
• Conectivitatea Ethernet/Web – implică existența unor resurse care
să permită integrarea cu ușurință într-o rețea de tip Ethernet, pentru
a face posibilă, în final, implementarea unui protocol TCP/IP (a unei
stive TCP/IP- TCP/IP stack).
• Resursele respective pot fi de natură software (stivă soft, un pachet
de biblioteci dedicate) care presupun o viteză de prelucrare (putere
de calcul) a CPU suficient de mare pentru a nu afecta vizibil
operarea propriu-zisă a controlerului, sau hardware (stivă
hardware).
– Conectivitatea WiFi este realizata cu ajutorul unor module/interfete
suplimentare
• Pe baza acestei stive se poate realiza o conectivitate tip HTTP, FTP,
STMP, POP3, etc.

29
Sistemul de intrări şi ieșiri - USB
• Conectivitate USB - magistrala serială USB (Universal Serial Bus) a fost
creată pentru conectarea cu uşurinţă a diverselor periferice la un calculator
PC (cu rolul de gazdă - host).
• Conexiunea permite si furnizarea tensiunii de alimentare.
• Varianta USB 1.1 permite atingerea unei rate de transfer maxime a datelor
de 12Mbytes/sec, varianta USB 2.0 a unei rate maxime teoretice de cca.
60MBytes/sec, iar varianta USB 3.0 625 60MBytes/sec;
• La ora actuală există pe piaţă multe firme care oferă o gamă largă de
microcontrolere cu conectivitate USB (majoritatea compatibile USB 1.1), cu
un preţ de cost minim pentru componentele hardware şi software:
Microchip, Intel, Cypress, ST, Infineon, s.a.
• Majoritatea sunt destinate realizării unor periferice USB si mai puține
realizării unui USB host.

30
Sistemul de intrări și ieșiri-
conectivitate wireless
• Conectivitate Wireless- se referă la existența unor
resurse hardware si/sau software care să permită
integrarea cu ușurință şi la un preț de cost avantajos
într-o rețea de tip wireless (comunicație radio, fără fir),
pentru a face posibilă, în final, implementarea unui
protocol wireless(a stivei aferente protocolului).
• Este astfel posibilă inserarea cu ușurință a
microcontrolerului ca un nod într-o rețea locală wireless
de tip “personal” PAN (Personal Area Network)
• Exemplele cele mai cunoscute de astfel de rețele,
protocoale şi stive sunt Bluetooth (IEEE 802.15.1),
Zigbee, MiWi sau Z-Wave
• Ultimele 3 tipuri menționate implementează standardul
IEEE 802.15.4

31
Sistemul de intrări și ieșiri – conversia analog-
numerică, intrări analogice
• Intrări analogice: Convertoarele analog - numerice (CAN, ADC –
Analog to Digital Converters)
– Permit interfața cu semnale analogice, continue
– Convertoarele utilizate fac parte de regulă dintr-un sistem de achiziție de
date, existând şi un multiplexor analogic cu mai multe canale de intrare.
– Rezoluția (exprimata ca număr de biți) disponibilă este tipic de 8, 10 sau 12,
14 sau, mai rar, 16 biţi, uneori cu precizia (rezoluția adevărată) tipic
corespunzătoare unui număr mai mic de biți.
– In marea majoritate a cazurilor ele sunt realizate pentru mărime de intrare
unipolară (intrare asimetrică)
– Intrarea poate fi asimetrică si/sau diferențială (da)
– Sursa de referință utilizată este internă si/sau externă.
– Timpul minim de conversie este în plaja x usec la x10 msec.
– Există microcontrolere care utilizează tehnici de recalibrare (auto-zero,
corecție de câștig/amplificare, etc.) pentru mărirea şi/sau menținerea
preciziei.

32
Sistemul de intrări şi ieșiri –ieșiri analogice
• Ieșiri analogice: Convertoarele numeric - analogice (CNA, DAC-
Digital to Analog Converters)
– Permit generarea de către sistemul numeric de semnale analogice, cu alte
cuvinte realizarea unui sistem de ieșiri analogice, continue
– Mai puțin întâlnite ca periferice standard
– In cazul MCU cea mai răspândită tehnică de conversie numeric analogică
folosită este una bazată pe modulația în factor de umplere (PWM- Pulse Width
Modulation)
• La un microcontroler fără un sistem PWM dedicat, în acest scop se poate
utiliza, cu o flexibilitate mai scăzută, sistemul de temporizare/numărătoare
și orice ieșire numerică.
– La foarte multe microcontrolere există unul sau mai multe canale pe care se
poate genera un tren de impulsuri cu factor de umplere programabil (de la 0 la
100%).
– Factorul de umplere este controlat cu o rezoluție de la 8 biţi sau 16 biţi.
– Frecvența trenului de impulsuri este şi ea programabilă, în limite largi.
– Printr-o filtrare exterioară relativ simplă, de tip trece jos (FTJ, LPF- Low Pass
Filter), se poate obține o tensiune continua de ieșire proporțională cu factorul
de umplere.

33
Sistemul de intrări și ieșiri- ieșiri PWM
• Sisteme dedicate de modulare în durată a impulsurilor (PWM- Pulse
Width Modulation)
– In mod obișnuit o formă de undă PWM poate fi obținută de orice microcontroler
cu ajutorul sistemului de temporizare/numărare si al unei ieșiri numerice,
existând însă restricții asupra frecvenței maxime şi a vitezei de actualizare
datorită codului care trebuie executat în acest scop.
– Există însă microcontrolere cu sub sisteme dedicate generării automate a
formelor de undă PWM cu rezoluții de 8, 16 sau chiar 32 de biți şi frecvențe de
ordinul sutelor de kHz.
– Acest sub sistem dedicat este uneori denumit generator de formă de undă
(„waveform generator”) datorită şi altor facilități pe care le are legate de sinteza
formelor de undă.
– Iesirile PWM pot fi utilizate ca atare pentru comanda unor (micro) motoare de cc

34
Sistemul de intrări și ieșiri- intrări /
ieșiri de mare viteză
• Sisteme de intrări - ieşiri numerice de mare viteză
– Există microcontrolere care utilizează un subsistem (numit
uneori HSIO –High Speed Input Output) care permite
eșantionarea intrărilor si actualizarea ieșirilor numerice
cu o viteză mult mai mare comparativ cu viteza obținută
dacă aceleași operații ar fi fost efectuate prin program
(inclusiv cu utilizarea întreruperilor).
– Este posibilă astfel obținerea pentru funcționalitatea de
controler a unui timp de reacție (de la modificarea intrării
la actualizarea ieșirii) foarte scurt (xusec .. x100nsec).
– Ele se bazează pe utilizarea unor memorii dedicate (de tip
FIFO) sau chiar pe existența unui co-procesor specializat
care tratează aceste evenimente (numit uneori „event
processor”, procesor de evenimente).

35
Sistemul de intrări şi ieșiri- panouri LCD
• Interfața pentru sisteme de afişare tip LCD (panou LCD
- LCD panel)
– În ultimul timp în familiile de microcontrolere deja consacrate sau în
familiile noi au apărut variante care posedă un subsistem destinat
conectării directe, cu utilizarea unui număr minim de componente
exterioare, unui sistem de afişare (un panou) de tip LCD (cu cristale
lichide).
– Interfața respectivă generează toate semnalele si tensiunile
necesare pentru comanda panoului LCD.
– Panourile pot fi de tip alfanumeric si/sau grafic
– Complexitatea sa este descrisă prin numărul maxim de segmente
LCD care pot fi controlate, fiind limitată în primul rând de numărul
de conexiuni externe necesare (pentru un număr mare de
segmente oricum se folosesc tehnici de multiplexare).

36
Câteva familii reprezentative de microcontrolere
(of the past..)
• 8051 (Intel MCS-51 şi mulţi alţii: Intel, NXP, Dallas-Maxim , Atmel, etc.)
– Arhitectura sa are spații de memorie separate pentru program şi date
– Deși există încă sub forma unor variante de 8 biti mult mai rapide (x10 ori) si eficiente, este o
familie de microcontrolere aflată totusi pe calea demodării/perimării!

• 80C196 (Intel MCS-96)


- A fost un microcontroler de 16 biţi făcând parte din generaţia treia de microcontrolere a firmei
Intel (destinată iniţial controlului injecţiei la un motor cu ardere internă)
- A existat si un 80C296, dar toate sunt demodate
• 68HC05 (NXP, fost Freescale, fost Motorola Semiconductor )
- Un microcontroler de 8 biți derivat din vechiul microprocesor 6800 şi care prezintă multe
asemănări cu un alt microprocesor răspândit, la timpul său, 6502 (utilizat la primul calculator
Apple II).
- A fost unul din cele mai răspândite microcontrolere (comparabil cu 8051), demodat.

• 68HC11, 68HC12, 68HC16 (NXP)


- 68HC11 a fost unul din cele mai puternice microcontrolere pe 8 biţi, foarte răspândit în ciuda
faptului că Motorola/Freescale a fost un timp singurul producător.
- A fost unul din primele microcontrolere cu program de încărcare rezident (bootstrap loader în
ROM-ul intern), demodat
• TMS370 (Texas Instruments)
- A fost microcontrolerul standard pe 8 biţi al firmei TI realizat în multe variante (de ordinul zecilor),
prezintă unele asemănări cu 8051
- Perimat, demodat (obsolete)

37
Familii reprezentative de microcontrolere
– NXP (fost Freescale, fost Motorola)
• 68HCS08
– Este singurul microcontroler de 8 biți al firmei, denumit generic 68HC08,
bazat pe o nouă unitate centrală de 8 biți numită CPU08, dezvoltată sub
forma seriei 68HCS08 destinată în mod special unor aplicații din industria
automobilului
• 68HC12, 68HC16
– Variantele care mai exista actualmente sunt de fapt microcontrolere de 16
biți:
– un "super 68HC11", numit 68HC12 si apoi HCS12 (9S12) bazat pe o nouă
unitate centrală numită CPU12, care reprezintă extensia la 16 biţi a
arhitecturii HC11; utilizat in aplicații critice
– un 68HC16, mai puțin răspândit, bazat pe o unitate centrală numită
CPU16
• 683xxx
– Microcontrolere mai vechi de 32 de biți construite în jurul unui CPU analog
vechiului microprocesor M68020, numit CPU32, denumite acum de NXP şi
"procesoare integrate“- integrated processors.
– Putere de calcul comparabilă sau mai mare ca a unui Intel 80386.

38
Familii reprezentative de microcontrolere
– NXP/IBM/Apple
• Exista o mare diversitate de microprocesoare si
microcontrolere bazate pe o unitate centrală denumită
PowerPC, un RISC de 32/64 de biți, cu arhitectura Von
Neumann, creată de fapt de o alianță Apple-IBM- Motorola
la începutul anilor ‘90.
– Din PowerPC deriva si arhitectura Power dezvoltata ulterior numai
de IBM
• MPC5XX, MPC5xxx (PowerPC e200, e300, e500, e5500
core), s.a
– Pe lângă o gamă foarte largă de periferice performante includ și o
unitate de prelucrare în virgulă mobilă.
– Foarte răspândite in industria aplicațiilor critice (automobile,
aeronautică, spațiu)
– Vezi si prezentarea arhitecturii de calcul PowerPC:
https://en.wikipedia.org/wiki/PowerPC

39
Familii reprezentative de microcontrolere
– Intel
• Intel realizează la ora actuala o familie de microcontrolere
de 32 biți bazata pe arhitectura de calcul x86, familie
numită Quark
• Quark este realizat pe baza unjei tehnologii SoC, de
32nm, si a fost lansat in 2013
• Setul de instrucțiuni si arhitectura de calcul a unității
centrale este similară microprocesoarelor Pentium –i586
(P54C)
• Oferă suport doar pentru sisteme de operare de tip
incorporat (embedded)
• Există mai multe modele/generații Quark : X1000, X1020,
D1000, C1000, etc. , cu o gamă largă de resurse periferice
si diverse configurații de memorie (Flash, SRAM, SDRAM
extern)
– Arduino 101 este realizat cu un Intel Quark
– Vezi si prezentarea Intel Quark:
https://en.wikipedia.org/wiki/Intel_Quark

40
Familii reprezentative de microcontrolere -
Microchip
PIC (Microchip- www.microchip.com )
• Este o familie de microcontrolere care, după lansarea de la începutul anilor ‘90 , a
cunoscut o dezvoltare explozivă.
• Familii (serii) de 8 biți : PIC10, PIC12, PIC16 și PIC18.
• Familii (serii) de 16 biți : PIC24 si dsPIC30(33).
• Familia de 32 biți: PIC32 are unitate centrala bazata pe o arhitectura de calcul
MIPS32 (fără vreo legătură cu celelalte PIC-uri)
• Exista si variante funcție de aplicații: CAN, Ethernet, USB, LCD, Motor control,
eXtreme Low power
• In seriile respective există variante cu memorie de program de tip
EPROM/OTP(HV) sau FLASH(F).
– Au fost primele microcontrolere de 8 biţi cu arhitectură RISC: PIC16C5x avea un set de doar 33
instrucțiuni (la vremea respectiva microcontrolerul CISC Intel 8048 avea 90).
• Arhitectura este de tip Harvard şi, ca o particularitate, dimensiunea cuvântului
pentru program pentru seriile de 8 biți este variabila, funcție de varianta (de 10,
12, 14, 16 biţi, etc.)
• Nota Microchip si Atmel au fost practic singurele firme care au mai
investit in ultimii 10 ani (la nivel 2016) in dezvoltarea de microcontrolere
de 8 biti

41
Familii reprezentative de
microcontrolere
• AVR 8 biți ( fost Atmel , acum www. Microchip.com )
– Un concurent puternic al seriei PIC a fost familia numită AVR 8biti, a
firmei ATMEL, care oferă variante de microcontrolere oarecum
asemănătoare ca resurse cu familia PIC, la performanțe similare sau mai
bune.
– Sunt bazate pe o arhitectură diferită, dar unitatea centrală este tot de tip
Harvard si RISC, cu cuvântul de date de 8 biți si cu cuvântul de program
de 16 biţi.
– Au existat si mai există multe sub-familii si/sau variante dedicate unor
aplicații specifice: AT90 (matur si perimat-obsolete), AT Tiny, ATMega,
XMEGA (cea mai noua), AVR Automotive, AVR Lighting, AVR Battery
Management, CAN AVR, USB AVR, AVR Z-Link (aplicații Zigbee)

AVR32 (32biți) exista ca o serie de microprocesoare (AP7) si


Microcontrolere (UC3) bazate pe o unitate centrală originală RISC de 32 de
biți, care nu are nici o legătură cu AVR 8 biți; are multe din caracteristicile
unui procesor numeric de semnal, la o putere consumata foarte mică; din
păcate probabil se află pe calea perimării si dispariției..

Firma Atmel a fost cumpărată de Microchip in 2016, iar AVR 8 biți sau 32 biți
nu este chiar singurul motiv acestei achiziții..
42
Familii reprezentative de
microcontrolere - TI
• MSP430 (Texas Instruments)
– Este familie de microcontrolere de 16 biţi cu arhitectura RISC, cu posibilitatea
controlului foarte bun al compromisului viteză de calcul/consum propriu, destinată
in principal unor aplicații portabile cu alimentare de la baterie (și nu numai)
– Are un spațiu de adresare de 64KBytes sau mai mare, diverse variante de realizare
a memoriei interne de program (OTP, FLASH), resurse diverse (printre care şi o
interfață pentru un sistem de afișare LCD).
– Este printre puținele microcontrolere (variantele MSP430F) care au memorie interna
de tip FRAM (RAM feroelectric)
Nota
Tot la Texas Instruments există si seria MSP432 care nu are de fapt nici o legătură cu
familia MSP430, fiind un microcontroler de 32 de biți cu o unitate centrală ARM Cortex-
M4F (cu unitate de prelucrare in virgulă mobilă si unitate de protecție a memoriei)

43
Familii reprezentative de
microcontrolere- Spansion, Renesas
Spansion Inc. (www.spansion.com, parte a grupului Cypress
Semiconductor); Spansion Inc. care a cumpărat portofoliul de
microcontrolere de la Fujitsu Semiconductor oferă familii deosebit
de puternice si diverse de microcontrolere pe 8 biţi (FMC-8), 16 biţi
(FMC-16) sau 32 de biţi (FR).
– În fiecare familie există zeci de variante.
– Multe dintre ele sunt orientate pe aplicațiile din industria de
automobile sau din electronica de consum (audio, video,
electrocasnice).
Renesas (www.renesas.com) – oferă de asemenea o gamă largă de
microcontrolere organizate în familii de 8, 16 şi 32 de biți.
– Produce familii de 32/64 de biți bazate pe unitatea centrala ARM:
familiile RA si RZ
– Exista si două mari familii proprietate a firmei: una de 32 de biți
CISC/RISC numită RX si una de 16 biți numită RL78
• Există un număr foarte mare de variante constructive în fiecare familie.

44
Familii reprezentative de microcontrolere
- ARM
• Este vorba de microcontrolere care au o unitate centrala cu o
arhitectura de calcul ARM
• ARM (Advanced RISC Machine, www.arm.com ) - este de fapt o unitate
centrală de 16/32 sau 64/32 de biţi care face parte din categoria
structurilor IP (“Intelectual Property”), sintetizabile.
• Extrem de răspândit, si nu numai in aplicații mobile!
• Consorțiul ARM a oferit licențe ale acestei micro arhitecturi (nucleu ARM)
pentru numeroși producători de circuite (Microchip, NXP, TI, OKI –
www.okisemi.com , ST, Renesas, s.a.).
• Pe baza acestor licențe se realizează și microcontrolere de mare
performanță.
• Arhitectura este suportata si de foarte multe sisteme de operare
• Cele mai cunoscute şi răspândite variante de nuclee sunt ARM7 şi
ARM9, cu implementările lor simplificate numite ARM7T, ARM9T (T-
“Thumb”) sau ARM Cortex M.
• Vezi si prezentarea arhitecturii de calcul ARM (ARM_RO.ppt)

45
Limbaje de programare pentru
microcontrolere - limbajul de asamblare
• Limbajul mașină şi de cel de asamblare
– Limbajul mașină (cod mașină, instrucțiunile mașină – machine code)
este singura formă de reprezentare a informației pe care un CPU/un
microcontroler o "înțelege“: ca orice alt sistem de calcul sau CPU,
el nu înțelege decât un șir de cifre binare, de “1” si de “0” !
– Din păcate această formă de reprezentare a informației este total
nepractică pentru un programator, care va utiliza cel puțin un limbaj
de asamblare (assembly language), mai aproape de limbajul natural
– Limbajul de asamblare este un limbaj de nivel scăzut (low level
language) dar care nu este penalizat de abstractizarea arhitecturii de
calcul
– In limbajul de asamblare o instrucțiune (adica o mnemonică cu
operanzi si moduri de adresare) are drept corespondent o instrucțiune
în limbaj mașină
• excepție fac macroinstrucțiunile disponibile la unele asambloare
– Unealta software care realizează “traducerea” limbajului de asamblare
in limbaj mașină se numește asamblor (“assembler”)
– Un program scris numai în limbaj de asamblare poate fi foarte rapid
şi foarte compact.
• Aceasta nu înseamnă că un astfel de program, prost scris, nu poate fi lent şi de mari
dimensiuni, programatorul având controlul total (şi responsabilitatea !) pentru execuția
programului şi gestiunea resurselor. 46
Limbaje de programare - limbajul de
asamblare
– Limbajul de asamblare, datorita faptului ca el
practic nu abstractizează componentele arhitecturii
de calcul, ar trebui sa fie primul învățat, chiar
sumar, atunci când dorim să proiectăm o aplicație
hard/soft cu un anume microcontroler (familie), el
permițând înțelegerea arhitecturii de calcul şi
utilizarea ei eficientă
– Utilizarea (numai) a limbajului de asamblare
pentru dezvoltarea unei aplicații complexe este
actualmente neproductivă de cele mai multe ori,
printre cauze fiind si faptul ca există şi familii de
microcontrolere cu CPU de tip CISC cu un număr
foarte mare de instrucțiuni (x100) combinate cu
moduri de adresare numeroase şi complicate,
foarte greu de învățat de folosit eficient !
– Limbajul de asamblare este încă folosit acolo
unde exista constrângeri dure de timp real
(hard real time), adică multa funcționalitate care
trebuie realizată intr-un timp scurt si foarte
scurt
• Nu trebuie uitat că la ora actuală mulți din producătorii mari de
microcontrolere oferă medii de dezvoltare software gratuite
care includ programe asambloare gratuite (cum este
asamblorul AVR 8 biti, AVR 32 biti sau ARM din mediul AVR
Studio 4/5/6/7 sau asambloarele Microchip din mediul MPLAB
X).
– De asemenea, comunitatea utilizatorilor diverselor
familii de microcontrolere a dezvoltat şi ea, în timp,
multe astfel de asambloare, care sunt disponibile
ca software freeware/open source.

47
Limbaje de programare pentru
microcontrolere – limbaje de nivel înalt:
interpretoare
- Un limbaj de nivel înalt (high level language) nu este numai un limbaj mai apropiat de
limbajul natural (el poate include elemente ale acestuia) dar este caracterizat printr-un
grad mare de abstractizare a componentelor unei arhitecturi de calcul
- Interpretoarele
– Un interpretor (interpreter) este o modalitate de implementare a unui limbaj de nivel înalt, limbaj
mai apropiat de limbajul natural.
– Un interpretor este de fapt un program rezident care, în acest caz, rulează pe o platformă de
calcul de tip microcontroler, aceiasi pe care se executa aplicația scrisa in limbajul respectiv.
– Caracteristic pentru execuția unui program interpretat, este citirea și executarea secvențială a
instrucțiunilor de nivel înalt (instrucțiune cu instrucțiune) de către interpretor (programul
rezident).
– De fapt fiecare instrucțiune de nivel înalt este interpretată/tradusă într-o secvență de
instrucțiuni mașină, care se execută imediat.
• In lumea microcontrolerelor cele mai răspândite interpretoare sunt cele pentru limbajele Basic
şi, mai recent, Java Bytecode sau Python.
• Limbajul BASIC a fost remarcabil prin simplitatea şi accesibilitatea codului, dar în varianta
interpretată (pentru că există si variante compilate: vezi compilatoarele Basic pentru AVR 8 biți
si PIC) și prin viteza mai mică de execuție a aplicației, acesta fiind de altfel prețul plătit
pentru utilizarea oricărui interpretor.

48
Limbaje de programare – limbaje de nivel
înalt: compilatoare
• Compilatoarele
– Un compilator combină ușurința în programare oferită de un interpreter (de fapt de limbajul de nivel
înalt) cu o viteză mai mare de execuție a codului.
– Pentru aceasta programul în limbaj de nivel înalt, ca un întreg ansamblu (ca un tot, NU
instrucțiune cu instrucțiune), este translatat (tradus) în limbaj de asamblare, urmând a fi apoi
asamblat, adică tradus în cod mașină de un asamblor
– Codul mașină rezultat in urma acestui proces (care tipic mai include si alte operații in afara de
translatare) va fi cel executat, tot ca un întreg
– Codul mașină rezultat are dimensiuni relativ mari (mai mari decât cel rezultat dintr-un program scris
in limbaj de asamblare, dar mai mici decât cel interpretat) şi este executat direct, ca un tot, de CPU.
– Spre deosebire de interpretor unde codul sursă este “interpretat” de fiecare dată când se execută
programul, in cazul compilatorului compilarea (generarea codului mașină) se face o singură dată
– Codul mașină generat de un compilator poate fi optimizat fie ca dimensiune (dimensiune cat mai
mică, timpul de execuție nefiind foarte important), fie ca timp de execuție (timp cat mai mic,
dimensiunea nefiind foarte importanta), fie, in mod tipic, ca un compromis intre cele două criterii
• Se pot enumera compilatoare pentru limbajele: C/C++, Pascal, Fortran, BASIC, Ada, PL/M (Intel)
si altele…

49
Limbaje de programare – compilatoare C
• Cele mai populare şi utilizate compilatoare sunt cele pentru limbajul C, un limbaj
universal folosit atât pentru supercalculatoarele cum ar fi Cray sau Blue Gene, cât
şi de microcontrolerele de 4 biţi (care încă mai există..).
• C este un limbaj procedural, puternic şi flexibil care, deși de nivel înalt, poate
permite şi accesul direct la resursele sistemului de calcul fiind astfel preferat
pentru programatorii de sisteme incorporate (si de microcontrolere…)
• Un program bine scris in C, utilizând un compilator de calitate, poate genera un
cod rapid şi compact.
• Totuși, in anumite situații, porțiuni critice din punct de vedere al vitezei de execuție
si al utilizării anumitor resurse (mai ales a inițializării acestora), sunt încă scrise în
limbaj de asamblare, sub forma unei funcții (start-up code) dedicate care se
executa înainte de funcția main () si o lansează pe aceasta in execuție
• Există numeroase implementări ale acestor compilatoare, pentru toate familiile de
microcontrolere, de la 4 biți la 64 de biți.
• Cu anumite limitări legate de arhitectură şi mai ales legata de resursele
microcontrolerului, asigură portabilitatea cu relativă ușurință a unei aplicații
scrisă pentru un anumit tip (familie) de microcontroler la un alt tip (familie).

50
Limbaje de programare- compilatoare C
• Pentru familiile puternice de microcontrolere, mai ales in cazul unor CPU
CISC, datorită complexității setului de instrucțiuni şi al numeroaselor
moduri de adresare, este descurajată în mod explicit utilizarea
exclusivă a limbajului de asamblare în momentul în care se
programează aplicații performante.
• Unitatea centrală a noilor generații de microcontrolere RISC, apărute
după 1990, a fost proiectată şi optimizată pentru utilizarea unor
limbaje de nivel înalt cum ar fi C-ul (vezi AVR sau PIC)
• Funcție şi de familia de microcontrolere în cauză, prețul unor astfel de
compilatoare de C poate fi destul de ridicat, începând cu x100USD şi
ajungând la x1000USD.
• Există însă şi variante freeware sau open source de compilatoare de
C, cum ar fi gc (gnu c), care este o portare open source a
compilatorului omonim din Linux în lumea microcontrolerelor.
– Există implementări diferite ale acestui compilator care generează cod pentru familii
diferite de microcontrolere de 8, 16 sau 32 de biti (de exemplu AVR 8 biti, MSP430, 9S12,
MPC 55xx, ARM, AVR 32, etc.).

51
Limbaje de programare – medii IDE
CE NE MAI TREBUIE IN AFARA DE UN LIMBAJ DE PROGRAMARE?
• Codul mașină este obținut cu ajutorul unui set de aplicații (unelte) numit
mediu integrat de dezvoltare a programelor (IDE - Integrated
Development Environment) care conține în mod tipic, pe lângă un
asamblor si/sau un compilator, următoarele componente software/aplicaţii
accesibile, pentru ușurință, prin intermediul unei interfețe grafice utilizator
(GUI- Graphical user Interface):
– un editor specializat (orientat pe codul sursă), un asamblor/compilator,
– un editor de legături/locator ("link-editor/locator"),
– programe de gestiune a unor biblioteci de cod ("librarians"),
– programe de conversie a formatelor de reprezentare a codului (de
exemplu din binar în format Intel HEX sau Motorola S) şi,
– nu în ultimul rând, un simulator şi/sau depanator ("debugger").
• Codul astfel obținut cu ajutorul acestui lanț de unelte software (software
toolchain) trebuie încărcat/programat în memoria de program a
mașinii țintă unde va rula, fiind de fapt programat într-o memorie de
program de tip (EP)ROM/FLASH sau încărcat direct (up-loaded) într-o
memorie de program de tip RAM.
– Deoarece lanțul de unelte, inclusiv compilatorul si asamblorul, se execută pe un
calculator gazdă (host) a cărui unitate centrală, de cele mai multe ori, este diferită de
unitatea centrala țintă (target) pe care se va executa acesta, avem de a face cu o
compilare încrucișată (cross compilation) 52
Testarea si depanarea aplicațiilor –
simulatoarele de unități centrale
• Simulatoare de microcontrolere
– Un simulator (simulator) este un program care rulează programul
microcontrolerului - implementează un microcontroler virtual - folosind un alt
sistem de calcul- de fapt o alta unitate centrala - drept gazdă - host (tipic un PC).
– Programul se poate executa pas cu pas, conținutul variabilelor şi registrelor poate
fi vizualizat și modificat.
– Reprezintă si un punct de plecare atunci când se abordează un microcontroler,
pentru familiarizarea cu arhitectura si resursele lui precum si, daca se dorește, cu
limbajul de asamblare.
– Nu permite simularea în timp real a întreruperilor și, de regulă, programul rulează
mai încet decât pe mașina reală.
– Întotdeauna există însă mijloace pentru evaluarea vitezei de execuție a codului
simulat (ca număr de cicluri mașină sau de stări).
– Ideal, un simulator ar trebui să permită și simularea completă a interacțiunii cu
lumea externa si nu numai, cel puțin din punct de vedere logic, cu toate perifericele
disponibile la nivelul microcircuitului (lucru care nu se întâmplă, mai ales pentru
variantele freeware)

53
Testarea si depanarea aplicațiilor-
resident debuggers
• Programele de depanare ("debbugers") rezidente
– Sunt programe (denumite uneori în română şi programe "monitor") care rulează pe maşina
ţintă -target (microcontrolerul) oferind facilități de depanare similare simulatorului.
– Ele trebuie să fie tot timpul rezidente, adică memorate/prezente in memoria acesteia!
– Interfața cu utilizatorul este realizată prin intermediul unui sistem gazdă (PC) şi/sau a unui
terminal alfanumeric, conectate prin intermediul unui port serial.
– Utilizează o parte din resursele microcontrolerului: memorie de program pentru el însuși (de
tip ROM) şi memorie de date (RAM) pentru variabile proprii, memorie de program (de multe ori
memorie externa de tip RAM, pentru a se putea încărca și modifica cu ușurință codul!) pentru
programul ce se depanează, un port serial pentru comunicația cu sistemul gazdă, eventual
întreruperi, etc.
– Se utilizează de regulă împreună cu un sistem de dezvoltare - development system, starter
kit, evaluation system - care este un sistem minimal realizat în jurul microcontrolerului pe
care rulează depanatorul, dar având resurse suficiente pentru a permite testarea şi depanarea
aplicațiilor uzuale.

54
Sisteme de dezvoltare si depanatoare
(debugger) rezidente

Si acesta este tot un sistem de dezvoltare


(desi arata ca o cheie –dongle- USB)!

55
Testarea si depanarea aplicațiilor
• Emulatoarele In Circuit (ICE - In Circuit Emulators)
– Sunt cele mai eficiente mijloace de testare şi dezvoltare şi au fost, mult timp, cele
mai complexe şi mai costisitoare.
– Varianta integrală (full ICE) presupune existența unui hardware dedicat (scump şi
complicat!) care înlocuiește practic microcontrolerul (se conectează în locul
acestuia) în sistemul pentru care se dezvoltă aplicația, în același timp fiind
disponibile toate facilitățile descrise anterior şi altele suplimentare.
– Permit un control total al mașinii țintă, în timp real, fără a folosi nimic din
resursele acesteia (la variantele cele mai costisitoare).
– Ele sunt realizate de cele mai multe ori ca un mijloc de testare şi depanare de sine
stătător, conectat la un PC prin intermediul unui port paralel, serial USB sau
dedicat.
– Emulatoarele full ICE sunt si cele mai scumpe ICE: x1000$.
– Variantele noi de emulatoare folosesc interfețele specializate de programare şi
depanare integrate la nivelul microcontrolerelor moderne (JTAG, BDM, etc. atunci
când ele există), înlocuind variantele full ICE.
– Nu mai este necesară înlocuirea microcontrolerului de pe sistemul țintă, conectarea
cu acesta făcându-se serial, printr-un număr minim de interconexiuni (fire).
– Exemple de astfel de interfețe ar fi: JTAG/ICE – In Circuit Emulation - la multe familii
de microcontrolere, BDM (Background Debug Monitor) - pentru
NXP/Freescale/Motorola.
– Existența acestui tip de interfețe face posibilă realizarea de emulatoare cu un preț
de cost mult mai mic decât cele clasice: < x100$
Nota Pentru sistemele moderne de dezvoltare un astfel de emulator JTAG
sau BDM (cu performante mai reduse ce e drept) este inclus pe placa
sistemului, având o conectivitate USB directă cu sistemul gazdă (PC).

56
Emulatoare ICE
Emulator cu interfață BDM (NXP/Freescale)

Emulator full ICE (DIP 40)


Emulatoare ICE JTAG

57
Testarea si depanarea aplicațiilor -
simulatoarele de sistem
• Simulatoarele de sistem
– Reprezintă o categorie aparte de simulatoare destinate simulării cat mai complete a
sistemului și a aplicației în ansamblu, cu alte cuvinte a microcontrolerului împreuna cu
o dispozitivele hardware externe.
– Ele integrează şi un simulator SPICE.
– Cele mai cunoscute sunt Proteus VSM (Virtual System Modelling) al firmei Labcenter
Electronics (http://www.labcenter.co.uk/) şi UMPS (Universal Microprocessor Program
Simulator) al firmei Virtual Microdesign (www.vmdesign.com).
– Un astfel de simulator permite rularea aplicației (codului), în mod continuu sau pas cu
pas și evaluarea în detaliu a modului cum aceasta (si microcontrolerul) interacționează
cu hardware-ul extern.
– El permite ceea ce se numește co-simularea (Co-simulation): interacțiunea dintre
software-ul microcontrolerului și dispozitivele electronice analogice sau numerice
conectate cu acesta.
• Sunt bazate pe utilizarea unor modele avansate ale unor familii de microcontrolere precum și pe
modelele SPICE ale dispozitivelor electronice.
– De exemplu, medii de simulare SPICE, cum ar fi Multisim (National Instruments )
integrează acum plug-in uri pentru simularea unor aplicații cu microcontrolere PIC cu
mediul de dezvoltare MPLAB

58
Testarea si depanarea aplicațiilor -
simulatoarele de sistem
• Pentru fiecare model de microcontroler există un asamblor şi un editor de legături integrat
astfel că se poate face, în anumite limite, şi dezvoltarea codului în asamblare.
• Pe lângă aceasta ele au asigurate şi interfeţe corespunzătoare pentru a se putea dezvolta
codul cu medii de programare consacrate pentru familia respectivă de microcontrolere,
folosind de exemplu un compilator C.
• Facilitățile de simulare a codului sunt similare celor întâlnite la simulatoarele deja
menționate.
• Pe lângă numeroasele dispozitive electronice discrete, circuite integrate analogice sau
numerice (la Proteus VSM există peste 6000 de modele), circuite de memorie sau
periferice, în categoria dispozitivelor externe se mai pot menţiona şi sisteme de afişare
(LED, LCD), tastaturi matriciale sau butoane, relee, etc.

59
Simulatoarele de sistem: Proteus VSM

60
Sisteme de operare de tip incorporat
• Există implementări diferite funcţie de familia de microprocesoare / microcontrolere:
x86, ARM, PowerPC, etc.
• Întâlnite/utilizate pentru MPU/MCU de 16/32 biţi, dar există si pentru cele de 8 biţi!
• Sisteme de operare de tip “embedded” variante : ROM-DOS, Windows CE, Palm OS,
Windows Embedded, Window IoT sau Linux Embedded (exista foarte multe distribuții)
– De tip “embedded” nu înseamnă neapărat si de timp real!
• Nucleele sau sistemele de operare de timp real (Real Time kernel, Real Time
Operating System-RTOS) sunt cele asigură o comportare perfect deterministă, cu un
timp maxim de răspuns la un eveniment intern/extern previzibil si garantat
– Pe piaţa de software pentru microcontrolere exista şi componente numite nuclee de timp real (real
time kernels) sau sisteme de operare în timp real (RTOS).
– Un astfel program de sistem de nivel profesional este o componenta software scumpă sau foarte
scumpă, funcție de complexitatea lui, de accesibilitatea surselor programului, de familia de
microprocesoare căreia ii este adresat, de modul in care va fi distribuit împreuna cu aplicația.
– Există însă și variante de RTOS, de mai mică complexitate, din categoria freeware sau shareware,
care pot fi utilizate cu performanțe mulțumitoare.

61
Sisteme de operare: RTOS
• Nucleele (sistemele de operare) de timp real (Real Time kernel, Real Time
Operating System-RTOS)
– Un sistem de operare în timp real facilitează crearea aplicaţiilor aşa zise de timp
real, dar nu garantează şi faptul ca ele chiar se vor executa în timp real, aceasta
depinzând de modul în care este utilizat acest software la nivel de sistem.
– Spre deosebire de un calculator cum este PC-ul, un sistem integrat (embedded
system) este proiectat întotdeauna într-un anumit scop şi are un cod care se
execută aproape întotdeauna dintr-o memorie ROM, fiind de presupus că nu se
modifică pe parcursul execuției aplicației.
– Astfel lucrurile sunt ușurate deoarece comportarea sistemului poate specificată
complet încă din faza de proiectare.
– Din aceasta cauză, în cazul multora din aplicații, multe probleme se pot rezolva în
timp real şi fără să se utilizeze un RTOS.
– Esențială este până la urmă si calitatea şi competența celui care programează
aplicația!

62
Criterii de alegere a unui
microcontroler (de fapt a unei
familii de microcontrolere) pentru
o anumită aplicație
• Costurile permise pentru aplicaţie
– Care va fi scara de producţie: prototip,
producţie mică/medie sau de masă?
– Care sunt costurile permise pentru
microcontroler?
?
– Care sunt costurile permise pentru mediul de
programare şi dezvoltare?
• Timpul de dezvoltare al aplicaţiei (legat
si el de costuri!)
– Ce limbaj de programare să aleg?
– Ce limbaje de programare cunosc mai bine şi
ce medii de dezvoltare am utilizat?
– Ce modalitate de testare şi depanare folosesc:
simulator, sisteme de dezvoltare, emulator?
63
Criterii de alegere a unui microcontroler
Caracteristicile fizice si arhitecturale (o enumerare doar a celor mai importante):
– Care este gama temperaturilor de lucru necesare?
– Aplicația va funcționa într-un mediu cu caracteristici speciale, de exemplu în care
există perturbații electromagnetice puternice sau radiatii ionizante?
– Care este viteza de prelucrare (de calcul) necesară?
– De câtă memorie am nevoie pentru program şi respectiv date?
– Va fi necesară şi o memorie externă?
– Ce fel de alimentare este disponibilă şi care sunt limitările acesteia?
– De câte intrări şi/sau ieşiri am nevoie?
– Ce fel de intrări şi/sau ieșiri sunt necesare: intrări/ieşiri analogice, ieşiri numerice de
curent mai mare?
– Care sunt resursele necesare în materie de temporizare/numărare şi care ar fi
caracteristicile lor cele mai importante (de exemplu rezoluție, frecvență maximă de
numărare) ?
– Ce tip de capsulă, ce dimensiuni fizice și număr de pini ar trebui să aibă?
– Circuitul respectiv este disponibil şi în variante care nu utilizează plumbul ca material
constructiv (Pb-free, lead-less) conform directivelor ROHS?

64
Criterii de alegere a unui microcontroler
• Conectivitatea
– Care sunt resursele de comunicație necesare: câte porturi seriale
asincrone şi cu ce caracteristici, ce tipuri de magistrale seriale
sincrone (SPI, I2C) sunt disponibile?
– Este necesara si o conectivitate CAN sau LIN ?
– Este necesară o conectivitate Ethernet (o stivă TCP/IP), USB sau
wireless (stive Bluetooth, Zigbee, etc.)?
• Compatibilitate, scalabilitate şi dezvoltarea ulterioară
– Cu ce tipuri de circuite se poate interfața cât mai simplu (si mai ieftin):
sisteme de afișare, senzori, elemente de comandă şi execuție (relee,
motoare de curent continuu, motoare pas cu pas, etc.)?
– Cum se poate realiza extinderea ulterioară, atunci când ar fi
necesară?
– Există mai multe variante în familia respectivă de microcontrolere,
care să acopere eventualele cerințe suplimentare în materie de viteză
de lucru, resurse periferice sau de memorie?
– Diversitatea variantelor constructive pentru o anumită familie
constituie întotdeauna un argument puternic pentru alegerea ei.

65
Criterii de alegere a unui microcontroler
• Alte aspecte
– Care sunt informațiile relevante despre fiabilitatea familiei respective de
microcontrolere?
– Noile familii precum şi variantele noi ale unor familii consacrate pot avea la început
diverse „probleme de creștere” (bugs!), care țin mai mult de hardware decât de
software; o familie consacrată de mulți ani de utilizare prezintă mult mai puține
riscuri din acest punct de vedere, lucru esențial pentru utilizarea in aplicații critice
(aviație, spațiu, nuclear, feroviar, automobil).
– Ce distribuitori există şi cât sunt de accesibili pentru mine?
– Care este suportul oferit de fabricant sau distribuitor şi care este baza de cunoştinţe
existentă: site-uri web, documentație on-line sau pe CD-uri, note de aplicaţii,
exemple de proiectare complete (reference designs), software din categoria
freeware / shareware / OPEN SOURCE si, nu în ultimul rând, forumuri de discuţii
pentru utilizatori?
• Din păcate răspunsurile la multe din aceste întrebări nu sunt simple, mai
trebuie si corelate între ele, experiența si calitatea proiectantului fiind
decisive.
– Un exemplu este legătura care există între criteriile de cost şi cele de timp de
dezvoltare.
– Principial, utilizarea unui limbaj de nivel înalt împreună cu un emulator pentru
testare şi depanare poate duce la scurtarea consistentă a timpului de dezvoltare.
– Dar prețul unui compilator este întotdeauna mai mare decât cel al unui asamblor
(nimic nu e mai ieftin decât ceva ce poate fi gratis!), iar prețul unui emulator este şi
el mai mare decât cel al unor mijloace mai simple de testare şi depanare.
66
Microcontrolere (si microprocesoare)

Introducere in familia Microchip (ex ATMEL) AVR 8 biți:


arhitectură unitate centrală (CPU), registrele, instrucțiunile si
modurile de adresare, memoriile (de program si date),
sistemul de generare al ceasului, fuzibilele

1
Alf (Egil Bogen) and Vegard (Wollan)'s RISC processor

Vegard Wollan in Trondheim 2015..


Când nu știau ce ii așteaptă..
Familia de microcontrolere AVR 8
bits – Atmel/Microchip
• Familia de microcontrolere de 8 biţi denumită generic AVR 8 biti, a
fostei firme Atmel, este o familie apărută şi dezvoltată începând cu anul
1996, oarecum similară familiei PIC a firmei Microchip, cu performanțe
asemănătoare sau mai bune ca raport performanţă-preţ.
• A fost creată ca să concureze PIC-ul, fiind însă microcontrolere bazate
pe o arhitectură, cu o unitate centrală considerată tot de tip RISC, cu
cuvântul de date de 8 biți si cu cel de program de 16 biti.
• Pentru obținerea unui maxim de performanța și implementarea
paralelismului în execuție, AVR folosește o arhitectură Harvard - cu
memorii separate şi magistrale interne separate pentru program şi date,
iar instrucțiunile din memoria de program sunt executate cu două nivele
de pipeline de instructiuni.
– Astfel, în timp ce o instrucțiune este executată, instrucțiunea următoare este
decodată din memoria de program.
– Acest concept permite ca, în mod ideal, să fie executată o instrucțiune în
fiecare ciclu de ceas (perioadă a semnalului de ceas).
• Arhitectura AVR a fost optimizată pentru utilizarea ca limbaj de
programare a limbajului C, permițând compilatorului generarea de cod
foarte eficient atât ca dimensiune cât și ca viteză de execuție. 3
Începând cu anul 2016 Atmel a fost
cumpărată de Microchip așa că rămâne de
văzut ce viitor va avea familia AVR …

De notat însă că există si “clone” AVR 8 biți!


“Clonele” au același set de instrucțiuni, tip de
memorie si periferice ca originalele 89AT, Mega sau
Tiny.
Sunt/erau produse (2017) de firmele
LogicGreen Technologies (SUA) si respectiv NIIET 4
(Rusia).
Familia AVR 8 biţi
• La fel ca la familia PIC de 8 biti, dimensiunea cuvântului de memorie
program este mai mare decât cea a cuvântului de date, fiind întotdeauna de
16 biţi.
• Mai există (2019) trei sub familii mari, în ordinea crescătoare a complexității
resurselor, acestea fiind: ATtiny (Tiny AVR), ATMega (Mega AVR) şi
XMEGA.
• În fiecare din aceste sub familii există numeroase variante constructive, care
diferă între ele prin resursele de memorie şi perifericele disponibile on-chip.
• Începând cu anul 2016 in familia AVR au apărut (si vor mai apărea) variante
de Tiny, Mega si XMega care incorporează tehnologie Microchip, tehnologie
existentă si utilizată la microcontrolerele din familiile PIC de 8 biti
• Aceasta tehnologie se numește CIP- Core Independent Peripherals
(periferice independente de unitatea centrala), un termen utilizat de
Microchip, si are drept caracteristici principale:
– realizează in mod automat anumite sarcini ale perifericelor, fără
intervenția unității centrale (CPU)
– CIP degrevează unitatea centrală de un efort computaționale legat de
periferice, CPU limitându-se doar la supraveghere
– CIP include o mare diversitate de periferice (inclusiv unele care nu au
existat înainte de preluarea Atmel de Microchip)
5
CIP- Core Independent Peripherals

Toate categoriile de CIP disponibile pentru microcontrolerele AVR si PIC de 8 biti sunt
prezentate in figura de mai jos, categoriile fiind grupate/colorate similar

6
Familia AVR 8 biti
• Diversele variante Mega, Tiny sau XMega diferă practic prin
dimensiunea memoriei locale de program de tip FLASH, de
date de tip SRAM si EEPROM si prin caracteristicile și
varietatea resurselor de tip periferice.
• Descrierea care urmează este axată pe familia cea mai
bogată în variante si resurse, şi anume familia AVR Mega, iar
sub familia AVR Tiny prezintă eventual anumite particularități
care vor fi menționate atunci când este cazul
• Datorita faptului ca noile variante AVR Mega si Tiny produse
după preluarea de către Microchip au caracteristici noi sau
unele similare familiei XMega, in prezentare vom pune
accentul pe ce vom numi AVR clasic
– Acolo unde este cazul se vor discuta sumar si aceste caracteristici
specifice (in special in prezentarea pentru AVR XMEGA)

7
Familia AVR 8 biti - 2
• Ultima familie AVR de 8 biți (apărută din perioada Atmel!) a fost
familia AVR XMEGA :
– putere de calcul crescută (32 MIPS la 32 MHz),
– dimensiuni maxime mai mari ale memoriei de program (FLASH de pana la
256 KOcteți) si date (SRAM de pană la 8KOcteti),
– consum foarte redus (bazat pe tehnologia picoPower),
– o gamă foarte largă de periferice (inclusiv DMA),
– un sub-sistem zis revoluționar de control si corelare a perifericelor (Event
System)
• Actualmente (2019) numărul de variante produse s-a redus drastic si
in acest moment coexistă variante clasice de AVR Mega si Tiny cu
variante Mega si Tiny “modernizate” (seriile zise 0, 1 si 2), care
incorporează sistemul CIP si/sau alte caracteristici noi sau provenind
de la XMega (Event System, mod Sleep Walking, etc.), de exemplu:
– ATMega 48 varianta clasica si ATMega 4809 varianta modernizata
– ATTiny 88 varianta clasica si ATTiny 809 varianta modernizata
• Din punct de vedere didactic, variantele modernizate sunt mai greu
accesibile, fiind mai complexe, mai ales datorita numărului foarte
mare de registre periferice, in comparație cu variantele clasice,
aceasta fiind si o explicație pentru accentul pus pe acestea din urmă
8
AVR 8 biti, încapsulare, alimentare
- Variante diverse de încapsulare pin-through sau SMT: PLCC,
TQFP, SSOP, UQFN, BGA, etc.
- Variantele Pin-Through (DIL, DIP) sunt din
ce in ce mai rar întâlnite!
- Numărul de pini ( si vom vedea ca si numărul de porturi de I/O)
depinde de varianta de încapsulare: de la 6 sau 8 pini la 100 !
-Tensiuni de alimentare (Vcc) in gama 1.5…6V; există însă
variante care pot fi alimentate începând de la 0.7- 0.8V
(utilizează un așa zis Boost Converter pentru creșterea interna
a tensiunii la 3V)!
- Gama a temperaturilor de lucru: -40 ..+85 oC sau -40..+125 oC

9
Schema bloc AVR 8 biti (Mega si Tiny)
Schema bloc prezentată
este cea clasică, din foile de catalog
Atmel (in plus, nu acoperă si
varianta XMEGA)
Memoria de program este
întotdeauna o memorie de tip FLASH,
reprogramabilă în sistem (ISP), prin
intermediul unei interfețe seriale dedicate
(similară SPI) sau a uneia JTAG standard (la
toate variantele mai noi).
Memoria de date este
implementată odată ca memorie volatilă
SRAM (RAM static) internă, ca memorie
de date externă (de un tip ales de utilizator)
precum şi ca memorie internă EEPROM
(nevolatilă).
Memoria EEPROM are un
mecanism de acces diferit, fiind accesată
prin intermediul unor registre de adresă şi
date aflate în spațiul I/O.
Dimensiunile celor două tipuri interne
de memorie depind de varianta constructivă 10
Schema bloc AVR 8 biți (Mega si Tiny) -2
• În figura este prezentată o schemă
bloc a unui microcontroler AVR cu
doar câteva din resursele tipice
de tip periferic:
– intrări/ieşiri numerice (grupate în
porturi-module)- I/O
– un port serial de tip SPI,
– un comparator analogic,
– ceasul de gardă (watchdog), etc.
• Configurarea unora din resursele
tipice cum ar fi sistemul de ceas,
sistemul de generare a reset-ului,
protecţia unor zone de memorie,
etc,. se face prin intermediul unor
biţi de control nevolatili care sunt
implementaţi ca fuzibile (fuses)
FLASH care se programează, în
mod tipic, la fel şi odată cu
programarea memoriei de program.
11
Schema bloc AVR 8 biti: Mega si Tiny - seria 0
• În foile de catalog ale noilor
variante produse de
Microchip apare o altă formă
a schemei bloc, nu doar mai
decorativă, dar care pune in
evidentă noua arhitectură de
periferice, împreună cu noile
tipuri de periferice
disponibile:
– Interfața universala de
programare si depanare (UPDI-
Universal Program Debug
Interface)
– Controlerul de reset
(RSTCTRL)
– Matricea de comutare a
magistralelor interne (Bus
Matrix)
– EventSystem
– Convertor numeric analogic
(DAC)
– Ceas de timp real (RTC)
– Blocul de logica configurabila
(CCL) 12
– etc..
AVR 8 biți: arhitectura, registrele
unității centrale
• Arhitectura de calcul AVR este o arhitectură de
calcul orientată pe registru şi nu pe acumulator.
• Registrele pot fi, la modul general, clasificate ca fiind:
– de uz general (folosite de ex. pentru memorarea rezultatelor
intermediare, si nu numai)
– dedicate, de uz special (PC - numărător program, SP -
indicator de stiva, SREG - registru de stare, registre utilizate
pentru periferice, intrari/iesiri etc. )
• Setul de registre al unităţii centrale (AVR CPU) conţine
32 registre de uz general (dar si exista variante Tiny cu
16 registre!), de 8-biţi, care pot fi accesate de CPU într-
un singur ciclu (perioadă) de ceas.
– Aceasta permite unităţii aritmetice şi logice (ALU) să execute
operaţiile într-un singur ciclu de ceas.
– Într-o funcţionare caracteristică a ALU, cei doi operanzi sunt
preluaţi din registre, operaţia este executată, şi rezultatul este
memorat înapoi într-un registru – totul realizat într-un singur ciclu
13
de ceas.
AVR 8 biți: arhitectură, registre,
pointeri
• Tipic, șase din cele 32 registre pot fi folosite,
în perechi, ca trei registre indicator (pointer) de
date de 16 biţi, pentru adresarea indirectă a
memoriei de date, permițând calcule de adresă
foarte eficiente.
– Unul dintre aceste trei registre indicator poate să fie
folosit şi ca adresă de căutare pentru tabele ( pentru
instructiuni de tip Table Look Up) din memoria FLASH
de program.
– Aceste registre de 16 biți cu funcții suplimentare sunt
denumite generic registrele X, Y, şi Z.
AVR 8 biți: Registrele de uz
general
• Setul de 32 de registre a fost optimizat pentru instrucțiunile RISC ale
AVR.
• Pentru performanță şi flexibilitate, în cazul în care operanzii unei
instrucțiuni sunt registrele, sunt posibile următoarele combinații (in
limbaj de asamblare) sursă/destinaţie (rezultat):
– un operand sursă pe 8 biţi şi un rezultat pe 8 biţi.
– doi operanzi sursă pe 8 biţi şi un rezultat pe 8 biţi.
– doi operanzi sursă pe 8 biţi şi un rezultat pe 16 biţi.
– un operand sursă pe 16 biţi şi un rezultat pe 16 biţi.
• Majoritatea instrucțiunilor operând cu registrele de uz general au
acces direct la acestea și majoritatea se execută într-un singur ciclu
de ceas.
• Nota Exista si variante de AVR Tiny care au un set redus de
instrucțiuni, prin raportare la toate celelalte variante
• Fiecare registru are asignată o adresă în memoria de date
(SRAM), ele fiind direct mapate în primele 32 locații din spațiul de
memorie de date utilizator.
– Ele sunt direct implementate în memoria de tip SRAM, această
organizare a memoriei oferă o flexibilitate deosebită în accesarea
registrelor
15
Registrele de uz general
- NU toate registrele de uz general sunt
“egale” intre ele!
- Exista si variante Tiny care au doar 16
registre: R16..R31!

- Registrele sunt împărțite, din punct de


vedere funcțional, în două sub seturi:
R0..R15 și R16..R31.

- Astfel există instrucțiuni care operează


doar cu unul din seturi (SBCI, SUBI, CPI,
ANDI, ORI sau LDI) precum şi instrucțiuni
care folosesc un anumit registru implicit
De exemplu o instrucțiune LPM poate avea ca
destinație doar registrul R0.

16
AVR: ALU si registrul de stare SREG
(Status Register)
• Unitatea aritmetică si logică (ALU) realizează operații aritmetice şi
logice între registre sau între o constantă şi un registru.
• După o operație aritmetică sau logică, registrul de stare
(SREG) al unității centrale este actualizat pentru a reflecta corect
rezultatul operației executate de ALU.
• SREG este de fapt un set de biți, care pot fi citiți si scriși, numiți
indicatori de stare

• I – activare globală întreruperi, nu este chiar un indicator de stare!


• T – utilizat in operațiile de copiere bit (BLD, BST)
• H – Half Carry (transport intermediar), utilizat in aritmetica BCD (CBZ)
• S – Sign (semn), un SAU EXCLUSIV intre N si V
• V – oVerflow (depășire), indică depășirea in aritmetica binară
complement față de 2 Operațiile de transfer de date nu afectează
• N – Negative (Negativ) SREG !
• Z – Zero 17
• C – Carry (Transport sau Împrumut)
AVR: numărătorul program (PC- Program
Counter), salturi si apeluri
• Fluxul program (înlănțuirea secvențială a instrucțiunilor) poate fi
modificat prin utilizarea de instrucțiuni de salt condiţionat şi
necondiționat (de tip JuMP) precum şi de instrucțiunile de apel
de subrutină (de tip CALL), toate capabile de a adresa si accesa
direct întreg spaţiul de adrese al memoriei de program.
• Ambele modifică conținutul/valoarea numărătorului program (PC),
dar instrucțiunile de tip CALL, spre deosebire de cele de salt,
salvează si restaurează in/din stivă o adresă de întoarcere, in mod
automat
– Cu alte cuvinte, instrucțiunile de tip JuMP sunt unidirecționale iar cele de tip
CALL sunt bidirecționale, permițând întoarcerea in punctul de apelare a
subrutinei
• Majoritatea instrucțiunilor AVR au un format pe 16 biți, care
reprezintă un cuvânt în memoria de program.
• Fiecare adresă de memorie de program, adresata de PC, va conține
o instrucțiune memorată pe 16 sau 32 biți (pe unul sau două
cuvinte).
• Pentru numărătorul program (PC) un increment reprezintă un
cuvânt (doi octeți), el numărând cuvinte de 16 biți (2 octeți) nu
octeți !
• Numărul efectiv de biți ai numărătorului program (PC) depinde
de dimensiunea memoriei de program implementate pentru o
anumit varianta, vezi memoria de program
AVR: formatul instrucțiunilor (limbaj de
asamblare)
• O instrucțiune constă din:
• Codul operației (opcod, opcode) care definește
operația care se execută
– In limbajul de asamblare este identificată printr-o
mnemonică (care este, de regulă, un acronim sugestiv,
din păcate sugestiv doar in limba engleza…)
• Operanzii (operands), cei asupra cărora se execută
operația si cărora li se aplică modurile lor de
adresare (cele care determina unde si cum anume
sunt memorați):
– O instrucțiune AVR poate avea 0,1,2 sau 3 operanzi
– Operanzii pot fi adrese de memorie, constante, adrese de
registre (numere de registre)

19
Exemple f. simple de instrucţiuni
Operand destinaţie
Mnemonica
Operand sursa
• Adunare: ADD r2, r1 Este de fapt o
adresa de destinatie
• Scădere: sub R13, R12
• Salt (ramificare, branching): breq 6
• Încărcare din memorie (load): LDI r30, $F0
• Memorare in memorie (store): ST X, R2
• Citire din port (input): IN R25, $16; Adrese

• Scriere in port (output): out $16, r17;


– OBS Adresa hex 0x16 ($16 in limbajul de asamblare
AVR) este adresa asociata portului B 20
Setul de instrucţiuni (descriere
sintetica, summary..)
Indicatorii de condiție (din SREG)
afectați

http://ww1.microchip.com/downloads/en/de
vicedoc/atmel-0856-avr-instruction-set- Durata de execuție in perioade ale
manual.pdf semnalului de ceas (cicluri masina)
Registrele X, Y şi Z
• Registrele din plaja R26.. R31 au câteva funcţii suplimentare faţă de
utilizarea lor generală.
•Aceste trei registre de adresare indirectă sunt numite X, Y, şi Z şi sunt
definite ca în figura.
• Aceste registre sunt în primul rând şi indicatoare (pointeri) de
adresă pe 16 biţi utilizabile pentru adresarea indirectă a spaţiului
memoriei de date (X si Y) si program (Z).
•Ele sunt identificate si prin doua registre de 8 biti, unul inferior (L-
Low) si unul superior (H- High); de ex. R26 = XL, R31 = ZH, etc.
• În diferitele moduri de adresare posibile, aceste registre de adresare
îndeplinesc şi funcţii ca incrementare automată sau decrementare
automată.

22
Indicatorul de stivă (SP – Stack Pointer)
• Stiva (stack) este folosită pentru memorarea temporară a datelor, pentru
memorarea temporară a variabilelor locale şi pentru memorarea adreselor de
întoarcere după tratarea întreruperilor şi apelurilor de subrutină.
• Registrul indicator de stivă SP (Stack Pointer) indică întotdeauna vârful
stivei si el adresează octeți, nu cuvinte, deoarece el adresează memoria de
date SRAM
– Pentru AVR 8 biți stiva creste de la adresele de memorie mai înalte în jos, către
adresele de memorie mai joase.
– Aceasta presupune că o comandă (instrucțiune) de tip PUSH (salvează in stivă)
decrementează indicatorul de stivă (SP), iar una de tip POP (restaurează din stiva)
îl incrementează
• Indicatorul de stivă indică o zona de stivă din SRAM-ul de date unde se
găsesc stivele subrutinelor şi întreruperilor.
• Acest spațiu de stivă din SRAM-ul de date trebuie să fie definit de către
utilizator înaintea realizării oricărui apel de subprogram sau de întrerupere,
deşi SP are şi o valoare implicită după reset (0x7).
– Indicatorul de stivă trebuie să indice mai sus de adresa $60 (deasupra spaţiului
I/O).
• Ca o particularitate, în cazul unor membrii ai sub familiei AVR Tiny, la care
tipic nu exista memorie SRAM ci numai registre, stiva este una hardware,
cu un număr mic de nivele de memorare (3 sau 5), limitând corespunzător
numărul de imbricări de subrutine
23
Indicatorul de stivă (SP)
• Indicatorul de stivă este decrementat cu o unitate când datele sunt împinse în stivă cu
o instrucţiune de tip PUSH sau este decrementat cu două unități când adresa de întoarcere
este împinsă în stivă de un apel de subprogram sau întrerupere.
• Indicatorul de stivă este incrementat cu o unitate când datele sunt extrase din stivă cu
o instrucțiune de tip POP şi este incrementat cu două unități când datele sunt extrase din
stivă la întoarcerea dintr-un subprogram cu RET sau întoarcerea din întrerupere cu RETI.
• Indicatorul de stivă al AVR este implementat ca două registre de 8 biți, SPH şi SPL mapate
în spațiul I/O al SRAM.
• Numărul real de biți folosiți depinde de implementarea memoriei SRAM locale (de cat de
mare este memoria SRAM pentru varianta respectiva).
• Este de observat faptul că zona de date în unele implementări ale arhitecturii AVR ea este
atât de mică (256 de octeți sau mai mică) încât numai SPL este suficient (in acest caz
registrul SPH nu există!)
• Pentru o variantă AVR la care numărătorul de program are mai puțin de 16 biți, dacă se
citeşte valoarea numărătorului program (PC) din stivă, după un apel de subrutină sau
întrerupere, biţii neutilizați din SPH trebuie să fie mascați (vezi şi figura).

24
Utilizare stivă, exemplu pentru ATTiny 2313 (care
datorita dimensiunii mic a RAM-ului intern are
doar SPL)

După iniţializarea SP După primul PUSH După al doilea PUSH

LDI R16, 0xDF


OUT SPL, R16

LDI R16, 0x33


LDI R17, 0x25
LDI R18, 0x0A

După POP După al treilea PUSH PUSH R16


PUSH R17
POP R19
PUSH R18
Execuția instrucțiunilor AVR 8 biți
• Execuția unei instrucțiuni AVR 8 biti tipice, cu un singur ciclu mașină,
va fi descrisă sumar în cele ce urmează.
– Exista si instrucțiuni, nu multe, care se executa in 2 sau cu 4 cicluri
mașină sau instrucțiuni care durează un număr variabil de cicluri
• Unitatea centrală (CPU) are ca semnal de ceas cel notat clkCPU, cu
perioadele notate Ti (i=1,2,3,…) care definesc durata unui ciclu
(perioada) de ceas sistem, ceas sistem care este generat direct de
sursa de ceas selectată pentru microcontroler (prin intermediul biților -
fuzibilelor de configurare corespunzători).
– Nu este folosită nici o divizare de ceas internă (deși ea este posibilă al
unele variante).
• Este utilizat conceptul de pipeline de instrucțiuni care presupune
suprapunerea decodificării instrucțiunii curente cu execuția următoarei,
principiu care poate fi utilizat numai la o arhitectura Harvard
• S-a dorit să se obțină o viteză de calcul de până la 1 MIPS ( Millions
Instructions Per Second - milioane de instrucțiuni în virgulă fixă per
secundă) per MHz (normată funcție de frecvența oscilatorului de ceas).
– Dacă frecvența de ceas a unității centrale va fi, de exemplu, de 8MHz,
viteza de calcul va fi și ea de 8 MIPS, s.a.m.d.

26
Pipeline- execuția unei instrucțiuni in paralel cu
decodificarea următoarelor instrucțiuni.
In figura următoare se prezintă execuția de instrucțiuni, în paralel cu
decodificarea unei alte instrucțiuni, posibilă datorită arhitecturii CPU
de tip Harvard.

Rezultatul final este că in 4 perioade al ceasului sistem clkCPU: T1..T4


se pot executa 4 instrucțiuni având durata de 1 ciclu mașină, adică un ciclu mașină
care este egal cu perioada ceasului sistem.

•Pentru durata in cicluri a instructiunilor, vezi descrierea completa a


setului de instructiuni la
http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-
instruction-set-manual.pdf 27
Ilustrare operaţie ALU cu registrele, într-un singur
ciclu masina

Într-un singur ciclu de ceas este executată o operație ALU folosind două registre
ca operanzi, iar rezultatul este memorat înapoi în registrul de destinație; de
exemplu instructiunea ADD R1, R2

In practică interesează mai puțin viteza de execuție exprimată in MIPS, însă


interesează durata/timpul de execuție al unei instrucțiuni, ca valoare absolută.
Exemplu
Dacă un microcontroler AVR 8 biti are configurată fosc=clkCPU=8MHz, in cât timp
se va executa instrucțiunea de un singur ciclu ADD R1, R2 (sau instrucțiunea NOP
care este una similară ca număr de cicluri) ?
Durata de execuție a unei instrucțiuni de 1 ciclu va fi de 125 nsec
clkCPU=8MHz -> Ti=1/(8*10e6) sec = 1*10e-6 /8 sec= 1usec /8 =125nsec 28
AVR 8 biți - arhitectura, evoluția
istorică a unității centrale
• In descrierea Atmel (AN-0856, 2014) a setului de instrucțiuni sunt
referite 5 variante de arhitecturi: AVR, AVRe, AVRxm, AVRxt si
AVRrc:
– AVR: AT90 Setul original de instrucțiuni din 1995 (AT90 nu mai exista!).
– AVRe: megaAVR; instrucțiuni adăugate la setul de instrucțiuni:
Multiply(xMULxx), Move Word (MOVW) si Load Program Memory (LPM)
îmbunătățită. Nu exista diferențe de temporizare la execuție
– AVRe: tinyAVR; fără instrucțiuni Multiply (xMULxx), temporizare identică
la execuție cu megaAVR.
– AVRxm: XMEGA; temporizarea la execuție in mod semnificativ diferită
fată de AVRe; adăugate instrucțiunile de criptare DES si instrucțiunea
Read Modify Write (RMW)
– AVRxt: AVR 2016 si in continuare. Varianta este bazată pe AVRe si
AVRxm dar mai apropiată de AVRe cu o temporizare îmbunătățită a
execuției
– AVRrc: tinyAVR , variantă limitată de unitate centrală (Reduced Core
AVR CPU) dezvoltată pentru variantele Tiny cu număr foarte mic de pini
(6 pini). Are numai 16 registre (R31-R16) si un set limitat de instrucțiuni.
Nota Temporizare execuție se referă la durata de execuție a unor
instrucțiuni, care eventual a devenit mai mică.
29
AVR 8 biți - arhitectura, evoluția
istorică a unității centrale -2
• După 2016 noile variante produse de Microchip si care
eventual înglobează si CIP sunt organizate in serii (series),
actualmente numerotate de la 0 la 2.
• Seriile respective, actualmente trei pentru Tiny si doar una
pentru Mega, sunt exemplificate mai jos, împreună cu câteva
variante constructive aflate in producție:
– Seria 0: ATtiny807, ATtiny1607, ATtiny204, ATtiny404
ATmega4808, ATmega3208
– Seria 1: ATtiny214, ATtiny417, ATtiny817, ATtiny1617,
ATtiny3217
– Seria 2: ATtiny1624
• Toate sunt identificate arhitectural nu după categoriile de
arhitecturi din setul de instrucțiuni Atmel (de exemplu AVRxt) ci
după o caracteristică (o opțiune) a compilatorului GCC WinAVR
si anume avrxmega3, opțiune care transmite compilatorului
despre ce arhitectura specifica a setului de instrucțiuni (ASI)
AVR 8 biti este vorba
30
Memoria microcontrolerelor AVR 8 biti
• Arhitectura AVR are în esență două spatii principale de memorie:
– o memorie de program (FLASH) şi
– o memorie de date (SRAM si EEPROM).
– memoria de date de tip EEPROM destinată pentru memorarea de date nevolatile, are un mecanism de
acces total diferit, si de fapt ea nu este mapată direct in spațiul de memorie AVR
• Potențialul actual de adresare al arhitecturii AVR, ca memorie de program FLASH
implementată este (față de un maxim de 32MB/16Mcuvinte):
– tinyAVR 0.5–16 kB
– MegaAVR 4-512kB
– XMEGA 16-384kB
• Potențialul actual de adresare al arhitecturii AVR, ca memorie de date SRAM
implementată este (față de un maxim de 64kB): :
– tinyAVR 0.03-1kB
– MegaAVR 0.5–16 kB
– XMEGA 2-32kB

31
Harta memoriei unui sistem de
calcul AVR 8 biti
In figura alăturată avem harta de memorie a unui uC AVR de 8 biți (un
ATMEGA8515) unde lucrurile sunt complicate si de implementările fizice
diferite ale memoriilor de program si mai ales date: FLASH, registre si
SRAM (RAM static) si respectiv EEPROM

32
Memoria de program- FLASH
• Orice microcontroler AVR 8 biti are 2N KOcteţi (Bytes) de memorie
internă de program de tip FLASH (NOR), programabilă în sistem
(ISP).
• Deoarece toate instrucțiunile AVR sunt memorate pe 16 sau 32 de
biţi (1 sau 2 cuvinte), memoria FLASH are intotdeauna o organizare
de tip NKcuvinte x 16 biţi.
• Astfel pentru un ATMega32 avem N=16, adica 32Kocteţi de
memorie organizată în 16 Kcuvinte x 16 biţi.
• Spațiul de memorie de program FLASH este împărţit principial în
două zone (pentru ATMega si XMEGA), zona de Bootloader şi
zona de aplicație.
– Pentru un ATtiny, si in general pentru variante cu putina memorie
FLASH, nu exista o zona de Bootloader
• Cele două secțiuni/zone diferă şi prin nivelele de protecţie la
ștergere oferite/disponibile.
• Memoria FLASH AVR are garantat un număr minim de cel puţin
10 000 de cicluri de ștergere şi scriere.

33
Memoria de program- FLASH
• Numărătorul de program PC al unui AVR 8 biți numără cuvinte (de 2
octeți), numărul lui de biți implementat efectiv depinzând de dimensiunea
memoriei FLASH implementată pentru o anumită variantă
• Dacă avem, de exemplu, un ATMEGA16, cu 16kB de FLASH, dar de fapt cu 8
kcuvinte, el va trebui să adreseze 8 kcuvinte si are efectiv 13 biti (213=8192)
• Pentru un ATiny13, cu 1kB de FLASH, dar de fapt cu 512 cuvinte, el va trebui
să adreseze 512 cuvinte si are efectiv 9 biți (29=512)
• Actualmente (2013) circuitele ATMEGA2560/2561 (utilizate si de Arduino
2560..) sunt cele care au implementată memoria FLASH cea mai mare de
256kB/128kcuvinte, deci PC-ul are 17 biți (217=131072)
• S-a spus anterior că registrul Z este utilizat pentru adresarea indirectă a
memoriei de program
– Aceasta este necesară pentru instrucțiunile care citesc si scriu din memoria de
program (tip LPM si SPM) precum si pentru instrucțiunile de salt/apel subrutina
(IJMP/ICALL)
• Dar Z are doar 16 biți, fiind posibilă adresarea a maxim 64 de kcuvinte
• Pentru variantele de AVR (MEGA si XMEGA) care au mai mult de 64kcuvinte,
există niște registre suplimentare 8 biți (implementare maximă) numite RAMPZ
(Extended Z-pointer Register) si EIND (Extended Indirect Register) care se
concatenează cu registrul Z, obținându-se un registru extins de 24 de biți, si
deci un domeniu de adresare maxim de 16Mcuvinte pentru memoria de
program !
Memoria de program: exemple (ATMega)
• În figura este prezentată o organizare a memoriei
FLASH de program pentru N=4 (8 Kocteţi de
memorie organizată în 4 Kcuvinte x 16 biţi,
0x000..0xFFF).
• Memoria de program este împărțită in 2 zone:
– Aplicație
– Boot(loader)
• Dimensiunea celor două zone poate fi controlată prin
intermediul fuzibilului BOOTSZ, si eventual întreaga
memorie fiind alocată ca zonă de aplicație dacă nu
este nevoie de un Bootloader
• Numărul de biți ai numărătorului de program - PC
depinde de dimensiunea memoriei implementate
pentru o anumită variantă.
– Astfel pentru un ATMega64 numărătorul program este
unul pe 15 biţi, el adresând 32K cuvinte de memorie de
program.
– Dar pentru un ATTiny2313 numărătorul program este
unul pe 10 biţi, el adresând doar 1K cuvânt de memorie
de program.
• Tabelele de constante pot fi memorate în întreg
spațiul de adrese al memoriei de program, existând
modalități eficiente (instrucțiuni) de citire a acestora, 35
cum ar fi instrucțiunea LPM (Load Program Memory).
Memoria de program: Bootloader
• Conceptul de Bootloader (vezi introducere) poate fi materializat cu relativă
ușurință datorită existenței unei instrucțiuni care permite si scrierea in memoria
FLASH, in cazul acesta instrucțiunea SPM (Self Programming Memory)
• Instrucțiunea SPM are o funcționalitate complexă deoarece ea permite
scrierea într-o anumită zonă a memoriei de program, in același timp cu
citirea din alta zonă, citire necesară pentru a se putea executa programul!
• Numai astfel este posibilă programarea memoriei de program de către
unitatea centrală a microcontrolerului(CPU), in timp ce CPU execută cod
preluat din aceiași memorie!
• Toate operațiile cu instrucțiunea SPM se realizează prin intermediul registrului
SPMCR (sau SPMCSR) care conține un ansamblu de biți de comandă si/sau
stare
• La fel ca la orice memorie de tip NOR FLASH ștergerea/ scrierea se face
pagină cu pagină si nu octet cu octet
• Pentru a putea fi scrisă, o pagină trebuie mai înainte ștearsă
– Scrierea se face cu ajutorul unei memorii RAM intermediare (transparentă pentru utilizator) numita
buffer de pagină
• Durata operațiilor de ștergere si scriere a unei pagini este mult mai mare
decât durata unei operații de citire (de aceea există biți de stare prin
intermediul cărora se poate afla când s-a finalizat operația) !

• OBSERVAȚIE Memoria nevolatila (NVM), de program si date, precum si harta


de memorie aferentă, a suferit unele evoluții importante la noua familie XMEGA
si la variantele Microchip, prin introducerea unui așa zis controler de memorie
nevolatila NVMCTRL, cu un set de registre dedicat. Vezi prezentarea aferentă
si mai ales foile de catalog/manualele XMEGA sau MegaAVR seria 0!
Despre fuzibilele(fuses) AVR
• In memoria de program FLASH a oricărui microcontroler AVR de 8 biți există o
zonă specială, de cel putin 3 octeți: octet inferior (low byte), octet superior (high
byte), octet extins (extended or lock byte) ai căror biți au o funcționalitate
specială servind la o configurare nevolatilă a unor resurse (periferice, memorie)

• Acești biți sunt denumiți generic fuzibile (fuses), denumirea fiind o reminiscență
istorică din timpurile primelor circuite PROM; singurul lucru pe care îl au in comun
cele 2 tehnologii (FLASH si cea utilizată la vechiul PROM) este faptul ca biții
respectivi sunt nevolatili, isi păstrează starea dacă tensiunea de alimentare
dispare
– Fuzibilele nu sunt altceva decât niște locații speciale de memorie nevolatila
FLASH, accesibile (programabile) la nivel de bit, cu niște proceduri speciale
• Biții respectivi au si niște valori implicite pentru un microcontroler AVR care nu a
fost programat niciodată (așa cum este livrat din fabrică), aceasta însemnând că
există si o configurare implicită a resurselor, configurare care in mod tipic este
foarte puțin probabil să fie cea dorită de utilizator si cea necesară pentru aplicație
• Aceasta înseamnă că fuzibilele (tipic doar o parte a lor) vor trebui sa fie
programate înainte de rularea codului aplicației, cu ajutorul aceluiași
programator hardware extern cu care se programează memoria de program
FLASH si/sau cea de date EEPROM
• Fuzibilele nu pot fi programate dinamic (starea lor nu poate fi modificată),
prin program, ci numai static cu ajutorul un programator extern!
• OBSERVAȚIE Sistemul de fuzibile a suferit unele evoluții importante la noua
familie XMEGA si la variantele Microchip, vezi prezentarea aferentă si mai ales
foile de catalog/manualele XMEGA sau MegaAVR seria 0!
Fuzibilele AVR – valoare si
funcționalitate
• Întotdeauna trebuie citită foaia de catalog a microcontrolerului respectiv si
înțeleasă bine valoarea si funcționalitatea biților respectivi (vezi si observația
de la sursele de ceas)
• Fuzibilele de la ATTiny sunt diferite de cele de la ATMega, si mai mult, pot
diferi de la o variantă de AVR Tiny sau Mega la alta
• Funcție de varianta de AVR ele au legătură si cu configurarea:
– sistemului de generare al ceasului,
– sistemului de generare a reset-ului (valoare brownout, pin extern),
– alegerea interfeței de programare (ISP sau JTAG sau alta),
– memoriei de program Flash (protecție, zona bootloader),
– memoriei de date EEPROM (ștergerea ei),
– ceasului de gardă (activare watchdog)
OBS O locație de memorie (un octet) cu proprietăți similare este utilizată la (auto)calibrarea
oscilatorului de ceas in varianta cu grup RC intern – calibration value
• Programarea acestor fuzibile poate fi una mai ușoară, vizuală prin
intermediul unei interfețe grafice pentru un programator (universal)
sau mai complicată utilizând valorile efective ale locațiilor respective
(caz AVRDUDE)
• Un “calculator” pentru fuzibilele multor variante de AVR găsiți aici:
http://www.engbedded.com/fusecalc/
• Vom reveni cu informații sintetice despre ce înseamnă “programarea” unui
microcontroler AVR 8 biți
Fuzibile sistem ceas ATtiny2313: un programator
universal paralel (“HV- High-Voltage”)

Interfața utilizator este explicită si lizibilă (fără acces la foaia de catalog)


Fuzibile sistem ceas ATtiny2313: Ponyprog, un
programator ISP (http://www.lancos.com/prog.html) pentru hobbyiști

Este esenţial sa intelegeti ca “bifat” înseamnă bit programat adică in “0”, iar
“nebifat” înseamnă bit neprogramat adică in “1”
Atenţie, CKDIV8 programat înseamnă ca ceasul sistem va fi divizat cu 8!
Deci totul va merge de 8 ori mai încet!
Interfața utilizator nu este explicită si nici lizibilă (fără acces la foaia de catalog)
40
Fuzibile sistem ceas ATtiny2313: simulatorul
Proteus VSM (ISIS-7)

Fuzibilele CKSEL (4 biţi) si


SUT (2 biţi) sunt grupate

Interfața utilizator a simulatorului Proteus VSM nu cuprinde de fapt toate


41
fuzibilele (BODLEVEL si EESAVE lipsesc) !
Memoria de date- memoria externă
• AVR 8 biți permite eventual doar utilizarea unei memorii de
date externe nu si a uneia de program
• Principial memoria de date poate fi internă și externă.
– Spațiul de adresare maxim posibil (de fapt actualmente
implementat) pentru ambele tipuri este de 128KOcteţi (Bytes).
• Utilizarea unei memorii externe de date (numită generic
XMEM) atunci când este posibilă (de fapt ea este posibilă
numai la variante de încapsulare cu cel puțin 40 de pini), nu
este o opțiune foarte fericită, prezentând două dezavantaje
majore:
– este necesar un număr mare de interconexiuni externe/pini
pentru implementarea magistralelor externe de adrese și date, care
nu mai pot fi utilizate pentru intrări/iesiri de uz general
• Pentru adresarea memoriei externe, magistrala externă de date
(D0..D7, 8 biţi) este multiplexată in timp cu octetul inferior (A0..A7) al
magistralei de adrese (A0..A15, 16 biti), fiind necesar si un circuit de tip
latch transparent de 8 biți (gen 74HC373 sau 74HC573) pentru
demultiplexarea octetului inferior de adresa (A0..A7);
• conexiunile externe “pierdute” vor fi in număr de 18: AD0..AD7
(adrese/date multiplexate) si A8..A15, plus un semnal de scriere /WE si
unul de citire /RD
– un ciclu de acces la memoria externă durează mai mult decât
unul la memoria internă. 42
Memoria de date SRAM- organizare
În figura alăturată este prezentată
organizarea memoriei SRAM
pentru varianta ATMega32.
• Cele 2144 locaţii inferioare
ale memoriei de date sunt
dedicate registrelor de uz
general, registrelor I/O şi
memoriei interne de date
SRAM.
• Primele 96 locaţii sunt
destinate registrelor de uz
general şi memoriei I/O, iar
următoarele 2048 locaţii sunt
memoria internă de date
SRAM.

În particular, familia AVR Mega poate utiliza memorie de


date externă (şi cu posibilitatea introducerii de stări de Wait),
iar unele microcontrolere din familia AVR Tiny nu aveau
deloc memorie internă de date (de tip SRAM). 43
Exemplu ATMEGA32, registre si SRAM (vedere AVR
Simulator IDE Oshonsoft, http://www.oshonsoft.com/avr.html )

Aici incepe SRAM-ul 44


Exemplu ATMEGA32, registre si SRAM (AVR Studio 4
Simulator/Debugger)

Aici începe SRAM-ul

Indicatorul de stiva

45
Exemplu ATMEGA32, registre si SRAM,
conexiuni externe (pin-out)

Indicatorul de stiva Aici se termina SRAM-ul Pentru o capsula DIL40 46


Exemplu ATMEGA32, registre si SRAM
(AVR Studio 4 Simulator/Debugger)

Aici se termina SRAM-ul

47
Exemplu ATTiny2313, registre si SRAM, pin-out

Capsula DIL20 48
Exemplu ATTiny2313, registre si SRAM
(AVR Studio 4 Simulator/Debugger)

Cycle Counter (numărător de cicluri mașină) si Stop Watch


(cronometru) sunt 2 resurse virtuale ale simulatorului
(nu există fizic); ele permit, pe baza cunoașterii
frecvenței oscilatorului de ceas (Frequency), măsurarea49unor
timpi/durate de execuție
Exemplu ATTiny13, registre si SRAM, pin-out

Capsula este DIL8 ! 50


Exemplu ATTiny13, registre si SRAM
(AVR Studio 4 Simulator/Debugger)

51
Exemplu ATMega328, registre si
SRAM (Atmel Studio 7 Simulator/Debugger)

52
Memoria de date, timpii de acces
• Timpul de acces la memoria internă de date este ilustrat în figura de mai
jos unde accesul la memoria internă SRAM este executat în două cicluri de
ceas ale unității centrale.
• Sunt ilustrate ambele tipuri de acces: citire (Read) şi scriere (Write) în
SRAM-ul intern, validate de semnalele interne RD şi WR (intern ele sunt
active în „1”)
• Instrucțiunile care accesează memoria interna de date durează, in mod
tipic, cel puțin 2 cicluri mașină

53
Memoria de date: modurile de adresare
• Există cinci moduri posibile de adresare pentru memoria de date şi ele sunt:
1. adresare directă (ex. LDS R16, k; k= o adresa in SRAM)
2. adresare indirectă cu deplasare (ex. STD Y+q, R22; q – deplasament de 6 biți)
3. adresare indirectă (ex. LD r15,X)
4. adresare indirectă cu pre-decrementare (ex. LD r15, -X)
5. adresare indirectă cu post-incrementare (ex. ST X+, R15)
• Adresarea directă poate fi utilizată pentru tot spațiul memoriei de date.
• Modul de adresare indirect cu deplasare permite adresarea a maxim 63 de
locații începând de la adresa de bază din registrele Y sau Z.
– Registrele R26..R31 se utilizează ca pointeri pentru adresarea indirectă.
• Când se folosește adresarea de tip registru indirect cu pre-decrementare
automată şi post-incrementare, registrele de adresă X, Y, şi Z sunt
decrementate sau incrementate corespunzător.
• Cele 32 de registre de uz general, cele 64 de registre (locații) din spaţiul I/O şi
cele n locaţii din SRAM-ul intern de date sunt accesibile în toate aceste moduri
de adresare.

54
O memorie internă de date particulară: memoria
EEPROM
• Majoritatea variantelor familiei AVR au şi o memorie de tip EEPROM locală
destinată memorării nevolatile a datelor.
– Atmega32 are 1024 octeţi de memorie de date EEPROM, ATTiny2313 doar 128
octeti
• Această memorie este organizată ca un spațiu de date separat printr-un
mecanism special de acces, în care octeţi singulari pot să fie citiţi şi/sau
scriși.
• Memoria EEPROM AVR are garantat un număr minim de 100 000 de
cicluri ştergere şi scriere.
• Accesul este realizat prin intermediul registrelor EEPROM din spaţiul
I/O: nu se citește si scrie ca o memorie de tip SRAM, utilizarea ei este
mai complicata!
– Deoarece operația de scriere are o durată destul de mare (de ordinul
milisecundelor) există o modalitate automată de sincronizare care permite
utilizatorului să detecteze când s-a finalizat operația de scriere a unui octet și
poate fi scris octetul următor.
– Pentru a împiedica posibilitatea unor scrieri accidentale în EEPROM, trebuie să
fie urmată o procedură de scriere specifică.
– Mai trebuie menționat că atunci când EEPROM-ul este citit, unitatea centrală
este oprită pentru patru cicluri de ceas înainte de execuția următoarei
instrucțiuni.
– Când EEPROM-ul este scris, unitatea centrală este oprită pentru două cicluri de
ceas înaintea de execuția următoarei instrucțiuni
55
Memoria EEPROM si registrele aferente
(interfața programator)

56
EEPROM_write, un exemplu de funcție care
scrie un octet in memoria internă EEPROM
void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
/* Asteapta terminarea operatiei de scriere anterioare */
while(EECR & (1<<EEWE))
;
/* Stabilim adresa unde vrem sa scriem si data de scris in registrele
corespunzatoare*/
EEAR = uiAddress;
EEDR = ucData;
/* Scriem un “1” in bitul EEMWE */
EECR |= (1<<EEMWE);
/* Declansam operatia de scriere scriind un “1” in bitul EEWE */
EECR |= (1<<EEWE);
}
EEPROM_read, un exemplu de funcție care
citește un octet din memoria internă EEPROM

unsigned char EEPROM_read(unsigned int uiAddress)


{
/* Asteptam finalizarea unei eventule operatii anterioare de scriere */
while(EECR & (1<<EEWE))
;
/* Stabilim adresa de unde vrem sa citim */
EEAR = uiAddress;
/* Declansam operatia de citire scriind un “1” in EERE */
EECR |= (1<<EERE);
/* Returneaza data din registrul de date */
return EEDR;
}
AVR 8 biti: sistemul de generare si distribuţie a
ceasului (clock generation system)
• Sistemul de generare a ceasului este descris ca fiind
unul complex şi flexibil, care generează și distribuie
și alte semnale de ceas pentru diversele sub sisteme
AVR.
– Descrierea de mai sus (complex si flexibil) este adevărată de
fapt doar pentru familia XMEGA
– Exista puține variante specializate de AVR care au modalități
de multiplicare a frecventei (cu bucle PLL digital sau
similare), si aceasta nu pentru unitatea centrala ci doar
pentru periferice (de exemplu pentru generarea PWM)
• Nu toate semnalele de ceas interne aferente
diverselor sub-sisteme / module trebuie să fie active la
un moment dat!
• În ideea reducerii consumului de energie, semnalele
de ceas pentru modulele inactive pot fi oprite folosind
diferitele moduri de control a puterii consumate
(moduri “sleep”) sau prin biți de configurare individuală
59
AVR 8 biți - Sistemul de generare si distribuție a
ceasului

60
Semnalele de ceas AVR 8 biți : interne si/sau externe

• Semnalele de ceas menționate în continuare, tipice pentru un ATMega, pot fi


controlate, în sensul opririi şi pornirii, implicit (prin intrarea într-un anumit mod
sleep) sau explicit cu ajutorul unor biți de comandă din registrele de control.

• Ceasul CPU – clk CPU este dirijat către părțile sistemului legate de unitatea
centrală (CPU).
– Exemple de asemenea module sunt registrele de uz general, registrul de stare şi
memoria de date pentru indicatorul de stivă.
– Prin oprirea acestui ceas nu mai este posibilă execuția calculelor şi operațiilor
specifice de către CPU.
• Ceasul I/O – clk I/O este folosit de majoritatea modulelor I/O, precum modulele
de temporizare-numărare, SPI sau USART.
– El este folosit şi de modulul de întreruperi externe, dar întreruperile externe sunt
detectate cu o logică asincronă, permițând acestor întreruperi să fie detectate chiar
dacă ceasul I/O este oprit.
– De asemenea, recunoașterea adresei de către modulul TWI (Two Wire Interface =
I2C) este realizată tot asincron când clk I/O este oprit, făcând posibilă recepția adresei
TWI în toate modurile de tip sleep.

61
Semnalele de ceas AVR 8 biți : interne si/sau
externe

• Ceasul FLASH– clk FLASH controlează funcţionarea


interfeţei cu memoria FLASH, fiind de obicei activ
simultan cu ceasul CPU.
• Ceasul modulului de temporizare asincronă – clk
ASY permite modulului de temporizare-numărare
asincronă să fie controlat de un ceas provenind de la un
cristal extern de joasă frecvenţă, de 32.768 KHz.
– Este astfel posibilă utilizarea acestuia ca un ceas de timp real
(RTC) chiar şi când dispozitivul este în modul sleep.
• Ceasul convertorului analog–numeric (ADC) – Clk
ADC este cel pe baza căruia este periodizată conversia
analog-numerică (daca exista un astfel de convertor).
– Este posibil ca pe durata efectuării unei conversii să oprim
ceasurile CPU şi I/O pentru a reduce nivelul zgomotului numeric,
cu efecte pozitive asupra preciziei măsurării.
62
AVR 8 biți: sursele de semnal de ceas
• În mod tipic sistemul de ceas al microcontrolerelor AVR permite
alegerea tipului sursei de ceas de bază sau cu alte cuvinte a tipului
de oscilator care va fi utilizat pentru generarea ceasului.
• Opțiunea este realizată cu ajutorul unor fuzibile (biţi de configurare
FLASH) dedicate CKSEL (ClocK SELect)
• Programarea acestor fuzibile se face de regulă odată cu programarea
codului în memoria FLASH.
• Ceasul provenind de la sursa selectată este de fapt intrarea
sistemului de ceas AVR.
• Tipuri posibile de generatoare/configurații de ceas:
1. Oscilator stabilizat cu ajutorul unui rezonator extern, de tip cristal de
cuarţ sau piezoceramic
2. Oscilator stabilizat cu ajutorul unui cristal extern de joasă frecvență
(cristal ceas 32.768kHz)
3. Oscilator stabilizat cu ajutorul unui grup RC (rezistenta, capacitor) extern
4. Oscilator stabilizat cu ajutorul unui grup RC intern (pre-calibrat, prin
intermediul registrului intern OSCCAL)
5. Sursa externa de semnal de ceas

63
AVR 8 biți: sursele de semnal de ceas, ilustrate
Oscilatorul cu cristal de cuarţ (sau rez. ceramic) Oscilatorul RC extern

Cristal 32.768kHz

Sursa de ceas externa

Oscilatorul RC intern (calibrat)


Oscilatorul RC intern calibrat poate genera frecvenţe
de ceas fixate la 1.0, 2.0, 4.0, sau 8.0 MHz.
Aceste valori nominale sunt calibrate la tensiunea de
alimentare de 5V şi temperatura de 25°C.
De exemplu, la frecvența de 1.0 MHz, această
calibrare asigură deviații de frecvenţă de maxim ±1%
faţă de frecvența nominală.

64
Sursele de semnal de ceas – timpul de pornire
(SUT – Start Up Time )
• În configurarea sursei de ceas şi a oscilatorului de ceas trebuie luat
în considerare şi faptul că fiecare configurație de oscilator are și un
anumit timp de pornire, din momentul conectării alimentării (de
fapt al ajungerii tensiunii de alimentare la o valoare cvasi-
nominala) și până la stabilizarea semnalului de ceas generat,
ca frecvență și amplitudine
• Numai după această stabilizare unitatea centrală poate fi inițializată
(resetata) corect sau instrucțiunile pot fi executate corect începând
de la adresa 0.
• Acesta este motivul pentru care există o corelație între evoluția
tensiunii de alimentare la conectare, logica de inițializare (reset) și
configurarea sistemului de ceas.
• Această corelare poate fi controlată, în anumite limite, cu ajutorul
fuzibilelor numite SUT (SUT – Start Up Time, care
definesc/stabilesc un timp de pornire).
• SUT este exprimat in perioade ale oscilatorului de ceas si trebuie
corelat cu tipul de oscilator ales (trebuie neapărat consultată si foaia
de catalog)
65
Evoluția tipică a ieșirii unui oscilator (stabilizat cu un
rezonator extern cuarț) la conectarea tensiunii de
alimentare

Oscilatie stabilizata
Iesire oscilator

Vcc

Aici (in acest moment) se conectează


tensiunea de alimentare
Scara timp: 4msec/div
66
Sursele de semnal de ceas – sursa
implicită
• Sursa de ceas implicită este cea cu care funcționează
un microcontroler AVR “neprogramat” (așa cum provine
de la fabricant).
• Valoarea implicită a fuzibilelor critice din acest punct de
vedere este CKSEL = “0001” şi SUT = “10”.
• Sursa de ceas implicită pentru orice variantă AVR este
oscilatorul intern RC, cu frecvența de 1 MHz şi cu
timpul de pornire (SUT – Start Up Time) cel mai lung.
– Această setare garantează faptul că toţi utilizatorii vor putea să
aleagă sursa de ceas dorită utilizând o programare serială (ISP)
sau paralelă high voltage (cu ajutorul unui programator dedicat).

67
Sursele de semnal de ceas – fuzibilele aferente

OBSERVAŢIE IMPORTANTĂ
• Flexibilitatea configurării prin fuzibile a acestui sistem de ceas ascunde şi
capcane.
• Astfel este posibil ca, dintr-un motiv sau altul, pentru o anumită configurație
hardware externă, programarea fuzibilelor să se facă greșit de către utilizator.
• De exemplu, hardware-ul extern existent este un grup RC asociat configurației
specifice de oscilator, dar “programarea” tipului este făcută pentru configurația
oscilator cu cristal extern.
• Programarea respectivă va fi şi ultima care se poate face prin intermediul
interfeței seriale ISP, deoarece după programare oscilatorul nu va mai
funcționa, iar microcontrolerul nu mai are semnalul de ceas intern necesar
pentru funcționarea programării ISP!
• Soluția de rezolvare a problemei intr-un astfel de caz este:
– utilizarea unui programator extern paralel – HV- High Voltage (daca microcontrolerul poate
fi scos din sistem!) pentru reprogramare sau
– a unei improvizații pentru hardware-ul extern (dacă se cunoaște ce anume s-a programat
greșit!): un grup RC extern, un cristal de cuarț cu 2 capacitori, un ceas extern ..

68
Microcontrolere (si
microprocesoare)

Microchip AVR 8 biți : inițializarea hardware (Reset-ul),


ceasul de gardă (watchdog), intrări-ieşiri numerice (porturi
I/O), metode pentru a realiza accesul la intrări -ieșiri,
sistemul de întreruperi AVR (partea 1)

1
Inițializarea AVR 8 biti (reset)
• După o inițializare hardware (un reset), la fel ca la orice alt
microprocesor/microcontroler, şi cel puţin o parte din resurse au o
stare inițială precizată, astfel:
– Toate registrele I/O sunt setate la anumite valori iniţiale (implicite),
descrise in foaia de catalog/manual
– Prima instrucțiune executată este cea din vectorul de Reset, de la
adresa respectivă- 0x0000; cu alte cuvinte valoarea initiala a
numaratorului program PC este 0x0000
• Instrucțiunea memorată în vectorul de reset este de obicei o instrucțiune de salt absolut
(JMP) la prima instrucțiune din programul propriu-zis.
• Daca vorbim de initializarea hardware, pentru orice
microcontroler exista doua tipuri de baza de reset hardware:
– Un reset generat de conectarea si reconectarea sursei de
alimentare (power down + power up), numit reset la rece (cold
reset)
– Un reset generat de orice altceva (de exemplu prin intermediul
unui pin de reset), numit reset la cald (warm reset)
• După un reset la cald conținutul memoriei SRAM de date
rămâne nemodificat!
• După un reset la rece, conținutul RAM-ului de date (SRAM),
deci si al registrelor de uz general, este neprecizat (SRAM-ul
este o memorie volatila)! 2
Inițializarea AVR (reset)

• Valori inițiale (initial value) ale biților unui registru I/O, după reset,
asa cum apar in foaia de catalog.
• Dacă programul nu activează şi nu utilizează întreruperile, vectorii
de întrerupere nu vor fi folosiți, şi codul programului poate scris şi la
aceste adrese- vezi sistemul de intreruperi.
– Acest lucru este, de asemenea, posibil şi în cazul în care vectorul de
reset este în zona de aplicaţie în timp ce vectorii de întrerupere sunt în
zona de bootloader sau invers.
• După ce „sursa externă” care a generat semnalul de reset devine
inactivă, intră în acțiune un numărător intern care va genera o
întârziere (time-out) cu scopul măririi perioadei cât reset-ul, intern
de data aceasta (internal reset), este activ.
– Aceasta va permite, de exemplu, tensiunii de alimentare să ajungă la o
valoare nominală stabilă înainte de se executa instrucţiuni.
– Acest timp de întârziere este definit si poate fi programat de utilizator
prin fuzibilele CKSEL.
3
Schema bloc a sistemului de generare a
reset-ului AVR 8 biti (AVR clasic)

4
Schema bloc a sistemului de generare a
reset-ului AVR 8 biti (AVR modernizat )

Variantele modernizate de Mega si Tiny (seriile 0, 1 si 2 ) introduc un nou asa


zis controler de reset RESCTRL care permite si:
• determinarea originii resetului (cine l-a generat) prin intermediul unui registru
de stare numit RSTFR - Reset Flag Register
• generarea unui reset software - CPU(SW)- prin intermediul registrului de
5
control SWRR- Software Reset Register
Inițializarea AVR 8 biti (reset): sursele

• Tipic, pentru un microcontroler AVR 8 biti (exemplificare ATMega)


există cinci surse de reset, care pot fi descrise astfel:

– Reset la conectarea tensiunii de alimentare (power-up reset): când


tensiunea de alimentare, crescătoare, depășește o anumită valoare de
prag (notată VPOT).
– Reset extern: când un nivel de „0” este prezent pe pinul RESET, pentru
o perioadă mai mare decât o durata minimă.
– Reset prin ceasul de gardă (watchdog reset): când ceasul de gardă
este activat şi perioada de gardă expiră.
– Reset la scăderea temporară a tensiunii de alimentare (Brown-out
reset): când detectorul de Brown-out este activat şi tensiunea de
alimentare VCC coboară sub pragul de brown-out (notată VBOT).
– Reset prin interfața JTAG (pentru variantele care au interfata
JTAG): când registrul de reset al interfeței JTAG este adus în “1”.

6
Reset-ul la conectarea tensiunii de alimentare
(POR)
• Un impuls de reset va fi generat la conectarea tensiunii de alimentare de
un circuit specializat (POR - Power On Reset) atunci când VCC va atinge
nivelul de prag VPOT atât în sens crescător cât şi descrescător.
• Circuitul POR garantează că microcontrolerul va fi resetat corect la
conectarea alimentării (Power-on).
• Atingerea tensiunii de prag în sens crescător declanşează numărătorul de
întârziere care va stabili durata de prelungire a reset-ului intern (tTOUT), după
dispariţia condiţiei.
• Reset-ul intern este activat (si mentinut) fără nici o întârziere atunci când
VCC coboară sub nivelul de detectare.
• Această variantă de reset este valorificată în practică prin conectarea
pinului RESET direct la tensiunea de alimentare Vcc: VPOT=VRST .

7
Reset-ul extern
• Un reset extern este generat practic de un nivel “0” pe pinul /RESET,
impuls care durează mai mult decât o lăţime de impuls minimă (din foaia de
catalog), chiar dacă ceasul CPU este oprit.
• Când semnalul aplicat pe /RESET atinge tensiunea de prag (VRST) pe
frontul crescător, pinul va fi considerat în „1”, condiția a dispărut şi un
numărător intern de întârziere va genera perioada suplimentară de reset
intern tOUT.
• În figuri sunt prezentate cele două situații relevante pentru activarea intrării
RESET: imediat după Power-up şi oricând în timpul funcționării.

8
Dacă nu utilizăm un reset de
Utilizare Reset extern tip extern, pinul respectiv
poate fi folosit ca intrare /ieşire
de uz general (in ex. PA2)

Utilizarea unui circuit extern


dedicat (de ex. DS1233 EconoReset de la
Reset manual – cu un buton; există/este activată Maxim) pentru generarea
Reset-ului la punerea sub tensiune
o rezistentă internă către Vcc, PA2 ieşire si =1)

9
Reset-ul la scăderea temporară a tensiunii de
alimentare (Brown-out)
• Unele microcontrolere AVR (ATMega, XMEGA si cateva ATTiny) au un circuit de
detecţie numit BOD- Brown Out Detection, pentru a monitoriza nivelul VCC în
timpul funcţionării, comparând-ul cu un nivel fix de declanşare.
• Nivelul de declanşare pentru BOD poate fi selectat cu fuzibilul BODLEVEL la
valoarea 2.7V (BODLEVEL neprogramat), sau la valoarea 4.0V (BODLEVEL
programat), funcţie de valoarea utilizată pentru tensiunea de alimentare.
• Nivelul de declanșare are asociat şi un histerezis VHYST pentru a garanta o detecţie
sigură şi a discerne între evoluţia crescătoare (V+ ) şi cea descrescătoare(V- ):
– VBOT+ = VBOT + VHYST /2 şi VBOT- = VBOT - VHYST /2.
• Circuitul BOD poate fi activat sau dezactivat prin intermediul unui fuzibil numit
BODEN.
• Când BOD este activat (fuzibilul BODEN programat) şi VCC scade la o valoare sub
nivelul de declanșare (VBOT - în figura), reset-ul intern este activat imediat.
– Când VCC crește deasupra nivelului de declanşare (VBOT+ în figura) numărătorul de
întârziere va genera perioada suplimentară de reset intern tOUT.
– Circuitul BOD va detecta o scădere a VCC numai dacă tensiunea se menţine sub nivelul de
declanșare mai mult decât un interval minim tBOD.

Se numeste “Brown-out” prin raportare


la ce inseamna un “Black-out” –
o căderea totala a tensiunii de alimentare

10
Conceptul de ceas de gardă (watchdog) si
utilizarea lui
• Un temporizator de tip ceas de gardă (watchdog timer) este un
subsistem hardware/software al unui sistem de calcul care declanșează
un Reset - o inițializare hardware- (sau o altă acţiune corectivă de aceiași
natură) atunci când programul aplicației, datorită apariției unei stări de
defect temporar sau permanent (având ca efect tipic gen programul se
“agață”, nu mai răspunde, se “înțepenește”, etc.), nu mai reușește să
“trateze” (tipic să inițializeze) acest temporizator in mod periodic si
regulat (la intervale previzibile de timp)
• Scopul final este de a readuce sistemul într-o stare cunoscută si, dacă
este posibil, o stare de funcționare normală sau sigură
– De regula aceasta stare este starea după reset (inițializare hardware)
• Un temporizator de tip ceas de gardă poate fi de asemenea utilizat pentru a
aduce un sistem de calcul utilizat pentru control (controler) de tip fail-safe
într-o stare sigură, de exemplu, cu motoarele oprite, cu ieșirile de înaltă
tensiune si cu alte sub-sisteme periculoase similare oprite/inactive.
– Un sistem fail-safe este un sistem zis cu securitate incorporată, care in cazul
apariției unui defect ajunge într-o stare sigură, prescrisă anterior
– Utilizarea acestor sisteme fail-safe este esențială in aplicațiile critice din
avionică, transport feroviar, industria automobilului sau domeniul medical

11
Ceasul de gardă (watchdog)
• Pentru toate sisteme incorporate (embedded systems) care nu
pot fi supravegheate in mod constant de un operator uman si
care trebuie să fie auto-suficiente, utilizarea unei astfel de
tehnologii este obligatorie (nu există nimeni care să apese pe
butonul de reset dacă sistemul nu mai reacționează!)
• In mod riguros(si din considerente de fiabilitate), un temporizator de
tip ceas de gardă trebuie să fie exterior sistemului (să nu fie realizat
pe acelaşi microcircuit cu unitatea centrala), reducând probabilitatea
ca același defect să afecteze sistemul de calcul si temporizatorul
simultan
• Atunci când el este inclus ca un periferic dedicat, ca in cazul multor
microcontrolere (inclusiv AVR), soluţia este una de compromis preţ
de cost-siguranţă in funcţionare
• Oricum ar fi implementat, mărimea lui de “ieşire” trebuie să
controleze direct intrarea de reset (iniţializare hardware) a sistemului
de calcul (microcontroler, microprocesor, etc. )
• In varianta sa cea mai simplă el este un temporizator/numărător
care, dacă nu este reîncărcat/resetat/rearmat periodic, ajunge la
depăşire (Overflow, Time-Out), aceasta condiție ducând la Reset-ul
12
CPU
AVR 8 biti: Temporizatorul ceasului de gardă
• Watchdog Timer (WDT) AVR este de fapt un numărător care are un semnal de ceas care
provine de la un oscilator RC separat on-chip (intern, independent de ceasul sistem)
de 128 kHz (asta la ATiny 2313, la alte variante poate avea alte valori).
• WDT va genera un reset sau o întrerupere dacă numărătorul ajunge la valoarea maximă
(la depășire).
• In funcționarea normală utilizatorul (aplicația software) trebuie să folosească
instrucțiunea WDR - Watchdog Timer Reset – pentru a reporni numărătorul de la 0 înainte
ca acesta să ajungă la valoarea maximă, in caz contrar el generând un reset sau o
întrerupere
• Pentru o evita a dezactivare/oprire accidentală a acestui sub-sistem trebuie utilizate
secvențe speciale de operații in momentul in care se lucrează cu biții din registrul
WDTCR- Watchdog Timer Control Register

13
Reset-ul prin ceasul de gardă (Watchdog Reset)
• Cu ajutorul divizorului (watchdog prescaler) se pot programa (alege)
intervale pentru declanșarea ceasului de garda (durată totală a ciclului de
numărare) intre 16msec si 8 sec.
• Dacă se dorește utilizarea acestui sub-sistem fuzibilul WatchDog
always ON (WDTON), trebuie să fie programat (in caz contrar acest
temporizator poate genera doar o cerere de întrerupere)
– Atunci când ceasul de gardă generează o depășire (Time-out, ca urmare a ne
reîncărcării/repornirii lui în timp util), el va genera un impuls scurt de reset cu durata de un
ciclu de ceas (1CK), iar pe frontul căzător al acestuia va fi declanșat numărătorul de
întârziere reset care la rândul lui va genera perioada suplimentară de reset intern tOUT.

14
Fuzibile Reset ATTiny2313-
Proteus VSM

Modelele AVR nu au
toate fuzibilele, de ex.
lipsesc fuzibilele
BODLEVEL!

15
Fuzibilul RSTDSBL si utilizarea pinului
/RESET
• Pentru variantele de microcontrolere AVR 8 biți la care
pinul /RESET poate avea si funcții alternative de intrare-
ieșire (ca parte a unui port), cum ar fi:
– ATTiny2313: /RESET si PA2
– ATMEGA48, ATMEGA88: /RESET si PC6
– ATMEGA329: /RESET si PG5,
– etc.
in setul de fuzibile există un fuzibil numit RSTDSBL
(external Reset Disable) care trebui să fie programat
(Programmed) pentru ca pinul respectiv să poată fi
programat si utilizat ca un pin de intrare/ieșire obișnuit;
altcumva el poate fi utilizat eventual doar ca intrare de
reset extern!
16
Intrările și ieșirile numerice (porturile de
intrare/ieșire)
• Toate microcontrolerele AVR 8 biți au un număr oarecare de intrări- ieșiri
numerice de uz general, grupate din punct de vedere funcțional în “porturi” de
intrare/ ieșire (I/O ports).
• Denumirea lor (Microchip/Atmel) este PORTA, PORTB, PORTC, PORTD, etc.
– Ele permit realizarea de cicluri de acces de tip Read-Modify-Write (citește –
modifică - scrie).
• Toti pinii asociați acestor porturi sunt bidirecționali
• Direcția unui pin (intrare si/sau ieșire) al portului poate fi schimbată individual,
fără a schimba şi direcția oricărui alt pin din același port
– Direcția, adica utilizarea sa ca intrare sau ieșire, este programabilă individual
pentru fiecare pin din port
• Dacă un pin este programat ca fiind de tip ieșire, tipul de ieșire este si el
programabil, prin activarea sau dezactivarea rezistoarelor de sarcină interne
Rpu= x10KOhmi:
– De tip cu drenă în gol (fără rezistență internă de sarcină) sau
– Normală, cu rezistență interna de sarcină, către Vcc(Rpu pull-up)

Dacă un pin este programat ca fiind de tip intrare, comportarea sa depinde de


conectarea sau nu a rezistentei interne de sarcina Rpu:
- daca Rpu e conectat intrarea respectiva are potențialul fixat la “1”, putând fi
eventual trasa la “0”
- daca Rpu nu e conectată intrarea respectiva va fi flotantă, într-o stare de înaltă
impedanță (Hi-Z) 17
Pin-out (conexiunile externe) pentru ATTiny
2313 (capsula DIP20)

Deși par a exista porturile A, B, C, D, etc. ele nu sunt “egale” intre ele:
nu au același număr de pini disponibili (biţi)- la fel ca si in cazul unor alte variante de
AVR cu număr relativ redus de pini, pentru acest tip de AVR anumite porturi sunt
implementate doar parțial, adică nu au toți cei 8 biți
18
Pin-out (conexiunile externe) pentru ATMega
328 (capsula PDIP28)

Deși par a exista porturile A, B, C, D, etc. ele nu sunt “egale” intre ele:
nu au același număr de pini disponibili (biţi)- la fel ca si in cazul unor alte variante de
AVR cu număr relativ redus de pini, pentru acest tip de AVR anumite porturi sunt
implementate doar parțial, adică nu au toți cei 8 biți
Obs. ATMega 328 este microcontrolerul utilizat de Arduino Uno. 19
Pin-out (conexiunile externe) pentru ATMega
2560 (capsula TQFP100)

In capsula de mai sus (TQFP100) sau in cea de tip CBGA100 de mai sus are 10 porturi:
PA…PL, din care doar portul PG este implementat incomplet (are doar 6 biti). 20
Obs. ATMega 2560 este microcontrolerul utilizat de Arduino 2560.
Intrările și ieșirile numerice (porturile I/O) –
caracteristici electrice
• Intrările sau ieșirile AVR 8 biti sunt compatibile TTL sau LVTTL (funcție si de
tensiunea de alimentare Vcc)
• Buffer-ele de ieșire au capacitatea de a absorbi/debita un curent IOL/IOH de
până la 20mA (la Vcc=5V) putând comanda astfel direct un LED sau optocuplor
• Capacitatea de a absorbi/debita curent depinde însă de tensiunea de
alimentare, de exemplu la Vcc= 3 V curentul maxim absorbit/debitat scade la
10mA.
• Toți pinii de port pot avea rezistoare de sarcină individuale interne, cu o
rezistență care nu depinde de tensiunea de alimentare (Rpu=20..50kOhmi).
• De asemenea toți pinii au diode de protecție atât către Vcc cât și către masă
după cum se observă în figură
– In figura de mai jos Cpin (xpF) este capacitatea parazită asociată pinului, are
conteaza in regim dinamic

Schema electrică
echivalentă a unui “pin”

21
Intrările şi ieșirile numerice AVR 8 biti
(porturile I/O) - caracteristici electrice (de cc)

Tiny2313

Mega32

Sunt specificate ca la orice familie standardizata de circuite integrate numerice


(aceleasi notatii)!

Atenție: Suma dintre IOL si/sau IOH de pe toate porturile existente nu trebuie să
depășească 200mA, iar de pe un singur port (de exemplu portul A) 100mA (valorile
depind însă si de tipul de încapsulare)

22
Intrările şi ieșirile numerice AVR 8 biti
(porturile I/O)- configurarea
• Referitor la notațiile utilizate în continuare (notatii Microchip/Atmel):
cu “x” s-a notat litera care identifică portul de 8 biţi (x= A, B, C, …), şi
cu “n” numărul bitului din port (n=0..7).
• Notația generala ar fi PORTxn, iar ca un exemplu particular bitul 6
din portul A va fi notat cu PORTA6 sau PA6
• Pentru fiecare din porturile existente sunt alocate trei locații de
memorie (trei registre) în spațiul I/O:
– registrul de date de ieşire – notat PORTx,
– registrul pentru stabilirea direcţiei datelor – notat DDRx (Data
Direction Register),
– şi pinii portului (registrul de date de intrare) – notat PINx.
• Locațiile corespunzătoare pinilor de intrare ai portului PINx pot fi
numai citite, în timp ce registrul de date PORTx şi registrul pentru
direcția datelor DDRx pot fi scrise şi citite.
• Majoritatea acestor pini de port au şi funcții alternative relevante
pentru perifericele microcontrolerului, existând un mecanism de
multiplexare adecvat.
– Activarea şi utilizarea funcțiilor alternative pe unii dintre pinii portului nu
influențează folosirea celorlalţi pini din port ca intrări/ieşiri de uz general.
23
Bitul PUD: exemplu ATTiny2313 si ATMega
328

ATTiny2313

ATMega 328

Un bit de comanda particular este bitul de dezactivare a rezistoarelor de


sarcină PUD (Pull Up Disable) din registrul MCUCR (MCU Control
Register) bit care atunci când este setat dezactivează simultan
rezistențele de sarcină interne Rpu pentru toți pinii, pentru toate
porturile.

Ceilalți biti din registrul MCUCR depind de varianta de


microcontroler AVR (au functionaliatati diferite functie de varianta) 24
AVR 8 biți: porturile I/O utilizate ca intrări/ieşiri de
uz general, programarea lor.
• Prima operație care trebuie realizată de utilizatorul intrărilor şi ieșirilor numerice ale unui
microcontroler AVR este cea de “configurare” a pinilor.
• Din punct de vedere al programatorului fiecare pin al portului se compune din trei biţi:
– DDxn,
– PORTxn şi
– PINxn.
• Biţii DDxn sunt accesați la adresa I/O DDRx, biții PORTxn la adresa I/O PORTx şi biţii
PINxn la adresa I/O PINx.
• Bitul DDxn în registrul DDRx selectează direcția acestui pin:
– Dacă DDxn este “1” logic, Pxn este configurat ca pin de ieșire.
– Dacă DDxn este “0” logic, Pxn este configurat ca pin de intrare.
• Dacă PORTxn este programat “1” logic când pinul a fost configurat ca pin de intrare,
rezistorul de sarcină este activat şi va „trage” în „1” intrarea neconectată (nu mai este
nevoie de o rezistenta externă către Vcc dacă ar fi cazul).
• Pentru a dezactiva acest rezistor, PORTxn trebuie să fie “0” logic
• Atâta timp cât reset-ul este activ pinii portului sunt într-o stare similară de înaltă
impedanță High-Z (tri-state), chiar dacă ceasul I/O nu este activ.
• După un reset, toti pinii sunt configurați ca intrări (DDRx=0) fără rezistențe interne
către Vcc (PORTx=0), fiind într-o stare similară High-Z (stare de înaltă impedanță)

• OBSERVATIE: Pentru familia XMEGA si pentru seriile Mega si Tiny modernizate


acest model de programare s-a modificat, devenind mult mai complex (cu 11 + 8 =
19 registre per port!) dar si mai flexibil! 25
Registrele aferente porturilor I/O pentru ATtiny
2313
Pentru Tiny2313
portul A are
doar 3 pini
accesibili si doar
3 biţi
implementaţi

Portul B
este
complet -
8 pini/biţi

26
Porturile I/O ca intrări/ieșiri de uz general –
comutarea intrare-ieșire si invers
• Dacă PORTxn este =“1” când pinul este configurat (cu DDRxn) ca
ieșire, pinul portului va fi şi el în “1”.
• Dacă PORTxn este =“0” când pinul este configurat ca ieșire, pinul
portului va fi şi el în “0” .
– Când se trece de la o stare tip intrare High-Z ({DDxn, PORTxn} = 0b00)
la o stare tip ieşire în „1” ({DDxn, PORTxn} = 0b11), apare o stare
intermediară, fie cu rezistoarele de sarcină activate ({DDxn, PORTxn}
= 0b01) fie cu ieşirea in „0” ({DDxn, PORTxn} = 0b10).
• În mod normal, starea cu rezistoarele de sarcină activate este
complet acceptabilă, deoarece in cazul unei intrări având o
impedanță mare nu se va observa diferența între un pin in starea “1”
şi prezența rezistoarelor de sarcină.
– Dacă este însă cazul ieşirii „0”, bitul PUD din registrul SFIOR poate fi
setat pentru a dezactiva toate rezistoarele de sarcină .
• Când se trece de la o stare cu intrarea cu rezistoare de sarcină la o
ieșire în „0” apare aceeași problemă.
– Utilizatorul trebuie să folosească starea tri-state ({DDxn, PORTxn} =
0b00) sau ieșire “1” ({DDxn, PORTxn = 0b11) ca un pas intermediar.

27
Porturi I/O: configurația implicită (după
reset), intrare, fără Rpull-up
Vcc
DDx

0 R Pull-Up

PORTx

PINx Pinul fizic

? ?

Direcţia: INTRARE
R Pull-Up: DECONECTATA (OFF)
Porturi I/O: intrare, cu RPull-Up conectat

DDx Vcc

0 RPull-Up

PORTx

PINx Pinul fizic

? 1

Direcţie: INTRARE
RPull-Up: CONECTATA (ON)
Porturi I/O: ieşire, in “1”

Vcc
DDx

1 RPull-Up

PORTx

PINx Pinul fizic

1 1

Direcţie: IEŞIRE
RPull-Up: DECONECTATA (OFF)
Exemple elementare de cod, porturi I/O

• Următorul exemplul de cod (în limbaj de


asamblare şi apoi în C) arată cum se pot
programa pentru portul B:
– în “1” pinii 0 şi 1 ca ieşiri ,
– în “0” pinii 2 şi 3 tot ca ieşiri şi cum
– se definesc pinii de la 4 la 7 ca intrări,
• cu rezistenţe de sarcină doar pentru pinii 6 şi 7.
– Valorile setate şi rezultate pentru pini sunt citite
înapoi, dar o instrucţiune NOP este inserată înainte
pentru a face posibilă citirea corectă a valorilor recent
asignate pinilor (ea introduce o mică întârziere).

31
Exemple de cod: programare porturi
In limbaj de asamblare AVR (asamblor AVR Studio 4):

;Definirea rezistenţelor şi setarea ieşirii in 1.


;Definirea direcţiei pentru pinii portului
ldi R16,(1 << PB7) | ( 1 <<PB6) | (1 << PB1) | (1 << PB0)
ldi R17,(1 << DDB3) | ( 1 <<DDB2) | (1 < <DDB1) | (1 << DDB0)
out PORTB, R16
out DDRB, R17
nop ; Inserarea unei instrucţiuni NOP
; Citirea pinilor portului
in R16, PINB

Pentru codul în asamblare sunt utilizate două registre temporare R16 şi


R17 pentru a minimiza timpul de când rezistenţele de sarcină sunt
activate pe pinii 0, 1, 6, şi 7 şi până când direcţia biţilor este corect
setată, definind biţii 2 şi 3 ca “0” şi redefinind biţii 0 şi 1 ca ieşiri în “1”.

Operatorul “<<” este cel de deplasare (shift) stânga, iar “ | “ este un SAU
logic la nivel de bit, identici cu operatorii bitwise din C 32
Exemple de cod: programare porturi
In limbaj C (WinAVR):

unsigned char i;
/* Definirea rezistenţelor de sarcina şi setarea ieşirii
in 1. */
/* Definirea direcţiei pentru pinii portului */
PORTB =(1 << PB7) | (1 << PB6) | (1 << PB1) | (1 << PB0);
DDRB = (1 << DDB3) | (1 << DDB2) | (1 << DDB1) | (1 <<
DDB0);
/* Inserarea unei instrucţiuni NOP */
_nop();
/* Citirea pinilor portului */
i = PINB

Operatorul “<<” este cel de deplasare (shift) stânga, iar “ | “


este un SAU logic la nivel de bit (bitwise)

VEZI SI PREZENTAREA MM0 ! 33


Exemple de cod, ce înseamnă PORTB sau
PB2.. (WinAVR)
• In fişierul header notat ioyXXXX.h, (de ex. iotn2313.h) cu ajutorul unor directive
#define sunt (pre)definite valorile pentru porturi si biţi.
• De exemplu, pentru portul B avem:

/*Data Register, Port B */


#define PORTB _SFR_IO8(0x18)//adresa din RAM-ul de date
…..

/*Port B Data Register – PORTB */


#define PB7 7 //practic doar numarul bitului
#define PB6 6
#define PB5 5
#define PB4 4
#define PB3 3
#define PB2 2
#define PB1 1
#define PB0 0

34
Exemple de cod, manipulare biţi

• Prin folosirea de operatorilor logici la nivel de bit (bitwise) de tip AND,


OR, XOR si NOT se pot manipula biţii individuali

/* XOR comutam starea bitului 5 */


PORTB = PORTB ^ 0x20; /* adica il inversam */
PORTB ^= 0x20; /* mai inversam odata, dar altfel */

/* OR setam biti 7 si 2, ceilalti nu ne intereseaza!*/


PORTB = PORTB | 0x84;
PORTB |= (1<<PB7)|(1<<PB2) ; /*acelasi lucru dar mai
portabil*/

/* AND stergem biti 0 si 1, dar numai pe ei! */


PORTB = PORTB & 0xFC;
PORTB &= ~((1<<PB0)|(1<<PB1)); /* acelasi lucru dar mai
portabil, folosim si un NOT */

35
Exemple de cod, măşti

• Prin utilizarea unei “măşti” (constante) putem testa


starea unor biţi individuali:
/*ne intereseaza daca bitul 0 din Portul D este 1*/
if(PIND & 0x01){facem_ceva();}
• Valoarea constanta 0x01 utilizată aici este numită
“mască” (mask).
• Ne permite să “anulăm” ceilalți biţi (fara insa a le
modifica valoarea din registru) si să determinăm dacă un
bit particular este in 1.
• O filozofie asemănătoare se poate aplica dacă ne
interesează să testăm dacă un bit in 0:

/* ne intereseaza daca bitul 5 din Portul B este 0*/


if(~PIND & 0x20){facem_ceva();}
36
Exemple de cod, o aplicaţie cu intrări/ieşiri
elementare
• Să presupunem (de altfel in mod corect) că după
inițializare (reset) starea registrelor asociate porturilor B si
D este:
– DDRD = 0x00 (intrare..)
– DDRB = 0x00 (intrare..)

• Pe pinul corespunzător bitului 0 din portul D este conectat


un comutator normal deschis.
– Atunci când comutatorul se va închide pinul va fi conectat la masă
(“0”).
• O să citim starea bitului 0 din portul D, o să o inversăm si
valoarea rezultată va oferita ca ieşire pe pinul (bitul) 0 din
portul B- acesta va trebui deci sa fie (re)configurat ca
iesire
• Valoarea/starea tuturor celorlalţi biti si pini din porturile
utilizate nu trebuie să fie afectată!
37
Exemple de cod, o aplicaţie I/O
Hardware-ul..
Vcc
Atenţie: nu există rezistentă externă
către Vcc, obligatoriu trebuie activată
(conectată) cea internă R

PB0 IF
“0” LED
PD0
Comutator
LED-ul se va aprinde când
PB0=“0”, pinul PB0 absorbind
Masa (Gnd) curentul de conducţie directă
IF al LED-ului

Evident, bornele de alimentare ale microcontrolerului Vcc si Masa (GND)


38
nu au mai fost figurate!
Exemple de cod, o aplicație..
si software-ul ..
#include <avr/io.h>
int main()
{
DDRD &= 0xFE; /*ne asiguram ca numai bitul 0 din portul
D este definit ca intrare */
PORTD |= 0x01; /*conectam rezistenta interna de pull-up
pentru bitul bitul 0*/
DDRB |= 0x01; /*configuram numai bitul 0 din Portul B
este iesire */

while (1) /*o bucla fara sfarsit */


{
if(PIND & 0x01){PORTB &= 0xFE;} // daca bitul este 1
else {PORTB |= 0x01;} // daca bitul este 0
}
}

39
Ce facem cu pinii I/O neutilizați / “neconectați”

• Dacă unii dintre pinii de intrare/ieşire rămân neutilizaţi,


este bine să se garanteze că aceşti pini au o stare
definită şi nu rămân flotanţi (in gol)
• Metoda cea mai simplă pentru a garanta o stare definită
(“1”) pentru un pin neutilizat, este definirea lui ca
intrare şi activarea rezistenţelor de sarcină.
• Trebuie ţinut cont că în cazul unei reiniţializări (reset)
rezistenţele de sarcină vor fi (re)activate
• Dacă un consum scăzut de energie este important în
timpul (re)iniţializării, este recomandat să se folosească
rezistoare externe de sarcină către VCC („1”) sau
rezistoare externe către masă („0”).
• Nu este recomandată conectarea pinilor neutilizați
direct la VCC sau la masă, deoarece aceasta poate
duce la apariția unor curenți excesivi dacă pinul este
configurat din greșeală ca ieşire. 40
Ce facem când numărul de pini I/O este insuficient?
Cum putem eventual “multiplica” numărul de intrări?
Prin utilizarea unui registru de deplasare extern
de tip paralel -> serie (74165 in exemplu):
aici cu ajutorul a 3 pini putem citi 8 intrări
8 intrări numerice
Algoritm:
-PB5(ieșire) = intrare /LOAD registru =“0”
încarcă datele paralel
-PB6 (ieşire) = intrare CLK registru este
ceasul de deplasare
- PB6 (intrare) = iesire Qh registru
-Se generează 8 cicluri de ceas (impulsuri)
-La fiecare ciclu se citește in bitul PB7=Qh
data de ieşire (serială, bit cu bit) din registru
-Microcontrolerul (aplicația) “asamblează”
cei 8 biţi citiți secvențial intr-un octet
Registrul de deplasare poate avea o
dimensiune mult mai mare (obținută de
exemplu prin cascadarea a mai multe registre)
Conectarea cu microcontrolerul utilizează
doar 3 pini (si 3 fire) si o masa comuna.
Putem avea, de exemplu, 64 de intrări numerice 41
citite doar cu ajutorul a 3 pini!
Ce facem când numărul de pini I/O este
insuficient?
Cum putem eventual “multiplica” numărul de ieșiri?
8 ieşiri numerice Prin utilizarea unui registru de deplasare extern
(CD 4094)de tip serie -> paralel
Algoritm:
-PB6 (ieșire) = intrare CLK registru, este ceasul de
deplasare
-Se generează 8 cicluri de ceas (“0”,”1”, “0”..,)
-La fiecare ciclu se scrie bitul PB7 (ieșire) = intrare
DATA registru care este data de intrare (serială) in
registru
- Cei 8 biți, scriși secvențial de microcontroler
(de aplicație), sunt asamblați intern
(sunt desocializați de registru) intr-un octet
- La final PB5 (ieșire) = intrare Strobe registru = “1” si
datele sunt transferate la ieșirile registrului , acestea
fiind actualizate (vezi si foaia de catalog a lui CD4094!)

Soluția de mai sus poate fi utilizata si pentru mai multe


ieșiri prin cascadarea mai multor registre
42
Ce mai putem face când numărul de pini I/O este
insuficient?
Utilizarea unor dispozitive
periferice dedicate, cu magistrală
serială de tip I2C care necesită
doar 3 fire (folosesc doar 3 biţi,
conexiuni I/O)
Interfaţa I2C poate fi implementată
software pentru ATTiny 2313, sau se poate
utiliza un ATMega care are si o
interfaţă TWI (I2C) hardware

PCF 8574 este un exemplu de


circuit I/O expander (8 biţi intrări
si/sau ieşiri), cu interfaţă serială de
tip I2C
Există soluţii similare si pentru
Magistrala serială SPI (disponibilă si
ea la ATMega).
Vezi capitolele despre interfeţele seriale
sincrone TWI si I2C ! 43
Care sunt metodele pentru a realiza accesul la
intrări/ ieşiri (I/O) pentru o unitate centrala
(CPU)?
• Cum ar trebui să procedeze unitatea centrală (CPU)
a unui microcontroler / microprocesor pentru a
comunica cu si a controla dispozitivele de intrare si
ieșire (I/O)?
– Transferul de date înseamnă o relație intre două entități: un
producător de date si un consumator de date
• Dispozitivele I/O sunt “văzute” de CPU prin intermediul
unei interfețe I/O care înseamnă un set de registre sau
locații de memorie specifice
• Tipic putem spune că ea este alcătuită (exemplu
generic):
– registre de date (un set de biți utilizați pentru transferul de
date, atât pentru intrări cat si ieșiri),
– registre de stare si control (un set de bit utilizați pentru
sincronizarea intre cele două entități, care permit citirea stării
si implementarea controlului prin comenzi)
• Interfața I/O face parte din modelul de programare
pentru dispozitivele de intrare si ieșire 44
Metode pentru a realiza accesul
la intrări/ieșiri ( I/O)
• Câteva întrebări (relevante):
• Ce fel de date trebuie să fie transferate?
– Aceasta depinde de natura specifica a intrării / ieșirii, a dispozitivelor respective
de I/O
– O imprimanta este diferita de o tastatura si ambele sunt diferite de un robot
industrial sau un sistem de achiziții de date..
• Cine produce si cine consumă informația/datele?
– Avem, contextual, diverse tipuri de producători de date si consumatori de date
– Unitatea centrala poate fi producător de date si dispozitivul I/O consumator de
date (operație de ieșire)
– Unitatea centrala poate fi consumator de date si dispozitivul I/O producător de
date (operație de intrare)
• Care este viteza cu care un producător produce datele si care este
viteza cu care un consumator poate să le consume?
• Care este volumul de date care trebuie transferat per unitatea de timp?
• Ținând cont de viteza si volumul datelor, care sunt modalitățile prin care
se poate obține un schimb de date fiabil (a.i. sa nu se piardă date!) si
eficient (din punct de vedere al timpului de calcul utilizat) intre
producători si consumatori, cum anume se pot “sincroniza” cei doi
parteneri de dialog ?
45
Transferul programat (bazat pe interogare in
buclă)
• Cu ajutorul celor două seturi de registre I/O (date si stare/ control) se
poate realiza o “tranzacție” de date intre cele două părți
(producător si consumator) pe baza unei bucle de așteptare:
fiecare parte va aștepta un timp nedefinit într-o buclă in care testează
starea indicatorului înainte de produce/consuma.
– Starea poate fi citita si pe baza ei se poate elabora o comanda de transfer de date
– Pe baza comenzii se realizează transferul efectiv de date si se elaborează
informația de stare (care spune ca transferul s-a finalizat) si eventual una de eroare
(transfer finalizat corect)
• Acest gen de gestionare a intrărilor/ieșirilor se numește transfer
programat sau transfer bazat pe interogare (polling) printr-o bucla
de așteptare (busy waiting loop)
• Acest mod de transfer de date are un mare dezavantaj: consumă
inutil puterea de calcul si timpul de prelucrare al CPU:
– Când CPU execută bucla de așteptare el nu face nimic util in afara de
aceasta așteptare.
– Ca să aveți idee de cat timp CPU se pierde, pentru acest exemplu
comparați viteza de calcul a oricărui CPU cu viteza cu care un operator
uman poate introduce datele (poate apăsa tastele unei tastaturi)!

46
Întreruperi si rutine de tratare a
întreruperilor
• Modalitatea programată de intrare/ieșire este afectată in primul
rând de faptul ca participanții la o astfel de tranzacție I/O pot avea
viteze de acces la informație mult diferite si diverse
– Luând ca exemplu tastatura, bănuim că un sistem de calcul (un CPU)
poate citi de mii si mii de ori mai rapid decât un operator poate tasta
(fie el si un Speedy Gonzalez…)
• Astfel, “partenerul” rapid va trebui să aștepte după “partenerul”
lent, ducând la o irosire masivă de resurse (de exemplu putere
computațională): astfel intre 2 prelucrări succesive nu se face
nimic, doar se așteaptă, irosindu-se timpul unității centrale

• Asincronismul dintre un sistem de calcul, sincron prin natura
lui, si lumea exterioară lui, cu care interacționează, necesită
de cel mai multe ori soluții mai eficiente.

• Utilizarea întreruperilor reprezintă o astfel de soluție


47
Principii de bază pentru utilizarea
întreruperilor
• Pentru un sistem de calcul o întrerupere este un “semnal” care
provine de la un sub-sistem hardware (întreruperi hardware) sau in
urma execuției unor instrucțiuni (întreruperi software) si care indica
necesitatea tratării unui eveniment de unitatea centrală
• Dacă evenimentul respectiv este legat de necesitatea realizării unei
operații de intrare/ieșire atunci întreruperile reprezintă o modalitate
de a le trata
– In cazul unei astfel de întreruperi (si nu numai) unitatea centrala va
presupune că pentru a trata intrarea sau ieșirea respectivă activitățile
de intrare/ieşire sunt temporar suspendate (cum ar fi situația in care
operatorul uman nu a apăsat încă următoarea tastă) si își va planifica
singur (adică automat sau cvasi-automat) execuția unei alte sarcini
computaționale legata de prelucrarea acestei intrări sau ieșiri
• O întrerupere este o discontinuitate, o “ruptură” (trap) in derularea
secvențială (normală) a fluxului program, forțând CPU să își
întrerupă/suspende programul curent si să transfere controlul unei
(sub)rutine de tratare a întreruperii.
– Este echivalentul unui apel de subrutină/funcţie sau de salt dar care
este realizat in mod “automat” de un sub-sistem hardware dedicat: 48
sistemul de întreruperi
Exemplu de tratare al unei întreruperi provenind de la
o tastatură

Re-activează introducerea datelor


de la tastatura si întreruperile
Activează introducerea datelor
de la tastatura si întreruperile

Întoarcere din
întrerupere

Citeşte/prelucrează
Face tot felul de
datele provenind
lucruri utile.. de la tastatura
Întrerupere
Programul “principal”:
Alte activităţi ale CPU DA
Am terminat?

NU

(Sub)rutina de tratare a
întreruperilor 49
Observații cheie legate de utilizarea
întreruperilor
• Deoarece unitatea centrală nu mai trebuie să execute
bucla/buclele de așteptare, ea poate realiza, in marea
majoritate a timpului, alte sarcini utile, până când va fi
întreruptă din nou.
• Aceasta îmbunătățește utilizarea resurselor CPU si
a sistemului/timpului de calcul in ansamblu, având
ca efect si un timp mai bun de răspuns pentru toți
“utilizatorii”
• Prelucrarea I/O se poate realiza astfel intr-un mod
total asincron, fără a face nici o ipoteză legată de
momentul apariției evenimentelor legate de
intrări/ieșiri
• Orice microprocesor sau microcontroler modern are
un sub-sistem de întreruperi hardware, care la
rândul lui are si propria interfață de programare, cu
registre de stare si control / comanda
50
Multiplicitatea surselor de întreruperi
• Întreruperile pot proveni de la mai multe dispozitive de intrare/ieșire (de la mai
multe surse de întreruperi )
• Intr-un sistem tipic de calcul cereri de întrerupere ar putea fi cauzate de (doar
câteva exemple):
– Defecte ale surselor de alimentare: cădere iminenta a sursei de alimentare
– Sisteme de temporizare/numărare: depășiri
– Dispozitive de intrare/ieșire, convertor analog - numeric, interfață serială
asincronă: terminarea operațiilor de conversie sau transfer
– Apariția unor erori de natura hardware: eroare de paritate memorie, etc.
– Apariția unor erori de natura software: împărțire la zero, etc.
• In acest context rezulta probleme specifice:
– Care sunt prioritățile acestor întreruperi: dacă mai multe cereri de
întreruperi apar simultan care va fi procesata prima, o întrerupere poate fi la
rândul ei întreruptă?
– Cum se face identificarea (individualizarea) întreruperilor: funcție de
natura specifică a întreruperii vor exista rutine de tratare diferite, care din
ele se va fi selectată si se va executa?
• Cum știm de fapt cine a generat de fapt cererea de întrerupere?

51
Prioritățile întreruperilor
• Când putem să-i permitem unei întreruperi să întrerupă la rândul
ei rutina de tratare a unei alte întreruperi? De ce? Care
întrerupere va fi tratată următoarea?
– In mod tipic prioritățile pot fi asignate de proiectant si programator
diverselor surse de întreruperi conform unor criterii funcționale cum ar
fi: care sunt penalitățile dacă nu se reacționează in timp util, utilitatea
valorilor returnate de rutina de tratare a unei întreruperi specifice, etc.
– Astfel următoarea ordonare a priorităților, de la mai mare la mai mic, ar
putea fi tipică:
• Defect sursă alimentare; Temporizări; Erori; I/O;
• Alocarea priorităților se poate face de programator prin
intermediul unor biți dintr-un registru de comanda sau este
impusă de arhitectura sistemului de întreruperi
• Eventual fiecare sub-clasă de priorități ar putea avea drept
corespondent un bit intr-un registru de stare al unui semnal
transmis către CPU.
– Aceasta ar fi o cerere de întrerupere specifică pentru această sub-clasă
de priorități.

52
Identificarea întreruperilor
• Selecția rutinei de tratare a întreruperii adecvate poate fi
rezolvată in mai multe feluri
• In general, CPU trebuie să identifice sursa întreruperii
(eventual începând cu cea având mai mare prioritate)
pentru a o trata corespunzător
• Identificarea poate fi realizată folosind o interogare
software (software polling) a întreruperilor: rutina de
tratare a întreruperii este cea care “caută” prin interfeţele
de intrare/ieșire (registrele de stare asociate), începând cu
cea mai prioritară interfață
• Odată ce a ajuns la prima interfață care are o cerere de
întrerupere activă, va selecta rutina de tratare a
întreruperii corespunzătoare acelui dispozitiv (interfețe)
• Sincronizarea cu dispozitivul care a generat întreruperea
este facuta pe baza un semnal / unei condiții provenind de
la CPU indicând ca CPU este gata să proceseze
întreruperea (Interrupt Acknowledge ), astfel încât
acesta să o identifice, eventual sub forma unui vector de
întrerupere (interrupt vector).

53
Vectorii de întrerupere
• Un vector de întreruperi face parte dintr-o tabela de
vectori de întrerupere care este o structură de date
care asociază o listă de rutine de tratare a întreruperilor
cu o listă de cereri de întreruperi
– Vectorul de întrerupere este primit de CPU care îl va utiliza ca un
pointer (indicator)/ sau adresa a punctului de început a rutinei de
tratare a întreruperilor, funcție de natura si sursa întreruperii.
• O tabelă de vectori de întrerupere, o tabelă care conține
mai mulți vectori de întrerupere, reprezintă modalitatea
tipică de a asocia fiecare sursă de întrerupere cu o
(sub)rutină de tratare specifică a întreruperii (RTI)
• Conținutul/valoarea acestor vectori indică (direct -
adresa sau indirect - adresa adresei, funcție de familia
concretă de microcontrolere/ microprocesoare) adresa
de început a rutinei de tratare a întreruperii dorite (de
unde se execută prima instrucțiune a RTI)
• Si AVR 8 biți folosește o astfel de tabelă de vectori de
întrerupere
54
Activarea si dezactivarea
întreruperilor
• Deși utilizarea priorităților, intr-un anume sens, deja
dezactivează întreruperile de priorități mai mici
nepermițându-le să întrerupă o rutină de tratare a
întreruperii a unei întreruperi mai prioritare, de multe ori este
necesară si o dezactivare dinamică (pe parcursul
execuției programului) sau statică (de la începutul
execuției programului in cazul in care întreruperile
respective nu sunt utilizate )
• Un exemplu activare/dezactivare dinamica ar fi existenţa a
două procese, unul de intrare si unul de ieşire, de exemplu:
– Procesul de intrare citește un caracter de la tastatură si procesul de
citire afișează acest caracter pe o consolă.
– Intrarea si ieșirea trebuie realizate aici in secvență, alternativ
– Pentru a sincroniza cele doua procese s-ar putea utiliza activarea/
dezactivarea întreruperilor pentru cele două surse asociate celor
doua procese.
55
Activarea si dezactivarea întreruperilor(2)

• Activarea/dezactivarea întreruperilor poate fi realizată prin procedeul


generic numit “mascare” (masking)
• Un indicator (un bit) de “mascare” este asociat fiecărei surse de
întrerupere.
• Indicatorii respectivi sunt grupați in cadrul unor registre “de control” al
întreruperilor
– Similar pot fi controlate si prioritățile
• O cerere de întrerupere va ajunge la CPU doar dacă nu este mascată,
adică doar dacă are bitul mască asociat =1.
– In acest exemplu generic “mascarea” înseamnă bit=0, “demascarea” bit=1
(valorile măștii sunt convenționale)
• Dacă o întrerupere poate fi astfel dezactivată prin “mascare” ea este
denumită întrerupere mascabilă: ea poate fi dezactivată/activată
individual de programator
• Exista însă si întreruperi pe care proiectantul arhitecturii de calcul le-a
socotit drept critice, care nu pot fi dezactivate de programator, ele fiind
tot timpul active: ele sunt întreruperi nemascabile
– De exemplu reset-ul (inițializarea hardware) poate fi considerat si o întrerupere
nemascabila, de prioritate maxima! 56
“Comutarea” contextului
• O rutină de tratare a întreruperilor utilizează resurse ale CPU
(registre de uz general, registrul de stare, etc.) si, mai mult,
poate modifica starea acestor resurse
• Este iarăși esențial să se cunoască adresa la care se va
face întoarcerea din RTI (este de fapt o valoare a
registrului numărător program)
• Starea acestor resurse in momentul inițierii procesării
întreruperii alcătuiește cea ce se numește contextul in care
programul a fost întrerupt
• Acest context trebuie salvat înainte de execuția rutinei de
tratare a întreruperii si trebuie restaurat după
întoarcerea din rutina de tratare a întreruperii, astfel încât
după întoarcere contextul original să fie disponibil si intact
• Salvarea si restaurarea contextului este descrisă si ca o
comutare (înainte/înapoi) a contextului (context switching)
• Salvarea/restaurarea contextului este realizată tipic de
compilatoare cu ajutorul uneia sau mai multor structuri
de date de tip stiva, in memorie: se scrie si se citește in/din
aceste structuri de date din memorie
– Aceste scrieri / citiri multiple pot reprezenta eventual penalități din
punct de vedere al timpului de execuție si al efortului
computațional

57
Care ar fi dezavantajele utilizării
întreruperilor?
• Întreruperile sunt asincrone si “eliberează” CPU de alte sarcini, dar
numai dacă este realizată comutarea corectă si eficientă a contextului
• Comutarea contextului este prețul plătit (ca timp de calcul si resurse
de memorie) la fiecare procesare a unei întreruperi: trebuie sa se
scrie si sa se citească informație in/din memorie
• Dacă întreruperile sunt foarte “dese” aceasta comutare a
contextului s-ar putea să consume mai mult timp decât
activitățile utile!
• Ce alternative avem:
– De ce nu am putea elibera (aproape) total CPU de activitatea de tratare a
intrărilor/ieșirilor efectuată de rutinele de tratare a întreruperilor?
– In practică aceasta se poate realiza cu ajutorul unui mecanism
(hardware) de acces direct la memorie (DMA- Direct Memory Acces)
– DMA este utilizat tipic când se dorește un transfer masiv de date de
intrare/ieșire
– Un subsistem DMA este prezent la majoritatea microcontrolerelor de 32 de
biti
– In cadrul familiilor AVR de 8 biți un astfel de mecanism este disponibil la
familia AVR XMEGA si la noile variante AVR Microchip (seriile 0,1,2)
– Daca va interesează subiectul DMA:
https://en.wikipedia.org/wiki/Direct_memory_access
58
Exemplu de interogare cu bucla de așteptare.. In
limbaj C
Cum s-ar realiza interogarea: Dacă programul mai are si alte sarcini de
realizat:
main () main ()
{ {
while(1){/*bucla fara sarcina1();
sfarsit*/ Interogheaza_Tast
Interogheaza_Tast(); sarcina2();
Interogheaza_Tast ();
} …
}
Cum s-ar realiza interogarea tastaturii: Efortul de calcul suplimentar:
• Citim registrul de stare ca să vedem • Efort = “cat de des trebuie să
dacă o tastă e apăsată, dacă este o interogăm” × “ce presupune
citim din registrul de date interogarea ca prelucrări”
• Trebuie să o facem la fiecare N Cat este de uşor de programat? :
msec, intervalul minim de timp in • Este dificil de “combinat” codul pentru
care o tastă poate fi apăsată, interogare/bucla de aşteptare cu
altcumva apăsarea de tastă de către sarcinile normale de prelucrare:
utilizator poate fi pierdută! depinde de cate bucle avem, de
natura sarcinilor de prelucrare normale

59
Întreruperi…. in C
char input_buffer[1024]; void
rutina_tratare_intrerupere_tas
main() tatura(void)
{ {
initializeaza_intreruperi (); Interogheaza_Tast ();
/* scrie in input_buffer*/
while (1){ …….
sarcina1(); }
sarcina2();
Detaliile depind si de natura sistemului de
calcul:
/* prelucreaza ce gasesc in • PC: Tipic sistemul de operare gestionează
input_buffer */ întreruperile
………. • Sisteme incorporate, controlere: daca nu
/* multe alte sarcini..*/ există un sistem de operare, aplicaţia
…….. trebuie să trateze întreruperile
}
}

60
Un model generic de programare utilizând
întreruperile

start Întrerupere Întrerupere Întrerupere

RTI pentru RTI pentru RTI pentru


Iniţializare
sarcina 1 sarcina 2 sarcina 3

Aşteaptă
Întoarcere -I Întoarcere -I Întoarcere -I
evenimente

Procesare
Memorie

61
Sistemul de întreruperi AVR 8 biți
• Arhitectura AVR 8 biți permite tratarea cererilor de întrerupere
provenind de la mai multe surse diferite, acestea fiind tipic
asociate unor periferice, cu ajutorul unor vectori de
întrerupere care aici sunt adrese fixe de tratare.
– De exemplu, pentru ATMega64 există 34 de surse potențiale de
întrerupere, ATTiny2313 are “doar” 19.
• Există şi posibilitatea ca un eveniment extern să declanșeze
o cerere de întrerupere: exista posibilitatea tratării unor
întreruperi externe.
• În mod convențional si reset-ul (iniţializarea) hardware pentru
un AVR 8 biti poate fi descris ca fiind o întrerupere specială,
cea mai prioritară şi, datorită faptului că ea nu poate fi
dezactivată, numită şi nemascabilă.
– Toate celelalte întreruperi sunt descrise ca mascabile putând fi
dezactivate/activate individual si global

62
Sistemul de întreruperi AVR 8 biți: Întreruperi
externe si Reset pentru ATTiny2313

Întreruperile externe INT0, INT1


pot fi programate ca active pe nivel (L sau H) sau front (L->H sau H->L)

63
Sistemul de întreruperi AVR 8 biți :
vectorii de întrerupere
• ATENŢIE:
• Funcție de varianta de AVR, același tip periferic poate avea
vectori (adrese) diferite de tratare
• Mai mult, pentru variantele MEGA si XMEGA care au si o
zona de Bootloader in memoria program, tabela de vectori
poate fi relocata corespunzător prin programarea unui fuzibil
sau a unui bit dintr-un registru (de exemplu IVSEL din
MCUCR) astfel încât Bootloaderul să poată si el utiliza
întreruperile
• Trebuie consultată neapărat tabela de vectori si eventual
facilitățile de relocare a lor din foaia de catalog a variantei
respective!
– De exemplu pentru ATTiny2313 comparatorul analogic are
vectorul 11 (la adresa 0x000A), iar pentru un anumit ATMega
același periferic are vectorul 19 (0x0024), s.a.m.d

64
Cea mai prioritară

Prioritate
descrescătoare

Cea mai puţin prioritară 65


Iniţializarea vectorilor de întrerupere pentru un ATTiny2313
(exemplu in limbaj de asamblare)
Adresa Eticheta/Cod Comentarii
0x0000 rjmp RESET ; Tratare Reset
0x0001 rjmp INT0 ; Tratare intrerupere externa 0 Prima instrucţiune se execută
0x0002 rjmp INT1 ; Tratare intrerupere externa 1
0x0003 rjmp TIM1_CAPT ; Tratare Timer1 Capture
de aici, de la adresa 0x0000
0x0004 rjmp TIM1_COMPA ; Tratare Timer1 CompareA De fapt este un salt aici..
0x0005 rjmp TIM1_OVF ; Tratare depasire Timer1
0x0006 rjmp TIM0_OVF ; Tratare depasire Timer0
Vectorul este un cuvânt (2 octeti)
0x0007 rjmp USART0_RXC ; Tratare USART0 RX Complete
0x0008 rjmp USART0_DRE ; Tratare USART0,UDR Empty care aici conţine opcodul instrucţiunii
0x0009 rjmp USART0_TXC ; Tratare USART0 TX Complete rjmp INT0 (salt la subrutina de tratare
0x000A rjmp ANA_COMP ; Tratare Comparator Analogic a întreruperii “numita” INT0)
0x000B rjmp PCINT ; Tratare modificare stare Pin
0x000C rjmp TIMER1_COMPB ; Tratare Timer1 Compare B
0x000D rjmp TIMER0_COMPA ; Tratare Timer0 Compare A
0x000E rjmp TIMER0_COMPB ; Tratare Timer0 Compare B
0x000F rjmp USI_START ; Tratare start USI rjmp este o instrucţiune de salt
0x0010 rjmp USI_OVERFLOW ; Tratare depasire USI la adresa de început a subrutinei
0x0011 rjmp EE_READY ; Tratare EEPROM gata (in acest caz, una de tratare a
0x0012 rjmp WDT_OVERFLOW ; Tratare depasire Watchdog
; unei întreruperii)
0x0013 RESET: ……………. ; Inceput program principal
Pentru o aplicaţie in limbaj C, compilatorul va realiza completarea
tabelei de vectori, prin intermediul unor funcţii si directive specifice 66
Se va reveni cu un exemplu complet de utilizare întreruperi (in C)..
Întreruperi externe si Reset la ATMega16

Întreruperea externă INT2


poate fi programată ca activă
doar pe front (L->H sau H->L)

Reset

Întreruperile externe INT0, INT1


pot fi programate ca active pe nivel (L sau H) sau front (L->H sau H->L)
67
Cea mai prioritară

Prioritate
descrescătoare

68
Cea mai puţin prioritară
Tabela de vectori pentru ATMega32

69
Întreruperi externe si Reset la ATMega 328
(capsula PDIP28)

Pe langa INT0 si INT1 mai exista (tot ca functii alternative ale pinilor) PCINT0
la PCINT23: aproape toti pinii pot fi utilizati pentru intreruperi externe!

70
Tabela de vectori pentru ATMega 328

71
Sistemul de întreruperi AVR 8 biți
• Schema utilizată este una vectorială, cu adrese (vectori) de tratare fixe, la fel
ca la multe alte familii de microcontrolere.
• Pentru fiecare întrerupere există rezervat un vector separat, având
dimensiunea fixă de 2 octeți (1 cuvânt), la fel ca și pentru reset, în zona
de început a memoriei de program.
• Toate întreruperile (mai puțin reset-ul) au asignat un bit de activare
individuală care trebuie să fie “1” logic, împreună cu bitul I de activare
globală al întreruperilor în registrul de stare, pentru a se putea utiliza/trata
întreruperea respectivă.
– Prin intermediul acestui bit se spune ca întreruperile pot fi mascate (bit in “0”) sau nu (bit in “1”)
• Bitul I din registrul de stare SREG acționează ca o mască globală (pentru
toate întreruperile) si este controlat de instrucțiunile (limbaj de asamblare)
dedicate SEI (I=“1”) si CLI (I=“0”)
• Întoarcerea dintr-o subrutina de tratare a întreruperii se face cu
instrucțiunea dedicata RETI
– Funcție de valoarea curentă a numărătorului program PC, întreruperile mai pot fi în mod
automat dezactivate atunci când biții (fuzibilele) “Boot Lock” BLB02 sau BLB12 sunt programați
(la un ATMEGA).
• Aceasta caracteristică poate eventual îmbunătăți “protecția” software-ului la copieri neautorizate.

72
Sistemul de întreruperi AVR 8 biți
• Cele mai joase adrese în spațiul de memorie de program, în zona de aplicaţie, sunt
implicit definite ca vectorii de reset şi întrerupere.
• Această listă definește şi nivelele de prioritate ale diferitelor întreruperi.
• Adresa cea mai de jos are nivelul de prioritate cel mai înalt.
– Astfel reset-ul are cea mai mare prioritate, urmat de INT0 – cererea de întrerupere externă 0,
ş.a.m.d.
• Deși vectorii de întrerupere sunt la adrese fixe, ei pot să fie “mutaţi” de la începutul
zonei de aplicație la începutul zonei de Bootloader setând bitul IVSEL în registrul de
control general al întreruperilor GICR (General Interrupt Control Register) – doar la
variantele cu Zona Boot (ATmega).
– Vectorul de reset poate fi, de asemenea, mutat la începutul zonei de Bootloader programând fuzibilul BOOTRST
– doar la ATMega sau Xmega.
• Când o întrerupere este recunoscută şi tratată, bitul I din SREG este
șters şi toate întreruperile sunt dezactivate.
• Utilizatorul poate eventual, in rutina de tratare a întreruperii, să scrie bitul I în “1” logic
pentru a (re)activa întreruperile.
– Toate întreruperile active pot atunci să întrerupă rutina de tratare a întreruperii curente: aşa se
pot imbrica întreruperile (întreruperea întreruperii..)
– Bitul I este în mod automat setat când are loc execuția unei instrucțiuni de revenire
(întoarcere) din rutina de tratare a întreruperii (RETI), făcând posibilă tratarea unei
noi întreruperi: aceasta este diferența esențială intre instrucțiunile RETI si RET
(întoarcerea dintr-o subrutină obișnuită)

73
Exemple: bitul I, biţi de activare întrerupere
- Interrupt enable

74
Tipuri de întreruperi AVR 8 biți: întreruperi
bazate pe un eveniment memorat
• Există în două tipuri de întreruperi din punct de vedere al
comportării/utilizării cererii de întrerupere.
• Acest prim tip de întrerupere este declanșat de un eveniment care
setează un bit (un flag) asociat unei anume întreruperi: cererea de
întrerupere este deci memorata
• La tratarea întreruperii în numărătorul program PC se aduce automat
vectorul corespunzător pentru a se putea executa rutina de tratare a
întreruperii, iar bitul corespondent întreruperii este setat.
• Acești biți asociați întreruperilor pot să fie însă șterși de utilizator
scriind un “1” logic în poziția bitului respectiv.
• Dacă apare o cerere de întrerupere în timp ce bitul corespondent
activării întreruperii este șters, bitul va fi setat şi memorat până când
întreruperea este activată sau bitul este şters prin soft.
• Similar, dacă una sau mai multe cereri de întrerupere apar în timp ce
bitul I este șters, bitul corespondent întreruperii va fi setat şi memorat
până când bitul I este setat din nou, şi atunci cererile vor fi executate în
ordinea priorității.
• Exemple (AVR 8 biti): depășirile in cazul sistemului de temporizare
/numărare

75
Tipuri de întreruperi AVR 8 biți: întreruperi bazate
pe o condiție (nememorată)
• Acest al doilea tip de întrerupere va declanșa o întrerupere doar
atât timp cât condiția de întrerupere este activă (adevărată) si
întreruperea poate fi tratată.
– Aceste întreruperi nu au biți asociați cererii de întrerupere (nu există
fizic o memorare a ei) dar tratarea ei (dacă are loc) este similară
primului tip
– Dacă este posibilă tratarea întreruperii, atunci în numărătorul
program PC se aduce automat vectorul corespunzător pentru a se
putea executa rutina de tratare a întreruperii
– Dacă însă condiția de întrerupere dispare înainte ca
întreruperea (cererea) să fie recunoscută de unitatea centrala,
întreruperea nu va fi luata in considerare şi nu va fi tratată
(informația asociată ei va fi pierdută!).
• La întoarcerea (cu instrucțiunea RETI) dintr-o rutină de tratare a unei
întreruperi în programul principal se vor executa una sau mai multe
instrucțiuni înainte ca orice nouă cerere de întrerupere să poată fi
recunoscută şi tratată.
• Exemple (AVR 8 biți): recepția unui caracter pe portul serial (USART)

76
Întreruperi AVR 8 biți: bitul I din SREG
• Registrul de stare SREG NU este în mod automat
memorat (salvat) când se intră în rutina de tratare a
unei întreruperi şi nici nu este restaurat când se
revine din rutină.
– Această operație trebuie să fie realizată de utilizator
(aplicație), dacă este vorba de limbaj de asamblare
– Pentru limbajul C ea este realizată de compilator
• Când se folosește instrucțiunea CLI pentru a dezactiva
global întreruperile (ștergerea bitului I), ele vor fi imediat
dezactivate.
– Nici o întrerupere nu va fi executată după execuția instrucțiunii
CLI, chiar dacă se ea apare simultan cu instrucțiunea CLI.
• Când se folosește instrucțiunea SEI(setarea bitului I)
pentru a activa global întreruperile, instrucțiunea ce
urmează instrucțiunii SEI va fi executată înaintea de
tratarea oricărei cereri de întrerupere

77
Sistemul de întreruperi AVR 8 biți: timpul de răspuns
al unității centrale la o cerere de întrerupere
Timpul de răspuns la o cerere de întrerupere (numit si
latența întreruperii - interrupt latency ) pentru toate
întreruperile active este de minim patru cicluri (perioade)
de ceas sistem.
• După patru cicluri de ceas rutina de tratare a întreruperii
curente va începe să fie executată.
– În timpul celor patru cicluri de ceas, valoarea PC-ului
corespunzătoare instrucțiunii următoare (doi octeți) este
memorată în stivă, indicatorul de stivă SP este decrementat cu
două unități, şi bitul I din SREG este șters (dezactivare globală a
întreruperilor).
• Tratarea întreruperii presupune un salt la rutina de
tratare a întreruperii şi efectuarea acestui salt durează
încă trei cicluri de ceas.
• Dacă mai apare o cerere de întrerupere în timpul execuției
unor instrucțiuni care durează mai mult de un ciclu (de
exemplu 2 sau 4 cicluri), această instrucțiune multi-ciclu va
fi finalizată înainte ca întreruperea să poată fi tratată.
78
Sistemul de întreruperi AVR 8 biți: timpul de
răspuns in modurile cu putere redusă
• Dacă apare o cerere de întrerupere în timp ce unitatea
centrală este în modul de putere redusa “Sleep”, timpul
de răspuns la cererea de întrerupere este mărit cu încă
patru cicluri de ceas.
– La aceasta se va adăuga și timpul de repornire (de trezire) dintr-
un mod de putere redusa „sleep”.
• Timpul de revenire (întoarcere) din rutina de tratare a
unei întreruperi este de patru cicluri de ceas.
– În timpul acestor patru cicluri ceas, PC-ul (cei doi octeţi) este
extras din stivă, indicatorul de stivă SP este incrementat cu două
unități şi bitul I din SREG este setat (reactivare globală a
întreruperilor)..
• Vom mai reveni asupra descrierii si utilizării
sistemului de întreruperi pentru AVR 8 biți

79
Microcontrolere (si
microprocesoare)
Controlul dimensiunii timp in aplicațiile de tip
incorporat: temporizatoare si numărătoare
Microchip AVR 8 biți:
Sistemul de temporizare/numărare
Întreruperi (partea 2):
Întreruperile externe
Utilizarea întreruperilor cu compilatorul WinAVR

1
Temporizatoare si numărătoare -1

• Un temporizator/numărător (timer/counter), de fapt un sistem de


temporizare/numărare, reprezintă una din resursele esențiale ale
oricărui microcontroler sau mai degrabă ale oricărui sistem incorporat
– Funcționalitatea lui este asemănătoare cu a unui astfel de sistem (temporizator/
numărător) de sine stătător, cum exista multe utilizate in industrie si nu numai
– Cele două denumiri pot fi si sunt folosite interșanjabil in cele ce urmeaza
• Referința de timp este data de un semnal de ceas/ de tact (clock)
• Diferența intre cele două denumiri este data de sursa semnalului de
ceas
• Ele reprezintă o resursă hardware care permite fie “măsurarea” unui
interval de timp pe baza numărării perioadelor ceasului sistem (sau a
unuia derivat din acesta), fie numărarea de evenimente (contorizarea
lor), evenimente in mod tipic externe sistemului
– Hardware un temporizator/numărător este un numărător (o mașină secvențială
sincrona formata dintr-un set de circuite bistabile) de cele mai multe fiind utilizat ca un
numărător binar
– In continuare vom folosi de multe ori termenul generic de timer
– Vom mai presupune, cum ar fi normal după atâta școală, că știți ce este
acela un numărător, dacă nu, vezi Wikipedia,
http://en.wikipedia.org/wiki/Counter
2
Temporizatoare si numărătoare -2
• In figură este prezentat un timer simplu care constă dintr-un numărător (registru de
numărare) de 8 biţi pre-încărcabil, cu un semnal de ceas si un semnal de ieșire
• Programul (aplicația software) poate încărca (load) registrul de numărare cu o valoare
inițială, intre 0x00 si 0xFF; cu alte cuvinte se poate si scrie in registrul de numărare
• Fiecare tranziție a semnalului de ceas va incrementa (de exemplu) această valoare
• Când valoarea numărătorului de 8 biți ajunge la maximum, la următoarea tranziție de ceas
semnalul de ieșire își modifică starea, indicând o depășire superioară (overflow), in acest
caz
• Semnalul de ieșire poate fi utilizat pentru a genera o întrerupere sau a seta un bit, pe care
unitatea centrala îl poate citi
• Pentru a reporni un ciclu de numărare cu aceiași lungime, programul re-încărcă (re-load)
registrul de numărare cu aceiași valoare sau cu o valoare diferită
• Dacă numărătorul este unul care numără in sens crescător (up counter) el numără de la
aceasta valoare către valoarea maximă, 0xFF in acest exemplu.
• Dacă numărătorul este unul care numără in sens descrescător (down counter) el va
număra către valoarea minimă, 0x00, indicând, la depășirea inferioară (underflow) a acestei
valori de fapt o cerere de împrumut (borrow)

Registru de numărare
Magistrală de date
Ieşire depăşire/
(internă)
împrumut
Semnal intern scriere-
(re)încărcare 3
Ceas numărare
Temporizatoare si numărătoare - 3
• Însă un registru de numărare poate fi si citit (tipic prin intermediul unui alt registru
intermediar)
• O facilitate des întâlnită la un sistem de temporizare/numărare este aşa zisa funcție de
captură/captare/memorare a intrării la un moment definit de timp(input capture)
– Un astfel de timer similar celui prezentat in figură, are un registru de tip D Latch (transparent) conectat la
ieșirea registrului de numărare
• Timer-ul are un semnal de ceas stabil, cu frecventa constantă (tipic provenind din ceasul
sistem) astfel că el incrementează sau decrementează in mod constant, liber (free
running timer)
• Un semnal extern poate înscrie si memora valoarea curentă a registrului de numărare in
registrul latch, de unde aceasta, garantat stabilă, poate fi citită de unitatea centrală
– Acest semnal de ceas definește si momentul din care conținutul registrului poate fi citit
• Tipic acest eveniment generează si el un semnal de ieșire – un eveniment (care nu a
mai fost ilustrat in figură), putând genera de exemplu o întrerupere
• O funcție ceva mai complicată (neilustrată aici), este cea de comparare a ieșirii (output
compare); ieșirea numărătorului este comparată cu ieșirea unui registru (cu aceiași
dimensiune, programabil de utilizator) cu ajutorul unui comparator numeric; la egalitate se
generează un eveniment (schimbare stare pin sau întrerupere)
Registru de numărare Registru latch (memorare iesiri)

Magistrală de date
(internă)
Ceas
numărare
Semnal extern de scriere, 4
captura intrare
Temporizatoare si numărătoare - 4

• Depășirile superioare sau inferioare in cazul unui


temporizator/ numărător (si nu numai ele) sunt asociate
unor evenimente
• Aceste eveniment pot fi memorate cu ajutorul unor circuite
bistabile suplimentare (unor biți suplimentari)
• Prin raportare la evoluția programului (a unității centrale)
aceste eveniment sunt asincrone in cazul utilizării ca
numărător (ceas extern) si sincrone in cazul utilizării ca
temporizator (ceas intern)
• Unitatea centrală poate “afla” despre aceste evenimente
prin două modalități:
– Una neeficientă, prin interogarea bitului asociat
evenimentului într-o buclă de așteptare (polling)
– Una eficientă, cu utilizarea sistemului de întreruperi, in
care situație, evenimentul declanșează o cerere de
întrerupere (interrupt request)

5
AVR 8 biți: temporizatoare si numărătoare
(Timer / Counters)
• Microcontrolerele din familia AVR 8 biti au un sistem de
temporizare/numărare care cuprinde un anumit număr de
temporizatoare/ numărătoare, funcție de variantă, numerotate cu 0, 1,
2, etc., având registre de numărare de 8 sau 16 biți
• Trebuie consultată foaia de catalog a variantei respective de AVR,
pentru a vedea cate temporizatoare sunt disponibile pentru o anumita
variantă si ce caracteristici au ele; de exemplu:
– ATTiny 2313 are 2 temporizatoare/numărătoare: Timer 0 de 8 biți, Timer 1
de 16 biți
– ATMega16 are 3 temporizatoare numărătoare: Timer 0 de 8 biți, Timer 1
de 16 biti si Timer 2 de 8 biți
– ATMega64 are 4 temporizatoare/numărătoare: Timer 0 de 8 biți, Timer 1
de 16 biti si Timer 2 de 8 biți si Timer 3 de 16 biti
– ATMega 1280 sau 2560 au 6 temporizatoare/numărătoare: Timer 0 de 8
biti, Timer 1 de 16 biți si Timer 2 de 8 biți, Timer 3 de 16 biți, Timer 4 de 16
biti, Timer 5 de 16 biți
• Timerele 3, 4, 5 sunt similare Timer-ului 1
– ATTiny 13 are doar un singur temporizator/ numărător Timer 0 de 8 biți
• Prezentarea care urmează este una introductivă, fără pretenții de
exhaustivitate 6
AVR 8 biți, sistemul de temporizare
numărare la variantele modernizate
(Microchip)
• Variantele modernizate de Tiny si MEGA (seriile 0
si 1) au un sistem de temporizare / numărare
reorganizat, cu denumiri actualizate si oarecum
diferite pentru registrele si câmpurile de biți
aferente
• Exista acum:
– un Timer A (TCA) de 16 biți
– de la unul la patru Timere B (TCB), de 16 biți, cu intrări
de captare
• Există in continuare toate facilitățile existente la
vechile Timer 0 si Timer 1
• Pe lângă unele modificări de funcționalitate
trebuie ținut cont ca schimbarea numelor
afectează si mnemonicile utilizate de compilator
așa ca obligatoriu trebuie consultate foile de
catalog
7
AVR 8 biti: temporizatoare (Timers)
• Fiecare temporizator/numărător este compus dintr-un
registru de numărare (numărătorul propriu-zis), care este
de fapt si un registru de date (el poate fi citit si/sau scris)
• Semnalul de ceas poate incrementa acest registru:
numărătoarele AVR 8 biti numără tipic in sus (sunt up
counters)
– Exista si situații speciale când pot număra in jos
• Numărătoarele AVR sunt numărătoare binare
• Numărătoarele AVR sunt numărătoare programabile,
adică in ele se poate (pre) înscrie o valoare de la care să
înceapă să numere- astfel lungimea ciclului de numărare
este programabila
• Dacă semnalul de ceas pentru acest numărător provine,
eventual printr-o divizare suplimentară (realizată cu un mic
numărător, programabil, numit prescaler), din ceasul
sistem, avem o funcționare ca temporizator (timer)
– In modul Timer evoluția lui este una sincronă cu cea a unității
centrale si a perifericelor AVR, având același semnal de ceas intern

8
Rezoluția si durata maximă de numărare /
temporizare
• Rezoluția (resolution) unui numărător poate fi exprimată absolut
prin numărul de biți N utilizați efectiv de registrul de numărare
binar: putem o avea o rezoluție de 8, 10, 12, 16 biţi sau exprimată
ca valoare relativă de 1/28, 1/210, 1/212, 1/216, etc.
• In aplicații interesează însă ca rezoluția (in modul temporizator) sa
fie exprimata absolut ca valoare de timp.
• Rezoluția va fi dată de perioada TClock a semnalului de ceas sau
frecvența FClock a acestuia: TClock = 1/ FClock , ea fiind si
ponderea celui mai puțin semnificativ bit (a unui increment) a
numărătorului exprimata in unități de timp;
• Funcţie de perioada semnalului de ceas TClock = 1/ FClock si
dimensiunea registrului ca număr de biţi N, rezultă o
durată/lungime maximă (a unui ciclu complet) de
numărare/temporizare de la 0 la o valoare maximă: 2N * TClock
• Dacă dorim să obținem o durată mai mică, in registrul respectiv de
numărare(care este un registru in care se poate si scrie) se poate
scrie o valoare mai mică decât valoarea maximă, scurtând
corespunzător durata ciclului de numărare (el va număra de acea
valoare la valoarea maximă)
9
AVR 8biti - numărătoare (Counters)
• Dacă semnalul de ceas provine din exteriorul
microcontrolerului, prin intermediul unor pini dedicați,
avem o funcționare in modul numărător (counter),
deoarece el practic numără evenimentele externe
– In acest mod evoluția lui este, tipic, asincronă cu cea a
unității centrale si a perifericelor AVR, cele care folosesc
ceasul sistem
• Din punct de vedere funcțional nu sunt diferențe intre
modul temporizator si cel numărător, utilizându-se
practic si același hardware (cu excepția circuitului
care furnizează semnalul de ceas)
– Din acest motiv, in continuare, pentru a fi si mai conciși
(limba română nu excelează prin aşa ceva) de multe ori le
vom numi pe scurt si Timer sau Timere înțelegând că este
vorba de fapt, din punct de vedere funcțional, de un
numărător (ca mașină secvențială) cu anumite caracteristici
specifice
• Evenimentele asociate acestor temporizatoare /
numărătoare pot declanșa întreruperi care sunt
integrate in sistemul de întreruperi AVR 8 biți 10
Evenimentele asociate sistemului de
temporizare/numărare
• Principalele eveniment sunt descrise mai jos.
• Depășirea (Timer OVerflow)
– In funcționarea normală (când se numără in sus) depășirea apare atunci când
valoarea registrului de numărare TCNT (Timer CouNTer) trece de la 0xFF la
0x00 (pe 8 biti) sau de la 0xFFFF la 0x0000 (pe 16 biți): adică la 0xFF+1 sau
0xFFFF +1
– Ca efect al depasirii este setat (=‘1’) indicatorul/bitul TOVi din registrul TIFR;
unde i =0, 1, 2… identifică numărătorul in cauză
• Egalitatea la (egalitate) comparare (Output Compare match)
– Utilizează ca hardware suplimentar un registru cu un număr de biți egal cu al
numărătorului- registru de comparare- in care utilizatorul poate scrie o valoare
– Si un comparator numeric pe mai mulți biți care compara ieșirea registrului cu
cea a numărătorului
– Utilizatorul este informat despre egalitatea atunci când valoarea registrului de
numărare TCNT devine egală cu cea a registrului de comparare pentru ieșire -
registrul OCR (Output Compare Register)
– Ca efect, este setat (=‘1’) indicatorul/bitul OCFi din registrul TIFR; unde i =0, 1,
2… identifică numărătorul in cauză
• Captare/memorare conținut (Input Capture)
– Timerul 1 mai are si un eveniment care înseamnă, “capturarea” / memorarea
(capture) valorii curente a numărătorului, la un moment de timp dat de un semnal
extern (aplicat pe pinul ICP - Input CaPture)
– Ca efect, pe lângă memorarea valorii numărătorului in acel moment, mai este
setat (=‘1’) indicatorul/bitul ICF1 din registrul TIFR, astfel încât utilizatorul sa știe
ca avut loc un astfel de eveniment ;
11
Modurile de operare / funcționare pentru
sistemul de temporizare/numărare
• Descrierea care urmează este una sumară si orientată pe familia
ATMega (exemplu ATMega 32)
• Modurile de operare sunt stabilite/configurate, in principal, prin
intermediul câmpurilor de biţi de control WGM si COM, aflate in
registrele TCCR0, TCCR1A, TCCR1B (si TCCR2 dacă Timer 2 există)
– Funcție de varianta de AVR, numele registrelor pot fi puțin diferite, așa ca este
esențial sa fie consultata foaia de catalog
• Modul Normal
– Numărătorul numără in sus, TOV este setat atunci când atinge valoarea 0
(valoarea maximă +1)
• Modul ștergere numărător la (egalitate) comparare: CTC - Clear
Timer on Compare Mode
– Numărătorul numără in sus până când ajunge la o valoare egală cu cea
aflată in registrul de comparare ieșire OCR (Output Compare Register): la
următorul ceas de numărare el va fi resetat la 0 si bitul OCFx (Output
Compare Flag) va fi setat
• Modurile PWM (Pulse Width Modulation), permit generarea, pe
anumiți pini de ieșire, a unor trenuri de impulsuri modulate in durată
(in factor de umplere), sunt mai multe, vom reveni asupra
subiectului …

12
Valorile BOTTOM, MAX, TOP: cazul lui
Timer 0
• In diagramele din foile de catalog AVR, care descriu
funcționarea sistemului de temporizare/numărare se face
mereu referință la un set de 3 valori, numite generic:
BOTTOM, MAX si TOP; ele sunt explicate in continuare
pentru Timer 0 si respectiv Timer 1
• De subliniat ca Timer 0 este unul de 8 biți, așa ca valorile
respective sunt pentru acesta valori exprimate pe 8 biți
– BOTTOM: Numărătorul ajunge la valoarea BOTTOM atunci când
devine 0x00.
– MAX: Numărătorul ajunge la valoarea lui MAX-imă atunci când
devine 0xFF ( 255 in zecimal).
– TOP: Numărătorul ajunge la valoarea TOP atunci când devine
egal cu cea mai mare valoare din secvenţa de numărare.
• Valoarea TOP poate fi asignată valorii fixate 0xFF (MAX) sau este valoarea
memorată in registrul OCR0
• Aceasta asignare depinde de modul de operare ales.

13
Valorile BOTTOM, MAX, TOP: cazul lui
Timer 1
• Timer 1 este unul de 16 biți, așa ca valorile respective sunt
pentru acesta valori exprimate maxim pe 16 biți
– BOTTOM: Numărătorul ajunge la valoarea BOTTOM atunci când
devine 0x0000.
– MAX: Numărătorul ajunge la valoarea lui MAX-imă atunci când
devine 0xFFFF (65535 in zecimal).
– TOP: Numărătorul ajunge la valoarea TOP atunci când devine egal
cu cea mai mare valoare din secvența de numărare:
• Valoarea TOP poate fi asignată uneia din următoarele valori fixate:
– 0x00FF ( valoarea maximă pe 8 biți),
– 0x01FF ( valoarea maximă pe 9 biți),
– 0x03FF ( valoarea maximă pe 10 biti) sau
– o valoare pe 16 biti memorată in registrul OCR1A sau o valoare pe
16 biti memorată in registrul ICR1.
• Aceasta asignare depinde de modul de operare ales.

14
Schema bloc a unui temporizator / numărător:
Timer 0 (8 biţi)

Semnalizare depasire sau cererea


de întrerupere depăşire TOV

Pin Semnal
extern de
Timer 0: registrul de numărare TCNT0 are 8 biţi ceas

Observație
Timer 1, Timer 2: registrele de numărare TCNT1 sau TCNT2 au 16 biţi, respectiv 8 biţi,
15
dar schema principială este practic similară
Unitatea de comparare a ieșirilor (Timer 0):
registrul OCR si comparatorul

Cererea de întrerupere
egalitate comparare

Pin ieşire
externa

Are la bază un comparator numeric (de 8 biţi pentru Timer 0), ale cărui intrări provin de
la ieşirile registrului de comparare OCR si cele ale registrului de numărare TCNT
Pentru Timer 1 unitatea de comparare este similară, dar este una de 16 biţi
(comparator, OCR si TCNT). 16
TCA – seriile Tiny si Mega modernizate

In foile de catalog ale variantelor


modernizate apare o noua schema
bloc care ilustrează si
funcționalitățile disponibile- practic
aceleași ca la variantele clasice:
aici facilitatea de comparare si
generare forme de unda

17
TCB – seriile Tiny si Mega modernizate

In foile de catalog ale variantelor


modernizate apare o noua schema
bloc care ilustrează si
funcționalitățile disponibile- practic
aceleași ca la variantele clasice:
aici facilitatea de captare, de
comparare si generare forme de
unda

18
Acțiuni automate ale sistemului de
temporizare/numărare
• Timerele 1 si 2 (când acestea există) pot fi configurate să
realizeze in mod automat ștergerea (reset), setarea (set) sau
comutarea stării (toggle) unor biţi, având asociați si anumiți pini
de ieșire, atunci când apare o egalitate de comparare
• Este o caracteristică hardware si nu presupune intervenţia
CPU sau a programului utilizator
• Pinii asociați sunt numiți OCnx (Output Comparenx - funcție
alternativă a unor biţi din porturile respective)- si ei trebuie să
fie configurați ca ieșiri (prin intermediul registrului DDR al
portului respectiv)
• Atunci când sunt utilizați in acest mod ei, nu mai pot fi folosiți
ca intrări ieșiri de uz general, ei fiind sub controlul hardware al
sistemului de temporizare numărare, nu sub cel al programului!
• Trebuie consultată foaia de catalog pentru identificarea lor:
– De exemplu la ATtiny 2313 avem (2 timere, 4 canale):
• OC0A PB2; OC0B PD5 ; OC1A PB3 ; OC1B PB4
– la ATMega 16 avem (2 timere, 3 canale):
• OC0 PB3 ; OC1A PD5 ; OC1B PD4
19
Pinii OCnx, ICP, T0 si T1
ATMega 16
T0, T1 – Intrări ceas extern pentru Timer 0 si Timer1

ATtiny 2313

ICP (Input CaPture) - Intrare capturare Timer1


20
Funcția de capturare (captare, memorare)
a intrării (Input Capture Unit)
• Trebuie reamintit că de fapt sub controlul unei intrări se
“capturează”/memorează valoarea numărătorului in momentul
apariției evenimentului si nu a intrării!
• Timer/Counter 1 incorporează un sub-sistem care ii permite să
“captureze” evenimente externe si să le asocieze o “ștampilă de
timp”” (time-stamp) generata de evoluția numărătorului si care să
permită determinarea momentului in care au apărut
• Semnalul extern care indică apariția unui eveniment este aplicat pe
pinul ICP1 (o funcție alternativă a unui pin) sau prin intermediul
comparatorului analogic
• Ștampilele de timp, memorate in registrul de 16 biţi ICR1, pot fi
apoi utilizate pentru a calcula perioada, frecvența, durata unui
impuls, factorul de umplere sau alte caracteristici ale semnalului
aplicat, pe baza cunoașterii perioadei semnalului de ceas
• Aceleași ștampile de timp mai pot fi utilizate, de exemplu, si pentru
a realiza un jurnal (log), in care să fie înregistrate evenimente, in
ordinea apariției lor temporale
• OBSERVATIE Alternativ, registrul ICR1 poate fi utilizat si pentru a
memora/defini valoarea TOP utilizată de numărător

21
ICRn are 16 biti si cele două registre de de
capturare de 8 biţi ICRnH si ICRnL ICR se citesc
la fel ca cele două registre de numărare TCNTnH
si TCNTnL, prin intermediul lui
TEMP un registru buffer (temporar) de 8 biţi

22
Registrul de control pentru Timer0, moduri de
operare
Registrul TCCRO Timer/Counter 0 Control Register
7 6 5 4 3 2 1 0

FOC0 WGMO0 COM01 COM00 WGM01 CS02 CS01 CS00

• WGM0 1:0 Modurile • COM0 1:0 Modul


generare formă de undă egalitate comparare la
– 00 Normal ieșire (mod Normal)
– 01 PWM fază corectă
– 00 Pinul nu face nimic,
– 10 CTC este deconectat
– 11 PWM rapid
– 01 Comută (toggle -
• CS0 2:0 Selecţie ceas schimbă starea)
– Codifică 8 variante de – 10 Şterge (clear)
ceas (vezi slide biţi CS),
inclusiv oprirea lui – 11 Setează (set)
• Comportarea / descrierea
este puţin diferită in fiecare
WGM- Waveform Generation Mode 23
mod WGM
Modul Normal (Timer 0): principiul de funcţionare
• Modul Normal este selectat cu Setare TOV0 -
ajutorul câmpului de biti
WGM0 1:0 = 00 (din registrul Întrerupere
TCCRO) depăşire Timer 0
• Numărătorul poate fi încărcat td
cu o valoare iniţială intre 0x00
si 0xFF (0..255), care va defini
lungimea ciclului de TOP=255
numărare:
– Ca timp td= tOV0 Evoluţie
– Ca număr de valori nd
crescătoare nd
• Când atinge valoarea 0xFFH
are loc depăşirea, la următorul numărător
ceas va trece in 0x00H si reia
ciclul de numărare
• La atingerea valorii 0x00H TOP - nd
este setat si indicatorul TOV0
• Tipic, in rutina de tratare a
întreruperii, este re-încărcat, Încărcare iniţială Re-încărcare
cu aceiaşi valoare iniţială,
pentru a avea aceiaşi lungime (prima iniţializare)
a următorului ciclu de
numărare
BOTTOM=0
tTOV0

24
Trece prin 0x00
La egalitatea TCNT=OCR0:
Modul CTC (Timer 0) - Iniţializare numărător
- Setare OCF0 si cerere
de întrerupere
• Modul CTC este - Eventual schimbare de
selectat cu ajutorul stare pentru pinul OC0
câmpului de biti
WGM0 1:0 = 10 (din MAX=255
registrul TCCRO)
• Valoarea scrisă in Evoluţie numărător
registrul OCR0 este
folosită pentru a td Aici TOP =
“programa” lungimea valoare OCR0
ciclului de numărare (nd,
td, tOC0) Ştergere iniţiala
• Pinul OC0 poate (prima iniţializare)
eventual să-si schimbe nd
starea la egalitate
(comutare, ştergere sau
setare)
BOTTOM=0
tOC0

25
Re-iniţializare
PWM - Pulse Width Modulation (modulația in
durată sau in factor de umplere)
O modulație PWM înseamnă modificarea dinamică, sub controlul
programului in acest caz (cu sau fără contribuția unui hardware dedicat) a
factorului de umplere pentru o formă de undă numerică :
FU% = (TH / T)*100 Perioada T (si deci si
frecvența f) rămâne
T constantă, se modifică
TH doar TH (cat este in “1”)
Având la dispoziție numai o ieșire
numerica se poate implementa un
PWM software

AVR 8 biți are si posibilitatea


realizării unui PWM hardware, cu
ajutorul unor funcționalități ale
sistemului de temporizare
numărare.
26
Modul PWM rapid ( Fast, High-Speed
PWM)
• Este modul care permite obținerea celei mai mari frecvențe de
ieșire, ușurând eventual filtrarea trece – jos a semnalului, dacă
se dorește extragerea componentei de cc (cazul implementării
unei tehnici de conversie numeric-analogica) – frecvența
maximă fiind dublă fata de modul cu fază corectă
– Are dezavantajul unei asimetrii a semnalului datorita evoluției doar
crescătoare a valorii
• Modul PWM rapid este selectat cu ajutorul câmpului de biți
WGM0 1:0 = 11 (din registrul TCCRO) si poate furniza un tren
de impulsuri PWM cu o frecvență relativ ridicată (comparativ
cu celelalte moduri PWM)
• In acest mod numărătorul are o evoluție doar crescătoare
• Numărătorul va număra de la BOTTOM la MAX si apoi
repornește de la BOTTOM
• In modul Comparare ieşire fără inversare ( non-inverting
Compare Output mode), pinul OC0 (Output Compare 0) este
șters la egalitatea dintre TCNT0 si OCR0, si este setat atunci
când numărătorul ajunge la BOTTOM.
• In modul Comparare ieșire cu inversare (inverting Compare
Output mode), pinul OC0 este setat la egalitate si șters la 27
BOTTOM.
Modul PWM rapid
• In acest mod numărătorul va fi incrementat pană se ajunge la
valoarea MAX
• După aceasta numărătorul este șters la următorul ceas de
numărare
• O diagramă temporală (din foia de catalog AVR) este prezentată in
slide-ul următor
• Este reprezentată ca histogramă evoluția crescătoare a valorilor
lui TCNT0
• Ieșirile PWM (OC0) pot fi utilizate in două moduri: cu inversare
(/OC) si fără inversare (OC)
– Valoarea lui OCR0 este actualizată (update) de program, de mai multe
ori, pentru a controla dinamic factorul de umplere
– Liniile scurte orizontale marchează punctul in care apare egalitatea
dintre OCR0 si TCNT0.
• Tipic, modul PWM rapid se utilizează acolo unde se poate valorifica
frecvența potențial mai ridicată a formei de undă,
– De exemplu, la implementarea unei tehnici de conversie numeric-
analogice (cu modulație PWM urmată de o filtrare trece-jos)

28
Dacă fclock este frecvenţa oscilatorului sistem, iar
N = {1, 8, 64, 256, 1024} este factorul de (pre)divizare ales
Atunci frecvenţa de comutare a lui OC0 (TOP=256 ) va fi:
fOCnPWM = fclock / (N*256);
29
Rezoluția in modul PWM rapid (cazul
Timer1)
• Rezoluția (dimensiunea numărătorului) in modul PWM
rapid poate fi fixă, de 8, 9 sau 10 biţi, sau definită de
valorile din ICR1 sau OCR1A.
• Valoarea minimă permisă este de 2 biți (ICR1 sau
OCR1A conțin 0x0003), si rezoluția maximă este de 16
biți (ICR1 sau OCR1A conțin pe MAX).
• Rezoluția, exprimata ca număr de biți, poate fi calculată
cu o relație de forma:

• rFPWM = log (TOP +1) / log (2)

• In acest mod numărătorul va fi incrementat până când


ajunge la:
– una din valorile fixe 0x00FF (8 biti), 0x01FF (9 biti), sau 0x03FF
(10 biti), pentru WGM1 3:0 = 5, 6, sau 7,
– la valoarea din ICR1 (pentru WGM1 3:0 =14), sau
– la valoarea din OCR1A (pentru WGM1 3:0 = 15). 30
Modul PWM cu fază corectă (PWM Phase
Correct Mode)
• Acest mod, selectat prin intermediul câmpului de biti WGM0 1:0 = 01
(din registrul TCCRO), face posibilă generarea unor forme de undă
PWM într-o relație de fază corectă pentru mai mult ieșiri PWM (de
exemplu OC1 ci OC3) datorita simetriei semnalului (valoarea creste si
descreste)
• Rezoluția (dimensiunea numărătorului) in acest mod este fixată la 8
biţi
• OBS. Timerul 1 mai are si un mod PWM cu fază si frecvență corectă
• Acest mod este bazat pe evoluția crescătoare si descrescătoare a
numărătorului (numără in sus si apoi in jos)
• Numărătorul TCNT0 numără, repetat, crescător de la BOTTOM(0x00)
la MAX (0xFF) si apoi descrescător de la MAX (0xFF) la BOTTOM
(0x00)
• In acest mod frecvența maximă a formei de undă va fi la jumătate
față de modul rapid
• In modul Comparare ieșire fără inversare (non-inverting Compare
Output mode), pinul OC0 (Output Compare 0) este şters la egalitatea
dintre TCNT0 si OCR0, si este setat atunci când numărătorul ajunge
la BOTTOM.
• In modul Comparare ieşire cu inversare (inverting Compare Output
mode), pinul OC0 este setat la egalitate si şters la BOTTOM.
31
Modul PWM cu fază corectă
• Valoarea factorului de umplere este fixată/programată prin intermediul lui
OCR0
• Datorită naturii simetrice a acestui mod el este preferat in aplicații de
natura controlului motoarelor electrice (control PWM)
• Numărătorul este incrementat până când ajunge la valoarea MAX (adică
0xFF).
• Când ajunge la valoarea MAX, își va schimba direcția de numărare si va fi
decrementat
• Valoarea lui TCNT0 va rămâne egală cu MAX pentru o perioadă a
semnalului de ceas, începând apoi să scadă pană la BOTTOM (adică la
0x00); apoi procesul este reluat
• O diagramă temporală (din foia de catalog AVR) este prezentată in slide-ul
următor
• Este reprezentată evoluția crescătoare/descrescătoare a lui TCNT0 (ca
histogramă)
• Precum si evoluția ieșirilor PWM (OC0) in cele două moduri: cu inversare
(/OC) si fără inversare (OC)
– In exemplu valoarea lui OCR0 este actualizată (update) de mai multe ori pentru
a controla dinamic factorul de umplere
– Liniile scurte orizontale marchează punctul in care apare egalitatea dintre
OCR0 si TCNT0.

• Datorita simetriei semnalului acest mod este preferat pentru comanda


PWM a (micro)motoarelor de cc
32
Dacă fclock este frecvenţa oscilatorului sistem, iar
N = {1, 8, 64, 256, 1024} este factorul de (pre)divizare ales
Atunci frecvenţa de comutare a lui OCn, in acest mod, va fi:
fOCnPCPWM = fclock / (N*512); 33
Determinarea stării sistemului de
temporizare/numărare prin interogare

• Starea unui temporizator/ numărător (din punct de


vedere al evenimentelor asociate) poate fi
determinată si prin interogarea într-o buclă (“polling”)
a indicatorilor de stare asociați (care sunt aceiași cu
cei utilizați si de sistemul de întreruperi)
– In mod tipic, se citește registrul TIFR - Timer Interrupt Flag
Register si unde se verifică care din biți sunt setați
– Evenimentele de tip depășire, egalitate comparare,
capturare intrare, setează biții corespunzători din TIFR
• TOVn si OCFn (n=0, 1 sau 2)
– Timerul 1 are de fapt două registre de comparare, câte unul
pentru fiecare din cele canale A si B: OCR1A si OCR1B
• ICF1
• Biții pot fi șterși si “manual”, de utilizator/aplicație, scriind
un “1” in poziția corespunzătoare
34
Registrul TIFR: indicatorii de cerere de întrerupere
pentru sistemul de temporizare/numărare

• Registrul TIFR - Timer/counter Interrupt Flags

7 6 5 4 3 2 1 0

OCF2 TOV2 ICF1 OCF1A OCF1B TOV1 OCF0 TOV0

Timer 0
Timer 1
- Indicator (cerere întrerupere) comparare ieşire OCF
- Indicator (cerere întrerupere) depăşire Timer TOV Timer 2
- Indicator (cerere întrerupere) capturare (capture) intrare ICF

ATENTIE: Acești indicatori vor fi șterși in mod automat atunci când se


utilizează sistemul de întreruperi (nu se folosește polling-ul) si se 35
intra in rutina de tratare a întreruperii respective.
Determinarea stării sistemului de
temporizare/numărare utilizând sistemul de
întreruperi
• Este vorba de identificarea evenimentelor asociate stării
unui temporizator/ numărător cu ajutorul sistemului de
întreruperi
• Pentru aceasta in primul rând trebuie activate
întreruperile corespunzătoare in registrul TIMSK-
Timer Interrupt MaSK (presupunând ca întreruperile sunt
activate global)
• Fiecare eveniment legat de sistemul de
temporizare/numărare are un bit de activare pentru
întreruperea corespunzătoare in registrul TIMSK:
– TOIEn si OCIEn (n = 0, 1, 2)
• Timerul 1 are doi biţi de tip OCIE1, OCIE1A si OCIE1B, câte unul pentru
fiecare canal A si B
– TICIE1 (capturare intrare, doar pentru Timerul 1)
– Vectorii de întrerupere din tabela sunt OVFn.., OCn… si IC1
36
Registrul TIMSK de activare/dezactivare a
întreruperilor asociate sistemului de
temporizare/numărare

• TIMSK - Timer/Counter Interrupt Mask

7 6 5 4 3 2 1 0

OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 OCIE0 TOIE0

Timer 0

Timer 1
– Activare întrerupere comparare ieşire OCIEi (2 canale A si B)
– Activare întrerupere depăşire Timer TOIEi Timer 2
– Activare întrerupere capturare (capture) intrare TICIE1

37
Sursele de ceas utilizabile pentru sistemul de
temporizare/numărare
• Sistemul de temporizare/numărare poate folosi drept ceas de numărare:
– Un ceas provenit, eventual prin (pre)divizare (prescaling), din ceasul sistem (intern):
funcționare in mod temporizator sau
– Un semnal extern de ceas: funcționare in mod numărător
• Funcție de dimensiunea numărătorului (de numărul sau de biţi, 8 sau 16) si de
perioada ceasului de numărare vom putea determina:
– Durata maximă a intervalului de temporizare
– Rezoluția cu care putem controla această durată: cât înseamnă ca timp un increment
al numărătorului
• Ceasul sistem poate fi (pre)divizat, înainte de a deveni ceas pentru Timer,
pentru a putea genera intervale de temporizare mai mari:
– Este disponibilă o (pre)divizare cu factorii ficși de: 8, 64, 256 si 1024
– Tot prin intermediul acestui sistem de predivizare ceasul de numărare poate fi
oprit (ceasul oprit este starea implicită după un Reset!)
– Timerul 2 (atunci când el există) are mai multe opțiuni, permițând si (pre)divizarea
semnalului de ceas extern, nu numai a celui intern, mai mulţi factori de divizare, etc.

38
Exemplu de determinare a duratei maxime de
temporizare si a rezoluției de numărare

• Să presupunem că:
– Avem frecvența ceasului sistem este de 8 MHz (cu perioada
de 125nsec sau 0.125usec)
– Utilizăm un timer de 16 biți (valoarea lui maximă va fi 0xFFFF)
– Dorim să obținem cel mai mare interval de temporizare
posibil, si vom folosi cel mai mare factor de divizare, adică
1024
• Avem (0xFFFF + 1) * 1024 * perioada ceasului sistem =
65536*1024*125 nsec = 67 108 864 * 125 nsec = 8.388608
secunde=cca 8.3 sec ca durată maximă a unui ciclu de
numărare.
• Deoarece numărătorul incrementează la fiecare 1024
perioade ale ceasului sistem, vom avea o rezoluție (ca timp)
de: 1024* 125nsec = 0.000128 secunde (cca 0.12msec sau
128usec)
• Fără a folosi nici o (pre)divizare rezoluția ar fi fost de
125nsec (0.125µs), iar valoarea maximă a duratei doar de
0.008192 secunde (cca. 8msec)
39
Unitatea de (pre)divizare (prescaler) a ceasului
pentru ATMega16 ( pentru Timer 0 si Timer 1)

Semnale
externe
de
ceas 40
Selecţia sursei semnalului de ceas
TCCR0 and TCCR1B – Timer/Counter Control TCCR2 – Timer/Counter Control
Register (Timerul 0 si Timerul 1) Register (Timerul 2)
CSn2, CSn1, CSn0 (Biţii 2:0) sunt biţii de CS22, CS21, CS20 (Biti 2:0) sunt biţii
selectare a semnalului de ceas (n = 0 sau de selectare a semnalului de ceas
1) 000 = Ceasul este oprit; timerul nu mai
numără (implicit după reset!)
• 000 = Ceasul este oprit; timerul nu mai 001 = ClkT2S:1
numără (implicit după reset!) 010 = ClkT2S :8
• 001 = fără divizare a lui ceasul Clk I/O :1 011 = ClkT2S :32
• 010 = divizare a lui Clk I/O :8 100 = ClkT2S :64
• 011 = divizare :64 101 = ClkT2S :128
• 100 = divizare :256 110 = ClkT2S :256
• 101 = divizare :1024 111 = ClkT2S :1024
• 110 = Ceas extern, pe pinul Tn, numărare Unde, implicit, după reset:
pe front căzător ClkT2S= Clk I/O
• 111 = Ceas extern, pe pinul Tn, numărare Prin setarea bitului ASR2 din registrul
pe front ridicător ASSR , ClkT2S va proveni de pe pinul
TOSC1 (aplicație de tip ceas de
timp real – RTC , cu o frecventa de
31.768kHz )
ATENTIE: Ceasul sistem este de fapt clk I/O (vezi sistemul de generare al ceasului pentru
AVR) care poate fi oprit si prin intrarea in unele moduri de tip “sleep”
Daca se utilizează oscilatorul intern RC, frecventa oscilatorului fosc = Clk I/O=Clk CPU doar
daca fuzibilul CKDIV8 (daca el exista) este neprogramat 41
Daca fuzibilul CKDIV8 este programat atunci Clk I/O=Clk CPU = fosc :8 !
Registrele de control pentru Timerul 1
•Registrul TCCR1A
TCCR1A Timer/Counter 1 Control Register A
7 6 5 4 3 2 1 0

COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10

Biţii din câmpurile numite WGM1: WGM13, WGM12, WGM11 si WGM10


codifică pentru Timerul 1:
- 1 Normal15 moduri de funcţionare
- 2 de tip CTC
- 12 de tip PWM
Consultați foaia de catalog pentru a afla semnificaţia exactă!
Biţii din câmpurile numite COM1.. codifică cele 4 moduri de control pentru
ieşirile / pinii OC1 ale celor 2 canale A si B ale Timerului 1 (similar Timer 0)
•Registrul TCCR1B
TCCR1B Timer/Counter 1 Control Register B
7 6 5 4 3 2 1 0

ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10 42


Valoarea registrului de numărare TCNT
• Valoarea curentă a registrului de numărare TCNTi; i=0, 1, 2,..
poate fi citită sau scrisă in orice moment
• Un exemplu in C de citire si scriere pentru valoarea respectiva
in cazul Timer0 (TCNT0, 8 biti) este:
unsigned char numarator;
…..
numarator=TCNT0;
…..
TCNT0=0x55;
….
ATENTIE
• Funcția de comparare a ieșirii este dezactivată pentru un ciclu
de numărare după o operație de scriere in numărător
• Modificarea valorii registrului de numărare, atunci când el
numără, poate duce la pierderea unui eveniment de tip
comparare ieșire

De cele mai multe ori procedura corectă de citire sau scriere a


registrului (registrelor) de numărare este:
Se oprește numărătorul
Se citește sau se scrie registrul (registrele)
Se repornește numărătorul 43
Valoarea registrului de numărare pentru
Timer/Counter 1: accesul pe 16 biţi
• Este vorba de un temporizator/numărător de 16 biţi!
– Registrul de numărare are un octet superior TCNTH si unul
inferior TCNTL
– Accesul la acesta pereche de registre (TCNTH:TCNTL) si
construirea unei valori pe 16 biți (într-o variabilă
corespunzătoare) presupune o tehnică specială: contează
ordinea in care se citesc cele doua jumătăți!
• Întotdeauna se citește primul octetul inferior TCNTL
– Aceasta realizează si memorarea internă a octetului superior
ce va fi citit la următoarea citire
• Întotdeauna se scrie primul octetul superior TCNTH
– Scrierea următoare, cea pentru octetul inferior, va duce la
memorarea in registrul intern si a octetului superior

Este o consecință a faptului ca intern există doar un singur buffer (registru


tampon) TEMP de 1 octet care este folosit “in comun” de toate registrele de
16 biţi aferente Timerului 1.

44
Alte registre de date pentru Timer 1
• Pentru Timer 1 in afară de registrele de numărare, la
categoria registre de date mai există si alte registre
de 16 biți, si toate se citesc / scriu la fel ca registrele
de numărare!
• Unele din ele au o utilizare duală, vezi registrul ICR1
• Toate registrele asociate Timer 1 au 16 biţi, având un
octet superior (H) si unul inferior (L)
– TCNT1H:TCNT1L (16 biţi)
• Registrul de numărare pentru Timer 1
– OCR1AH:OCR1AL (16 biţi)
• Valoare comparare ieşire Timer 1– canalul A
– OCR1BH:OCR1BL (16 biţi)
• Valoare comparare ieşire Timer 1– canalul B
– ICR1H:ICR1L (16 biţi)
• Valoare capturare intrare Timer 1 (Input Capture)

45
Configurarea generală a sistemului de
temporizare numărare AVR 8 biți
• Înainte de a fi utilizat, orice numărător – temporizator trebuie
configurat/inițializat corespunzător

• ATENTIE: Denumirile registrelor (si mnemonicile utilizate de compilator)


si gruparea biților pentru același timere (0, 1, ..) pot fi diferite, funcție de
varianta de AVR, consultați foaia de catalog; de exemplu pentru Timer 0 la
ATiny avem 2 registre TCCR0A si TCCR0B, pe când la ATMEGA avem un
singur TCCR0, etc.
• Configurarea se face prin intermediul unor biți dedicați de control in registrele
de control si stare deja menționate, si ea presupune:
– Programarea modului de lucru: normal, CTC, PWM, etc.
– Programarea valorilor inițiale ale registrelor de numărare (dacă este cazul)
– Configurarea întreruperilor aferente lor (dacă este cazul)
– Alegerea/programarea sursei de ceas si eventual a valorii frecventei semnalului
de ceas (a factorului de divizare dorit pentru ceas); odată ce a fost
aleasă/programată sursa de ceas numărătorul începe să funcționeze / să numere
(cu excepția cazului in care aici este selectată combinația “ceas oprit”), poate
genera întreruperi
– Dacă aplicația utilizează întreruperile, atâta timp cât se face aceasta configurare,
este bine ca întreruperile să fie dezactivate global (cu instrucțiunea cli), ele
activându-se (cu instrucțiunea sei) eventual după terminarea acestei configurări
46
Un exemplu de utilizare/configurare Timer 0, modul
normal (ATMega16), pentru generarea unei întârzieri

#include <avr/io.h>

void Timer0_init()
{
/* frecventa oscilatorului fosc= 1MHz (RC intern)
factorul de divizare = 1024
Fclock= 1000 000 /1024 = 975.56Hz
Tclock= 1/ 975.56 = 0.001024 sec
adica CS02= 1, CS01=0, CS00=1 */
TCCR0 |= (1 << CS02)|(1 << CS00);
/*toti ceilalti biti din registrul TCCR0 au valoarea implicita dupa reset,
adica 0:
FOC=0 fara fortare iesire la out. compare
WGM00=WGM01=0, mod normal, Top= 0xFF ATENTIE care va fi valoarea maxima a
intarzierii!!
COM01=COM00=0, mod normal, OC0 deconectat de pin
*/
/* initializam la 0 registrul de numarare timer */
TCNT0 = 0;
} 47
Un exemplu de utilizare/configurare Timer 0
(ATMega16), in modul normal, pentru generarea unei
întârzieri -cont
/*====================================================*/
int main(void)
{
/* sa zicem ca avem un LED conectat pe pinul PC7, deci este iesire */
DDRC |= (1 << PC7);
/* initializam timerul */
Timer0_init();
/* o bucla fara sfarsit */
while(1)
{
/* dorim o intarziere sa-i zicem de 200msec = 0.2 sec
daca timerul pleaca de la 0, vom avea 0.200/0.001024 = 195 (195.31
trunchiat)
de incrementi pt acest interval de timp, deci verificam daca timerul
a ajuns la 195 */
if (TCNT0 >= 195)
{
PORTC ^= (1 << PC7); /* comutam starea pinului/LED-ului, la
fiecare 200msec */
TCNT0 = 0; /* si aducem la 0 registrul de numarare*/
} //end if
} //end while
} 48
Un exemplu de utilizare/configurare Timer 0,
modul PWM rapid (ATTiny 2313)
/* Exemplu PWM hardware folosind Timerul 0 de 8 biti*/
/* Se pot utiliza doar iesirile OC0A = pin PB2 si OC0B = pin
PD5*/
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 4000000UL /*utilizata de biblioteca delay*/

/*O functie de initializare a lui Timer 0 si a canalelor de


iesire OC0A si OC0B in modul dorit*/
void InitPWM()
{
/*Mod PWM rapid, ceas fara divizare (:1), control al lui OC0
pe ambele canale A si B*/
TCCR0A|=(1<<WGM00)|(1<<WGM01)|(1<<COM0A1)|(1<<COM0B1);
TCCR0B |= (1<<CS00);
/* OC0A = pin PB2 configurat ca iesire
OC0B = pin PD5 configurat ca iesire */
DDRB|=(1<<PB2);
DDRD|=(1<<PD5);
}
49
Explicarea programării registrelor de
control din funcţia InitPWM()
TCCR0A - Timer Counter Control Register (TIMER0)
TCCR0B - Timer Counter Control Register (TIMER0)

Mod de lucru
Câmpul WGM0 2:0 = 011 Mod PWM rapid
Modul de control al pinilor OC0
Câmpul COM0A 1:0 = 10 In modul PWM rapid şterge pe OC0 la
egalitate cu OCR0 si-l setează la BOTTOM (mod
fără inversare)
Câmpul COM0B 1:0 = 10 Idem pentru canalul B
Ceasul pentru Timer 0
Câmpul CS0 2:0 = 001 Ceasul sistem, fără divizare (:1)

Determinarea frecventei PWM


Dacă avem un ceas sistem de fclock=4 MHz (perioada de 0.25 usec) vom avea
o durată a ciclului de numărare de 28 * 0.25usec = 256 * 0.25usec = 64
usec, deci f PWM = cca. 15.6 KHz
Sau folosind formula deja data f PWM= fclock / (1*256) = 4000 000/256 =
15625Hz = 15.625 kHz 50
Exemplu pentru Timer 0, PWM rapid
/*Factorul de umplere: dat printr-o valoare pe 8 biti fara
semn, ca o valoare intre 0 – 255
0 -> FU% = 0% si 255-> FU% = 100% */

/*actualizeaza factorul de umplere , pe 8 biti pe cele 2


canale A si B, cu valori complementare */
void SetPWMOutput(unsigned char factor_umplere)
{
OCR0A = factor_umplere;
OCR0B = 255-factor_umplere; /*complement fata de 255*/
}

/*O functie simpla care realizeaza o intarziere software*/


void Asteapta()
{/*functia se afla in biblioteca descrisa de delay.h */
_delay_loop_2(10000);
/*realizeaza o intarziere de 4*argument cicluri masina,
adica de 4*10000*0.25usec = 10000 usec = 10msec */
} 51
Exemplu pentru Timer 0, mod PWM rapid-2
int main() /*Programul principal*/
{
unsigned char val_PWM =0;
InitPWM(); /*Initializeaza Timer 0, PWM rapid 8 biti */
while(1) /* bucla fara sfarsit /*
{

/*o prima bucla in care crestem factorul de umplere de la 0 la 100% */


for(val_PWM =0; val_PWM; val_PWM ++)
{ /* Actualizam factorul de umplere PWM */
SetPWMOutput(val_PWM);
Asteapta(); /*O mica intarziere*/
} /*in timp real bucla ar trebui sa dureze cam 2.5 sec*/

/*a 2a bucla in care descrestem factorul de umplere de la 100% la 0 */


for(val_PWM =255; val_PWM >0; val_PWM --)
{ /* Actualizam factorul de umplere PWM */
SetPWMOutput(val_PWM);
Asteapta(); /*O mica intarziere*/
}
}/*end while*/
}
52
AVR 8 biti, din nou despre sistemul de
întreruperi si sursele de întreruperi
• Întreruperile, la modul general (nu neapărat in contextul AVR 8
biti), pot fi clasificate ca:
– interne sau externe
– software sau hardware
• O întrerupere externă este declanșată de un dispozitiv extern
microcontrolerului (aflat in exteriorul lui)
• O întrerupere internă este declanșată de un dispozitiv integrat
microcontrolerului (aflat pe același cip), tipic un periferic
• Putem avea o întrerupere hardware care apare datorită
modificării stării unei componente hardware a unui sistem
de calcul, in particular a unui MCU
• Putem avea si o întrerupere software care este
declanșată de execuția unei instrucțiuni specifice de către
unitatea centrala (CPU)
– AVR 8 biți nu are instrucțiuni specifice de intrerupere software
– care sa genereze o intrerupere - in setul de instrucțiuni, dar
problema poate fi eventual conturnată, astfel încât să avem o
întrerupere generată de execuția unei instrucțiuni

53
Rutinele de tratare a întreruperii
• O rutină de tratare a întreruperii este de fapt
subrutina care are ca particularitate (in limbaj e
asamblare) că se termină cu o instrucțiune
specială AVR numită RETI (Return from INTerrupt):
întoarcere din întrerupere
• Rutinele de tratare a întreruperilor nu sunt apelate
explicit, ci in mod implicit/automat, de un
mecanism hardware
• Adresa lor de început este “plasată” automat in
numărătorul program al CPU, de un hardware
dedicat
– Cele de mai sus se refera si interesează in primul rând la
programarea in limbaj de asamblare; in limbaj evoluat
(de exemplu C) funcțiile aferente sunt practic identice cu
o funcție normala, diferă doar modalitatea de apelare,
care este controlata de compilator
54
Sistemul de întreruperi al AVR 8 biti
• Microcontrolerele din familia AVR 8 biti pot gestiona,
funcție de variantă, un număr diferit de surse de
întrerupere, de la câteva pana la câteva zeci
• ATMega16 are 21 de surse, ATTiny2313 are 19,
ATMega 128 are 35, s.a.m.d
• Numărul de întreruperi pentru o anumita varianta
depinde de natura perifericelor (un periferic poate avea
asociate una sau mai multe întreruperi), precum si de
cât de multe periferice sunt implementate
• Sursele de întreruperi sunt numerotate de la 1 la n,
prioritatea lor fiind in aceasta ordine, cu numărul 1
(Reset) cel mai prioritar si n cel mai puțin prioritar
• Fiecare întrerupere provoacă apelarea automată a unei
rutine de tratare specifică, de la o anumită adresă din
memoria de program
– Reset-ul este văzut ca un tip particular de întrerupere, “rutina de
tratare” a Reset-ului fiind plasată la adresa 0x0000, adică locul
de unde se va executa prima instrucțiune a programului AVR
55
Vectorii de întrerupere AVR 8 biti
• O rutina in limbaj de asamblare de tratare a întreruperii k trebuie
plasată in memoria de program la adresa de forma 2*(k-1)
– La adresa 0x0000 este rutina pentru “reset”
– La adresa 0x0002 este rutina pentru întreruperea externă 0
– La adresa 0x0004 este rutina pentru întreruperea externă 1
– Dar in continuare lucrurile pot diferi funcție de variantă!
• ATENTIE: funcție de varianta de microcontroler AVR, același tip
periferic poate avea vectori (adrese) diferite de tratare
– De exemplu pentru ATTiny2313 comparatorul analogic are vectorul 11
(0x000A), iar pentru ATMega același periferic are vectorul 19 (0x0024),
s.a.m.d
– Trebuie verificată neapărat tabela de vectori dată in foaia de catalog a
microcontrolerului in cauză!
• Pentru că “in vectorul de întrerupere” este rezervat un “loc” doar de 32
de biţi (2 cuvinte program) per întrerupere, loc suficient numai pentru
una sau doua instrucțiuni, de fapt fiecare rutina de tratare începe cu
o instrucțiune de salt la o altă locație din memoria program de
unde începe de fapt codul rutinei de tratare propriu-zise
• Completarea tabelei este realizată de compilatorul C, prin mijloace
specifice puse la dispoziția programatorului C sau in mod explicit
de programatorul in limbaj de asamblare
– La adresă se va afla in mod tipic o instrucțiune de tip jmp rutina, care este
o instrucțiune de 32-biti (2 cuvinte in memoria de program), care încape 56 in
spațiul rezervat pentru fiecare intrare in tabela de vectori
Tabela de vectori pentru ATtiny 2313

57
Tabela de vectori pentru ATMega32

58
AVR 8 biti: activarea individuală si
globală a întreruperilor
• Fiecare sursă potențială de întreruperi poate fi activată
sau dezactivată individual
• Dezactivare întrerupere = mascare întrerupere
– “Întreruperea” corespunzătoare Reset-ului este singura
excepție: ea este nemascabilă, nu poate fi dezactivată
• Indicatorul global de întreruperi I, din registrul de stare
SREG trebuie să fie setat (=1) pentru ca orice
întrerupere să aibă loc si să poată fi tratată: el este un
bit de activare globală a întreruperilor AVR 8 biti (desi
se află in registrul de stare…)
– Din nou “întreruperea” corespunzătoare reset-ului este o
excepție; ea nu poate fi dezactivată nici global

59
AVR 8 biti: acțiunile asociate utilizării
unei întreruperi
• DACA
– Întreruperile sunt activate global
– SI o întrerupere specifică este activată
– SI condiția / evenimentul de întrerupere este prezent(ă)
• ATUNCI se va genera o cerere de întrerupere si va avea loc
tratarea ei
• Ce se întâmplă atunci din punct de vedere al unității
centrale?
– După terminarea execuției instrucțiunii curente:
• Valoarea curentă a lui PC (a numărătorului program) este salvată in
stivă (este singura componentă a contextului astfel salvată!)
• Întreruperile sunt dezactivate global (I=0)
• Vectorul corespunzător de întrerupere (o adresă fixă) este adus in PC
(PC=vector)
• Se execută instrucțiunea de la acea adresă

60
Utilizarea stivei in cazul
întreruperilor
• Pentru ca execuția unei rutine de tratare a întreruperii este similara
unui apel de subrutina, stiva are un rol esențial pentru salvarea
contextului (adică cel puțin a adresei de întoarcere)
• Deoarece întreruperile au nevoie să utilizeze stiva, este esențial ca,
in faza de inițializare a unei aplicații care folosește întreruperile, să fie
inițializată corect si stiva (prin intermediul indicatorului de stivă SP)
– Cu alte cuvinte trebuie sa ne asiguram ca este suficient “loc” in stiva si ca in
urma salvării contextului sau a mai multor contexte, stiva nu se “ciocnește” cu
alte zone utile de memorare (variabile, etc.) ducând la distrugerea datelor
• Un compilator rezolvă automat această problemă (prin intermediul
unor mijloace specifice), alteori ea trebuie realizată explicit de
programator (obligatoriu la limbajul de asamblare!)
• In cazul unui compilator rutinele de tratare a întreruperilor vor/pot
utiliza stiva si pentru a salva contextul in momentul apariției
întreruperii, nu numai adresa de întoarcere, aceasta acțiune fiind
aproape transparenta pentru utilizator

61
Registrul de stare AVR 8 biti:
SREG
• Rutinele de tratare a întreruperilor nu trebuie să modifice
registrul de stare SREG (el trebuie să fie neschimbat), el
făcând parte din context
• Registrul SREG nu este salvat automat in stiva!
• In limbaj de asamblare, un exemplu de salvare si
restaurare a lui SREG:

rutina_tratare_intrerupere:
push r0 ;salvez pe r0 in stiva
in r0, SREG ;salvez in r0 pe SREG
… ;aici nu folosesc la altceva pe r0
out SREG, r0 ;restaurez pe SREG din r0
pop r0 ;restaurez pe r0 din stiva
reti

Un compilator C rezolvă el această problema de salvare a


contextului, deoarece generează automat codul pentru 62
salvarea si restaurarea intregului context, context care include
si SREG.
Întreruperile AVR 8 biți: evenimente
si condiții
• Toate întreruperile/cererile de întrerupere AVR se
încadrează in două mari clase/categorii:
– Întreruperi bazate pe un eveniment
• Sunt declanșate de un eveniment si sunt memorate in mod automat;
cererea de întrerupere este ștearsă automat la intrarea in rutina de
tratare sau trebuie ștearsă prin program (de utilizator, “manual”).
• O puteți imagina ca ieșirea unui bistabil care este setat de acel
eveniment, memorand faptul ca evenimentul a avut loc
• Daca ea trebuia ștearsă de utilizator si nu a fost ștearsă de el in rutina
de tratare a întreruperii, după întoarcerea din aceasta, va fi tratata din
nou, deși acum nu mai are legătură cu evenimentul!
– Întreruperi bazate pe o condiție
• Provocate dacă o anumită condiție este îndeplinită (este adevărată);
cererea de întrerupere este ștearsă/dispare atunci când condiția nu
mai este îndeplinită (devine falsă), si nu sunt memorate
• O puteți imagina ca ieșirea unei porți care este setată de o anumita
combinație a intrărilor, fara capacitate de memorare

63
Întreruperi AVR 8 biti bazate pe
evenimente
• Chiar dacă întreruperile sunt dezactivate (individual
si/sau global), indicatorul aferent cererii de
întrerupere poate fi setat de evenimentul asociat, in
mod independent
– Aceasta se întâmplă deoarece ele trebuie sa poată fi
testate si prin polling
• Odată setat, indicatorul poate rămâne setat
(memorează evenimentul) si poate declanșa o
întrerupere, odată ce întreruperile vor fi din nou
activate
– Acest gen de indicator de cerere de întrerupere este
șters:
• Automat când are loc tratarea a întreruperii (când se intră in
rutina de tratare a întreruperii) sau
• “Manual”, prin program, scriind un “1” in el (in bitul respectiv)
• Trebuie însă citită cu atenție foaia de catalog si văzut care sunt
șterse in mod automat si care trebuie șterse de utilizator!

64
Întreruperi AVR 8 biti bazate pe
condiţii
• Chiar dacă întreruperile sunt dezactivate, global
si individual, indicatorul aferent acestui tip de
cerere va fi setat când condiția asociată devine
adevărată
– Similar precedentei categorii, aceasta se întâmplă
deoarece ele trebuie sa poată fi testate si prin polling
• Dacă însă condiția devine falsă înainte ca
întreruperile să fie (re)activate, indicatorul este
șters si cererea de întrerupere va fi “pierdută”
– Aceste indicatoare sunt șterse imediat ce condiția
devine falsă
– Mai pot fi necesare si alte acțiuni “manuale” ale
utilizatorului pentru a gestiona corect aceasta
ștergere

65
Exemple de întreruperi AVR

• Bazate pe • Bazate pe condiție:


evenimente:
– Întreruperi externe
– Întreruperi externe declanșate pe nivel
declanșate pe front
(tranziție de semnal) – Recepție caracter
– Depășirile pentru USART (port serial):
temporizatoare Data Ready, Receive
/numărătoare si Complete
eveniment – EEPROM disponibil
comparare ieșire pentru operare
(match)

66
AVR 8 biti - Întreruperile externe
ATMega16
• Luând ca exemplu un
ATMega16 (in capsula DIP40)
avem 4 întreruperi externe –
care corespund unor semnale int2
aplicate pe anumiţi pini:
– RESET (pin 9)
– INT0 (pin 16 – PD2) reset
– INT1 (pin 17 – PD3)
– INT2 (pin 3 – PB3)
int0

67
AVR 8 biti - Întreruperile externe
ATTiny 2313

• Pentru ATTiny 2313 (DIP20)


avem 3 întreruperi externe –
care corespund unor semnale
aplicate pe anumiţi pini: int0
– RESET (pin 1 – PA2)
– INT0 (pin 6 – PD2)
– INT1 (pin 7 – PD3)

68
AVR 8 biti: configurarea întreruperilor externe
• In primul rând trebuie stabilit cum/ când semnalul
extern declanșează o cerere de întrerupere:
• Pe baza îndeplinirii unei condiții:
– Când nivelul logic pe pin este “0”
• Sau declanșate de un eveniment:
– Când nivelul pe pin s-a modificat (a comutat din “0” in
“1” sau din “1” in “0”)
– Front căzător - negativ (tranziție nivel pin din “1” in “0”)
– Front ridicător - pozitiv (tranziție nivel pin din “0” in “1”)

69
Registrul MCUCR - registrul de control (si)
pentru întreruperile externe

• Registrul MCUCR - MCU Control Register


7 6 5 4 3 2 1 0

ISC11 ISC10 ISC01 ISC00

• Bitii ISC – Interrupt Sense Control bits


– 00 – nivel “0” INT0
– 01 – modificare nivel INT1
– 10 – front negativ
– 11 – front pozitiv
70
Cum sunt identificate evenimentele de tip
întreruperi externe: dimensiunea timp

• Unitatea centrală (CPU) testează starea logică a


pinilor corespunzători lui INT0, INT1, .. la fiecare
ciclu (perioadă) a ceasului sistem (clkCPU)
• Pentru a detecta / identifica o tranziție sau
modificare de nivel, intr-un ciclu trebuie să avem
detectat un “0” si in următorul un “1” sau invers
– Impulsurile foarte scurte (cu durata mai mică de un ciclu)
pot să nu fie detectate (nu este văzută de CPU nici o
modificare sau tranziţie)
• O întrerupere pe nivel “0” va fi luată in considerare
doar dacă, la sfârșitul execuției instrucțiunii curente,
starea pinului aferent este “0”

71
Registrul MCUCSR- registrul de control si
stare pentru cazul in care există INT2
• Registrul MCUCSR - MCU Control and Status Register

MCUCSR – MCU Control and Status Register


7 6 5 4 3 2 1 0

ISC2

• Bitul ISC – Interrupt Sense Control bit INT2


– 0 – front negativ
– 1 – front pozitiv
• Spre deosebire de INT0 si INT1, doar aceste configurări există
pentru INT2 (la ATMEGA16 sau similar)!

72
Registrul GICR- activarea individuala a
întreruperilor externe

• GICR General Interrupt Control Register


GICR – General Interrupt Control Register
7 6 5 4 3 2 1 0

INT1 INT0 INT2

• Aici întreruperile externe pot fi activate/dezactivate individual


(mascate)

//exemplu activare int1 si dezactivare int0

GICR |= (1<<INT1);
GICR &= ~(1<<INT0);

73
Registrul GIFR- aici se gasesc indicatorii
corespunzători cererilor de întrerupere externe

• GIFR- General Interrupt Flag Register


7 6 5 4 3 2 1 0

INTF1 INTF0 INTF2

• Un indicator setat (in ‘1’) arată că o întrerupere


externa se află in aşteptare pentru a fi tratată
• Indicatoarele pot fi oricând citite
– Aceste indicatoare sunt utilizate doar dacă configurarea
este pentru tranziţii (modificare nivel)
• Pentru configurarea pe nivel indicatorul este întotdeauna
“0”
– Evenimentul specificat va seta flagul; el va fi şters prin
tratarea întreruperii sau eventual poate fi sters si
“manual”
74
AVR 8 biti- cum se pot realiza si
întreruperi software
• In setul de instrucțiuni AVR 8 biti, spre deosebire de
alte unitati centrale, nu există o instrucțiune care să
producă o întrerupere software (gen trap), dar este
posibilă o soluție de conturnare a acestei lipse
• Dacă pinii corespunzători întreruperilor externe sunt
disponibili si sunt configurați si utilizați ca ieșiri de
aplicație, programul poate controla el starea
indicatorilor respectivi (de ex. INT0 sau INT1),
aducându-i in “1” sau “0”
– Aceasta acțiune poate declanșa o întrerupere conform
configurării întreruperilor externe
• Deoarece o instrucțiune a programului este cea care
a generat astfel întreruperea, ea poate fi numită
întrerupere software
75
Întreruperile AVR 8 biti si compilatorul WinAVR
• Nu există un consens general in ce privește proiectarea
compilatoarelor C legat de cum anume pot fi manipulate
mai bine de programator întreruperile, făcând ca detaliile
care sunt dependente de mașină (CPU) să fie cat mai
bine „ascunse” utilizatorului.
• Pentru un microcontroler AVR 8 biți (si nu numai)
compilatorul C va crea o tabelă corespunzătoare de
vectori, prin compilarea codului sursă.
• Compilatoarele C existente pentru AVR 8 biti sunt
proiectate cu metode specifice pentru a realiza
completarea acestei tabele de întreruperi, cum este
cazul si compilatorului WinAVR pe care il vom discuta in
continuare.
• Fiecare întrerupere va fi identificată printr-un nume
predefinit, care este prezent intr-un fișier header
specific fiecărei variante de microcontroler AVR.

76
Întreruperi si compilatorul WinAVR -1
De exemplu in cazul ATTiny2313 acesta se numeşte iotn2313.h. Aici
găsim, de exemplu:

/* Intreruperea Externa 0 */
#define INT0_vect _VECTOR(1)
/*vectorul corespunzator intreruperii externe 0 este
primul din tabela*/
Sau

/* Intrerupere depasire Timer/Counter1 */


#define TIMER1_OVF_vect _VECTOR(5)
/*vectorul corespunzator intreruperii data de depasirea
Timer-ului 1 este al 5-lea din tabela*/

Pentru ca compilatorul să înţeleagă aceste macroinstrucţiuni (si altele),


mai trebuie inclus si un alt fişier header specific interrupt.h.

#include <avr/interrupt.h>
77
Întreruperi si compilatorul WinAVR - 2
Toate întreruperile pot fi descrise folosind macroinstrucţiunea ISR(vector),
de exemplu o subrutina care tratează depăşirea Timer-ului 1 este declarata
ca mai jos:
ISR(TIMER1_OVF_vect)
{
//codul care trateaza intreruperea
}

In afara de întreruperile „dorite” pentru evitarea unor întreruperi parazite (care


de fapt nu ar trebui sa apară) se poate folosi tot macroinstrucţiunea ISR() cu un
argument specific:

ISR(_vector_default)
{
//codul care trateaza intreruperile parazite
}

Este o măsura de siguranţa care imbunătăteste fiabilitatea aplicaţiei.

78
Întreruperi si compilatorul WinAVR - 3
• Dacă dorim ca pentru o întrerupere particulară, rutina de tratare să
nu facă practic nimic, cu excepţia întoarcerii din subrutină, se utilizează
macroinstrucţiunea EMPTY_INTERRUPT (vector) astfel :

EMPTY_INTERRUPT(ADC_vect)

• Ea nu face altceva decât să pună codul instrucțiunii RETI (întoarcere


din întrerupere) in poziția corespunzătoare vectorului specificat in
tabela de întreruperi.

• Alte macroinstrucţiuni importante (fără nici un argument) definite in


același fișier header sunt:

cli() care şterge bitul I (=0) din SREG dezactivând global sistemul de
întreruperi

sei() care setează bitul I (=1) din SREG activând global sistemul de
întreruperi

79
Întreruperi si compilatorul WinAVR - 4

• Versiunile mai vechi ale compilatorului WinAVR foloseau o


macroinstrucţiune similară lui ISR numita SIGNAL() care nu mai este
utilizată la versiunile curente (este deprecated, obsolete).

• O altă macroinstrucţiune legată de manipularea întreruperilor este


ISR_ALIAS(vector_actual, vector_tinta) care este utilă pentru a face ca
un vector să indice de fapt un alt vector.
– In felul acesta se pot trata întreruperi diferite cu aceiaşi rutina de tratare a
întreruperilor.
• Dacă de exemplu am dori ca cele două întreruperi externe INT0 si INT1 să
fie tratate cu o rutină unică de tratare, am avea:

ISR (INT0_vect) //rutina de tratare a intreruperii INT0


{ PORTB = 0x42;
}
……..
ISR_ALIAS(INT1_vect, INT0_vect);

80
Întreruperi si compilatorul WinAVR, exemplu de utilizare a
întreruperilor externe
• Un mic exemplu de program care utilizează întreruperile externe 0 si 1 pentru a
aprinde/stinge un LED conectat pe pinul PB0 al portului B.
• Întreruperile sunt generate cu ajutorul unor comutatoare puse pe pinii PD2 (INT0) si PD3
(INT1).
• Acționarea comutatorului aduce intrarea respectivă in „0”, generând cererea de întrerupere
externă corespunzătoare.
– Se presupune că am “deparazitat” corespunzător contactele!

#include <avr\io.h>
#include <avr\iotn2313.h>
#include <avr\interrupt.h>
/*doua exemple de macroinstructiuni folosite pt a citi scrie in
porturi*/
#define outp(a, b) b = a
#define inp(a) a

unsigned char led;

/* rutina de tratare a intreruperii externe int0 */


ISR(INT0_vect) { led = 0x01;
}
/* rutina de tratare a intreruperii externe int1 */
ISR(INT1_vect) { led = 0x00;
81
}
Întreruperi si compilatorul WinAVR: întreruperile
externe
Programul principal:

int main(void) {
/* doar PB0 din PortB va fi iesire pt LED */
outp(0x01, DDRB);
/* tot Portul D ca intrari, PB2 si PB3 */
outp(0x00, DDRD);
/* activam individual pe int0, int1 /*
outp((1<<INT0)|(1<<INT1), GIMSK);
/* activarea globala a intreruperilor */
sei();
led = 0x01;
/*aici se termina partea de initializare */
for (;;) {/* o bucla fara sfarsit */
/*in care doar actualizam portul B din variabila led */
outp(led, PORTB);
}
}

82
Întreruperi si compilatorul WinAVR: un exemplu de
utilizare a lui Timer1 - 1
/* Definire vector intrerupere depasire:
Timer/Counter1 Overflow */
#define TIMER1_OVF_vect _VECTOR(5)

int main(void)
{
//initializam timerul 1
Init_Timer1 ();
/*Activam global sistemul de intreruperi, pana aici
intreruperile au fost dezactivate! */
sei();
//o bucla fara sfarsit
while(1)
{ //..programul “principal” va fi intrerupt
// periodic, executandu-se rutina de tratare
// a intreruperii ISR(TIMER1_OVF_vect)
}
}
83
Întreruperi si compilatorul WinAVR: exemplu utilizare
Timer1 - 2
O funcție de inițializare a lui Timer 1 :

Init_Timer1 (){
/** Configuram Timer1- de 16 biti,
folosind ceasul sistem ca sursa de ceas
cu o divizare suplimentara de :64 **/
TCCR1B |= (1 << CS10 | 1 << CS11 );
/** Ceasul pt Timer 1 = system clock/64
Ceasul sistem este de 4MHz (perioada 0.25usec)
Perioada semnal ceas = 16 usec (.25usec x 64 )
Dorim o perioada de numarare de cca. 0.5sec
adica 500 000 de usec / 16 usec
Initializam Timer1, pe 2 octeti: ca valoare pe 16 biti **/
TCNT1H=(-500000/16) >> 8; // intai octetul H !
TCNT1L=(unsigned char)(-500000/16); // apoi octetul L !
/* Activam intreruperea lui Timer1 */
TIMSK |= 1 << TOIE1;
}

84
Întreruperi si compilatorul WinAVR: exemplu de
utilizare Timer1 - 3
/*============================================
Rutina de tratare a intreruperii Timer1 - la depasire
=============================================*/
ISR(TIMER1_OVF_vect)
{
TIFR |= 1<<TOV1; /*stergem flagul de cerere de
intrerupere */

/*reinitializam numaratorul pentru urmatorul ciclu de


numarare */
TCNT1H=(-500000/16) >> 8;
TCNT1L=(unsigned char)(-500000/16) ;

/*… aici vom pune prelucrarile din subrutina de tratare a


intreruperii */
}
85
Un exemplu de utilizare/configurare Timer 0, modul normal
(ATMega16) si sistemul de întreruperi - 1
#include <avr/io.h>
#include <avr/interrupt.h>
/* variabila globala pentru contorizarea numarului de depasiri 8 biti, valoare maxima este
256 */
uint8_t total_depasiri;
void Timer0_init()
{
/* frecventa oscilatorului fosc= 1MHz (RC intern)
factorul de divizare = 1024
Fclock= 1000 000 /1024 = 975.56Hz
Tclock= 1/ 975.56 = 0.001024 sec
adica CS02= 1, CS01=0, CS00=1 */
TCCR0 |= (1 << CS02)|(1 << CS00);
/*toti ceilalti biti din registrul TCCR0 au valoarea implicita dupa reset, adica 0:
FOC=0 fara fortare iesire la out. compare
WGM00=WGM01=0, mod normal, Top= 0xFF
COM01=COM00=0, mod normal, OC0 deconectat de pin */
/* dorim o intarziere de baza sa-i zicem de 200msec=0.2 sec
aceasta corespunde la 0.200/0.001024 = 195 (195.31 trunchiat)
de incrementi pt acest interval de timp, deci
registrul va numara incepand de la 256-195 pana la valoarea maxima 256 (255+1)
moment in care va avea loc depasirea */
/* initializam registrul de numarare timer */
TCNT0 = 256-195;
/* initializam variabila de contorizare */
total_depasiri = 0;
/* activam intreruperea corespunzatoare lui Timer 0*/
TIMSK |= (1 << TOIE0);
} 86
Un exemplu de utilizare/configurare Timer 0, modul normal
(ATMega16) si sistemul de întreruperi -2
/* functia/subrutina de tratare a depasirii pentru Timer 0 TCNT0 apelata de fiecare data cand are loc o
depasire */
ISR(TIMER0_OVF_vect)
{
/* reincarcam pentru ca urmatorul ciclu sa aiba aceiasi lungime */
TCNT0 = 256-195;
/* incrementam contorul, el va numara modulo 256! */
total_depasiri++;
}

int main(void)
{
/* sa zicem ca avem un LED conectat pe pinul PC7, care trebuie sa fie iesire */
DDRC |= (1 << PC7);
/* initializam timerul */
Timer0_init();
/* activam global intreruperile*/
sei();
/* o bucla fara sfarsit */
while(1)
{
/* verificam doar daca numarul de depasiri a ajuns = 10 */
if (total_depasiri >= 10) /* ATENTIE '>=' ! */
{
PORTC ^= (1 << PC7); /* comutam starea pinului/LED-ului */
total_depasiri = 0; /* aducem la 0 contorul de depasiri */
}
/*intarzierea totala va fi deci de 10*0.2 sec = 2 sec
atat sta LEDul aprins, respectiv stins*/
87
}
}
Microcontrolere (si
microprocesoare)

Microchip AVR 8 biți:


Intrări analogice si conversia analog-numerică
(generalități)
Sistemul de conversie analog-numerică AVR 8 biti

1
Două exemple de aplicații simple pentru care un
microcontroler ar avea nevoie si de intrări analogice

MCU
MCU

Măsurarea temperaturii
cu un termistor NTC, a unui
Măsurarea luminozității cu ajutorul unei
divizor rezistiv si a unui repetor.
fotorezistențe si a unui divizor rezistiv.
Un termistor NTC (Negative
O fotorezistență (LDR – Light Dependent
Temperature Coefficient
Resistor) este o rezistență (neliniară) a
thermistor) este o rezistență (neliniară)
cărei valoare scade cu creșterea intensității
a cărei valoare scade cu creșterea
luminii incidente
temperaturii
Sunt 2 exemple foarte simple de senzori rezistivi 2
împreună cu circuitele de adaptare (si ele f. simple-niste divizoare rezistive)
O intrare analogică presupune transformarea unei unei
mărimi fizice analogice intr-una numerică (digitizarea
ei): conversie analog-numerica

Proces/Instalatie/
Zgomot MCU
Mediu
înconjurător electromagnetic

Prelucrare

Mărimea Adaptare/ CAN N -


Senzor/ Filtrare / mărime
fizica, poate Protectii Amplificare
Traductor numerică
fi si V1 V2 V3
neelectrică codificată
binar, o
Tensiuni masura a
Bloc de prelucrare lui V3
analogică a semnalului

CAN – Convertor Analog Numeric


ADC – Analog to Digital Converter
3
Conversia analog-numerică (CAN):
regimul static
Un exemplu
Uin
pentru un CAN de A
3 biţi ( n = 3 )
N
Numărul N este
exprimat pe 3 biţi:
a2, a1, a0
a2 - este MSb
valori diferite

a0 - este LSb
Rezoluţia (analogica)
Avem 8

r = 5/8 = 0.625V
r = Umax / 2n [V]

max
Conversia analog
numerica introduce Uin
întotdeauna o eroare
de cuantificare Avem o infinitate de valori
LSb – Least Significant Bit , cel mai puţin semnificativ bit 4
MSb – Most Significant Bit , cel mai semnificativ bit
Rezoluția (resolution) determina si eroarea de
cuantificare (quantization error)
Rezoluția numerică indică numărul de valori
numerice distincte optenabile in domeniul
Uin
A 0..Umax: n biți, adică 2n valori
biţi
max Rezoluția analogică este exprimată in unități
N ale mărimii de intrare): r = U max /2n [V]
Caracteristici statice de transfer
Pentru un
CAN ideal:
n→∞
r→0

Uin (V) Uin (V)

Eroarea analogică = r Eroarea analogică : ± r/2


Eroarea numerică = 1 LSB Eroarea numerică : ± 1/2 LSB

Un CAN are rezoluția adevărată de n biţi doar dacă eroarea numerică este ± 1/2 LSB
5
Exista si alte erori de regim static: liniaritate, decalaj (offset), câștig, ..
Regimul dinamic: cum procedam in cazul mărimilor variabile
in timp, ce este perioada de eșantionare (sampling period)
In « fața » CAN se află un circuit de
Uin (V) eșantionare si memorare (Sample/Hold)
Avem o infinitate de valori
care prelevează in mod regulat o valoare
Uin si o menține constantă un interval de
timp Te pană la prelevarea eșantionului
următor (actioneaza ca o memorie
analogică).
Tensiunea de intrare in CAN
Te Timpul de conversie al CAN
trebuie să fie inferior lui Te

Comanda circuitului de eşantionare


perioada de eşantionare este Te , frecvenţa de
eşantionare este Fe = 1/Te

Timpul de conversie (conversion time) este intervalul de timp din


momentul declanșării unei operații de conversie si momentul in care
rezultatul ei este disponibil integral.
Conversia analog numerică implică o dublă cuantificare:
• cuantificare temporală, este eșantionarea propriu-zisă
6
• cuantificare in amplitudine (cea care da rezoluția)
Regimul dinamic. Fenomenul de dedublare, replicare a
spectrului (aliasing)
Daca frecventa de eșantionare este prea mica, in semnal sunt “detectate” frecvențe mai joase
decât exista in realitate!
Exemplu: un semnal sinusoidal de perioada T eșantionat cu Te= 1.25 T
T
Fe= 0.8 F
T' = 5 T
F' = 0.2 F
F' = F - Fe

Te=1.25 T
Teorema lui SHANNON ( Criteriul lui
Nyquist), cat de “repede” trebuie
eșantionat semnalul :
Spectrul real al Are loc
semnalului de Fe > 2 * Fmax
« replicarea »
eşantionat spectrului Fmax : frecvența maximă din spectrul
lui Uin
La intrarea CAN (înainte de
F
circuitul de eşantionare
/memorare) este necesar un
filtru trece jos (FTJ) cu frecvenţa 7
de tăiere Fc = Fe/2
Schema principială a unui circuit de eșantionare si memorare
(S/H): se utilizează un capacitor pentru memorarea
semnalului pe durata cat care loc conversia

Repetor (opamp)
Repetor (opamp) Comutator / cheie
de tensiune

Vo
C
Semnal Vc
Vi de ceas
Capacitor
de memorare

8
Principiul de funcționare al unui circuit de
eșantionare si memorare (S/H)
V3
Vi
V2 V4
V1 V5

t
Semnal K inchis
ceas
K deschis
V3 t
Vc=Vo V4
V2
V5
V1
t
Th Ts Th Ts

Th timp de memorare (hold)


Ts timp de eşantionare (sample) Aici Vc =Vo urmăreşte tensiunea de intrare
9
AVR 8 biti- sistemul de conversie analog-
numerică
• Anumite microcontrolere AVR 8 biti, în toate sub familiile (doar anumite Tiny,
majoritatea Mega, toate XMEGA), au printre resursele de tip periferic și un
sistem de conversie analog-numerică, cu mai multe canale de intrare.
• Mărimea de intrare pe un astfel de canal este întotdeauna de natura unei
tensiuni, astfel că orice altă mărime analogică, de altă natură (curent,
rezistență, etc.) care se dorește măsurată, trebuie convertită mai întâi in
tensiune si scalată (adaptare de nivel) corespunzător domeniului tensiunii
de intrare pentru canalele de intrare
• Sistemul constă in: un multiplexor analogic si un convertor analog-
numeric de tipul cu aproximări succesive (care include un circuit
eşantionare – memorare: Sample/Hold) şi o sursă de referință de
tensiune, internă si/sau externă).
• Utilizarea unui circuit de eșantionare-memorare este esențială dacă
CAN-ul este de tipul cu aproximări succesive, daca se dorește
valorificarea timpului de conversie relativ scăzut
– Pentru acest tip de CAN, orice modificare a mărimii de intrare, pe durata
conversiei, mai mare de ±1 LSB, poate duce la erori grosolane
• Descrierea care urmează este bazată pe sistemul de conversie analog-
numeric existent la familia ATMega (de exemplu ATMega 16).

10
Schema bloc funcțională a sistemului de conversie
analog numerică AVR 8 biți (exemplu cu 8 canale de
intrare ADC0..ADC7)

ADC7
ADC6 Registru rezultat
ADC5
Octet superior (ADCH)
N
Vin
ADC4 CAN 10 biţi 10 biti
ADC3
Multiplexor CAN 10bits
ADC2 Registru rezultat
Vref+
ADC1 Octet inferior (ADCL)
ADC0

Registru de control Registru de control/


ADMUX stare ADCSRA

Registru de control
SFIOR 11
Convertorul analogic-numeric : schema bloc detailată
(ATMega16)

Registrele utilizator

Sursa referinţa
interna

Convertorul analog numeric -


cu aproximaţii succesive

Multiplexorul analogic Amplificator programabil (care nu exista la 12


orice varianta!)
AVR 8 biti - sistemul de conversie analog-
numerică -2
• Din punct de vedere al utilizatorului există, odată, 8 intrări analogice
asimetrice (notate ADC7..ADC0) care de fapt sunt cele 8 canale de intrare
ale unui multiplexor analogic.
• Cele 8 intrări analogice sunt de fapt funcții alternative ale pinilor portului A
(PORTA) - la ATMega16/32.
• Tensiunile de intrare, în acest mod asimetric, sunt raportate faţă de borna
de masă GND, care definește potenţialul de 0V.
– In acest mod putem avea maxim 8 canale de intrare
• Există însă şi posibilitatea ca aceste canale de intrare să fie folosite şi într-
un mod diferenţial.
– Sunt posibile până la 16 combinaţii, toate descriind diferite moduri de intrare
diferențială.
– In acest mod putem avea maxim 4 intrări diferenţiale adevărate (fiecare utilizând
2 pini) si maxim 7 intrări pseudo diferenţiale (de exemplu, borna inversoare Vin-
de intrare este ADC1, celelalte 7 canale fiind utilizate ca borne de intrare
neinversoare Vin+).
– Doar in modul diferențial se pot măsura tensiuni “negative”, sursa echivalenta
având borna negativa conectata la Vin+ si borna pozitiva la Vin-

13
Intrării asimetrice si/sau diferențiale

Intrare asimetrică (single ended) – o singură


bornă de intrare(single input), cealaltă bornă,
comună cu sursa din intrare, este legată la masă!

Intrare diferenţială (differential) – nici o bornă nu


este legată la masă, avem o bornă de intrare
pozitivă (In+) sau neinversoare si una de
intrare negativă (In-) sau inversoare

14
Multiplexorul analogic (ca exemplu, un multiplexor 4:1)
este un circuit selector: selectează la ieșire una din mai
multe intrări
Doar un singur comutator este închis la un moment dat,
altcumva scurtcircuităm intre ele sursele de tensiune de la intrările Ii!
K1
I0
4 Intrări K2
I1 1 Ieșire
Analogice K3 - O
I2 + Analogică
(tensiuni K4
I3 (tensiune
față de față de masă)
masă) S1 S2
Semnale de
selecţie
(numerice!)
Multiplexorul analogic este o rețea de comutatoare (chei)
electronice de tensiune Ki, care sunt comandate de o logică de
decodificare, prin intermediul unor semnale de selecţie (S1, S2
reprezintă “adresa” intrării pe care vreau să o aduc la ieşire) 15
Intrări analogice: ATMega

ATmega 32 (8 intrări, identic cu ATMega16) ATmega 8 (doar 6 intrări)

16
Intrări analogice: ATtiny 15 si ATtiny 24

ATtiny 15 are doar 4 canale


analogice ADC0..ADC3

Datorită numărului redus de pini,


nu au borne AVcc si AVREF, se pot utiliza
doar cu sursa de referinţă internă
ATtiny 24/44/84 are 8 canale
analogice ADC0..ADC7

17
AVR ATMega- convertorul analogic-numeric,
caracteristici
• Pentru ATMEGA 16, două dintre intrările - perechile diferențiale (ADC1/ADC0 şi
ADC3/ ADC2) pot utiliza un amplificator de câștig programabil (Gain Amplifier),
cu paşii de amplificare de 0 dB (x1), 20dB (x10), sau 46 dB (x200).
– Utilizarea acestui câștig (GAIN) programabil reduce rezoluția (si precizia).
– Dacă este selectat câștigul de x1 sau x10, rezoluția rezultată va fi de 8 biţi, iar dacă este
selectat câștigul de x200, rezoluția rezultată va fi de 7 biți.
• Datorită tehnicii de conversie utilizată (aproximări succesive) sistemul conține şi un
circuit eșantionare şi memorare (Sample Hold - S/H) conectat între ieșirea
multiplexorului analogic şi intrarea convertorului, care asigură menținerea
constantă a tensiunii de intrare a CAN–ului pe toată durata conversiei.
• Convertorul analog-numeric este unul având rezoluția de 10 biţi utilizând metoda
aproximărilor succesive
– Eroarea totală este de ± 2 LSB, deci el nu are precizia unui CAN de 10 biti (nu are rezoluţia
adevărată de 10 biţi!)
– Sunt necesari 2 octeți pentru memorarea rezultatului conversiei.
• Există o conexiune externă separată, AVCC pentru alimentarea sub-sistemului
CAN.
• AVCC nu trebuie să difere cu mai mult decât ±0.3V faţă de VCC (alimentarea
numerică).
• Există şi o sursă de referință internă de 2.56V (valoarea poate fi diferită funcţie de
variantă!) precum şi un pin dedicat VREF pentru conectarea unei surse de tensiune
de referință externe.
• Caracterizarea preciziei acestui sistem de conversie (erori: liniaritate, offset, câştig,
etc.) este detailată în foile de catalog Microchip/Atmel.
18
Convertorul analogic-numeric AVR ATMega :
registrele asociate
• Sistemul CAN al AVR 8 biți este configurat şi controlat, la fel
ca orice periferic AVR, prin intermediul unor registre mapate
în spațiul I/O.
• Există o serie de biți de comandă/control precum si biți de
stare, grupați in diverse registre, a căror semnificație
particulară va fi detailată .
• Registrele de comandă, control si stare sunt:
– ADMUX - prin intermediul lui se stabilește canalul sau canalele de
intrare al multiplexorului (intrarea analogica care va fi utilizata in
operația de conversie), modul de intrare (asimetric sau diferențial),
câștigul programabil (daca e cazul) şi se selectează referința care
va fi utilizată
– ADCSRA – este registrul de control şi stare al convertorului analog
numeric şi este un set de biți de control şi stare
– SFIOR – în acest registru există un câmp de 3 biţi prin care se
selectează cine va declanșa operația de conversie

19
Combinaţiile posibile (ex. ATMega16)
de intrări si câştig pentru
amplificatorul programabil (MUX4..MUX0)

ADMUX
Selectarea sursei
de referinţă

Dar există si variante (ex.


ATMega169) care nu au un
un amplificator cu câştig
programabil
Tabela este diferită pentru
20
acestea !
Intrarea asimetrică si/sau diferenţială:
selecţia canalului/canalelor de intrare
MUX 4…MUX0= 00000 MUX 4…MUX0= 10001

Vin Vin+

Vin-

21
AVR 8 biți- controlul operației de
conversie analog-numerică
• Funcționarea convertorului analog numeric (si in particular cea a unuia cu
aproximații succesive) este una periodizată cu ajutorul unui semnal de
ceas si a unei mașini secvențiale sincrone
• Exista mai multe etape/faze ale procesului de conversie analog-numerică
realizat de acest convertor
• Procesul începe cu declanșarea operației de conversie (SOC- Start Of
Conversion) si se termină cu finalizarea conversiei (EOC- End Of
Conversion), atunci când valoarea numerică rezultată este integral
disponibilă pentru utilizator
• Pentru un CAN cu aproximații succesive una din fazele importante este cea
de eșantionare/memorare (S/H- Sample/Hold)
• Utilizatorul (programatorul) trebuie să aibă mijloace specifice pentru a
controla declanșarea operației de conversie si pentru a determina momentul
când s-a finalizat operația de conversie
• In cazul AVR 8 biți aceste mijloace specifice sunt, in primul rând, biţii de
comandă/control precum si cei de stare din registrele aferente CAN
• Sistemul de temporizare numărare AVR 8 biți poate fi utilizat pentru
periodizarea operațiilor de conversie
• Sistemul CAN este integrat in sistemul de întreruperi AVR, CAN având un
vector de întrerupere dedicat

22
Registrul SFIOR- cine declanşează
si porneşte conversia?

Exista 8 moduri diferite de a


declanșa o operație de
conversie analog numerică:
- De către el însuși, auto-declanşare
sau conversie liberă (o operație de
conversie va începe imediat când
s-a terminat precedenta)
- De către ieșirea comparatorului
analogic
- De către pinul INT0 (întreruperea
externa 0)
- De către evenimente asociate
Ceilalţi biţi nu ţin de sistemul CAN! sistemului de temporizare
numărare (5 moduri) 23
Registrele ADCH si ADCL – rezultatul operației de
conversie analog numerică
• Rezultatul conversiei este exprimat pe 10 biți si este disponibil,
după finalizarea conversiei, în registrele ADCL și ADCH.
– Implicit, valoarea pe 10 biți este aliniată la dreapta, dar se poate
alinia și la stânga setând bitul ADLAR în ADMUX.
– Dacă rezultatul este aliniat la stânga și dacă o precizie de 8 biți
suficientă, atunci se poate citi/utiliza doar ADCH.
• Altcumva, trebuie citit mai întâi ADCL, urmat obligatoriu de
ADCH, pentru a garanta apartenența la aceeași conversie a
conținutului registrelor de date.
– Odată ce ADCL este citit, actualizarea registrelor de date este blocată
până la citirea lui ADCH.
– Aceasta înseamnă că dacă ADCL a fost citit, și o altă conversie s-a
încheiat înainte ca ADCH să fie citit, registrele nu sunt actualizate și
rezultatul conversiei este pierdut.
• Sistemul de conversie analog-numeric este integrat cu sistemul de
întreruperi AVR, tipic finalizarea unei conversii putând declanșa o
cerere de întrerupere.
– Rezultatul conversiei poate fi citit/salvat in rutina de tratare a întreruperii
24
Registrele de date ADCH si ADCL

Aliniere la dreapta (cea implicită, după reset )


MSB

MSB Aliniere la stânga

MSb=ADC9, cel mai semnificativ bit al rezultatului 25


Declanșarea unei operații de conversie
• O conversie singulară este una declanșată “manual” scriind un “1”
logic în bitul de start al conversiei ADSC (Analog to Digital Start
Conversion) din registrul ADCSRA.
– Acest bit se va menține în “1” logic atât timp cât conversia este în curs
de desfășurare și va fi șters hard când conversia este completă.
– Dacă un alt canal de intrare este selectat în timpul conversiei, se va
aștepta finalizarea conversiei curente înainte de a se schimba/comuta
efectiv canalul.
• Starea aceluiași bit ADSC poate să fie folosită pentru a
determina dacă o conversie este în curs de desfășurare.
– El va fi citit în “1” pe durata unei conversii, indiferent de modul de
declanșare a conversiei si va deveni “0” la finalizarea conversiei
– Astfel el poate fi interogat/testat într-o bucla de așteptare
• “Sursa” după care se va face declanșarea conversiei in mod
“automat” poate fi selectată prin intermediul câmpului de biți ADTSi;
i=0,1,2 din registrul SFIOR.

26
Registrul ADCSRA
O conversie poate fi declanșată si în mod
„automat”, în mai multe moduri (folosind
una din mai multe surse potențiale de
declanșare).
Declanșarea automată este activată
setând bitul ADATE în ADCSRA

Pentru a putea utiliza sistemul de conversie


analog-numeric, în ansamblul său, acesta
trebuie activat prin setarea bitului ADEN =1
(Analog to Digital conversion ENable) din
ADCSRA. Implicit după reset acest bit este șters.

Sistemul CAN are un consum nesemnificativ


atunci când ADEN este şters, lucru de care
trebuie ținut seama când se intră în unul din
modurile “Sleep” (ADEN trebuie să fie șters când 27
dorim sa intram intr-un astfel de mod).
Declanșarea/pornirea unei operații de conversie
• La apariția unui front crescător al semnalului ales de declanșare,
divizorul de frecvență (prescaler) care generează semnalul de ceas
pentru convertor va fi resetat (pentru sincronizare) și conversia este
pornită.
• Aceasta reprezintă o metodă de a realiza o conversie repetată, la
intervale fixe de timp sau, cu alte cuvinte, de a periodiza conversia.
– Dacă un nou front crescător apare în timpul conversiei, el va fi ignorat.
• Bitul ADIF din registrul ADCSRA va fi setat în momentul finalizării
conversiei şi al actualizării registrelor de date.
• Deşi el este destinat generării unei cereri de întrerupere (el este un
IF – Interrupt Flag) el va fi setat chiar dacă respectiva întrerupere
este dezactivată sau bitul global de întrerupere I din SREG este
șters.
– O conversie poate astfel să fie declanșată/finalizată fără să producă și o
întrerupere, bitul respectiv fiind folosit eventual printr-o interogare in
bucla.

28
Declanșarea unei operații de conversie -2

• Modificarea stării bitului ADIF poate fi folosită ca sursă de


declanșare, determinând convertorul să pornească o nouă
conversie, de îndată ce conversia în curs de desfășurare a luat
sfârșit.
• Astfel convertorul funcționează în modul numit “Free Running”
(achiziție liberă, cu auto-declansare, automată), eșantionând
intrarea analogica și actualizând în mod constant registrele de date,
cu o viteză dictată practic de timpul de conversie și de cel de
preluare a datelor de utilizator.
• Prima conversie trebuie să fie declanșată de utilizator scriind
un “1” logic în bitul ADSC din ADCSRA.
• În acest mod se vor face conversii succesive indiferent dacă bitul
ADIF este sau nu șters de utilizator.
• Chiar dacă auto-declanşarea este activată, conversiile singulare pot
fi declanșate prin setarea bitului ADSC.

29
Controlul vitezei de conversie (a timpului de
conversie)
• Timpul de conversie poate fi controlat/programat, in anumite
limite, de utilizator
• Durata unei operații de conversie, timpul de conversie - care este
invers proporțional cu viteza de conversie - depinde de un factor de
divizare programat și de frecvența oscilatorului de ceas sistem
(CK) care este semnalul de ceas pentru acest divizor
• Astfel, sursa de ceas pentru convertorul analog-numeric este un divizor
programabil de frecvență (prescaler) de 7 biți, având ca semnal de ceas
ceasul unității centrale CK=fCPU.
• Factorul de divizare (de 2, 4, 8, 8, 16, 32, 64 şi 128) poate fi programat
de utilizator prin intermediul câmpului de biți ADPS din registrul
ADCSRA (figura); atenție, factorii disponibili pot fi diferiți funcție de
varianta de AVR
• Divizorul de frecvență va începe să funcționeze din momentul activării
sistemului CAN, prin setarea bitului ADEN din ADCSRA.

30
Registrul ADCSRA: factorul de
(pre)divizare

Funcție de starea programată pentru acești biți ADPSi; i=0,1,2


se stabilește viteza de conversie (timpul de conversie): ei
controlează un factor de divizare programabil al ceasului
sistem

31
AVR 8 biți: cât durează de fapt o operație de
conversie analog- numerică?
• La fel ca si pentru alte sisteme de conversie –analog numerica de la
alte familii de microcontrolere, durata unei astfel de operații se
exprima intr-un număr de perioade ale ceasului CAN
• Convertorul analog-numeric AVR 8 biti asigură rezoluția maximă
adevărată de 10 biţi pentru frecvente ale ceasului CAN între 50 KHz
şi 200 KHz.
• Dacă este necesară o frecvență de eșantionare mai mare, cu o
rezoluție adevărată mai mică de 10 biţi (cu o precizie mai mică),
frecvența ceasului poate fi și mai mare de 200 KHz.
• Atunci când se lansează o conversie singulară, setând bitul ADSC în
ADCSRA, conversia va începe pe următorul front crescător al
ceasului CAN.
• O conversie obișnuită durează in total un număr de 13 cicluri
(perioade) de ceas CAN.
• Prima conversie după activarea CAN-ului (realizata dupa ce a fost
setat ADEN în ADCSRA) durează însă 25 cicluri de ceas CAN, cicluri
necesare şi pentru inițializarea circuitului analogic.
• Eșantionarea şi memorarea propriu-zisă durează 1.5 cicluri de ceas
CAN după pornirea unei conversii, dar durează 13.5 cicluri CAN după
pornirea primei conversii.
32
AVR 8 biți: cât durează de fapt o operație
de conversie analog- numerică? -2
• Când este folosită auto-declanşarea (free running), divizorul de frecvenţă va
fi şi resetat în momentul declanşării.
• Aceasta asigură o întârziere fixă din momentul declanşării până la pornirea
conversiei.
• În acest mod, eşantionarea şi memorarea durează 2 cicluri de ceas CAN,
după frontul crescător declanşator.
• Trei cicluri suplimentare de ceas CPU sunt folosite pentru logica de
sincronizare.
• Când se foloseşte modul de intrare diferenţial împreună cu auto-
declanşarea de la o altă sursă decât finalizarea conversiei curente, fiecare
conversie va necesita 25 cicluri (perioade) de ceas CAN.
• Aceasta datorită faptului că, după fiecare conversie, CAN-ul trebuie să fie
dezactivat şi apoi reactivat.
– O evaluare a timpului de conversie, exprimat in perioade ale sistemului de ceas
CAN, este dată în tabelul din slide-ul următor
• Practic, timpul de conversie, pentru o frecvenţa de ceas sistem de 8
MHz, poate fi de la ordinul x 10 μsec până la ordinul x100 sau x1000
μsec

33
AVR 8 biți: valori ale timpului de conversie
funcție de perioada ceasului CAN
Timpul total de
Timpul de eşantionare şi conversie
urmărire (Cicluri / perioade (Cicluri /
Condiţia
ale ceasului de la începutul perioade ale
conversiei) ceasului
CAN)

Prima conversie 14.5 25

Conversii normale,
1.5 13
mod asimetric
Conversii auto-
2 13.5
declanşate

Conversii normale,
1.5/2.5 13/14
mod diferenţial
34
Exemplu conversie singulară, prima
conversie

35
Exemplu conversie singulară, conversie
normală (următoarele conversii)

36
Exemplu conversie automată (auto-
declanşată)

37
AVR 8 biți: conversia analog-numerica,
modul de intrare diferențial
• Există anumite aspecte ale conversiei analog numerice care trebuie
să fie luate în considerație atunci când se folosesc canalele de
intrare în mod diferențial (se realizează conversii diferențiale).
• Conversiile diferențiale sunt sincronizate cu un ceas intern CKADC2
egal cu jumătate din ceasul CAN.
– Această sincronizare se face în mod automat astfel încât eșantionarea
şi memorarea să aibă loc într-o fază specifică a lui CKADC2.
• O conversie inițiată de utilizator (toate conversiile singulare şi prima
conversie în modul “ Free Running”) atunci când CKADC2 este “0”
va dura aceeași perioadă de timp ca şi o conversie in mod asimetric
(13 cicluri de ceas CAN).
• O conversie iniţiată de utilizator când CKADC2 este “1” va dura 14
cicluri de ceas CAN datorită mecanismului de sincronizare.
• În modul “Free Running”, o nouă conversie este inițiată îndată ce
conversia anterioară este completă, şi deoarece CKADC2 este “1”
logic în acest moment, toată conversiile pornite automat în modul
“Free Running” (mai puțin prima) vor dura 14 cicluri de ceas CAN.
38
AVR 8 biți: conversia analog-numerica,
modul de intrare diferențial -2
• Etajul de amplificare programabilă care poate fi utilizat numai în
modul diferențial este optimizat pentru o lărgime de bandă
(bandwidth) de 4 KHz, pentru amplificările posibile.
– Frecvențele mai mari pot fi afectate de o amplificare neliniară.
– Este recomandată o filtrare trece-jos externă, dacă semnalul de
intrare conține componente de frecvență mai mare decât lărgimea de
bandă.
– Nu există însă nici o legătură între frecvența de ceas CAN şi lărgimea
de bandă, putându-se realiza şi folosi rate de eșantionare mult mai mari
decât cele care ar rezulta din corelarea cu lărgimea de bandă.
• Dacă este utilizat modul de intrare diferențial şi conversiile sunt
pornite în mod automat, convertorul trebuie să fie oprit între
conversii.
• Când este folosită auto-declanşarea, divizorul de frecvenţă este
resetat înainte de pornirea conversiei.
• Astfel, deoarece câștigul este dependent de un ceas CAN stabil pe
perioada anterioară conversiei, această conversie nu va fi validă.
• Dezactivând şi apoi reactivând CAN–ul între conversii (scriind
în ADEN din ADCSRA “0” şi apoi “1”) se vor executa doar
conversii extinse, dar al căror rezultat va fi întotdeauna valid. 39
Comutarea canalelor de intrare sau a sursei
de referință

• Pentru comutarea (selectarea) canalului de intrare pe


care se va realiza conversia si/sau a referinței cu care se
va realiza conversia se utilizează câmpurile de biți
MUXi; i=0,1,2.. şi REFSi; i=0,1 din registrul ADMUX,
care sunt de fapt memorate într-un registru temporar, din
care sunt preluate la realizarea efectiva a conversiei.
– Aceasta garantează că selectarea referinței sau a canalului se
vor face numai în momente de timp sigure în timpul conversiei.
• Selectarea referinței şi canalului se poate face
oricând o conversie nu este pornită (nu este in curs
de desfășurare)!
– Odată conversia pornită, selectarea referinței şi canalului este
blocată pentru a se garanta un timp de eșantionare suficient.
• Este recomandat să nu se încerce selectarea unui nou
canal sau a unei noi referințe imediat după ce bitul
ADSC este setat, așteptându-se finalizarea conversiei. 40
Comutarea canalelor de intrare si/sau a
sursei de referință -2
• Dacă este folosită auto-declanşarea, momentul exact al declanșării nu este
precis determinat.
– Este necesară o atenție specială la actualizarea registrului ADMUX, pentru a
controla și a ști ce conversie va fi afectată de noile configurări.
• Dacă atât bitul ADATE cât şi bitul ADEN sunt în “1”, setarea bitului ADIF
poate avea loc în orice moment.
• Dacă registrul ADMUX este actualizat în această perioadă, utilizatorul nu va
putea discerne dacă conversia următoare este bazată pe vechea sau pe
noua configurare a intrării si a referinței (de pe care canal provine valoarea
si cu ce referință s-a făcut conversia).
• ADMUX poate fi actualizat într-un mod sigur astfel:
– Atunci când bitul ADATE sau bitul ADEN este șters.
– In timpul conversiei, după minim un ciclu de ceas CAN de la momentul
declanșării.
– După terminarea unei conversii, înaintea de ștergerea bitului ADIF folosit ca
sursă de declanșare.
• La actualizarea lui ADMUX în aceste condiții, noile configurări vor afecta
următoarea conversie.

41
Comutarea canalelor de intrare si/sau a
sursei de referință: modul diferențial -3
• Comutarea canalelor, în modul de intrare diferențial, pune şi ea niște
probleme mai deosebite.
• Din momentul comutării canalelor (al actualizării registrului ADMUX)
durează aproximativ 125 µs până ce câștigul programat se va
stabiliza la noua valoare.
• Astfel conversiile ar trebui să fie pornite la cel puțin după 125 µsec
de la realizarea noii selecții sau rezultatele conversiei pe această
perioadă nu trebuie luate în considerare.
• Același timp de stabilizare este necesar şi pentru prima conversie
diferențială realizată după comutarea referinței CAN (după
actualizarea câmpului REFS1:0 din ADMUX).
• Când se trece de la un mod de intrare asimetric la un mod
diferențial, rezultatul primei conversii este, în general de precizie
mult scăzută datorită timpului de stabilizare necesar pentru circuitul
de anulare automată a offset-ului (decalajului la intrare).
– Practic, valoarea rezultată nu trebuie luată în considerare.

42
Comutarea canalelor de intrare si/sau a
sursei de referință: recomandări generale - 4
• În concluzie există câteva recomandări care trebuie urmate pentru
a ne asigura ca selecţia canalului de intrare s-a făcut corect
• În modul conversie singulară (Single Conversion):
– întotdeauna se selectează canalul înainte de a porni conversia.
– selectarea canalului poate fi modificată după un ciclu de ceas CAN, din
momentul setării bitului ADSC.
– metoda cea mai simplă este să se aştepte terminarea conversiei
pentru a comuta canalul.
• În modul achiziţie liberă (Free Running):
– întotdeauna se selectează canalul înainte de a porni prima conversie.
– La fel ca la modul anterior selectarea canalului poate fi schimbată după
un ciclu de ceas CAN, din momentul setării lui ADSC şi cel mai simplu
este să se aştepte terminarea conversiei pentru a comuta canalul.
– Deoarece conversia următoare a pornit deja în mod automat, următorul
rezultat reflectă selecţia anterioară a canalului.
– Doar următoarele conversii vor reflecta selectarea noului canal de
intrare.

43
Sursa de tensiune de referinţă pentru
convertorul analogic-numeric
• Tensiunea de referință VREF este cea care practic stabilește
domeniul de conversie (domeniul mărimii de intrare pentru un canal
analogic) pentru CAN.
• Referința este selectată cu ajutorul biților REFS1 si REFS0 din
registrul ADMUX
• Dacă tensiunea de intrare (în modul mod asimetric) depășește
VREF, în urma conversiei vor rezulta coduri egale cu valoarea
0x3FF (valoarea maximă exprimabilă pe 10 biţi).
• Tensiunea de referință VREF poate fi selectată astfel:
– fie ca provenind de la pinul AVCC (alimentarea analogică),
– fie de la pinul extern dedicat AREF,
– fie de la o sursă de referinţă internă de 2.56V (la ATMega 16)

44
Sursa de tensiune de referință pentru
convertorul analogic-numeric -2
• Tensiunea de referință internă de 2.56V este oferită de o sursă de referință
cu bandă interzisă – band gap (VBG), printr-un amplificator intern de
separare (buffer).
• Atenție, pentru alte variante AVR sursa de referință internă poate avea
alte valori (de ex. pt. ATMega 169 sursa de referință interna este de
1.1V)
• Indiferent de selecția referinței, pinul AREF este direct conectat la intrarea
de referinţă a CAN, şi tensiunea de referință poate fi filtrată (decuplată)
conectând un capacitor între pinul AREF şi masă
• VREF poate, de asemenea, să fie măsurată pe pinul AREF, dar trebuie ținut
cont de faptul că ea este o sursă cu impedanță internă mare acceptând
practic numai o încărcare capacitivă (practic ea nu poate debita curent).
• Dacă utilizatorul folosește o sursă de referinţă externă conectată la AREF,
atunci nu se mai pot utiliza celelalte opțiuni pentru tensiunea de referință,
sursa externă scurtcircuitând variantele interne.
• Dacă însă nu se utilizează o sursă de referință externă, utilizatorul poate
oricând să comute între AVCC şi referința internă.
• Atenție, prima conversie realizată după comutarea referinței poate să dea
un rezultat incorect, astfel că ea nu ar trebui luată in considerare!

45
Schema electrică echivalentă pentru o
intrare analogică
• Schema electrică echivalentă, pentru regim static si regim dinamic,
pentru o intrare analogică (intrare asimetrică) este prezentată în
figura de mai jos.
• O sursă de tensiune aplicată la intrarea ADCn este implicit
încărcată (are ca sarcină) cu capacitatea şi rezistența acelui pin
către masă, indiferent dacă acel canal este selectat/utilizat sau
nu ca intrare pentru convertor.
• Când canalul este selectat, sursa mai trebuie să comande (sa
încarce si sa descarce) in plus şi capacitorul circuitului de
eșantionare/memorare (S/H) printr-o rezistență serie (rezistența
combinată din calea de intrare).

46
Schema electrică echivalentă pentru o intrare
analogică -2
• Circuitul de intrare al CAN–ului este optimizat pentru semnalele
analogice generate de surse de tensiune echivalente cu o
impedanță de ieșire mai mică de 10 KΩ, în sensul că, dacă este
folosită o astfel de sursă, contribuția impedanței sursei la timpul
necesar pentru eșantionare va fi neglijabilă.
• În practică daca avem surse cu o impedanță mică şi semnale cu
o variație lentă, nu mai trebuie să evaluăm în nici un fel contribuția
circuitului de eșantionare-memorare (S/H).
• Dacă este utilizată varianta de intrare diferențială, schema electrică
echivalentă de intrare este oarecum diferită, condițiile impuse
impedanței sursei de intrare fiind ceva mai relaxate ( < 100 KΩ ).
• Principial, în spectrul semnalului de intrare nu trebuie să apară
componente cu frecvența mai mare decât frecvența Nyquist
(fADC/2) pentru orice tip de canal, pentru a evita apariția unor
conversii cu rezultate imprevizibile.
• Eventualele componente de înaltă frecvență trebuie eliminate de
utilizator printr-o filtrare externă de tip trece-jos (FTJ)
corespunzătoare, înainte de aplicarea semnalelor la intrările
analogice.
47
Tehnici de reducere a zgomotului analogic

• La fel ca la orice sistem de mod mixt, componentele numerice


interne şi/sau externe generează un zgomot de comutaţie
(zgomot numeric, digital noise) care poate influenţa consistent
precizia măsurărilor analogice.
• Dacă precizia de conversie este critică, nivelul de zgomot poate fi
redus aplicând una sau mai multe din următoarele tehnici:
– Căile externe de semnal analogic trebuie să fie cât mai scurte, iar
circuitele de semnal analogic plasate cât departe de circuitele numerice
care comută rapid.
– Pinul de alimentare analogică AVCC ar trebui să fie conectat la
tensiunea de alimentare numerică VCC printr-un filtru LC ca în figura .
– Folosirea funcției de reducere a zgomotului numeric (ADC Noise
Reduction) specifică convertorului CAN AVR 8 biti
– În cazul în care există pini din portul de intrări analogice care sunt
folosiți ca ieșiri numerice, este esențial ca aceștia să nu comute pe
durata unei conversii.

48
Tehnici de reducere a zgomotului analogic-
decuplarea alimentarii AVcc

ATMega169
ATMega32 49
Caracteristica statică de transfer şi
rezultatul unei conversii analog-numerice
• După finalizarea unei operații de conversie (bitul ADIF este “1”),
rezultatul conversiei poate fi găsit în registrele pentru rezultat/date ale
CAN–ului: ADCL și ADCH.
• Pentru o conversie unipolară (asimetrică) pe 10 biți, rezultatul,
exprimat in cod binar natural, va avea valoarea zecimală, numită aici
generic ADC:
VIN ⋅1024
ADC =
VREF
– unde VIN este tensiunea pe pinul de intrare selectat şi VREF
tensiunea de referință selectată.
– rezultatul ADC este o mărime fără semn, exprimată in cod binar
natural, valorile extreme (în hex) exprimate pe 10 biţi fiind:
• minim 0x000 (0), pentru o tensiune de intrare VIN egala cu masa
analogică
• maxim 0x3FF+1 (1023+1), pentru o tensiune de intrare VIN egala cu
tensiunea de referință selectată VREF.

Dacă avem o conversie pe 8 biți, in care se folosește doar


valoarea din ADCH, in relația de mai sus vom avea 256 in loc de
1024. 50
Caracteristica statică de transfer și
rezultatul conversiei - 2
• Pentru o conversie diferențială, pe 10 biți, rezultatul, in
zecimal, va fi de forma:

ADC =
(VPOS − VNEG ) ⋅ GAIN ⋅ 512
VREF
• Unde:
– VPOS este tensiunea (fața de masă) pe pinul de intrare pozitivă (intrarea aleasa
ca neinversoare Vin+),
– VNEG este tensiunea pe pinul de intrare negativă (intrarea aleasa ca inversoare
Vin-),
– GAIN este factorul de câștig selectat pentru amplificatorul programabil (daca
acesta nu exista GAIN=1) şi
– VREF este tensiunea sursei de referință selectată.
• Rezultatul in acest caz este o mărime cu semn, exprimată în cod
binar complement față de doi, pe 10 biți, având valori de la
minimul negativ 0x200 (-512) până la maximul pozitiv 0x1FF
(+511).
– Dacă utilizatorul vrea să execute doar o verificare rapidă de polaritate, este
suficientă citirea doar a MSB-ului (bitul ADC9 din ADCH) care în acest caz este
bitul de semn. 51
Caracteristica statică de transfer şi
rezultatul conversiei - 3

Caracteristica statică de transfer a


convertorului, utilizat în modul cu
intrare diferenţială.

52
Caracteristica statică de transfer şi
rezultatul conversiei -4
• În tabelul următor sunt prezentate codurile de ieșire
rezultate dacă este selectată perechea de intrare
diferențială (ADCn – ADCm), cu un câștig GAIN şi o
tensiune de referință VREF.
• Un exemplu de calcul bazat pe această caracteristică
este prezentat în continuare:
– Registrul ADMUX = 0xED (adică intrare ADC3 - ADC2, câștig
x10, referință internă 2.56V, rezultat aliniat la stânga)
– Tensiunea pe ADC3 este de 300 mV, iar tensiunea pe ADC2 de
500 mV.
– ADC = 512 * 10 * (300 - 500) / 2560 = - 40010 = 0x270 in cod
binar complement fata de 2 !
– Dacă avem un “0” scris în bitul ADLAR rezultatul va fi aliniat la
dreapta cu: ADCL = 0x70, ADCH = 0x02.
– Dacă avem un “1” scris în bitul ADLAR rezultatul va fi aliniat la
stânga cu: ADCL = 0x00 şi ADCH = 0x9C.

53
Caracteristica statică de transfer și
rezultatul conversiei -5
Valoarea zecimală
VADCn Codul citit
corespunzătoare
VADCm + VREF/GAIN 0x1FF 511
VADCm + 0.999 VREF/GAIN 0x1FF 511
VADCm + 0.998 VREF/GAIN 0x1FE 510
… … …
VADCm + 0.001 VREF/GAIN 0x001 1
VADCm 0x000 0
VADCm – 0.001 VREF/GAIN 0x3FF -1
… … …
VADCm – 0.999VREF/GAIN 0x201 -511
VADCm – VREF/GAIN 0x200 -512
54
Sistemul de conversie analog numeric
– seriile Tiny si Mega modernizate

In foile de catalog ale variantelor modernizate apare o nouă schemă bloc care
ilustrează si funcționalitățile disponibile- practic aceleași ca la variantele clasice,
dar si unele noi gen măsurarea locală a temperaturii si compararea rezultatului
conversiei cu o fereastră de valori (din registrele duble WINLT si WINHT, cu
ieșirea WCOMP), posibilitatea de a acumula (ACC) pană la 64 de eșantioane
intr-un singur rezultat.
Nu mai există mod de intrare diferențial, intrările pot fi doar asimetrice.
Există acum 17 registre de comandă, stare si date asociate sistemului.
Denumirile registrelor s-au modificat (de exemplu registrele de date sunt acum
55
registrul dublu RES), deci obligatoriu trebuie consultată foaia de catalog.
AVR 8 biti: exemplu de programare al
convertorului analog-numeric, mod polling
int ADC_temp=0;/* pt. memorarea rezultatului, exprimat pe
16 biti */
/* Selectam canalul de intrare ADC0, referinta interna,
rezultat aliniat la dreapta */
ADMUX =0xC0 ;
// Activare ADC
// ADC Prescaler la fosc= 1MHz / 8 = 125kHz
// Declansare automata
// Dupa Reset bitii ADTSi din SFIOR sunt in 0, deci suntem
// si in modul Free Running
ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0 | (1<<ADATE);
//lansare conversie
ADCSRA |= (1<<ADSC);
//asteapta finalizare conversie, bitul ADIF =1?
while(!(ADCSRA & 0x10));
/*in ADC_temp se va reconstrui valoarea pe 10 biti */
ADC_temp = ADCL; /* citeste primul pe ADCL!!!! */
ADC_temp += (ADCH << 8); /* citeste, deplaseaza si aduna 56
si pe ADCH */
O schemă, doar pentru secțiunea
analogică..
ATMega16
+3.3V
Rt1 Rt2

R1 R2
+3.3V

Rt1 si Rt2 sunt doi senzori rezistivi care


formează divizoare rezistive cu rezistentele
fixe R1 si R2.
Tensiunea de alimentare de 3.3V este folosita
ca tensiune de referință si pentru alimentarea
divizoarelor.
Rezistenta interna a sursei de tensiune
echivalente este Rt1//R1 si Rt2//R2.
Din păcate nu pentru toți senzorii rezistivi57
interfața de adaptare este atât de simpla!
Si un alt exemplu, mai multe
canale, conversie singulară
O funcţie generică de iniţializare:

void adc_init()
{
// Referinta va fi una externa, cea preluata de pe pinul
// AVcc, adica AREF = AVcc
ADMUX = (1<<REFS0);
// Activare CAN si alegem divizorul (prescaler) 8
// daca avem un ceas sistem de 8 MHz
// f ceas CAN = 8 000 000 / 8 = 1 000 000 Hz = 1 MHz
// adica T ceas CAN = 1 usec
//adica o conversie obisnuita va dura 13 x 1 usec = 13 usec
// doar prima conversie va dura 25 x 1 usec = 25 usec
ADCSRA=(1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);
//avem conversie singulara (neautomata), pt. ca ADATE a ramas
in ‘0’
//de asemenea rezultatul este aliniat la dreapta, ADLAR a ramas
in ‘0’ 58
}
Un alt exemplu, citirea rezultatului, mod
polling
O funcție generică de citire a rezultatului (returnat ca un întreg fără semn pe 16 biţi) de pe
un canal specificat ca argument (întreg fără semn pe 8 biţi):

uint16_t adc_read(uint8_t ch)


{
uint16_t ADC;
// selecteaza un canal intre 0 si 7
// AND ch cu '7' ne asigura ca valoarea efectiv utilizata
// va fi intotdeauna ceva intre 0 si 7
ch &= 0b00000111;
// selectam canalul, ceilati biti nu vor fi afectati
ADMUX |= ch;
// start conversie singulara, scrie un '1' in ADSC
ADCSRA |= (1<<ADSC);
// asteapta finalizare conversie
// atunci cand ADSC devine '0' din nou
// pana atunci asteapta in bucla
while(ADCSRA & (1<<ADSC));
ADC = ADCL; // citeste primul pe ADCL!!!!
ADC += (ADCH << 8);
return (ADC);
} 59
Un alt exemplu, programul principal…
Si un program principal in care citim si prelucrăm două canale, ADC0 si ADC1:

#include <avr/io.h>

void adc_init();
uint16_t adc_read(uint8_t ch);

int main()
{
uint16_t adc_result0, adc_result1;
// initializare CAN
adc_init();
//o bucla fara sfarsit
while(1) {
adc_result0 = adc_read(0); // citim valoarea canal ADC0
adc_result1 = adc_read(1); // citim valoarea canal ADC1
// in continuare prelucram cele 2 rezultate
// eventual le “afisam”, etc.
…………….
} Intr-una din prezentările viitoare va apărea si
} un exemplu in care se utilizează întreruperea aferentă CAN 60
Exemplu de utilizare a convertorului analog-numeric
(CAN) si a întreruperii aferente lui : schema (se
utilizează oscilatorul de ceas RC intern)..
ATMega16
5V
Rt1

R1
5V

Rt1 este un senzor rezistiv de


luminozitate (o fotorezistenţă)
LED1
LED2

Atâta timp cât iluminarea este sub o anumită


limită LED1 este aprins si LED2 stins 61
Când se depăşeşte această limită, LED-urile isi schimbă starea
Întreruperi: exemplu de utilizare convertor
analog-numeric (CAN)
#include <avr/io.h>
#include <avr/interrupt.h>
/*cele doua LED-uri sunt conectate LED1 = PC6 si LED2= PC7
catre masa, astfel ca se aprind cu pinul in ‘1’*/
/* Rutina de tratare a intreruperii CAN, conversie
finalizata: indicator ADIF=1 */
ISR(ADC_vect)
{
/*totul se intampla in rutina de tratare*/
if(ADCH < 128) /* testare daca tensiunea de intrare este
mai mica de jumatate din AVCC*/
{
PORTC |= (1 << PORTC6 ); /* Aprinde LED1 */
PORTC &= ~(1 << PORTC7 ); /* Stinge LED2 */
}
/*daca nu */
else
{
PORTC &= ~(1 << PORTC6); /* Stinge LED1 */
PORTC |= (1 << PORTC7); /* Aprinde LED2*/
} 62
}
Întreruperi: exemplu de utilizare convertor
analog-numeric (CAN)
int main (void)
{
/* LED1 = PC6 iesire, LED2 = PC7 iesire */
DDRC |= ((1 << DDC6) | (1 << DDC7) );
/* Factor divizare ceas CAN =128, frecventa de esantionare va
fi de 31.25 KHz la un fosc = 4 MHz */
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
ADMUX |= (1 << REFS0); /* Referinta CAN este AVCC */
ADMUX |= (1 << ADLAR); /* Ajusteaza rezultatul la stanga, nu
se va citi decat un octet ADCH */
/* Nu sunt necesare valori pentru MUX, conversia se face
numai dupa canalul ADC0 */
ADCSRA |= (1 << ADATE); /* Modul achizitie libera Free-
Running */
ADCSRA |= (1 << ADEN); /* Activare CAN */
ADCSRA |= (1 << ADIE);
/* Activare intrerupere CAN */
sei(); /* Activarea globala a intreruperilor */
ADCSRA |= (1 << ADSC); /* Porneste conversiile AN */

for(;;) /* O bucla infinita, in care nu facem nimic */


{
}
} 63
Microcontrolere (si
microprocesoare)

Microchip AVR 8 biți:


Comunicația serială (generalități)
• RS-232, RS422/485, UART si comunicația serială
asincronă
• SPI, TWI (I2C), USI, comunicația serială sincronă
1
Un exemplu de sistem incorporat (un controler pentru o
“mașină” de vânzare) care, pentru a comunica cu alte
sisteme incorporate utilizează, printre altele, mai multe tipuri
de comunicație serială:
- 3 conexiuni de comunicație punct la punct (RS-232)
- 1 conexiune de comunicație multipunct (RS-485)
Ambele standarde menționate , RS-232 si RS-485, sunt
utilizate in comunicațiile seriale de date, asincrone sau
sincrone.

2
EIA RS-232C(F) – este un standard electric si
mecanic
Electric el specifică niște nivele logice (logic levels), in logică negativă (unde
nivelul de “1” este mai negativ decât cel de “0”).
Mecanic el specifică tipul de conector utilizat si pinii acestora asociați unor semnale.

Așa arată, ca tensiune, o comunicație serială asincronă cu nivele logice RS-232

Nivelul “0” sau L se cheamă


“Space” si este pozitiv ≥ 3V
Regiune nedeterminata,
nu avem un nivel logic RS-232

Nivelul “1” sau H se cheamă


“Mark si este negativ ≤ - 3V

Primul bit de date serializat este cel mai puțin semnificativ (LSB)
Caracterul ASCII (7 biti) emis este ‘A’ adică 0x41 3
RS-232 este un standard cu semnalizare
“asimetrică” (la fel ca la porțile obișnuite), pentru
legături punct la punct
- Ecartul (diferența) mare intre cele doua nivele RS-232 (H si L) asigură
margini mari de zgomot si deci potențial imunitate mare la perturbații
- Exista circuite emițătoare E (drivers, transmitters) RS-232 si receptoare
R (receivers) RS-232
- Exista si circuite care conțin si emițătoare si receptoare (transceivers)
- Si unele si altele sunt circuite inversoare, iar emițătoarele trebuie să aibă
un sistem de surse de alimentare bipolare (V+ si -V) prin raportare fata
de masa circuitului
- Pentru o legătură de date unidirecțională avem nevoie de un emițător si un receptor
- Pentru o legătură de date bidirecțională avem nevoie de 2 emițătoare si 2
receptoare
- Este o legătură punct la punct: putem avea doar o singură ieşire
conectată la o linie de semnal (si una sau mai multe intrări): două ieşiri RS-
232 NU pot fi legate împreună!

4
Cum se folosește RS-232 (conexiunea fizica)
Emițătorul si Receptorul sunt
întotdeauna inversoare, lucru de care
trebuie ținut cont dacă utilizăm o altă
soluție hardware, decât cea a unor circuite
standard (gen MAX232, ca mai jos),
pentru realizarea E(mitătorului) sau
RS-232 R(eceptorului).
E R Cele 2 sisteme conectate trebuie să aibă
TTL o masă comună GND (al 3-lea fir)!
TTL

GND

RS-232
R E
RS-232
TTL TTL

GND TTL/CMOS
5
RS-485 / RS-422 sunt standarde cu semnalizare
“diferențială”, pentru legături punct la punct (RS-422) sau
multipunct (RS-485): sunt standarde electrice, nu si
mecanice
- RS-422 si RS-485 au in comun aceleași nivele logice
diferențiale
-Pentru aceste standarde nu exista si o specificație mecanica
(conector, pini, ca la RS-232)
- Semnalizarea diferențială oferă potențial imunitate mare la
perturbații (la zgomot electromagnetic de mod comun)
- Avem circuite emițătoare (drivers, transmitters) RS-485 (422)
si receptoare (receivers) RS-485 (422) sau, similar RS-232,
transceivere (transceivers)
- Toate au intrări/ieşiri diferențiale si nu necesită un sistem de
surse de alimentare bipolare
-Pentru o legătură de date unidirecțională avem nevoie de un driver si
un receptor (si 2 fire)
-Pentru o legătură de date bidirecțională avem nevoie de 2 drivere 6si
2 receptoare (si 4 fire)
Standardul RS-422/RS-485: nivelele logice
Principial nu este nevoie
Contează tensiunea intre
de o masă comună intre D si R
cele 2 linii de semnal
dar in realitate de cele mai multe
RS-485!
ori ea există sau trebuie să existe TTL
Zgomotul care apare
pe mod comun este
RS-485 rejectat

TTL TTL

Driverele/emițătoarele si
receptoarele au două borne
TTL de ieșire respectiv intrare
borna inversoare: -, B, o
borna neinversoare: +, A, “ ”

VA - VB < -0.2V => "1"


Emitător Receptor VA - VB > 0.2V => "0"
7
0.2V este si marginea de zgomot!
Standardul RS-422/RS-485: nivelele logice -2

Vin+

Vin-

In figura de mai sus este reprezentat potențialul bornelor Vin+ si Vin-


A fost emis si este recepționat octetul 0xD3 (exemplul este din wikipedia).
Formatul cadrului de biți utilizat pentru comunicația asincrona este :
-1 bit de start,
-8 biți de date,
-1 bit de stop
- fără bit de paritate 8
RS-485 / RS-422, cum se realizează
conexiunea fizică
Pereche fire torsadate

Semnalizare diferențială, legătură punct la punct cu 4 fire, bidirecțională, full-duplex

9
Semnalizare diferențială, legătura multipunct cu 2 fire, suport half-duplex
RS-485 se folosește de obicei pentru implementarea unei
rețele (magistrale) half-duplex
•O topologie tipică este prezentată mai jos
•Există mai multe noduri conectate la o singura pereche de fire , fiecare
având asociat un transceiver (S- emițător, R-receptor).
• Tipic, la un moment dat, doar un nod emite (are ieșirea S activată,
“vorbește”) restul doar recepționează(R “ascultă”): este o configurație tipică
Master-Slave, in care un singur nod poate fi Master (single Master)

Fiecare nod poate fi si producător de Resursa comună folosită pentru


date (in emisie) si consumator de date transmiterea de date sunt cele 2 fire:
(la recepție) avem o magistrală serială (serial bus)
10
Standardele RS-232 si RS-
422/485
• Sunt standarde care specifică un nivel/strat fizic (physical
layer) de comunicatia (serială) de datelor
– Specifică nivelele de tensiune (nivelele logice) si eventual
caracteristicile mecanice ale conexiunilor fizice (conector, pini, etc.)
si
– Tipic, dar nu obligatoriu, pentru utilizarea acestor standarde, datele
sunt transferate ca o serie de biți, o înșiruire de nivele logice, care se
modifică in timp
– Ne putem imagina si un protocol paralel de transfer al datelor, in
pachete de biți disponibili simultan nu secvențial, care sa utilizeze
doar nivelele logice RS-232 sau RS-422/485, nu si conexiunea sau
comunicația seriala
• Codificarea datelor si interpretarea lor este realizată de
software cu suportul unui hardware specific

11
Principiul comunicației seriale asincrone
• Este numită asincronă deoarece nu există un semnal de
ceas explicit, ceasul urmând a fi regenerat intern, pe baza unei
temporizări riguroase
• Datele sunt transmise organizate in cadre de biţi (bit frames)
• Fiecare cadru are un bit de start, mai mulți biți de date,
opțional un bit de paritate pară sau impară si unul sau mai mulți
biți de stop
• Linia de emisie este adusă in “1” si/sau “0”, pe durata unor
intervale de timp succesive bine determinate, fiecare din aceste
intervale de timp (numite si timpi de bit) fiind alocat unor anume
biți dintr-un cadru de biți
• Pe baza cunoașterii poziției predeterminate a acestor biți,
receptorul monitorizează aceste date, “asamblând” valorile de
“1” sau “0” detectate in fiecare interval de timp, intr-un
“container” de dimensiuni corespunzătoare (de cele mai multe
ori un octet)
– Receptorul si emițătorul trebuie să utilizeze ceasuri riguros
“identice” ca frecvență pentru avea intervale de timp “identice” le
emisie si recepție si a putea interpreta corect datele recepționate
12
Comunicația serială asincronă- nivele
logice si formatul cadrului de biți
• Nivelul inactiv (idle) al liniei de emisie este “1” (o să-i corespundă un
mark ca nivel RS-232)
• Emiţătorul semnalează începutul unui cadru printr-o tranzitie din “1”
in “0” (o să-i corespundă un space ca nivel RS-232) pe TxD, adică cu
un bit de start (start bit)
• La intervale de timp regulate (date de rata baud/viteza de transmisie)
emiţătorul oferă biţii de date (data bits), începând cu cel mai puţin
semnificativ (LSB)
• Unul sau doi biţi de stop (stop bit) semnalează sfârşitul cadrului
(linia de emisie revine in “1”), procesul putând fi reluat

TxD

Biţii de date sunt serializaţi începând


Nivelele reprezentate sunt cele (LV)TTL, cu cel mai puţin semnificativ bit: LSB, 0
aşa cum se văd ele pe un pin TxD-ul al MCU. in figura alăturată (unde avem 8 biţi de
Ele trebuie translatate in nivele de un emiţător date)
RS-232 si apoi din nou in TTL cu un receptor 13
RS-232, ajungând la RxD-ul MCU2
Circuite/module dedicate pentru realizarea
comunicației seriale asincrone (si sincrone): U(S)ART
• U(S)ART = Universal Synchronous and Asynchronous serial
Receiver and Transmitter
• Utilizate de sistemele de calcul care trebuie sa realizeze si
sarcini de comunicație seriala
• Inițial au existat niște circuite periferice de sine stătătoare (de
exemplu circuitul 16C550(2) care este doar un UART care
există –într-o forma sau alta- intr-un chipset PC)
• Aceste circuite există acum ca un periferic integrat (un sub-
sistem) la majoritatea microcontrolerelor (chiar dacă nu se
numește așa: de exemplu la MCU NXP/Freescale el se
numește SCI - Serial Communication Interface)
• Este un dispozitiv I/O “standard” care realizează o conversie
de date de tip serie-paralel (la recepție) si paralel-serie (la
emisie)
– El asigură serviciile de bază pentru implementarea unui protocol
serial de comunicație asincron si/sau sincron.
• El este un dispozitiv programabil la care se pot programa caracteristici
cum ar fi: viteza de comunicație(rata baud), organizarea cadrului de biţi,
semnalizare/control erori de comunicație
14
AVR 8 biți: sub-sistemul U(S)ART
• UART sau USART este acum un dispozitiv cvasi-standard
de I/O serială pentru microcontrolerele AVR 8 biți
• Colocvial este numit si port serial
• Toate variantele ATMega, XMEGA ca si unele ATTiny au
ca periferic integrat cel puțin un UART
– Semnalele lor de intrare/ieşire, TxD, RxD si eventual XCK sunt
însă compatibile TTL (sau LVTTL)!
– Pentru interfața cu un dispozitiv RS-232 standard (de exemplu
portul serial al unui PC ) este necesară o adaptare/translație
de nivele (LV)TTL <-> RS-232, realizata cu ajutorul unor
circuite externe de interfață specifice (de exemplu MAX-232)

Observație: Variantele XMEGA au si două circuite USART, care


pe lângă modurile I/O bazate pe interogare si întreruperi suportă
si un mod I/O DMA (cu acces direct la memorie, fără intervenția
unității centrale)

15
AVR 8 biți: componentele U(S)ART-ului

Pentru orice circuit U(S)ART există trei componente


esențiale:
• Emițătorul (transmitter)
– Gestionează generarea fluxului serial de biți pentru
fiecare octet care se dorește emis (are ca sarcină
serializarea unui cadru de biti)
• Receptorul (receiver)
– Gestionează recepția fluxului serial de biți si asamblarea
lor intr-un octet (are ca sarcină de-serializarea unui cadru
de biti)
• Generatorul de ceas (clock generator)
– Generează semnalul de ceas pentru modurile de lucru
sincrone si asincrone (are ca sarcină implementarea
dimensiunii timp a transferului serial al cadrului de biți)

16
AVR 8 biți: conexiunile externe ale
U(S)ART
• Un U(S)ART utilizează doi pini (in modul asincron) pentru
emisie -TxD si recepție- RxD sau trei pini când mai există
încă un pin XCK pentru semnalul de ceas pentru modul
sincron.
– Pinii utilizați (si porturile aferente) sunt diferiți funcție de varianta
de AVR
– Pentru un Atmega 16 sau ATtiny 2313 avem TxD = PD1 si
RxD=PD0
– Dar la un ATMega169 avem RxD=PE1 si TxD=PE0 !
• Acești pini ai portului serial nu mai pot fi utilizați ca I/O de
uz general atâta timp cat ei sunt utilizați pentru comunicația
serială (emisia si recepția este activata)
• Implicit, după un Reset, U(S)ART-ul este configurat in mod
asincron cu emisia si recepția inactive (ele trebuie activate
de utilizator)
• Nu vom discuta aici despre comunicația serială sincronă
(comunicație de tip master-slave), in care se utilizează un
semnal de ceas explicit (pinul XCK – eXternal cloCk)
17
AVR 8 biți: conexiunile externe ale U(S)ART-ului,
exemple

ATmega16
18
AVR 8 biti
U(S)ART-
schema bloc
• Cele 3
registre de
stare si
control,
registrele de
date,
registrul de
ceas si
conexiunile
externe
19
AVR 8 biți U(S)ART: generatorul de
ceas
Rata Baud este specificata Circuit pentru crearea
ca un parametru in UBRR semnalului de ceas pentru
emisie si recepție

Semnal Un semnal extern de ceas este utilizat doar pentru


de ceas comunicația sincrona; dispozitivul care este master
va pune semnal de ceas pe XCK, dispozitivul slave va
asculta semnalul de ceas pe XCK

20
AVR 8 biti U(S)ART: emiţătorul

Pentru pornirea emisiei Registru de deplasare


este necesara “plasarea” paralel-serie, către TxD
unui octet in UDR

Un octet poate sta in “coada” in


Ceas UDR (Transmit) in timp ce alt
octet este serializat (este in
registrul de deplasare )
21
AVR 8 biți U(S)ART: receptorul
Registru de deplasare
Citire octet din UDR când serie-paralel, de la RxD
receptorul indică că este gata

Pana la doi octeţi pot sta “in coadă”


aşteptând să fie citiţi, in timp ce un al
Ceas
treilea este deserializat

22
AVR 8 biti UART : recepția asincronă a
datelor
• Deoarece nu există un semnal explicit de ceas UART-ul trebuie sa includă
subsisteme de refacere a semnalului de ceas (clock recovery) si
reconstruire a datelor (data recovery) pentru a putea realiza recepția
asincronă a datelor seriale.
• Receptorul UART este mai complicat decât emiţătorul!
• Circuitul de refacere a ceasului (clock recovery) este utilizat pentru
sincronizarea ceasului generat intern cu cadrele de biti asincrone care sosesc
pe pinul RxD.
• Circuitul de reconstruire a datelor eșantionează si filtrează trece jos fiecare bit
care sosește, îmbunătățind astfel imunitatea la zgomot a receptorului
• Domeniul de incertitudine in care este posibilă recepția asincronă a datelor
depinde precizia semnalului de ceas generat intern, de rata baud utilizată, de
dimensiunea cadrului ca număr de biți si de cât de des sosesc cadrele de biți
• Există cerințe stricte legate de egalitatea celor frecvențelor de ceas
utilizate la emisie si la recepție, precum si de stabilitatea lor (timp,
temperatura): cerințele sunt cu atât mai stricte cu cat viteza de
comunicație este mai mare 23
AVR 8 biti UART: recepția asincronă a
datelor -2
• Circuitul de refacere a ceasului sincronizează ceasul intern cu
cadrele de biți recepționate serial.
• In figura următoare este ilustrat procesul de eșantionare si
identificare a bitului de start al unui cadru de biți ce va fi
recepționat.
• Există de fapt o mașină secvențială care testează starea intrării si ia decizii
• Rata de eșantionare este de 16 ori rata baud pentru modul “normal” (U2X=0) si
de 8 ori rata baud pentru modul “viteza dublă” (U2X=1).
• “Viteza dublă” duce la dublarea ratei baud, prin reducerea numărului de
eșantioane testate per bit; de exemplu dacă pentru UBRR=23 avem o rată baud
de 9600 Bds cu U2X=0, la același UBRR, dar cu U2X=1 vom avea 19200 Bds

24
AVR 8 biți U(S)ART: registrele de stare
si control
• Pentru majoritatea variantelor de AVR există trei
registre de stare si control a căror denumire
poate fi eventual ușor diferită (a se consulta foaia
de catalog):
– Registrul UCSRA – USART Control and Status
Register A
• Conține in majoritate biți de stare, dar exista si doi biți
control
– Registrul UCSRB – USART Control and Status
Register B
• Conține in majoritate biti de control, dar exista si doi biţi de
date
– Registrul UCSRC – USART Control and Status
Register C
• Conține numai biţi de control

25
AVR 8 biți U(S)ART: seriile Tiny si Mega
modernizate

In foile de catalog ale variantelor modernizate apare o nouă schemă bloc care ilustrează
funcționalitățile disponibile - aceleași ca la variantele clasice.
Exista însă si unele noi cum ar fi:
- suport pentru comutarea sensului la RS-485 half duplex (pin XDIR)
- implementarea unui slave LIN bus (suport pentru un cadru de biti Break)
- implementare unui mod de comunicare in infrarosu (IRCOM- InfraRed COmmunication Mode )
compatibil IrDA1.4
- integrarea cu Event System
Există acum 15 registre de comandă, stare si date asociate sistemului.
26
Denumirile unora din registre s-au modificat, deci obligatoriu trebuie consultată foaia de catalog.
AVR 8 biți U(S)ART: structura
registrelor de stare si control

27
AVR 8 biți U(S)ART: registrul de date UDR
• Din punct de vedere al utilizatorului/
programatorului există un singur registru de
date, de 8 biti (dar fizic există două registre
buffer separate RXB si TXB) :
• Registrul UDR – USART Data Register
– Daca este accesat in scriere avem emisie: UDR=
data;
– Daca este accesat in citire avem eventual
recepție: data =UDR;

28
AVR 8 biti U(S)ART: iniţializarea
UART-ului
• Etapele utilizării unui UART sunt cel puțin următoarele:
– Se stabilește (se programează) rata baud dorită, funcție de
frecventa ceasului sistem utilizat
– Se stabilește formatul cadrului de biţi serial
– Se activează recepția si/sau emisia, eventual se activează si
întreruperile aferente
– Apoi se poate realiza emisia si recepția de octeți (“caractere”)
• Operațiile de emisie si recepție propriu-zise pot fi bazate
pe:
– interogarea (polling) unor indicatoare (biți de stare) din
registrele de stare ale UART-ului (într-o buclă de așteptare)
așteptând schimbarea stării lor sau
– utilizarea sistemul de întreruperi si a întreruperilor generate
de schimbarea de stare a acestor indicatoare
– Utilizarea DMA, numai la XMEGA
• ATENTIE: aceiași “inițializare” trebuie realizată si la
partenerul de “conversație” al USART-ului: trebuie să
avem riguros aceiași rată baud si același format al
cadrului
29
Viteza de comunicație serială asincronă: rata
Baud
• Rata baud reprezintă, exprimat colocvial (provenind dintr-o
traducere ad-literam), viteza cu care sunt transmişi/recepţionaţi biții:
rata Baud, RB: din engleza unde rate = “ceva” /timp , adică viteză
• Este exprimată in biți per secundă (bps) sau Bauds (Bds)
• In acest context si aici 1Baud=1bps, dar in alt context acest lucru
nu este neapărat adevărat
• Există un set de valori de rate Baud standard:
110, 150, 300, 600, 900, 1200, 2400, 4800, 9600, 14400, 19200,
38400, 57800..

Inversul ratei Baud adică intervalul de timp alocat unui bit, cat “durează
bitul”, este timpul de bit (bit time) Tbit=1/RB [sec].
De ex. dacă RB=9600Bd, Tbit=1/9600=104usec
Știind numărul total tuturor biților se poate calcula cat durează in total
emisia si/sau recepția unui caracter 30
AVR 8 biți UART: parametrul rată Baud (viteza
de comunicație)
• Reprezintă valoarea care va fi programată in perechea de
registre UBRR generatorului de ceas, compusa dint un octet
superior (UBRRH) si unul inferior (UBBRL)
• Pentru determinare lui se poate consulta tabela din foaia de
catalog sau se utilizează formula dată in aceiași foaie de catalog
• Valoarea UBRR (parametru rate baud) este un număr in
domeniul de la 0 la 4095
– fosc este frecvența ceasului sistem (oscilatorului de ceas)

– Din tabelele de pe slide-urile următoare (foi de catalog):


• 2400 Baud cu ceas de 4 MHz , prb = 103
• 9600 Baud cu ceas de 1MHz, prb = 6 (nu e însă si bine deoarece
abaterea este foarte mare!)

Frecvența ceasului sistem fosc se alege si din acest considerent!


Acest este si motivul pentru care oscilatorul de ceas este uneori ales având valori
“exotice”, cum ar fi 7.3728 MHz si nu valori “întregi” gen 7 MHz sau 8 MHz
31
( vezi tabel, astfel se pot obține 11 rate baud standard toate cu eroare de 0%)
AVR 8 biți UART: parametrul rata baud, tabele

Dacă eroarea (domeniul de incertitudine) este mai mare de cca. 2% comunicația


32
devine nesigură, crescând mult numărul de erori de comunicație, etc.
AVR 8 biți UART: parametrul rata baud, tabele - 2

Pentru AVR 8 biti ceasul sistem trebuie să fie intr-o variantă stabilizată
cu rezonator cu cuarţ!
Numai aşa sunt îndeplinite cerinţele legate de precizie si stabilitate (temperatura si timp)
pentru frecventa generatorului de ceas al UART-ului 33
Stabilitatea si precizia unui oscilatorul intern sau extern RC sunt insuficiente!
AVR 8 biți UART: exemplu de programare
a ratei Baud (in limbaj de asamblare)

.equ prb = 103; parametru rata Baud


ldi R17, high(brp)
ldi R16, low(brp) Parametrul depinde
out UBRRH, R17 de frecventa ceasului
sistem, de rata baud
out UBRRL, R16 dorita si de starea
bitului U2X
In limbaj de asamblare operatorii high () si low () returnează octetul superior si
respectiv inferior al unei valori presupuse ca exprimata pe 16 biti
In acest caz, in final, in UBRRH se va încărca 0, iar in UBRRL se va încărca 103,
De ce ?
34
AVR 8 biți UART: exemplu de
programare a ratei Baud (in limbaj C )

/*Pt. o rata de 9600 Bauds, cu U2X=0


pt. fosc=4MHz vom avea UBRRR = 25
(sau 51 daca U2X=1) deci UBRRL =25
si UBRRH =0 */
UBRRH = 0;
UBRRL = 25;

35
AVR 8 biți UART: formatul cadrului de biți
serial
• Întotdeauna se începe cu un bit de start (St)
• Urmează 5 până la 9 biți de date, începând cu cel mai puțin
semnificativ (pondere 0)
• Dacă paritatea este activată, un bit de paritate (programabil ca
bit de paritate pară - even sau impară - odd) va fi inserat in
continuare
• Urmează cel puțin un bit de stop (Sp) care este necesar pentru
a finaliza cadrul
– Următorul cadru poate începe imediat după bitul de stop sau linia
poate sta un interval de timp neprecizat in stare inactivă (idle)

Cadru biţi

Inactiv Inactiv sau


următorul
bit de start
Un cadru poate avea minim 7 biţi si maxim 13 biţi
36
AVR 8 biți UART: programarea formatului
cadrului de biți serial
• Programarea se face prin intermediul registrului
UCSRC
– bit 7: URSEL (selectarea registrului, 1=UCSRC )
– bit 6: UMSEL (selectare mod, 0=mod asincron)
– biţi 5:4: UPM1:0 (mod paritate)
• 00 fără paritate, 10 paritate pară, 11 paritate impară
– bit 3: USBS (nr. biți de stop, 0= 1 bit de stop)
– biţi 2:1: UCSZ1:0 (nr. biţi de date, 11 = 8 biţi de data)
• Mai există încă un bit in UCSRB2 (UCSZ2) care este setat la
1 pentru 9-biti de date
– bit 0: UCPOL (polaritate ceas, contează doar pentru
modul sincron)

37
Algoritmul utilizat pentru calculul bitului de
paritate
• Bitul de paritate pară (even) este calculat realizând un
XOR (SAU-EXCLUSIV) intre biții de date.
• Dacă se folosește paritatea impară (odd) rezultatul
XOR-ului este inversat.
• Relaţiile intre bitul de paritate si biţii de date sunt:
Ppara = dn ⊕ dn-1⊕ … ⊕ d1 ⊕ d0 ⊕ 0
Pimpara = dn ⊕ dn-1⊕ … ⊕ d1 ⊕ d0 ⊕ 1
Ppara Bitul de paritate folosind paritatea pară
Pimpara Bitul de paritate folosind paritatea impară
dn al n-lea bit de date
• Dacă este utilizat, bitul de paritate trebuie plasat intre
ultimul bit de date si primul bit de stop al cadrului
serial. 38
AVR 8 biți UART: configurarea tipică a cadrului serial
(in limbaj de asamblare)

• Configurare in mod asincron, cu paritate


pară, cu 2 biţi de stop:
ldi R16, 0b10101110
out UCSRC, R16
neutilizat
URSEL=1
pt. a scrie in 11 = 8 biţi date
UCSRC 1= 2 biti stop

0=Mod asincron
10 = paritatea para

Aceasta modalitate de specificare a valorilor de bit nu este recomandată, fiind foarte


39
puţin lizibilă: folosiţi numele predefinite ale biţilor!
AVR 8 biți UART: configurarea tipică a cadrului
serial de biti (in limbaj C)
/* Dorim 8 biti de date, 1 bit de stop, fara
paritate, adica 8N1 */
UCSRB &= ~(1 << UCSZ2);
UCSRC = ( (1 << UCSZ0) | (1 << UCSZ1));

40
AVR 8 biți UART: activarea emisiei si a
recepției (in limbaj de asamblare)

• Se setează biții corespunzători activării


emisiei si recepției, ștergându-i pe ceilalți:
ldi R16, (1<<RXEN)|(1<<TXEN)
out UCSRB, R16
• Sau se setează doar acești biți, lăsându-i pe
ceilalţi nemodificați:
sbi UCSRB, RXEN
sbi UCSRB, TXEN

41
AVR 8 biți UART: activarea emisiei si a
recepţiei (in limbaj C)
….
//Activeaza transmisia si receptia
UCSRB | = (1<<RXEN)|(1<<TXEN);

//Sau activeaza numai transmisia
UCSRB | = 1<<TXEN;
……

Exemplele care urmează de utilizare a emisiei si recepţiei


sunt bazate pe interogarea/testarea indicatorilor de stare
si asteptare (“polling”)
Cealaltă alternativă este utilizarea întreruperilor si va fi
ilustrată in alt curs
42
AVR 8 biți UART: emisia unui octet sau mai
corect a unui cadru de biti (in limbaj de
asamblare)
• Emisia unui octet este iniţiată ;octetul de emis este
printr-o scriere in UDR
• Trebuie aşteptat până când ;in R16
registrul de date este gol (până transmit:
când s-a terminat serializarea
caracterului curent ), si de aici o ;asteapta eliberarea
buclă de aşteptare ;registrului de
– Instrucţiunea sbis realizează
saltul (sare peste instrucţiunea ;date
următoare) dacă bitul testat din
registrul I/O este setat (=1) sbis UCSRA, UDRE
– Aşteptăm până când bitul rjmp transmit
UDRE din registrul UCSRA se
face “1” ;start transmisie
– Apoi putem emite octetul din out UDR, R16
R16

43
AVR 8 biți UART: emisia unui octet (in
limbaj C)

/* Se asteapta eliberarea bufferului de
emisie, functia este blocanta, nu se
iese din while decat atunci cand bitul
UDRE =1*/
while ( !( UCSRA & (1<<UDRE)) )
;
/* Dupa eliberare se pune data in buffer
si se incepe emisia */
UDR = data;
…..
44
AVR 8 biți UART: recepția unui octet (in
limbaj de asamblare)
• Octeții recepționați sunt
memorați temporar intr-o
“coadă” – un buffer FIFO
– bufferul USART-ului AVR are 2 ;Copiaza caracterul
octeți, FIFO cu 2 nivele
(ATMega16) ;receptionat in R16
• Indicatorul “recepție completă” receive:
RXC este setat atunci când
există un octet in așteptare ;asteapt data
(disponibil) in buffer sbis UCSRA, RXC
– Așteaptă până când RXC se rjmp receive
face “1”
– Apoi putem citi in R16 pe UDR ;ia octetul din
– Citirea lui UDR va șterge pe ;buffer
RXC atunci când bufferul s-a
golit in R16, UDR

45
AVR 8 biți UART: recepția unui octet
(in limbaj C)
unsigned char car;
/* Se asteapta pana avem ceva
receptionat in buffer, functia va fi
blocanta deorecea se asteapta in
while pana cand bitul RXC =1 */
while ( !(UCSRA & (1<<RXC)) );
/*Se citeste caracterul receptionat */
car=UDR;

46
AVR 8 biți U(S)ART: registrul de date
UDR, biții UDRE si RXC
• Scrierea in UDR memorează octetul in bufferul
de emisie al U(S)ART-ului si inițiază transferul
serial
– Începerea transferului va șterge bitul de stare UDRE
(Usart Data Register Empty)
• Registrul de date nu mai este gol
– UDRE va fi setat atunci când octetul este mutat in
registrul de deplasare paralel-serie si practic UDR
este gol putând fi scris următorul octet
• Citirea lui UDR înlătură si returnează următorul
octet din bufferul de recepție al U(S)ART-ului
– Dacă bufferul FIFO de recepție s-a golit si bitul
RXC- Receive Complete din UCSRA va fi șters (=0)

47
AVR 8 biți UART: UDR- registrul de
date, al 9-lea bit

Eventualul al 9-lea bit de date se gaseste in alt registru, registrul UCSRB:


bitii TXB8 (emisie) si RXB8 (recepţie)

48
AVR 8 biți U(S)ART: dezactivarea
emisiei
• Pentru a dezactiva emisia (emițătorul de fapt) trebuie
șters bitul TXEN ( =0) din registrul UCSRB
– De menționat ca dupa reset emisia este implicit dezactivata
ea trebuind sa fie activata de utilizator daca se dorește
utilizata, făcând TXEN=1
• Octeții care se află deja in așteptare pentru a fi emiși,
vor fi emiși, înainte de dezactivarea propriu-zisă a
emițătorului
– Bitul TXC (Transmit Complete) va fi setat (=1) atunci când
bufferul de emisie TXB este gol si registrul de deplasare
utilizat pentru emisie este gol
• Odată ce emițătorul a fost dezactivat, pinul TxD
poate fi utilizat ca un pin I/O normal din portul
PORTD (la ATMega 16 )

49
AVR 8 biți U(S)ART: dezactivarea
recepției

• Pentru dezactivarea recepției trebuie șters bitul


RXEN (=0)
– De menționat ca după reset recepția este implicit
dezactivata ea trebuind sa fie activata de utilizator
daca se dorește utilizata, făcând RXEN=1
• Receptorul este imediat dezactivat si
funcționalitatea lui RxD este redată portului I/O,
pinul respectiv putând fi utilizat ca un pin I/O
normal
– Toate datele recepționate aflate in acel moment
încă in bufferul FIFO de recepție sau in tranzit vor
fi pierdute!
50
AVR 8 biți U(S)ART: indicatorii de
eroare
• Acest set de biți este localizat in registrul UCSRA si
au următoarea semnificație:
– FE: Framming Error (eroare de încadrare)
• =1 indică că primul bit de stop nu a fost găsit/detectat
– DOR: Data OverRun error (eroare de suprascriere)
• =1 indică că octetul recepţionat nu a putut fi plasat/transferat in
bufferul de recepţie, dar intre timp a început recepţia unui alt
octet (octetul anterior fiind suprascris, deci pierdut)
– PE: Parity Error (eroare de paritate)
• =1 indică o eroare de paritate in data recepționată
• Paritate pară (even) înseamnă un număr par de “1” in data
recepționată; impară (odd) un număr impar de “1’-uri

51
AVR 8 biți U(S)ART: citirea indicatorilor
de eroare
• Erorile sunt si trebuie sa fie memorate împreună/sincron cu datele
recepţionate in bufferul FIFO de recepţie: un set de indicatori trebuie sa fie si
este asociat unui anumit octet receptionat
• Din acest motiv indicatorii de eroare (din UCSRA) trebuie citiţi înainte de a
citi datele care au pozitionat eventual acesti indicatori:

in R17, UCSRA
in R16, UDR

Sau in C:
….
eroare=UCSRA;
data =UDR;
….
• Tipic se pot verifica toţi biţii individuali, setarea oricăruia din ei însemnând o
eroare de recepţie, de exemplu (exemplu in limbaj de asamblare):
andi R17, (1<<FE)|(1<<DOR)|(1<<PE);oricare din ei ar fi in ‘1’
brne ReceiveError ;salt la o rutina de tratare a erorilor

52
AVR 8 biți U(S)ART: registrele
UCSRC si UBRRH (ATMega)
• Aceste registre de I/O asociate U(S)ART-ului pun o problemă
utilizatorului ele având alocată aceiași adresă I/O in spațiul dedicat
din memoria de date AVR
• De aici va rezulta o anumită constrângere si modalitate specifică de
a le accesa la scriere sau citire
• De fapt registrul UCSRC poate fi folosit ca atare sau ca UBRRH
selecția făcându-se cu ajutorul bitului URSEL din acest registru
• Când se dorește sa se scrie in UBRRH, cel mai semnificativ bit numit
URSEL (bitul 7) trebuie să fie “0”
– Dar UBRR este exprimat pe 12 biti (8 in UBRRL si 4 in UBRRH) astfel ca
UBRR are valoarea maximă de 4095, si această cerință este realizată
practic automat, bitul 7 din UBRRH fiind intotdeauna “”0”
• Când se dorește sa se scrie in UCSRC, bitul URSEL trebuie a fie
setat (“1”)
• Vezi slide-ul urmator
• Citirea acestor registre este mai puțin necesară in practică, dar este
posibilă

53
AVR 8 biți U(S)ART: registrele
UCSRC si UBRRH (ATmega) -2

54
AVR 8 biți U(S)ART: exemplu de interfaţă RS-
232 full-duplex

Pinii PD4 (XCK) si PD5


sunt folosiţi pentru
comunicaţia serială
sincronă (mai puţin
utilizată), caz in care intre cele
două sisteme se va vehicula
si un semnal de ceas 55
AVR 8 biți U(S)ART : exemple de funcții de bază
pentru utilizarea portului serial, inițializarea

void USART_Init(unsigned int baudrate);


char Usart_Rx(void);
void Usart_Tx(char);

/*initializare uart
rata baud primita ca un argument intreg fara semn */
void USART_Init(unsigned int baudrate)
{
/* Seteaza rata baud */
UBRRH = (unsigned char) (baudrate>>8);
UBRRL = (unsigned char) baudrate;
/* Activare 2x viteza dubla */
UCSRA = (1<<U2X);

/* activeaza receptia si emisia, precum si intreruperile aferente*/


UCSRB = (1<<RXEN)|(1<<TXEN)|(0<<RXCIE)|(0<<UDRIE);

/* Mod asincron, 8N1: 8biti de date, 1 bit de stop, fara paritate*/


UCSRC = (0<<UMSEL)|(0<<UPM0)|(0<<USBS)|(3<<UCSZ0)|(0<<UCPOL);
}
56
AVR 8 biți U(S)ART : exemple de funcții de bază pentru
utilizarea portului serial, scrierea si citirea in mod polling
/*emite caracterul primit ca argument
functie blocanta, se asteapta terminarea emisiei */
void Usart_Tx(char data)
{
while (!(UCSRA & (1<<UDRE)));
UDR = data;
}
/* returneaza caracterul receptionat
functie blocanta, se asteapta pana se receptioneaza un caracter
*/
char Usart_Rx(void)
{
while (!(UCSRA & (1<<RXC)));
return UDR;
}
/* doar initializarea */
int main (){
..
USART_Init(12); /* Baud rate = 9600bps, un exemplu
prost de programare! */
… 57
}
AVR 8 biți U(S)ART : inițializarea sistemului de
întreruperi pentru utilizare a portului serial
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 4000000
#define USART_BAUDRATE 9600
/*o relatie de calcul pentru rata baud functie de frecv.
ceasului sistem*/
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
int main (void)
{ /* Activare emisie si receptie */
UCSRB |= (1 << RXEN) | (1 << TXEN);
UCSRC |= (1 << UMSEL) | (1 << UCSZ0) | (1 << UCSZ1); /*
format 8N1*/
UBRRH = (BAUD_PRESCALE >> 8); /* Incarca octet superior UBRR
*/
UBRRL = BAUD_PRESCALE; /* Incarca octet inferior UBRR */
UCSRB |= (1 << RXCIE); /* Activeaza intreruperea USART
Recieve Complete (USART_RXC) */
sei(); /* Activeaza global intreruperile */

for (;;) /* O bucla infinita */


{ ; /* In care nu facem nimic, “ecoul” unui caracter
receptionat este facut in rutina de tratare a intreruperii */
}
}
58
AVR 8 biți U(S)ART : citirea portului serial
utilizând întreruperile
/*Exemplu de rutina de tratare a
intreruperii aferente portului serial,la
receptia unui caracter, indicator RxC =1
Rutina realizeaza “ecoul” unui caracter
receptionat pe portul serial care va fi
emis pe acelasi port */
ISR(USART_RX_vect)
{
char OctetReceptionat;
OctetReceptionat = UDR; /* Citesc
octetul receptionat in variabila temporara
*/
UDR = OctetReceptionat; /* Emite
“inapoi” octetul receptionat */
}
59
AVR 8 biți U(S)ART: exemplu de interfață
RS-485 half-duplex (2 fire)

RS-485 TTL

Pinul PD6 este folosit ca o


ieşire care activează/
inactivează emisia sau
recepţia:
PD6= /RE=DE
PD6=“0” recepţie activă,
emisie inactivă
PD6=“1” recepţie inactivă,
emisie activă
60
AVR 8 biți U(S)ART: comutarea emisie/recepție pentru
o comunicație RS-485 half-duplex
In mod tipic la inițializare (după reset) trebuie să ne poziționăm pe recepție,
urmând să comutăm pe emisie când este cazul si înapoi pe recepție.
Mai jos un exemplu de funcție care realizează comutarea modului pentru
transceiver:
#define RX_MODE 0
#define TX_MODE 1
void switch_mode(char mode) {
if (mode == RX_MODE)
{
PORTD &= ~(1<<PD6);//PD6=0
}
else
{
PORTD |= (1<<PD6); //PD6=1
}
}
..//este apelata astfel
switch_mode (RX_MODE); // la initializare
…..
switch_mode (TX_MODE); //inainte de a emite
//aici se va emite un caracter

switch_mode (RX_MODE); //pentru a trece inapoi pe receptie
In realitate comutarea nu este atât de simplă cum pare, mai există diverse aspecte
de timp real (întârzieri) care trebuie gestionate! 61
AVR 8 biți, interfețe seriale sincrone:
interfața SPI, magistrala SPI
• Practic toate microcontrolerele AVR 8 biți au suportul
hardware necesar pentru implementarea unei interfețe
seriale sincrone mare viteză, compatibilă cu o
magistrală SPI (Serial Peripheral Interface Bus)
• SPI a fost introdusă de fosta Motorola (fosta Freescale,
actualmente NXP, nu se știe cat timp..) ca o legătură
serială sincronă full-duplex
– SPI este sincronă fiindcă se vehiculează si un semnal de ceas
SCK împreună cu semnalul de date
– Prezentarea SPI care urmează este una doar la nivel introductiv!
• La variantele ATtiny (de exemplu la ATtiny2313) se
întâlnește o interfață serială sincronă simplificată, numita
USI (Universal Serial Interface), care pune la dispoziție
niște resurse hardware de bază pentru implementarea
unei comunicații seriale sincrone
– Utilizând USI unitatea centrală poate fi degrevată de unele sarcini
suplimentare, comparativ cu cazul in care comunicația serială ar
fi realizată doar sub controlul software, folosind intrări/ieşiri de uz
general (lucru de altfel întotdeauna posibil)
62
Magistrala SPI, generalități
• Este o magistrală sincronă (care foloseste un semnal explicit de
ceas) care implementează conceptul de Master-Slave, masterul
fiind acela care inițiază transferul unor cadre seriale de biţi (tipic
de 8 biti, dar nu limitat la această dimensiune), cu un dispozitiv
Slave
• Masterul este si cel care generează semnalul de ceas
• Mai multe dispozitive Slave pot fi selectate printr-un mecanism de
selecție, mecanism care folosește semnale de selecție individuale
• Permite comunicația full-duplex, având linii separate de date
pentru emisie si recepție
• Este destinată a fi utilizată pe distanţe mici (<1m)
• Este potențial o magistrală rapidă, cu viteze de până la 20 Mbps-
echivalentul unui ceas de 20MHz - (funcție si de lungimea firelor),
oricum mai rapidă decât magistrala I2C
• Interfața SPI permite schimbul de date serial utilizând doar 4 fire
(este o 4 wire interface), plus un fir de masă, cu un alt dispozitiv
compatibil SPI Slave (circuite de memorie, convertoare analog-
numerice/numeric-analogice, senzori, registre de deplasare, etc.)
– Daca comunica cu mai multe dispozitive SPI Slave, este necesar un fir in plus
pentru fiecare dispozitiv adăugat
• Vezi si https://en.wikipedia.org/wiki/Serial_Peripheral_Interface
63
SPI, interconexiunea Master- Slave,
semnale
• SC(L)K: Serial ClocK (Ieșire de la Master);
• MOSI; SIMO: Master Output, Slave Input (Ieșire de la Master);
• MISO; SOMI: Master Input, Slave Output (Ieșire de la Slave);
• /SS: Slave Select (activă in “0, ieșire de la Master, intrare la Slave).
• Masterul si Slave-ul SPI sunt de fapt două registre de deplasare serie -
paralel, aici de 8 biți, cu același semnal de ceas SCK, conectate “in inel”,
prin intermediul MISO si MOSI, astfel că practic formează un registru unic
de deplasare
• Semnalul de selecție /SS va spune Slave-ului când va începe transferul
(deplasarea serială de biți) propriu-zis
• Masterul generează informație pe linia MOSI si in același timp
eșantionează (citeste si memorează) informația care ii vine pe linia MISO

64
Magistrala SPI - semnalul de ceas SCK
• Deși datele sunt in mod conventional grupate in mod
tipic in pachete de 8 biți, adică 8 perioade ale ceasului
SCK, in realitate transferul de date poate avea un număr
arbitrar de biți/perioade ale ceasului
• Când nu mai sunt date de serializat Master-ul oprește
ceasul si, in mod normal, asta duce la deselectarea
Slave-ului
• Există multe exemple de periferice cu interfata SPI unde
se vehiculează pachete de 12 sau 16 biți, registrele de
deplasare respective având același număr de biți
• Starea de referință (inactivă) a semnalului de ceas SCK,
“0” sau “1”, precum si frontul activ (cel pe care se
memorează/eșantionează biții de intrare) crescător sau
descrescător, trebuie sa fie programabile de utilizator;
– De exemplu pentru AVR 8 biti, aceasta se face cu ajutorul biților
CPOL- Clock Polarity si CPHA- Clock Phase din registrul SPCR
– SPI Control Register

65
Magistrala SPI- diagrame de timp

In acest exemplu liniile MOSI/MISO comută (isi pot schimba starea) pe frontul căzător
al lui SCLK si sunt memorate/eșantionate/citite pe frontul crescător

Vezi si http://www.epanorama.net/links/serialbus.html 66
AVR 8 biți: schema bloc a interfeței SPI

ATMega16

Utilizarea SPI pentru un microcontroler


AVR se face prin intermediul a 3 registre:
de date (SPDR), stare (SPSR) si control
(SPDR) si a 4 conexiuni externe (MOSI,
MISO, SCK si /SS) 67
AVR 8 biți: interfața SPI, registrele de
control, stare si date (ATMega)

Semnificația tuturor biților si exemple de programare SPI le găsiți in foile de catalog


si notele de aplicații.
Vezi si http://maxembedded.com/2013/11/the-spi-of-the-avr/ 68
Exemple de utilizare SPI
1. Un SPI Master (AVR) conectat la doua
periferice Slave.
Pentru ca la AVR nu există decât un
singur pin dedicat de tip /SS, daca mai sunt
si alți pini de tip /SS, ei vor trebui
implementați cu pini de ieșire de uz general.
Exista o mare varietate de circuite/module
cu interfață SPI care pot fi conectate astfel
Legătura de masă numai cu 3+1 fire: circuite de memorie cu
comună nu este interfața seriala SPI, convertoare
figurată in aceste analog-numerice si numeric analogice,
scheme! diverși senzori, module de comunicație
radio (wireless), etc

2. Două ATmega 328


conectate prin SPI (4 fire),
unul este Master si unul
Slave.

69
AVR 8 biți: SPI si programarea ISP (ATMega)
• Nu in ultimul rând, in contextul AVR, interfaţa SPI poate fi utilizată si pentru o
programare de tip ISP (In System Programming ) a microcontrolerului (serial
downloading):
– a memoriei de program (Flash),
– a memoriei EEPROM si
– a fuzibilelor
Cu ajutorul acestei interfețe se pot realiza operații de scriere si citire(verificare)
din zonele de memorie enumerate mai sus atunci când:
- semnalul /RESET este ținut activ (=‘0’)
- exista semnal de ceas
- fuzibilul SPIEN (activare programare prin SPI) este programat
• Se utilizează un algoritm specific descris in foaia de catalog AVR

70
AVR 8 biți, interfețe seriale sincrone:
magistrala I2C (IIC)
• Prezentarea I2C care urmează este una sumara, doar la nivel introductiv!
– Pentru familia de microcontrolere AVR 8 biti interfaţa I2C se numește TWI (Two Wire serial Interface), interfață cu 2
fire
• Este o magistrală serială sincronă destinată interconectării de circuite integrate (IIC-
Inter Integrated Circuits), inventată in anii ’80 de fostul Philips Semiconductor (acum NXP)
– I2C este sincronă fiindcă se vehiculează si un semnal de ceas împreună cu semnalul de date
• Este o magistrală de tip Multi-Master, ceasul fiind furnizat / generat de Master
• Informația este organizată pe pachete
• Este o magistrală multi-punct, permite conectarea utilizând numai 2 fire (Two Wire-2W) a
până la 128 de dispozitive (sau 1024 pentru adresa extinsa) I2C diferite
• Este destinată a fi utilizată pe distanțe mici (<1 m)
• Este o magistrală cu linii bidirecționale, de tip drenă in gol (ca ieşiri)
– Obligatoriu trebuie să existe rezistente de sarcină externe, către Vcc (pull-up)
• Comunicația este doar Half-Duplex pentru că există o singură linie de date, bidirecțională!
• Este relativ lentă (este oricum mai lentă decât SPI):
– 100 kbiti/s (in modul normal-standard), 400 kbiti/s (in modul rapid-fast, disponibil si la variantele
mai noi de AVR XMEGA)
– La cele mai noi dispozitive există si un mod de mare viteză - high speed care poate asigura
potențial o viteză de 3.4Mbps

OBSERVAŢIE
Magistrala SMBus (System Management Bus), definită de Intel in 1995, este un subset al I²C care
(re) definește protocolul I2C intr-un mod mai strict. Este utilizata si o întâlniți de exemplu la plăcile
de bază PC pentru comunicația cu sistemul de alimentare de tip baterie reîncărcabilă. 71
I2C, exemple de utilizare

• Permite conectarea simplă si ieftină, a mai multor dispozitive de


intrare/ieşire (peripheral) diverse, cu ajutorul unei magistrale seriale
minimale (doar două fire plus masă, adică a 3 fire –este un 3 wire bus):
– circuite de memorie cu interfața seriala I2C, extensii de porturi paralele,
convertoare analog-numerice si numeric analogice, ceasuri de timp real
(RTC), afisoare LCD, senzori de temperatură, de umiditate, de
acceleraţie, de tip busolă (compass), de viteză unghiulară (gyro), etc
• Exemple multiple de utilizare: robotică, aparatură audio-video, TV,
diverse automatizări, etc. 72
I C,
2 definiții si concepte
• Master:
– Unitate (dispozitiv) care emite semnalul de ceas, iniţiază si
finalizează un transfer de date
– Furnizează adresa dispozitivului slave care va fi selectat si
stabileşte sensul transferului (citire sau scriere)
• Slave :
– Unitate (dispozitiv) selectată pentru transfer de către Master
– Recepţionează adresa si sensul transferului
– Achită transferul, dacă el este unitatea selectată
• Sistem Multi-Master
– Sistem in care una din mai multe potenţiale unităţi Master pot
prelua, pe baza unui arbitraj, controlul magistralei, fără a corupe
datele (informaţia vehiculată)
• Arbitraj (arbitration)
– Procedură pentru a prelua controlul asupra magistralei, dacă mai
multe unităţi doresc să o facă in acelaşi timp (doresc să devină
Master) 73
I C,
2 definiții si concepte -2
• Emițător (transmitter):
– Unitate care transmite o dată/un mesaj pe magistrală
– La scriere: emițătorul este Master
– La citire: emițătorul este Slave
• Receptor (receiver):
– Unitate care recepționează o dată/un mesaj de pe magistrală
– La scriere: receptorul este Slave
– La citire : receptorul este Master
• Sincronizare (synchronization)
– Metodă de sincronizare a semnalului de ceas pentru mai multe
dispozitive
• Adresa Slave (slave address)
– Adresa simplă (exista si o adresă extinsă de 10 biti) are 7 biţi permițând
adresarea a până la 128 de dispozitive slave
– Adresa simplă are 2 părți/câmpuri:
• Una (tipic 4 biţi) care identifică tipul dispozitivului: memorie, senzor, convertor,
etc.
• Una (tipic 3 biţi) care controlează activarea dispozitivului, care trebuie să fie
identică cu starea fixată extern (‘0’ sau ‘1’) a unor pini (tipic 2 sau 3, denumiti
A0, A1 sau A2) ai dispozitivului
• Este astfel posibilă astfel adresarea/conectarea a până la 8 dispozitive de
același tip, prin cele 8 combinații posibile de polarizare ale celor 3 pini
74
I2C, interconectarea mai multor
dispozitive

In exemplu avem 2 microcontrolere (UC) din care unul este Master,


altul Slave, un convertor analog-numeric (ADC) si unul numeric-analog
(DAC) conectate la aceiași magistrală I2C.
Sunt necesare doar 2 linii de semnal (plus o masă GND) si două
rezistențe de sarcină Rp:
•SCL : Ceas, semnal bidirecțional
•SDA : Date, semnal bidirecțional
75
•GND : Masa
I2C, interfața electrică
Vcc

• SCL: Serial Clock Line, linie de ceas,


• întotdeauna este activată de Master
• dar poate fi “trasă” in '0' de Slave
• SDA: Serial Data Line, linie de date
Liniile SDA si SCL sunt bidirecționale, ca ieșiri fiind de tip
cu drenă in gol:
- avem un AND (SI) cablat intre ieșirile de același tip
legate intre ele
- obligatoriu trebuie să existe si rezistențe de sarcină 76
(tipic 2..10kOhmi) externe către Vcc/VDD!
I2C, transmisia unui mesaj delimitat de
condițiile START/STOP

Transmis de emițător Confirmare transmisa de


receptor
• Liniile inactive (idle) sunt in ‘1'
• Înainte de a realiza orice tranzacție pe magistrală trebuie emisa o
condiție de Start: SDA ‘1' → '0', apoi SCL 'H' → '0‘
• Ea indică că va urma transmisia unui “mesaj” care trebuie ascultat de toi
cei conectați
• După finalizarea mesajului trebuie emisă o condiție de Stop : SCL '0' →
‘1', apoi SDA '0' → ‘1‘
• Ea indică ca s-a terminat transmisia unui “mesaj”, linia trecând într-o stare
inactivă
• Datele se modifică doar atunci când SCL este '0‘, serializarea începe 77
cu cel mai semnificativ bit, MSb
I C:
2 operația de citire (Read)
•Primul octet va conține:
• adresa destinatarului pe 7 biţi (maxim 128 de adrese
diferite)
• sensul de transfer (read in acest caz) codificat pe 1 bit
• Este urmat de o condiție de achitare (Acknowledge)
• Este urmat de octetul de date propriu-zis
• Este un exemplu de citire simplă / singulară (există si
citire multiplă, cu autoincrementarea adresei)

Adresa Data

Master Master Emitatorul datei Receptorul


Slave-ul este Slave-ul este Master
78
confirma identificarea adresei
I2C : operația de scriere (Write)
•Primul octet va conține :
•adresa destinatarului pe 7 biţi
•sensul de transfer (write in acest caz) pe 1 bit
• Este urmat de o achitare (Acknowledge)
• Este urmat de octetul de date
• Este un exemplu de scriere simplă / singulară (există si
scriere multiplă, cu autoincrementarea adresei)

Adresa Data

Master Master Emitatorul datei Receptor


slave este Master-ul slave
79
I2C: « încetinirea » transferului
(clock stretching)
Tras de Slave in ‘0’
pt. a încetini transferul Masterul isi dezactivează SCL
următor

Transmis de emiţător Transmis de receptor

Trăgând de semnalul de ceas in '0', un Slave poate


« încetini» viteza de transmisie (prin lungirea -stretching-
intervalului de timp cât semnalul de ceas SCL este in ‘0’):
efectul este marirea perioadei lui SCL .
Este astfel posibila comunicația cu parteneri mai “lenți”
care nu pot furniza sau recepționa datele in ritmul
80
semnalului de ceas SCL standard.
AVR 8 biți: I C=TWI
2

• Pentru familia de microcontrolere AVR interfaţa I2C


se numește TWI (Two Wire serial Interface),
interfață cu 2 fire
• Este întâlnită, ca periferic, in primul rând la
variantele ATMega si XMEGA
• O interfață de tip I2C (TWI) poate fi eventual si
implementată software – software I2C- la orice
varianta de AVR 8 biți (de fapt la orice
microcontroler), folosind numai 2 pini de
intrare/ieşire de uz general, dar cu o încărcare mult
mai mare ca timp de calcul a unității centrale (care
trebuie să implementeze protocolul numai prin
manipularea pinilor respectivi) si o viteză de transfer
a datelor eventual mai mică

81
AVR 8 biti TWI: schema bloc a sub-sistemului,
conexiunile externe (ATMega16)
ATMega16

82
AVR 8 biti, TWI: registrele asociate
• Pentru AVR 8 biti exista un set de 5 registre utilizate
pentru implementarea interfeței TWI:
– Registrul pentru stabilirea vitezei de comunicație (rata bit, bit
rate) TWBR - TWI Bit Rate Register
– Registrul de control TWCR - TWI Control Register
– Registrul de stare TWSR - TWI Status Register
– Registrul de date TWDR -TWI Data Register; este un singur
registru, utilizat la scriere pentru emisie si la citire pentru recepţie
– Registrul de adresa pentru Slave TWAR -TWI (Slave) Address
Register
• Pentru utilizarea lor si a interfeței TWI consultați foile de
catalog!

83
AVR 8 biti TWI: registrele

84
AVR 8 biti TWI: exemplu de conectare a unui
ATMega16 cu o memorie EEPROM serială, 24C02

Găsiţi si consultaţi foaia de catalog si a circuitului 24C02 pentru a înţelege


care este funcţionalitatea pinilor A0, A1, WP.
In acest exemplu, pe magistrala I2Car putea fi conectate pană la 4 circuite de
85
memorie de tip 24C02.
AVR 8 biti TWI: exemplu de conectare a unui
Attiny 45 cu un circuit PCF8574 –I/O expander
PCF8574 este un circuit care
implementează un port de 8 biți,
intrări si/sau ieșiri
numerice(identificate ca P0..P7)
In acest exemplu un circuit este
utilizat numai ca intrări (8 intrări)
pentru a citi starea unor
comutatoare, iar altul numai ca
ieșiri (6 ieșiri) pentru interfața cu
un modul de afișare LCD (interfață
paralela de 4 biți) LM016.
Cele doua PCF 8574 sunt
conectate pe magistrala I2C având
adrese diferite – vezi pinii A0, A1 si
A2.
ATTiny45 este o variantă de AVR 8
biți într-o capsulă PDIP de 8 pini,
de unde si utilitatea soluției I2C, cu
numai 2 fire (plus masă), de
interfață cu intrările/ ieșirile 86
numerice .
AVR 8 biți TWI: exemplu de conectare a unui
ATMega 8 cu un modul/senzor MPU6050

Găsiți si consultați foaia de catalog a circuitului


MPU6050 (TDK) pentru a înțelege
care este funcționalitatea acestuia.
Măsoară : accelerația (tri-axial), viteza unghiulară (gyro,
tri-axial) si temperatura.
Senzorul (circuitul) există si in varianta cu interfață SPI.
OBS. Rezistentele de pull-up pentru I2C sunt conectate
la Vcc pe placa senzorului

87
Microcontrolere (si
microprocesoare)

Microchip AVR 8 biți:


Familia XMEGA
Familia Tiny AVR 1 (Seria 1)

1
AVR XMEGA
• Prezentarea care urmează este una foarte sumară, care scoate in
evidentă doar principalele caracteristici noi sau îmbunătățite ale familiei
XMEGA fata de ATMega
• Pentru o informație fiabilă, completă si consistenta consultați manualele
utilizator (user manual), foile de catalog complete (complete datasheet)
si notele de aplicație (application note) disponibile pe site-ul Microchip.
• Din păcate la Microchip nu mai exista o pagina de plecare pentru toata
familia AVR XMEGA, trebuind accesate mai mult sau mai puțin direct
paginile dedicate unei anumite variante, gen:
• https://www.microchip.com/wwwproducts/en/ATXMEGA16A4U
• Distribuitori mai mențin eventual niște pagini sintetice pentru AVR
XMEGA, vezi:
• https://www.digikey.com/en/product-highlight/a/atmel/avr-xmega
• De notat că pentru fiecare modul periferic sau de memorie, nou sau
îmbunătățit, există si câte o notă de aplicații, in care sunt explicate
caracteristicile acestuia si modul de utilizare
• Exista zvonuri (si semne.. ) ca familia XMEGA va intra in ce se cheamă
EOL – End Of Life- urmând sa fie scoasa din fabricație si înlocuită total
de variantele modernizate de Tiny si MEGA

2
Indentificarea circuitelor AVR XMEGA
• Variantele propriu-zise de XMEGA sunt identificate cu ajutorul
unei litere: prima varianta disponibilă a fost varianta A (sub-
familia A).
– Literele spun ceva (dar nu foarte clar..) despre periferia disponibila
• Numărul din fața literei este dimensiunea memoriei de
program FLASH in kOcteți,
• După literă urmează un identificator al numărului de pini al
capsulei (1, 2, 3, 4, 5, etc.)
– De ex. 1 – 100 pini, 3- 64 pini, 4- 44 pini, 5-32 de pini
• Actualmente (2018) există variantele A, B, C si D, iar
dimensiunea maximă a memoriei FLASH este de 384kOcteti,
a celei SRAM de 32kOcteti, iar a celei EEPROM de 4kOcteti
• Exemple: ATXMEGA128A1, ATXMEGA384D3, etc.
• Oricum este obligatorie consultarea foii de catalog pentru
identificarea/ înțelegerea corectă a resurselor disponibile
pentru un anumit circuit XMEGA!

3
AVR XMEGA: încapsularea si domeniul de
temperatură
• XMEGA este actualmente disponibil in capsule (package) de 32, 44, 64 sau 100 de
pini
• Numărul de porturi si/sau de pini I/O disponibili este proporțional cu numărul de pini ai
capsulei
• Toate aceste capsule sunt de tipul SMD/SMT, cu montare pe suprafață: TQFP, QFN,
BGA
• Nu există circuite XMEGA in capsule pin-through gen DIL sau PDIP!
• Domeniul temperaturii de lucru este, pentru majoritatea, doar cel industrial, de -
40oC … +85oC
• Exista o categorie de circuite Xmega notate ca AUTOMOTIVE, calificate pentru un
domeniu extins de temperatură de -40oC … +105oC
• Nu există încă versiuni XMEGA calificate pentru un domeniu extins de temperatură
de -40oC … +125oC , cum există pentru ATtiny sau ATMega (AT90PWM)

4
XMEGA versus ATMega
• AVR XMEGA este tot un microcontroler AVR de 8 biți, având practic
aceiași unitate centrală (CPU) si aceiași arhitectură, dar având unele
caracteristici suplimentare, superioare precum si module periferice sau
de memorie reproiectate si/sau îmbunătățite.
• Spațiul de memorie adresabil a crescut până la 16 MOcteți de memorie
de program si 16MOcteți de memorie de date, de unde si apariția unor
noi registre de 8 biți:
– RAMPX, RAMPY, RAMPZ: pentru a se putea adresa întreg spațiul de
adrese al memoriei de program si de date au fost adăugate niște extensii
(registre suplimentare de 8 biți) la registrele X, Y, Z de 16 biți utilizate pentru
adresarea memoriei, ele putând avea acum si 24 de biți (necesari pentru
adresarea a 16 MOcteti, 224=16777216)
– RAMPD: poate fi concatenat cu un operand de 16 biți, rezultant o adresa de
24 de biti pentru adresarea întregii memorii de date
– EIND(Extended INDirect register): poate fi concatenat cu registrul Z pentru
a realiza salturi indirecte sau apeluri de subrutine peste limita de 128KB
(64kcuvinte) a memoriei de program
• Actualmente exista circuite care au implementat intre 16 si 384KOcteti
de memorie de program Flash si intre 2 si 32KOcteti de memorie de
date SRAM
• Bancul de 32 de registre de uz general nu mai este mapat direct in
spațiul de memorie SRAM(nu mai are adrese in SRAM), un registru de
uz general ne mai putând fi tratat ca orice alta locație de memorie
SRAM
• XMEGA are același set de instrucțiuni si dezvoltatorul utilizează același
set de mijloace de dezvoltare, IDE-uri, compilatoare, etc. 5
XMEGA vs. ATMega: programarea porturilor ca I/O
de uz general
• Prezentarea porturilor I/O pentru AVR XMEGA este una sumară, pentru detalii si
programare efectivă consultați foile de catalog si notele de aplicații.
– Caracteristicile respective se întâlnesc si la variantele Mega si Tiny modernizate (seriile 0,
1,2)
• Există multe facilități noi legate de programarea si utilizarea pinilor ca I/O de uz
general
• Ele se refera la noi configurații disponibile si corespunzător registre noi cu biți
corespunzători care permit programarea noilor configurații de ieșiri (mai ales)
• Șase din cele 8 configurații disponibile si programabile sunt prezentate mai jos si
explicate in continuare.

6
XMEGA vs. ATMega: programarea porturilor ca
I/O de uz general -2
• Prin totem-pole se înțelege o ieșire CMOS normală; ea poate fi combinata cu
rezistente de pull-up (către Vcc) sau pull-down (către masă) conectate intern
• Cu ajutorul rezistentele de pull-down este posibilă realizarea unui OR cablat (SAU
cablat) intre mai multe ieșiri de tip sursă in gol
• Folosind rezistentele de pull-up este posibilă realizarea unui AND cablat (SI-
cablat) intre mai multe ieșiri de tip drenă in gol
• Pentru intrări este posibilă utilizarea unei configurații bus-keeper , care asigură
memorarea ultimei stări a intrării/ ieșirii, astfel încât intrarea respectivă să nu
rămână flotanta (in Hi-Z)
• Dacă pentru ATMega existau practic 3 registre per port: DDR, PORT si PIN acum
există mult mai multe, iar cele de la ATMega au fost redenumite.
– Avem acum registrele DIR (Data Direction Register), OUT(Data Output Value Register)
si IN (Data Input Value Register), iar configurațiile din slide-ul anterior sunt programate
prin intermediul registrului PINnCTRL (Pin n Control Register)
– Pe lângă acestea mai avem: DIRSET (Data Direction Set Register), DIRCLR (Data Direction
Clear Register), DIRTGL (Data Direction Toggle Register), OUTSET (Data Output Value Set
Register), OUTCLR (Data Output Value Clear Register), OUTTGL (Data Output Value Toggle
Register), REMAP (Pin Remap Register) plus câteva registre asociate sistemului de
întreruperi (practic este posibil ca orice pin sa declanșeze o întrerupere)
– Alt set de registre permite o (re) configurare si mai flexibila a pinilor in contextul multi-
functionalitatii lor: MPCMASK (Multi-Pin Configuration Mask Register), CLKOUT (Clock
Output Register), ACEVOUT(Analog Comparator and Event Output Register), SRLCTRL
(Slew Rate Limit Control Register)
• Există si noul concept de port virtual care permite maparea a pana la 4 porturi
virtuale la orice adresa in zona bit adresabila a memoriei I/O:
– aceasta permite folosirea unor instrucțiuni specifice de manipulare a biților in memorie
(valorificata de compilator);
– de exemplu se poate mapa portul PORTD cu/in portul virtual 3, astfel încât scriind in portul
virtual 3 este același lucru cu a scrie in PORTD

7
XMEGA vs. ATMega: programarea porturilor ca
I/O de uz general -3

11 + 8 = 19 registre per port !

Plus 4 registre virtuale per port 8


XMEGA vs. ATMega
• La AVR XMEGA au apărut o serie de circuite periferice
noi sau îmbunătățite din care cele mai importante ar fi:
– un controler multi-canal de acces direct la memorie (DMA) numit
EDMA- Enhanced Direct Memory Access care permite transferul
de date intre periferice si memorie cu o intervenție minimala a
unității centrale
– un controler care tratează evenimentele de la nivelul modulelor
periferice (Event System)
– un sistem complex de conversie analog-numerică de 12 biți
– un sistem de conversie numeric-analogic de 12 biți
– un controler de întreruperi cu mai multe nivele de priorități (are 3
nivele fata de cele 2 de la Mega),
– un motor de criptare AES/DES (accelerator criptografic hardware)
– un modul de calcul al sumelor de control CRC16 sau CRC32
• De notat ca la fel ca multe din modulele periferice, si
controlerul DMA si precum cel numit Event System pot
funcționa, cu unitatea centrală trecută intr-un mod cu
consum redus - “adormită” (sleep), la tensiunea minimă
de alimentare de 1.6V, putând duce la o reducere drastică
a consumului
9
XMEGA vs. ATMega
• Ca o recapitulare a modulelor/sub-sistemelor, un AVR XMEGA poate
avea (eventual …pană la.. dacă e vorba de mai multe module), funcție de
variantă:
– 8 module USART
– 4 module TWI (I2C), cu frecvențe maxime de 100kHz, 400kHz si 1MHz (doar
la unele variante)
– 4 module SPI, cu frecventa maximă pană la 16MHz (viteza 16Mbps)
– 8 module temporizatoare/numărătoare cu 32 de ieșiri cu modulare in durată
(PWM)
• Apare un nou mod de lucru si modul utilizat pentru generarea formelor de unda numit AWeX –
Advanced Waveform Extension si
• Apare un mod de lucru si un modul numit Hi-Res- High-Resolution Extension, de înaltă rezoluție,
tot pentru generarea formelor de unda
– 1 modul USB (care asigură conectivitatea USB)
– 1 modul de interfața directa cu un panou de afișare LCD (4x40 segmente)
– 2 module convertoare analog-numerice de 12 biți
– 1 modul convertor numeric-analogic de 12 biți
– 1 modul ceas de timp real de 16 biți (RTC- Real Time Clock) si unul de 32 de
biți (RTC32)
– 1 modul XCL (XMEGA Custom Logic) care conține 2
numărătoare/temporizatoare de 8 biți si două tabele de adevăr (LUT - Look Up
Table) programabile, care pot fi folosite la implementare unui logici
combinaționale si/sau secvențiale (înlocuind bistabile, porți, etc.), cu scopul
măririi flexibilității si al reducerii numărului de componente necesare (in afara
microcontrolerului)
– Un modul IRCOM (Infra Red Communication), modul de comunicații seriale in10
infraroșu (conform standardului IrDA)
XMEGA vs. ATMega
• Microcontrolerele din cele două familii MEGA AVR, XMEGA si
ATMEGA, nu sunt pin la pin compatibile.
• Aceasta este datorită dorinței de a face noua familie mai modulară,
replicând funcții si module periferice pe fiecare port I/O.
– De exemplu UART-ul, interfața SPI si cea TWI sunt localizate întotdeauna
pe aceiași pini ai unui port I/O care are aceste caracteristici.
– La fel se întâmplă si pentru interfața analogică
• Aceasta face ușoară portarea de cod intre microcontrolerele XMEGA,
care devine practic trivială, dar a dus la incompatibilitatea pin la pin cu
ATMEGA.
• XMEGA funcționează la tensiuni de alimentare Vcc intre 1.6V si 3.6
V.
• Interfața electrică este una compatibilă LVTTL, dar capacitatea unui
pin, utilizat ca ieșire, de a debita (source) sau absorbi (sink) curent
este asimetrică ( |IOH|< IOL ), valoarea maximă fiind proporțională cu
tensiunea de alimentare
– De exemplu, pentru o varianta XMEGA A4, la Vcc= 3.3V avem IOL=15mA
si IOH=-8mA, iar pentru o varianta D4, la Vcc= 3.3V avem IOL=8mA si
IOH=-4mA
11
XMEGA vs. ATMega
• Fata de ATMega unitatea centrală poate funcționa la frecvențe de
ceas mai mari, la tensiuni de alimentare mai mici.
• In cazul XMEGA tensiunea mai mică de alimentare nu înseamnă
neapărat si viteză mai mică a CPU
– Toate circuitele XMEGA pot funcționa la o frecvență maximă de ceas de
32MHz, la tensiune de alimentare Vcc= 2.7V; dar chiar si la tensiunea
minima de alimentare Vcc= 1.6V frecvența maximă de ceas utilizabilă este
totuși consistentă, de 12MHz.
• XMEGA este descris ca fiind a doua generație a tehnologiei Atmel de
putere foarte scăzută numită picoPOWER
• Procesul tehnologic CMOS utilizat pentru realizarea familiei XMEGA a
fost unul optimizat pentru scăderea consumului propriu, dar limita
superioară a tensiunii de alimentare este acum de 3.6V, actualii
membrii a familiei XMEGA neputând să funcționeze la tensiunea
de alimentare de 5V.
• Dacă ne trebuie o interfață (de intrare) cu circuite alimentate la 5V,
obligatoriu trebuie utilizată o translație de nivele logice de la 5V la
3.3V si invers!

12
Utilizarea structurilor (limbaj C) si migrația
aplicațiilor intre variante XMEGA diferite
• Arhitectura XMEGA a fost concepută astfel încât să se ușureze si portarea
aplicațiilor intre diversele variante de microcontrolere XMEGA.
– De exemplu, la toate XMEGA, porturile PORTA si PORTB sunt dedicate si
funcțiilor alternative analogice (convertoare analog numerice -ADC, convertoare
numeric analogice - DAC, comparatoare analogice -AC)
• Toate modulele periferice sunt definite, din punct de vedere al utilizatorului,
cu ajutorul unor structuri in limbajul C (typedef struct).
• Aceasta înseamnă, de exemplu, că registrele convertorului analog numeric
(ADC) pot fi accesate prin intermediul structurii dedicate.
• Convertorul analog-numeric, fiind din punct de vedere software practic
definit de aceasta structură, ideea a fost ca această structură să fie una
identică, de exemplu, pentru toate variantele A.
• Dacă am început dezvoltarea aplicației folosind un ATXmega64A4, putem
migra ușor la un ATxmega128A4 sau ATxmega256A4, dacă avem nevoie
de mai multă memorie de program, utilizând exact același cod pentru
convertor.
• Vezi si nota de aplicatii AVR1000: Getting Started Writing C-code for
XMEGA, http://ww1.microchip.com/downloads/en/AppNotes/doc8075.pdf
• De ce nu s-a procedat la fel si pentru ATMEGA?
– Acolo nu a fost posibil să se utilizeze o structură unică pentru un anumit modul
pentru că modulele periferice nu aveau aceiași arhitectură, pentru diversele
variante.
– Pentru XMEGA modulele periferice cu o anumită funcționalitate au o arhitectură
identică, indiferent de variantă. 13
Sistemul de tratare a evenimentelor (Event
System)
• Acest sistem reprezintă o caracteristică nouă si inovatoare pentru microcontrolerele AVR
XMEGA (el nu există la ATTiny sau ATMega) si a fost preluat la seriile Microchip AVR
modernizate
– Un sistem similar exista la microcontrolerele ARM Cortex -M
• Este un sistem care poate gestiona direct, fără intervenția unității centrale (CPU),
„comunicația” intre diverse module periferice, într-o relație cauză - efect.
• Sunt disponibile opt „canale” de comunicație pe care utilizatorul le poate configura.
• Un „canal” eveniment nu este o magistrală, ci o modalitate de a semnala si transmite mai
departe apariția doar unui singur eveniment apărut la nivelul unui modul periferic.
• Deoarece evenimentul folosește un canal hardware dedicat, tratarea lui este foarte
predictibilă si rapidă, întârzierea fiind de maxim două perioade ale ceasului sistem.

14
Sistemul de tratare a evenimentelor
(Event System) -2
• Utilizarea conceptului de eveniment poate duce la
reducerea numărului de întreruperi care trebuie să fie
tratate de CPU, deoarece o întrerupere este si ea un
eveniment, dar aici nu este vorba de rutine de tratare
a întreruperilor, deoarece unitatea centrală nu este
implicată in tratare.
• Se obține astfel o degrevare a unității centrale de sarcini
de prelucrare, si eventual o creștere consistentă a
performantelor prin reducerea numărului de întreruperi
care ar trebui tratate.
• Mai mult, acest sistem poate funcționa independent,
atunci când unitatea centrală este trecută intr-un mod de
lucru cu consum redus (sleep), ducând la o reducere
dramatică a consumului.

15
Sistemul de tratare a evenimentelor
(Event System) -3
• Câteva exemple de utilizare in care este vorba de
utilizarea unor evenimente pentru sincronizarea a două
module sau mai multe module:
– cascadarea a două numărătoare/temporizatoare de 16 biți,
pentru a obține unul de 32 de biți, evenimentul transmis fiind
depășirea unuia din ele
– modificarea stării unui pin poate declanșa o operație de
conversie analog numerică si, in același timp, capturarea stării
unui numărător/temporizator, pentru a obține o ştampilă de timp
(time stamp) asociată măsurării respective
– un eveniment oarecare poate declanșa o operație de conversie
analog numerică, la terminarea conversiei (următorul
eveniment), rezultatul poate fi transferat direct in SRAM de
controlerul DMA, iar la următorul eveniment (de exemplu
apăsarea unui buton, schimbarea stării unui pin) controlerul
DMA transfera valoarea respectivă din SRAM direct la
convertorul numeric analogic (toate acestea putând fi făcute
chiar dacă unitatea centrală este intr-un mod sleep!)
16
Sistemul AWeX – Advanced
Waveform Extension
• Este o facilitate suplimentara de
utilizare a sistemului de
temporizare/numărare
• Reprezintă o dezvoltare a modului
de lucru generare formă de undă
(WG- Waveform Generation) cu
ajutorul unor unități de inserare de
timpi morți (DTI- Dead Time
Insertion)
• Este utilă mai ales pentru comanda
diverselor tipuri de motoare (sau
alte aplicații de electronica de
putere) pentru că permite
dezactivarea programabilă
circuitelor de comandă externe,
in scopul protecției la defect
(Fault Protection) a obiectului
comandat si cu ajutorul sistemului
de tratare a evenimentelor(Event
System)
• Permite generarea unei anumite
configurații de biți (Pattern
generation) pe pinii portului. 17
AVR XMEGA: funcționarea la tensiune
redusă de alimentare
• Toate microcontrolerele AVR XMEGA sunt testate, in
fabrică, la tensiunea minimă de alimentare, Vcc=1.6V.
• Toate perifericele si modulele care funcționează la 3.6V
funcționează până la 1.6V, sau la o tensiune de
alimentare nominală de 1.8V ±10%.
• Aceasta este valabil si pentru modulele interne FLASH,
EEPROM si toate perifericele analogice.
– O tensiune redusă de alimentare înseamnă un consum redus,
ducând la creșterea duratei de viață a bateriei/acumulatorului
pentru o aplicație portabila.
• Ceasul de gardă (watchdog) si circuitul pentru detecția
scăderii temporare a tensiunii de alimentare (brown-out
detection) au scheme noi față de ATMega, pentru a
permite minimizarea curentului de alimentare.

18
AVR XMEGA: sistemul de generare a
ceasului
• Sistemul de generare a ceasului este unul mult îmbunătățit in
comparație cu ATMega
• Sursa semnalului de ceas sistem si frecvența acestuia pot fi
modificate dinamic, in timpul funcționării si prin program, nu sunt
configurate doar static, cu ajutorul fuzibilelor, ca la ATMega sau
ATTiny.
• Sunt disponibile, putând fi selectate ca surse de ceas, oscilatoare
interne RC calibrate de 32MHz, 2MHz si 32.768kHz.
• Oscilatorul intern de 2MHz este oscilatorul care este utilizat
intotdeauna implicit după inițializare, acesta având si un timp de
start foarte scurt.
• Microcontrolerul poate începe să execute cod folosind această
sursă/frecvență de ceas, realizând eventual diverse inițializări
interne; ulterior, după ce si eventualul oscilator stabilizat cu cuarț a
pornit si este funcțional, se poate comuta pe sursa dorită de ceas.

19
AVR XMEGA: sistemul de generare a
ceasului -2
• Ceasul disponibil dintr-o sursă oarecare poate fi multiplicat prin utilizarea
unui PLL-Phase Locked Loop (buclă cu calare de fază) sau divizat cu
ajutorul unor divizoare, toate interne.
• Utilizând PLL-ul intern frecvența poate fi multiplicată x1, x2, x3, …, x31;
frecvența maximă optenabilă este de 128MHz, dar care nu poate fi
utilizată ca ceas sistem pentru CPU (a carui frecventa maxima este 32
MHz)
– In schimb ea poate fi utilizata pentru sistemul de temporizare/numărare permițând obținerea
unei modulații in durata (PWM) cu o rezoluție foarte mare.
• Un modul DFLL- Digital Frequency Locked Loop (o buclă digitală cu calare
in frecvență) face posibilă calibrarea dinamică, in timpul funcționării, a
oscilatoarelor interne.
• Precizia sporită obținută astfel face posibilă ca aplicații care au nevoie de o
dimensiune mai precisă a timpului/frecvenței, cum ar fi comunicațiile seriale
asincrone, să poate fi realizate la viteze mai mari si cu costuri mai mici (de
exemplu in acest caz se poate utiliza oscilatorul intern RC si nu este nevoie
de stabilizare cu un cristal de cuarț).
• O noua caracteristică utilă este si existenta unui sistem de
monitorizare/urmărire a unui defect al sursei externe de ceas, care
permite detecția absenței semnalului de ceas
– Acest sistem poate detecta un astfel de defect, de exemplu un defect al rezonatorului cu
cuarț extern, care va duce la dispariția ceasului.
– Intr-o astfel de situație de defect sursa de ceas este comutată automat pe oscilatorul RC
intern de 2 MHz, sistemul rămânând cvasi funcțional
20
AVR XMEGA: PMIC - controlerul de
întreruperi multi-nivel
• Deoarece un XMEGA este un AVR care are surse de întreruperi mai
multe si diverse decât un ATMEGA, se utilizează si un nou controler
de întreruperi, mai versatil decât cel anterior.
• Acest nou controler se numește PMIC – Programmable Multilevel
Interrupt Controller
• Acest sistem permite tratarea corespunzătoare in timp (timp de
răspuns scurt si predictibil) si conform unui sistem mai flexibil de
priorități.
• La fel ca la ATMega există o prioritizare a întreruperilor după nivele
de priorități si după adresa vectorului
• Adresele vectorilor sunt statice si la fel ca la ATMega pot fi plasate
in zona de aplicații sau zona bootloader a memoriei de program.
• Aici însă există 3 nivele selectabile de priorități: mic, mediu si mare.
• Pentru cele de nivel scăzut există si un algoritm de selecție de tip
Round-Robin, garantându-se astfel că toate cererile de întrerupere
vor fi tratate.
• Pentru funcțiile critice există si o întrerupere nemascabilă (NMI).
21
AVR XMEGA: interfața analogică-
convertorul analog numeric
• Noul sistem îmbunătățit de conversie analog numerică (ADC)
si noul sistem de conversie numeric analogică (DAC) au o
rezoluție de 12 biți.
– Este inclus si un senzor integrat de temperatură (ca intrare
internă a acestuia)
• Convertorul analog numeric (CAN) are acum o viteză
maximă de conversie de 2 Mega-eșantioane pe secundă, cu
2 intrări care pot fi eșantionate simultan si 4 intrări eșantionate
cvasi-simultan (pe durata a 1.5usec).
• O nouă facilitate a CAN este de a genera o întrerupere (sau
un eveniment) numai atunci când conversia este completă SI
rezultatul ei este sub sau deasupra unei anumite limite,
programabile (aceasta este programată intr-un registru de 12
biti).
– Astfel, ca un exemplu, nu vom mai „deranja” unitatea centrală, dacă
rezultatul conversiei este sub 1V, micșorându-i astfel încărcarea. 22
AVR XMEGA: interfața analogică-
convertorul analog numeric

23
AVR XMEGA: interfața analogică-
convertorul numeric-analogic
• Convertorul numeric-analogic (CNA) de 12 biți poate oferi două
ieșiri, chiar dacă microcontrolerul nu poate avea actualmente decât
un singur astfel de modul periferic DAC.
– Aceasta este posibil datorită existenței a două circuite de eșantionare –
memorare (S/H- Sample Hold) separate si diferite, conectate la ieșirea
sa.
• Comparatorul analogic (AC - Analog Comparator) are o nouă
caracteristică, un mod de lucru fereastră (window mode) care
utilizează două comparatoare in același timp.
• Astfel se pot programa 2 limite, una inferioară si una superioară, iar
rezultatul comparației poate fi evaluat ca fiind in interiorul ferestrei
(intre limite), sau in afara ei, sub limita inferioară sau peste cea
superioară.
• Mai mult, rezultatul comparației cu aceste limite poate fi oferit pe
niște pini de ieșire.

24
AVR XMEGA - interfața analogică-
convertorul analog numeric

25
AVR XMEGA - interfața pentru magistrala
externă (EBI- External Bus Interface)
• Interfața pentru magistrală externă a unui XMEGA asigură
conectarea unor memorii externe de date, cu interfață paralelă,
mult mai mari decât cele de la ATMega, de până la 512kB (EBI cu 2
porturi) sau 16MB (EBI cu 3 porturi).
• Se pot utiliza atât circuite de memorie SRAM (RAM static) cat si
SDRAM (RAM dinamic sincron).
• SDRAM-ul oferă un preț de cost per bit mai mic, dar nu poate fi
utilizat combinat in același masiv de memorie externă, împreună cu
circuite de memorie care au o interfață de tip SRAM: memoria
externa de date este fie SRAM fie SDRAM
• Datorită suportului pentru memorii de dimensiuni mari, timing-ul
instrucțiunilor care accesează aceste memorii este modificat.
• Mai mult, atunci când se compilează o aplicație care utilizează
memoria externă, compilare făcută pentru un model de memorie
mare (large memory model), tipurile de date utilizate pentru
adresare (pointers) sunt afectate, ele trebuind să aibă 24 de biți,
nu 16 biți.
26
AVR XMEGA - motorul de criptare (Crypto
Engine)
• Atunci când se dorește securizarea aplicației si/sau
implementarea unor protocoale de comunicație sigure, cu fir
sau fără, utilizarea tehnicilor criptografice de securizare si
autentificare a informației este esențială.
• AVR XMEGA oferă un suport hardware pentru implementarea
tehnicilor criptografice
• XMEGA implementează, cu ajutorul unui modul dedicat si a
setului de instrucțiuni, doua standarde utilizate pentru
criptarea si decriptarea informației, AES- Advanced
Encryption Standard si DES- Data Encryption Standard.
• Algoritmii AES si DES sunt implementați de fapt de un modul
periferic –motorul de criptare - un accelerator hardware de
algoritm care poate funcționa practic independent de unitatea
centrală, descărcând-o pe aceasta de sarcina computațională
• Algoritmul DES este suportat si prin intermediul unei
instrucțiuni noi in setul de instrucțiuni al unității centrale
• Modulul poate poate trata blocuri de date de 128 de biți
folosind chei de criptare AES de 128 de biți sau DES de 64 de
biți
Observație Dimensiunea cheilor de criptare de 64 sau 128 de
biti este însă una modestă, actualmente utilizându-se pentru o
securizare fiabilă chei de criptare de 192 sau 256 de biți. 27
AVR XMEGA: alte caracteristici utile

• In memoria FLASH poate fi definită o zonă numită


Tabela de aplicație (Application Table) care să
asigure o emulare, cu protecție la defect, a
memoriei EEPROM.
• Aceasta înseamnă că se pot memora aici variabile
nevolatile („constante”), separat de codul
programului.
• Variabilele „constante” utilizate pentru calibrarea
oscilatoarelor interne pot fi memorate intr-o astfel de
zonă specială.
• Aceasta zonă este accesibilă, la citire si scriere, atât
pentru aplicație cat si pentru interfața externă de
programare.
• Dar aceasta zona nu va fi ștearsă atunci când
trebuie să ștergem memoria de program, la
reprogramarea aplicației, lucru foarte util intr-o
sesiune de testare si depanare.
28
AVR XMEGA: alte caracteristici utile -
2
• Posibilitatea utilizării unor numere de serie unice per
unitate de microcontroler, pe lângă identificatorul de
tip care există si la ATMega sau ATtiny.
• Astfel orice microcontroler XMEGA are un identificator
unic.
– O „semnătură” unică pentru fiecare dispozitiv este utilă, de
exemplu, la identificarea nodurilor într-o rețea incorporată si/sau
la generarea secvențelor de numere aleatoare.
• Existența unui modul hardware de calcul CRC (CRC16
sau CRC32, sunt polinoame cu redundanță ciclică, pe
numărul respectiv de biți) utilizate pentru a verifica
consistența/validitatea informative (daca ea nu a fost
corupta din diverse motive), pentru următoarele surse de
date:
– Memoria de program Flash, pe durata de viață a aplicației
(periodic sau la fiecare pornire) sau după o re-programare
(actualizare a aplicației).
– Fluxul de date provenind de la o interfață I/O
– Fluxul de date provenind de la un canal DMA 29
AVR XMEGA: programarea si depanarea In
–System
• XMEGA nu are o interfață ISP (In-System Programming)
bazată pe interfața SPI cum are ATMega
– Aceasta nu înseamnă ca XMEGA nu a are un periferic standard de
tip SPI, acestea exista in continuare, sunt mai multe, dar nu pot fi
utilizate pentru programare!
• De asemenea nu există nici o interfață cu un singur fir, de tip
DebugWIRE, cum găsim la unele microcontrolere ATTiny.
• Ele au fost înlocuite cu o interfață nouă, tot serială si sincronă,
utilizabilă pentru programare si depanare, având 2 fire (ceas
si date bidirecționale), numită PDI - Programming and
Debugging Interface.
• In același timp, programarea si depanarea folosind o interfață
standard JTAG este in continuare posibilă.
• Emulatoarele AVR JTAG cum ar fi JTAGICE mkII, produse
după 2009, pot folosi pentru programare si depanare ambele
tipuri de interfețe, JTAG si PDI.

30
Alte considerații legate de proiectarea hardware –
condensatorii de decuplare a alimentării
• Deoarece XMEGA poate sa funcționeze la frecvențe de ceas mai mari decât ATMega decuplarea
corespunzătoare a bornelor / pinilor de alimentare este esențială pentru menținerea unui nivel minim
de zgomot
• Tipic fiecare pin de alimentare de tip Vcc trebuie decuplat, individual, la masă, cu un capacitor
ceramic multistrat, tipic in jur de 100nF.
• Astfel un ATXMEGA C3, într-o capsulă TQFP cu 64 de pini are, de exemplu, 6 perechi de pini
alăturați, Vcc si Gnd (inclusiv AVcc) distribuite relativ uniform pe cele 4 laturi ale capsulei (vezi figura)
pentru conectare cu ușurință, si cu o amprenta minima, a capacitorilor de decuplare a alimentarii

31
Noile variante Attiny:Tiny AVR 1
(ATtiny seria 1)
• Tiny AVR 1 a fost prima (sub)familie apărută după cumpărarea lui Atmel
de către Microchip, fiind o familie care incorporează unele caracteristici ale
familiei XMEGA precum si unele caracteristici de la microcontrolerele PIC
Microchip.
• Este o familie ai cărei membrii (vezi mai jos) au o memorie de program
(Flash) maxima de 16 kOcteti/8 kcuvinte si capsule un număr maxim de 24
de pini, numai in variante SMD!
– Deocamdată exista in variante de încapsulare VQFN 3x3 si SOIC300 cu 20 de pini
• Tensiunea de alimentare este in gama 1.8..5.5V, corelata cu frecventa
maxima, care poate fi de la 5MHz la 1.8V la 20MHz la 5V
• Domeniul temperaturilor de lucru este de -40o..105oC sau -40o..125o C
• Prezentarea care urmează este doar una succintă punându-se accentul pe
resursele suplimentare fata de familia clasica ATtiny
– Restul informațiilor il găsiți in foile de catalog relevante!

32
Tiny AVR 1 vs. Tiny AVR
• Tiny AVR 1, pe lângă o
serie de noi periferice, are
si o nouă reprezentare (in
foile de catalog) si o nouă
organizare internă asociată
conceptului de periferice
independente de unitatea
centrala: Core Independent
Peripherals , concept care
provine de la Microchip
– Independente de unitatea
centrala adică se utilizează
cu ambele tipuri de unități
centrale de 8 biți: AVR si
PIC!
• In schema alăturată sunt
utilizate si noi acronime/
denumiri pentru periferice
care există deja la celelalte
familii de AVR; de exemplu
TCA in loc de Timer 0,
TCB, in loc de Timer 2,
sistemul de generare a
reset-ului se numește acum
RSTCTRL- Reset
Controller, etc.
33
Tiny AVR 1 vs. Tiny AVR – module noi
• Principalele diferențe ar fi, prin raportare si la schema bloc din
slide-ul anterior:
• CLKCTRL- Clock Controller , Clock Generation- sistemul de
generare a ceasului/ceasurilor este unul cu mai multe facilități si
mai flexibil decât la ATtiny si ATMega, dar mai puțin evoluat
decât cel de la XMEGA; nu are posibilitatea de multiplicare a
frecventei, dar există posibilitatea divizării frecvenței si a
modificării/ comutării ei dinamic
• UPDI- Universal Programming and Debugging Interface, o nouă
interfață de programare si depanare, de tip cu un singur fir (1-
Wire) oarecum similară cu interfața DebugWire
• CRCSCAN- Cyclic Redundancy Check Memory Scan, un modul
hardware care poate realiza verificarea întregii memorii Flash
folosind un polinom cu redundanță ciclică si poate semnala o
eroare (genera o întrerupere nemascabilă)
• DAC0- un sistem de conversie numeric analogic, cu un singur
canal, cu rezoluția de 8 biți
• EVSYS - Event System, sistem similar cu cel de la XMEGA,
dar ceva mai simplu, face posibilă “semnalizarea” directa de la
un periferic către altul, fără intervenția unității centrale
34
Tiny AVR 1 vs. Tiny AVR - module
noi - 2
• ADC/PTC- sistemul de conversie analog numeric ADC-Analog to
Digital Converter poate fi utilizat acum si ca un PTC- Peripheral
Touch Controller, împreună cu un modul hardware numit Qtouch
realizând astfel o nouă interfață care face posibilă detecția atingerii
(touch) unor senzori capacitivi externi
– Modulul Qtouch exista si la unele din variantele XMEGA
• VREF - Voltage References, un sistem flexibil de surse de tensiune
de referință, una pentru ADC si una pentru DAC, fiecare având 5
valori diferite: 0.55V, 1.1V, 1.5V, 2.5V, 4.3V
• CCL- Configurable Custom Logic, la fel ca la XMEGA este un circuit
logic programabil, cu care se pot implementa funcții logice
combinaționale sau secvențiale de relativ mică complexitate, dar
care poate elimina nevoia unor circuite numerice externe
suplimentare (glue logic).
• CPUINT- CPU Interrupt Controller, controlerul de intreruperi, este
similar, ca facilitați suplimentare cu cel de la XMEGA; are are nivele
de priorități, are o întrerupere nemascabila (NMI), etc.
• Setul de instrucțiuni - spre deosebire de varianta clasică de
ATTiny care nu are in setul de instrucțiuni de înmulțire (in virgula
fixa), ATTiny seria 1 are la nivelul CPU un multiplicator hardware (la
fel ca seria ATMega), existând astfel in setul de instrucțiuni toate
instrucțiunile de tip MUL 35
Microcontrolere (si
microprocesoare)
Microchip AVR 8 biți:
Medii integrate de dezvoltare a aplicațiilor software (IDE)
Metode de programare a memoriilor FLASH si EEPROM
si de depanare software: interfețe hardware si software

1
AVR Studio 4 (Atmel)
• AVR Studio 4 este un IDE freeware
pentru familia de microcontrolere AVR
8 biți dar care, nativ, nu include un
compilator C, el nu are decât un
asamblor, un editor de legături si un
simulator/depanator (care are
integrată si o interfață de programare)
• Este un produs matur, a cărui
dezvoltare s-a finalizat la versiunea +
4.18, SP3 sau versiunea finala 4.19
– Nu mai exista suport pentru versiuni mai noi
de microcontrolere AVR 8 biți
• AVR Studio 4 împreună cu
compilatorul C open-source
WinAVR (care este portarea lui Gnu
C pentru AVR 8 biți) reprezinta un
IDE complet
• O să-l utilizați la laborator sau teme
de casă si proiect!
2 2
Atmel Studio 6
• Atmel Studio 6 este un mediu integrat de dezvoltare a aplicațiilor software
produs de Atmel, din categoria freeware
• El înlocuiește in primul rând AVR Studio 5 (pe care este de recomandat să-l
evitați!) constituind o platformă unică de dezvoltare pentru microcontrolerele
AVR de 8 biți si 32 de biți precum si pentru familiile de microcontrolere de 32 de biți
Atmel ARM Cortex-M (familia SAM), cu avantajele dar si dezavantajele de rigoare!
• Are integrate propriile compilatoare de C, AVR GNU C Compiler (GCC) – din
familia compilatoarelor Gnu C, astfel că nu mai este nevoie de instalarea/utilizarea
unui alt compilator (ca la AVR Studio 4)
• Este un mediu de dezvoltare care suportă 3 arhitecturi de calcul diferite!
• Include editor, simulator, depanator, aplicații de programare care suportă o
gamă largă de mijloace hardware de programare si depanare
• Poate importa explicit proiectele mai vechi create cu AVR Studio 4 (AVR 8 biți)
• Este bazat pe tehnologiile Microsoft Visual Studio si .NET, kitul de instalare este
mare, are nevoie de o mașină gazdă puternică, cu multe resurse, dar oricum va
fi relativ lent!
• Utilizarea lui Atmel Studio 6 pentru AVR 8 biți nu se justifică decât dacă trebuie
utilizată o platformă hardware nouă sau foarte nouă care nu este suportată si
nici nu va fi de AVR Studio 4
• Observație Începând cu 2015 a fost lansat si Atmel Studio 7! Ultima versiune
este (a rămas) Atmel Studio 6.22
– El este descris ca un mediu de dezvoltare de productivitate maxima pentru toate procesoarele
produse de Atmel (achizitionat intre timp de Microchip)
3
Atmel Studio 7
• Atmel Studio 7 (actualmente - 2018 – este la versiunea 7.0) reprezintă o
dezvoltare a lui Atmel Studio 6, fiind descris acum ca un IDP (Integrated
Development Platform) , adică o platformă integrată de dezvoltare a aplicațiilor
• https://www.microchip.com/mplab/avr-support/atmel-studio-7
• Este in continuare un produs freeware
• In ecosistemul Microchip este ultimul produs Atmel care mai poarta explicit acest
nume!
• Este o platformă unică de dezvoltare pentru toate microcontrolerele AVR de 8
biți si AVR 32 de biți precum si pentru familiile de microcontrolere de 32 de biți
SAM (ARM Cortex-M), adică pentru peste 500 de variante AVR si SAM
• Se conectează direct cu toate sistemele de programare/depanare precum si cu
toate sistemele de dezvoltare Atmel/Microchip si nu numai
• Include Atmel Gallery un apps store online care permite extensia mediului de
dezvoltare cu multe module suplimentare (plug-ins) dezvoltate de
Atmel/Microchip sau terțe părți, multe din ele din categoria freeware
• Permite importul direct de programe/proiecte/schițe(sketches) Arduino ca
proiecte C++, asigurând o tranziție simpla de la Makerspace la Marketplace
• Este bazat pe tehnologia Microsoft Visual Studio Shell 2015 4
MPLAB X
• MPLAB este un IDE freeware proprietate a Microchip, in mod
tradițional utilizat pentru dezvoltarea aplicațiilor cu
microcontrolerele PIC si dsPIC
• Varianta clasică s-a oprit la MPLAB8.x fiind apoi urmată de actualul
MPLAB X
– MPLAB X este un IDE cross platforma, existând variante si pentru MacOS sau
Linux
• In ciuda promisiunilor Microchip că va păstra si dezvolta in
continuare produsul Atmel Studio 7 se pare că viitorul nu arată
chiar așa ..
• Începând cu MPLAB X versiunea 5.05 beta (sfârșitul lui 2018)
acesta include si suport pentru majoritatea microcontrolerelor AVR
8 biți din fabricație curentă
• Pe lângă compilatorul C standard XC8 (aplicații PIC) este adăugat
acum si AVR MCU GNU Compiler Collection (GCC) făcând
posibilă dezvoltarea aplicațiilor si cu AVR 8 biți
– In final XC8 probabil va îngloba suportul pentru portarea GCC pentru AVR 8 biti
5
IAR Embedded Workbench
for Atmel AVR

• Este un mediu integrat complet, similar lui (AVR) Studio, care conține
cel puțin toate componentele acestuia, pentru toate familiile AVR 8 biți
• Este un compilator si IDE comercial (contracost)
• Compilatorul de C/C++ este unul de firmă (proprietar), oarecum diferit
de WinAVR (sintaxa specifică nu este identică, exista macroinstrucțiuni
si biblioteci diferite), dar este cel mai performant compilator C (ca
optimizare dimensiune cod - viteză de execuție) pentru AVR 8 biți
– Majoritatea exemplelor in C din notele de aplicații Atmel/Microchip AVR
folosesc sintaxa IAR Systems
– IAR Systems a lucrat împreuna cu ATMEL (in anii ‘90) la dezvoltarea
simultană a compilatorului de C odată cu unitatea centrală AVR 8 biți
• Foarte multe facilitați suplimentare, funcție si de costul plătit; de
exemplu verificare MISRA C, suport pentru diverse RTOS-uri, etc.
• Este disponibila o varianta de evaluare aproape integral funcțională,
pentru 30 de zile si o variantă freeware (Kickstart) cu limita maximă a
codului generat de 4kOcteti
• Actualmente (2018) este la versiunea 7.10
– https://www.iar.com/iar-embedded-workbench/#!?architecture=AVR
6
Alte medii integrate de dezvoltare, alte
compilatoare – MikroElektronika
• Compania sârbă (da, este vorba de Republica
Serbia!) MikroElektronika produce o serie
întreagă de compilatoare (împreună cu IDE-urile
corespunzătoare) pentru limbajele C, Pascal si
Basic pentru microcontrolerele AVR 8 biți
• Compilatoarele respective sunt numite mikroC
(limbaj C), mikroPascal (limbaj Pascal) si
mikroBasic (limbaj Pascal)
• Sunt compilatoare/IDE-uri performante dar din
categoria celor comerciale (contracost)
– http://www.mikroe.com/avr/compilers/
• Compania mai produce si hardware:
programatoare, sisteme de dezvoltare disponibile
la marii distribuitori mondiali (Mouser, DigiKey,
Future, etc.)

7
Alte medii integrate de dezvoltare,
alte compilatoare si interpretere –
Arduino IDE
• Platforma Arduino IDE este o platformă de dezvoltare scrisă in Java,
este una din categoria open-source (la fel ca si hardware-ul utilizat) si
este derivată dintr-o serie de proiecte open-source mai vechi, cum ar fi
cele numite “Wiring” sau “Processing”
• Este destinată învățării programării de microcontrolere de către persoane
care nu sunt familiare cu dezvoltarea de aplicații software (nespecialiști!)
• Programele Arduino sunt scrise intr-un limbaj asemănător C/C++.
– Compilatorul este unul derivat din Gnu C/C++(gcc)
• Programele/proiectele Arduino, ca unități de cod, poartă denumirea de
“schițe”(sketches)
• Foarte important este că Arduino IDE are inclusă o bibliotecă extensiva
de funcții numită "Wiring" care facilitează in mod major operațiile de
intrare-ieșire (cu avantajele si dezavantajele de rigoare!)
– http://arduino.cc/
OBSERVATIE Nu toate platformele (plăcile) Arduino folosesc procesoare AVR de
8 biti! De exemplu Arduino Due folosește un procesor Atmel SAM3X8E ARM
Cortex-M3, un procesor de 32 de biți din familia ARM!

8
AVR 8 biti - Programarea “in sistem”-
ISP
• In System Programming (ISP)
• Microcontrolere: majoritatea variantelor MEGA si TINY
• Exemple de programatoare (hardware): AVR ISP MKI/II, AVR JTAG ICE MKII,
STK500, STK600, Dragon, diverse clone AVRISP, programatoare AVR910 (un
protocol descris in nota de aplicații ATMEL AVR910), AVR ONE
– STK500, STK600, Dragon sunt sisteme de dezvoltare universale
– AVR JTAG MKII si AVR ONE (cel mai recent si cel mai complet) sunt unelte de
programare si depanare evoluate
• Este poate cea mai comună metodă de programare a memoriei FLASH,
EEPROM, a fuzibilelor (inclusiv a celor de zăvorâre - lock) pentru aproape toate
variantele de AVR, fiind varianta preferată de hobby-isti datorită informației
bogate existente pe Internet (scheme, cablaje, software, etc)
• Folosește interfața SPI si poate asigura programarea la viteze de ceas foarte
mari (daca ele sunt suportate de microcontroler si de programator)
• AVR ISP este un produs mai vechi, pentru care există multe clone sau produse
similare (de exemplu PonyProg), in variante care se pot conecta la mașina
gazdă (PC) la:
– Un port paralel (imprimanta)
– Un port serial (mai lente)
• Atenție: programarea ISP cere ca frecvența de ceas a microcontrolerului
programat sa fie de cel puțin 4 ori mai mare decât frecvența ceasului utilizat de
programatorul ISP
9
AVR ISP- Programarea se poate face cu ajutorul unor programatoare
dedicate sau cu ajutorul unor sisteme de dezvoltare
AVR Dragon

STK-500

AVR ISP

STK-600
AVR ONE!

STK-500 si STK-600
sunt de fapt niste sisteme de
dezvoltare multifuncționale cu AVR,
produse de ATMEL
Similar AVR Dragon este un sistem Cele 2 variante de pin-out (6 pini si 10 pini)10ale
de dezvoltare mai simplu conectorului standardizat
AVR 8 biți- Programarea cu ajutorul
interfeței JTAG
• JTAG(Joint Test Action Group)
• Microcontrolere: majoritatea variantelor MEGA si XMEGA (cu număr mai mare de
pini)
• Exemple de programatoare (hardware): JTAG-ICE MKII, JTAG-ICE3, Dragon,
diverse clone JTAG-ICE, AVR ONE, STK600
• Tehnic vorbind JTAG este un sistem de depanare “in - sistem”, cu o interfață serială,
nu o metodă de a programa un AVR, dar acest sistem de interfață, intre alte funcții,
permite si programarea
– JTAG este un sistem care permite manipularea si examinarea stării unui microcontroler AVR
(in acest caz) in timpul execuției programului
– Interfața / sistemul de depanare JTAG permite oprirea execuției programului, examinarea
registrelor , a memoriilor si multe alt lucruri
• Programatorul JTAG-ICE MKII care a înlocuit mai vechiul JTAG-ICE, suportă
majoritatea variantelor de AVR care au interfața JTAG;
– in plus suportă si un nou protocol de depanare/programare numit DebugWire (pentru variante
de AVR cu număr mic de pini)
• Diversele “clone” neoficiale JTAG-ICE sunt disponibile si/sau realizabile pentru prețuri
mici (comparativ cu originalele) dar mai au probleme de compatibilitate cu toată seria
de AVR-uri cu interfață JTAG

11
JTAG ICE-3

JTAG ICE MkII

O “clona” JTAG ICE

O varianta de pin-out (10 pini) a unui


Conector JTAG standardizat

12
Sisteme (mai) moderne de dezvoltare din perioada Microchip si Atmel
pre-Microchip

Sistemele din perioada Microchip sunt de fapt sisteme cross-platformă disponibile


pentru AVR, PIC sau microcontrolere din familia ARM

Platforma Curiosity Nano


• Prima cross-platformă din perioada
Microchip
• Există o serie diversificată de module
periferice

Sistemele Xplained
• Provin din perioada Atmel
• Mai sunt încă programabile si ISP..

13
14
Programarea cu ajutorul interfeței
DebugWire
• DebugWire (dW)
• Microcontrolere: majoritatea variantelor MEGA si XMEGA cu număr mic de
pini, unele ATTiny (de exemplu ATtiny2313)
• Exemple de programatoare (hardware): AVR ISP Mk II, JTAG-ICE MKII,
JTAG-ICE3, Dragon, AVR ONE
• DebugWire este mai degrabă o interfață de depanare decât una de programare,
dar printre funcțiile sale este si una care permite programarea.
• Interfața dW folosește un singur pin, pinul /RESET, pentru a comunica cu
microcontrolerul AVR, făcând-o ideală pentru variantele cu un număr mic de pini
– Pinul /RESET (RST, NRST) se află oricum printre semnalele din conectorul
programatoarelor ISP si JTAG, așa că nu este nevoie de un conector special

OBSERVAȚIE
Utilizarea interfeței dW sau JTAG si a celei ISP
sunt exclusive (ori un ori alta), alegerea
făcându-se prin programarea unui fuzibil
numit SPI Enable.
Implicit este selectata interfața ISP, fuzibilul fiind
programat. 15
Programarea cu ajutorul unui programator paralel
(High Voltage - de înaltă tensiune)

• High Voltage Parallel Programming (HVPP)


• Microcontrolere: majoritatea variantelor MEGA si XMEGA cu număr
mare de pini
• Exemple de programatoare (hardware): STK500, STK600, Dragon,
AVRONE, diverse programatoare universale
• Este o metodă de programare mai rar utilizată, deoarece presupune
scoaterea microcontrolerului din sistem
• Este disponibilă doar la variantele cu număr mare de pini, pentru că se
folosesc magistrale externe de date, adrese plus semnale de control
pentru transferul paralel al informație către microcontroler
• Este utilizată si pentru a “învia” microcontrolerele AVR făcute
nefuncționale de o programare greșită a fuzibilelor (cu o altă metodă de
programare)
– Se numește de înaltă tensiune deoarece in acest proces pinul /RESET al
microcontrolerului este adus la tensiunea de +12 V (este înaltă fată de
+5V!)
– La microcontrolerele care suportă acest tip de programare, pinul /RESET
este singurul pin a cărui tensiune poate fi ridicată la tensiune de +12V, in
condiții de siguranță! 16
17
AVR 8 biti- Alte interfețe de
programare
• High Voltage Serial Programming (HVSP)
• Microcontrolere: multe variante de ATTiny cu număr mic de pini
• Exemple de programatoare (hardware): STK500, STK600, Dragon,
AVRONE, diverse diverse programatoare artizanale
• HVSP este similara HVPP, doar că datele sunt transferate serial, nu paralel,
făcând-o adecvată pentru variantele de AVR cu număr mic de pini (la care nu
putem avea o interfață externă paralelă)

• Program and Debug Interface (PDI)


• Microcontrolere: toate variantele XMEGA
• Exemple de programatoare (hardware): JTAG ICE MkII (după o anumita
data), JTAG ICE-3, STK600, AVRONE,
• PDI este o noua intrefață de programare, cu un număr redus de semnale,
utilizabilă doar pentru seria XMEGA, bazată pe protocolul lui debugWire

Conectorul are doar 4 fire (cu masă si


alimentare)
18
Alte interfețe de programare - 2
• Tiny Programming Interface (TPI)
• Microcontrolere: variantele de ATTiny cu 6 pini (ex. ATTINY10)
• Exemple de programatoare (hardware): STK600, Dragon,
JTAG-ICE3, Dragon, AVRISP MKII
• TPI este interfața de programare creata special pentru
variantele de AVR Tiny cu număr foarte mic de pini (6 pini)
• La fel ca la dW, TPI folosește pinul /RESET ca parte a interfeței
de comunicație, dar aici similitudinile se opresc
• Ea este doar o interfață de programare si nu si una de
depanare, care folosește doar 3 pini (linia de date DATA fiind
bidirecțională, ca la PDI).

19
AVR 8 biti- Programarea cu ajutorul unui
bootloader pre-programat
• Bootloaders
• Microcontrolere: toate variantele ATMEGA, XMEGA, doar unele din
ATTiny
• Exemple de programatoare (hardware): Nu sunt necesare, este
nevoie doar de “o sursă de date” cum ar fi tipic o conexiune serială
funcțională (RS-232, RS-485, CAN bus, I2C, etc. )
• Din punct de vedere tehnic nu este direct o metodă de programare
• Un bootloader este un mic program AVR rezident intr-o zonă specială
a memoriei de program FLASH, zona de bootloader (la variantele de
AVR care au o astfel de zonă! )
• Un program bootloader valorifică existența instrucțiunilor care permit
scrierea in memoria FLASH de program (de fapt in zona de aplicații a
ei) a informației care provine dintr-o sursa externă
• In mod tipic aceasta sursă este o conexiune serială funcțională (de ex.
RS-232), dar poate fi si un SD card sau un Data FLASH
• După programarea memoriei de program cu codul aplicație, tot
bootloaderul este responsabil cu lansarea ei in execuție
• Cu alte cuvinte un bootloader este un program mic care încarcă
(programează) si apoi lansează in execuție un program mare 20
Programarea cu ajutorul unui bootloader
(pre-programat) -2
• Principalele limitări ale unui bootloader sunt:
– dimensiunea relativ redusă a zonei bootloader din memoria FLASH (deci
el trebuie să fie foarte compact) trebuind ca spațiul cel mai mare să fie
rezervat aplicației propriu-zise
– in mod tipic, nu poate modifica/ programa si fuzibilele
• Un bootloader pune problema clasică a oului si găinii, in sensul că,
daca nu a fost deja programat la fabricant, totuși ne trebuie un
programator (din tipurile menționate anterior) pentru programarea lui!
• Există multe exemple de bootloadere AVR pe Internet, freeware sau
contra cost, si nu la toate este disponibil codul sursă;
– Vă sunt necesare atât codul bootloaderului cat si o aplicație care să
ruleze pe o mașină gazdă (PC) si să transfere datele (codul care va fi
programat)
– Aveți nevoie si de un programator din categoria celor deja mentionate
pentru a programa bootloaderul
– De exemplu o pereche aplicație PC - bootloader găsiți aici:
http://www.chip45.com/avr_bootloader_atmega_xmega_chip45boot2.ph
p
• Se pot cumpăra si AVR-uri cu un bootloader pre-programat, vezi
placa AVR Butterfly
(https://www.microchip.com/Developmenttools/ProductDetails/ATAV
RBFLY ) sau cazul sistemelor Arduino.
21
Programarea cu ajutorul unui bootloader pre-
programat - interfata USB
Actualmente (2018) avem următoarele variante AVR 8 biți cu interfață
USB integrata si bootloader USB:
• ATMEGA 8U2/ 16U2 / 32U2
• ATMEGA 16U4 / 32U4
• ATXMEGA A1U / A3U / A4U (familii)
• ATXMEGA C3U/C4U (familii)

•Device Firmware Upgrade


(DFU) este un mecanism, o
clasa USB, implementat
pentru a putea realiza
modificări ale firmware-ului
unui dispozitiv (programarea
lui)
• Un alt dispozitiv USB
Calculator gazda (host)
poate valorifica această
cu interfata USB
capabilitate (tipic asociat 22
unui calculator gazda)
Programarea cu ajutorul unui bootloader pre-
programat - interfata USB

• Pentru circuitele menționate anterior bootloaderul USB este pre-


programat “din fabrică”, in secțiunea “Bootloader Flash Section” a
memoriei FLASH de program
• Evident, dimensiunea secțiunii respective trebuie să fie mai mare sau
cel puțin egală cu dimensiunea codului mașină al bootloaderului
• Operațiile pe care le poate realiza bootloaderul USB:
– Ștergerea memoriei FLASH
– Ștergerea memoriei EEPROM
– Programarea/citirea memoriei FLASH
– Programarea/citirea memoriei EEPROM
• El NU poate realiza programarea fuzibilelor, care vor trebui eventual
programate cu un alt fel de programator
• Circuitele AVR cu bootloader USB sunt furnizate si cu fuzibilul
BOOTRST programat (BOOTRST=0) astfel ca vectorul de Reset va
indica prima instrucțiune in zona/ secțiunea Bootloader nu in cea de
Aplicații
• De exemplu, Arduino Leonardo utilizează bootloaderul USB al unui
ATMEGA32U4, iar un ATMEGA 16U2 este folosit pentru a implementa
un bootloader USB pentru un ATMEGA2560 in cazul Arduino
Mega2560.
23
AVRDUDE – o soluție de programare
AVR 8 biti open source

• AVRDUDE (AVR Downloader/UploaDEr) este o aplicație


PC open source care rulează sub Linux, FreeBSD,
Windows si Mac OS X, si care suportă o gamă largă de
mijloace de programare hardware/software : AVR ISP
mkII, Atmel JTAG ICE, diverse programatoare ISP (pe
portul paralel, serial sau USB) si bootloadere
• AVRDUDE este si un protocol de comunicație intre un
bootloader AVR 8 biti si o aplicație care rulează pe un PC
host
– Este protocolul utilizat de bootloaderul Arduino si de Arduino IDE
• Ca aplicație host este o aplicație in linie de comandă,
fără o interfață GUI nativă
– http://www.nongnu.org/avrdude/
– http://www.ladyada.net/learn/avr/avrdude.html
OBS. In absența unei interfețe grafice programarea fuzibilelor este
ceva mai dificila, ele fiind programate de fapt prin programarea
separata a celor 3 octeți speciali de memorie FLASH: high, low si
extended (vezi prezentarea despre fuzibile)
24
AVR USBasp – o soluție de programator
hardware “open source”

• Este cel mai ieftin programator AVR 8 biți, cu conectivitate USB,


care folosește protocolul AVRDUDE
• http://www.fischl.de/usbasp/
• https://blog.manash.me/setting-up-atmel-studio-for-usbasp-and-
avr-programming-802bb4dcf1e9
• https://www.youtube.com/watch?v=b9bazqLUysY
• http://www.ladyada.net/learn/avr/avrdude.html
• https://www.optimusdigital.ro/ro/programatoare/143-programator-
avr-
usbasp.html?gclid=EAIaIQobChMI29CAhI671wIVajPTCh1WtwqtE25
AAYASAAEgIpCPD_BwE
In AVR Studio 4 platforma de programare si
depanare este aleasă la crearea proiectului

Ea poate fi accesibilă
prin intermediul meniului
Tools

Sau al meniului Debug, odată


cu lansarea depanării (Start Debugging), având loc
si încărcarea programului
26
Atmel Studio 6.2/7
Alegerea variantei de microcontroler
(Device family, Name) se face
la crearea proiectului

Alegerea metodei de programare si depanare


(din lista Supported Tools) nu se face tot la
crearea proiectului, ci doar mai tarziu:
Properties (in Solution Explorer), Tool

27
Programarea si depanarea
(debugging) aplicației
• La fel de importantă ca programarea (codului aplicației) este testarea
si depanarea aplicației in sine.
• După programarea aplicației, depanarea presupune cel puțin:
posibilitatea lansării in execuție si opririi aplicației, a definirii unuia sau
mai multor puncte de oprire (breakpoints), a execuției pas cu pas
(instrucțiune cu instrucțiune sau linie cu linie), a examinării si modificării
stării unor resurse (memorii, registre, etc.).
• Cel puțin in ce privește mediile IDE Atmel (AVR Studio 4 sau Studio
6/7 pentru AVR 8 biți) programarea codului si depanarea lui este
extrem de asemănătoare, ca interfețe utilizator, ca proceduri de lucru,
ca informație utilă, fie că folosim simulatorul (AVR Simulator), fie că
folosim o platformă hardware (emulator, sistem de dezvoltare) din
categoria celor menționate.
• Cu alte cuvinte, din punct de vedere al utilizatorului, există puține
diferențe intre o sesiune de depanare realizată cu ajutorul simulatorului
si una realizată cu o platformă hardware dedicată: deci dacă știți să
utilizați simulatorul pentru depanare, veți ști, cu eforturi minimale, să
utilizați si o platformă hardware in același scop..
28

S-ar putea să vă placă și