Sunteți pe pagina 1din 141

Flaviu Nistor, Tudor Orlandea

Sisteme Incorporate
n exemple simple

Editura Universitii Lucian Blaga


Sibiu 2012

Flaviu Nistor, Tudor Orlandea


TITLU: Sisteme Incorporate n exemple simple
ISBN:

Refereni tiinifici:
Prof. dr. ing. Ioan P. Mihu
Sl. dr. ing. Beriliu Ilie

Chenar ISBN

Universitatea Lucian Blaga din Sibiu


Bd. Victoriei 10, 550024 Sibiu, RO

Cuprins
Prefa ............................................................................................................ 1
1. Introducere ................................................................................................. 2
1.1. Introducere ......................................................................................... 2
1.2. Mediul de dezvoltare MPLAB IDE ................................................... 2
1.2.1. Selectarea dispozitivului............................................................. 3
1.2.2. Crearea proiectului ..................................................................... 4
1.2.3. Setarea limbajului de programare (alegerea compilatorului
folosit pentru proiect) ........................................................................... 5
1.2.4. Denumirea proiectului ................................................................ 6
1.2.5. Adugarea fiierelor n proiect ................................................... 7
1.2.6. Setrile microcontrolerului ....................................................... 10
1.3. Descriere general - Low Pin Count Demo Board ......................... 11
1.4. Schema electric - Low Pin Count Demo Board ............................ 12
1.5. Layout - Low Pin Count Demo Board ........................................... 13
1.6. Lista de materiale - Low Pin Count Demo Board ............................ 13
1.7. Probleme propuse ............................................................................. 14
2. Embedded C ............................................................................................. 15
2.1. Introducere ....................................................................................... 15
2.2. Sintaxa limbajului C ......................................................................... 17
2.2.1. Comentarii ................................................................................ 17
2.2.2. Directive de pre-procesare........................................................ 18
2.2.3. Variabile ................................................................................... 20
2.2.4. Funcii ....................................................................................... 22
2.2.5. Operatori ................................................................................... 23
2.2.6. Instruciuni de control .............................................................. 27
2.3. Programare embedded ...................................................................... 29
2.3.1. Bucla infinit ............................................................................ 29

2.3.2. ntreruperile .............................................................................. 30


2.3.3. Operaii pe bii .......................................................................... 30
2.4. Aplicaie propus ............................................................................. 31
2.5. Probleme propuse ............................................................................. 32
3. Prezentare C ........................................................................................... 33
3.1. Introducere ....................................................................................... 33
3.2. Caracteristici principale PIC16F690 ............................................. 33
3.3. Diagrama pinilor i descrierea acestora: .......................................... 35
3.4. Arhitectura microcontrolerului PIC16F690 ..................................... 38
3.5. Harta memorie .................................................................................. 39
3.6. Probleme propuse ............................................................................. 40
4. Pinul de ieire (Output pin) ...................................................................... 42
4.1. Introducere ....................................................................................... 42
4.2. Pinul de ieire ................................................................................... 42
4.3. Limitri electrice: ............................................................................. 47
4.4. Probleme propuse ............................................................................. 47
4.5. Aplicaie propus ............................................................................. 47
4.6. Model Software ................................................................................ 49
4.7. Problem propus ............................................................................. 50
5. Pinul de intrare (Input pin) ....................................................................... 51
5.1. Introducere ....................................................................................... 51
5.2. Pinul de intrare ................................................................................. 52
5.3. Pull-up/Pull-down: ........................................................................... 57
5.4. Switch Debounce ............................................................................. 58
5.5. Probleme propuse ............................................................................. 60
5.6. Aplicaie propus ............................................................................. 60
5.7. Model software................................................................................. 62
5.8. Problem propus ............................................................................. 65
6. Timer 1 ..................................................................................................... 66

6.1. Introducere ....................................................................................... 66


6.2. Descriere Timer 1 ............................................................................. 66
6.3. Aplicaie propus ............................................................................. 71
6.4. Configurarea timer-ului .................................................................... 72
6.5. Model software................................................................................. 74
6.6. Problem propus ............................................................................. 78
7. Timer 2 ..................................................................................................... 80
7.1. Descriere Timer 2 ............................................................................. 80
7.2. Aplicaii propuse .............................................................................. 84
7.3. Configurarea timer-ului .................................................................... 86
7.4. Model software................................................................................. 87
7.5. Problem propus ............................................................................. 89
8. Servomotor ............................................................................................... 90
8.1. Introducere ....................................................................................... 90
8.2. Comanda unui servomotor ............................................................... 91
8.3. Aplicaie propus ............................................................................. 93
8.4. Model software................................................................................. 95
8.5. Problem propus ............................................................................. 97
9. Convertor Analog Numeric ...................................................................... 98
9.1. Introducere ....................................................................................... 98
9.2. Descriere ADC pe 10 bii ............................................................... 100
9.3. Aplicaie propus ........................................................................... 105
9.4. Configurarea ADC ......................................................................... 107
9.5. Model software............................................................................... 108
10. UART ................................................................................................... 111
10.1. Introducere ................................................................................... 111
10.2. Descriere modul UART ............................................................... 111
10.2.1. Blocul de transmisie ............................................................. 114
10.2.2. Blocul de recepie ................................................................. 115

10.2.3. Setarea ceasului (rata de transfer) ........................................ 116


10.2.4. Regitri de configurare ai modulului UART ........................ 118
10.3. Aplicaie propus ......................................................................... 122
10.4. Configurarea modulului UART ................................................... 122
10.5. Model software............................................................................. 124
Anexa 1 ...................................................................................................... 127
Anexa 2 ...................................................................................................... 131
Anexa 3 ...................................................................................................... 132
Bibliografie ................................................................................................ 135

Prefa
Noiunea de sistem incorporat este folosit tot mai des n zilele noastre n
domeniul hardware i software. Un sistem incorporat poate fi definit ca i
sistem dedicat, proiectat pentru a fi capabil s realizeze o anumit funcie
ntr-un sistem mai complex, iar pentru aceasta sarcin are nevoie de intrri
prin care s citeasc starea sistemului i de ieiri pentru controlul unor
procese.
Tot mai multe dispozitive folosite zi de zi au la baz un microcontroler.
Chiar i un banal filtru de cafea sau un usctor de pr au la baza un astfel de
circuit (compus dintr-o parte hardware pe care ruleaz o aplicaie software).
Tocmai din acest motiv nelegerea funcionrii unui microcontroler nu ar
trebui s lipseasc din bagajul de cunotine al unui absolvent de
electronic, electromecanic sau calculatoare.
Aceast carte are ca i scop introducerea cititorului n lumea embedded prin
nite pai progresivi, mprii n zece capitole care trateaz noiunile de
baz necesare realizrii unor proiecte simple care au la baz un
microcontroler.
Cartea dorete s fie un suport pentru orice student care o parcurge i un
punct de plecare pentru cei care vor s cunoasc lumea embedded n detaliu
prin studiu individual ulterior.
Cartea este scris de nite foti studeni pentru actualii studeni, ntr-un
format pe care l-au considerat potrivit ca un prim contact al cititorului cu
noiuni despre microcontroler i programarea acestuia.
Dorim s mulumim fotilor notri profesori Mihu P. Ioan, Ilie Beriliu si
Toma Emanoil care nu de puine ori au fost mai mult dect profesori pentru
noi n timpul anilor de studiu i un permanent sprijin n cadrul activitilor
noastre. Mulumim i companiei Continental i n special lui Sorin Ban
pentru sprijinul acordat n vederea tipririi acestei cri. Nu n ultimul rnd
mulumim tuturor celor care au avut rbdarea necesar pentru a citi
materialul i s-au asigurat de forma lui corect nainte de tiprire.
Sibiu, 21 ianuarie 2012

1. Introducere
1.1. Introducere
Aceast lucrare se dorete a fi un suport pentru disciplina Sisteme
Incorporate i prezint o abordare practic asupra aplicaiilor cu
microcontrolere. Pentru a putea parcurge cu uurin acest material, cititorul
are nevoie de cunotine de baz n electronic i noiuni introductive de
programare. Materialul cuprinde paii necesari pentru a porni la drum n
acest domeniu, oferind o perspectiv asupra celor dou componente majore:
electronic i software. Pentru ilustrarea acestor concepte prin proiecte
practice am ales folosirea unei plci de dezvoltare relativ uor de gsit pe
pia i anume placa Low Pin Count Demo Board, produs de firma
Microchip. Aceasta are la baz un microcontroler pe 8 bii numit
PIC16F690.
n prima parte a acestui material vom prezenta uneltele de baz de care
avem nevoie pentru a ncepe un proiect (mediul de dezvoltare, placa i
microcontrolerul folosit, bazele limbajului C), trecnd apoi la descrierea
celor mai uzuale module ale unui microcontroler (porturi GPIO, module
timer, ADC). Fiecare capitol este structurat n dou pri: prima conine
informaiile teoretice necesare, iar a doua cerine practice (cu explicaii i
fragmente de cod) i probleme propuse.
1.2. Mediul de dezvoltare MPLAB IDE
MPLAB IDE este o aplicaie PC oferit de ctre firma Microchip i are ca
scop facilitarea dezvoltrii de cod pentru proiectele care folosesc
microcontrolerele acestei firme. Funcionalitatea de baz a mediului de
dezvoltare incorporeaz editare de cod, compilare, suport flashing i debug.
Mediul de dezvoltare este disponibil gratuit pe site-ul firmei Microchip
(www.microchip.com). Pentru realizarea acestui material am folosit
MPLAB IDE versiunea 8.73.
Pentru a putea folosi funciile mediului de dezvoltare este necesar crearea
unui proiect ce conine sursele aplicaiei ct i setrile microcontrolerului.
Pentru a crea un proiect trebuie realizai urmtorii pai:

Introducere

1.2.1. Selectarea dispozitivului


Se va activa meniul Configure / SelectDevice
Figura 1-1: Selectarea dispozitivului

n fereastra deschis alegei PIC16F690 din lista disponibil.


Figura 1-2: Fereastra Select Device

Introducere

Ledurile care sunt prezente n fereastr, n dreptul diverselor componente


MPLAB, indic tipul de suport pentru dispozitivul selectat:
LED verde: suport total.
LED galben: suport preliminar care se va dezvolta ulterior. Se mai
folosete i termenul de versiunea a componentei.
LED rou: lips suport.
1.2.2. Crearea proiectului
Pentru a crea un proiect se folosete opiunea Project Wizard. Pentru
activarea acesteia se alege meniul Project / Project Wizard.
Figura 1-3: Fereastra de ncepere proiect Project Wizard

Se apas butonul Next.

Introducere

5
Figura 1-4: Fereastra de selecie microcontroler

n acest moment selectm microcontrolerul dorit. Dac n prealabil am


urmat pasul 1.2.1 (selectarea dispozitivului), n mod automat n fereastr va
fi indicat microcontrolerul selectat n primul pas.
Se apas butonul Next.
1.2.3. Setarea limbajului de programare (alegerea compilatorului folosit
pentru proiect)
Figura 1-5: Fereastra selecie compilator

Introducere

Pasul doi din Project Wizard este setarea compilatorului folosit. Bifai
csua Show all installed toolsuite i selectai HI-TECH Universal
ToolSuite din lista de unelte active. Dup selectarea toolsuite-ului, n
fereastra Toolsuite Contents va aprea HI-TECH ANSI C Compiler. n
cazul n care n dreptul acestuia apare un X rou, locaia compilatorului
trebuie specificat. Dac instalarea s-a fcut n prealabil n directorul
Microchip, locaia executabilului asociat va fi cea implicit. Compilatorul
poate fi instalat n orice alt director, iar n acest caz, cu ajutorul butonului
Browse, se va indica manual locaia executabilului.
Compilatorul HI-TECH Universal ToolSuite va fi folosit pentru toate
proiectele prezentate n acest material i se descarc separat de mediul
MPLAB de pe site-ul firmei Microchip. Varianta LITE este gratuit i ofer
funcionalitate de baz, optimizrile de cod fiind ns dezactivate dup 60 de
zile.
Se apas butonul Next.
1.2.4. Denumirea proiectului
Pasul trei din Project Wizard presupune alegerea unui nume pentru proiectul
la care lucrm ct i locaia unde acesta va fi salvat. Alegerea locaiei se
face folosind butonul Browse.
Figura 1-6: Alegerea locaiei proiectului

Se apas butonul Next.

Introducere

1.2.5. Adugarea fiierelor n proiect


Figura 1-7: Fereastra pentru adugarea de fiiere

Pasul patru permite selectarea i adugarea fiierelor pentru proiect. Dac n


prealabil avem create fiiere *.c sau *.h, le putem aduga n proiect folosind
butonul Add. n cazul de fa nu vom aduga niciun fiier, ele urmnd s fie
create i adugate ulterior.
Se apas butonul Next i se obine fereastra de ieire din Project Wizard.
n acest moment putem vizualiza setrile fcute.
Figura 1-8: Fereastra de finalizare a proiectului

Introducere

Se apas butonul Finish i vom vizualiza fereastra proiectului. n cazul n


care aceasta nu apare automat, o vom activa din meniul View / Project.
Figura 1-9: Vizualizare proiectului n MPLAB IDE

Se pot aduga sau terge fiiere din proiect, accesnd meniul adiional din
fereastra proiectului, prin apsarea butonului dreapta a mouse-ului. Spre
exemplu, prin click dreapta pe cmpul Source Files, putem aduga un fiier
nou.
Pentru a crea un fiier C i a-l aduga n proiect, efectuai urmtorii pai:
Activai meniul File / New. Va aprea o fereastr Untitled n care se poate
edita poriunea de cod dorit. Orice fiier C trebuie s aib urmtorul
schelet:

Introducere

9
Figura 1-10: Crearea unui fiier nou

Salvarea: La nchiderea ferestrei Untitled se va apsa butonul Save, iar mai


apoi se va denumi main.c (sau orice alt nume sugestiv) i se va salva n
directorul proiectului. n cazul n care csua Add File to Project va fi
bifat, atunci fiierul nou creat va fi adugat automat n proiect.
Figura 1-11: Salvarea unui fisier *.c

Dup executarea acestor pai, fiierul nou creat va aprea n fereastra


proiectului. Prin click dublu pe numele fiierului acesta se va deschide ntr-o
fereastr de editare, unde se pot aduce modificri.

10

Introducere
Figura 1-12: Fiierul main.c adugat in proiect

1.2.6. Setrile microcontrolerului


Fiecare microcontroler conine un set de regitri prin care se pot realiza
setrile de baz ale core-ului. Dei acetia pot fi modificai direct n cod,
mediul de programare MPLAB ne ofer posibilitatea de a modifica setrile
de baz direct dintr-o fereastr a meniului. Modificarea acestor setri va fi
ultimul pas din pornirea unui proiect i se realizeaz prin accesarea meniului
Configure / Configuration Bits. Setrile prezentate n Figura 1-13 sunt
setrile ce vor fi folosite pentru toate proiectele prezentate n acest material.
Pentru a putea modifica valorile, este necesar debifarea csuei
Configuration Bits set in code care va rmne debifat i dup selectarea
opiunilor dorite. La nchiderea ferestrei, configuraia creat se pstreaz.
Figura 1-13: Configurarea microcontrolerului

Introducere

11

n funcie de versiunea de MPLAB folosit, este posibil s apar diferene n


denumirea setrilor i a categoriilor. n exemplul folosit, singurele categorii
ce au fost modificate sunt Oscillator Selection bits, Watchdog Timer
Enable bit i MCLR Pin Function Select bit.
Observaie 1: Este extrem de important ca aceste setri s fie fcute la
nceputul fiecrui proiect i cu exact aceleai valori. n caz contrar, este
foarte probabil ca proiectele s nu produc rezultatul ateptat.
Observaie 2: Pentru a pstra setrile biilor de configuraie i modul n
care sunt aranjate ferestrele n mediul de dezvoltare, este necesar salvarea
spaiului de lucru (workspace). Acest lucru se poate face din meniul File /
Save workspace sau din fereastra aprut automat la nchiderea MPLAB.
1.3. Descriere general - Low Pin Count Demo Board
Low Pin Count Demo Board este o plac de dezvoltare simpl, pentru
microcontrolere cu capsula DIP de 20 pini. Este populat cu PIC16F690, 4
leduri, un push-button i un poteniometru. Placa de dezvoltare are mai
multe puncte de acces pentru pinii microcontrolerului i o zon dedicat
construciei de prototipuri. Programarea microcontrolerului se va face cu
ajutorul programatorului PICKIT 2.

12

Introducere

1.4. Schema electric - Low Pin Count Demo Board


Figura 1-14: Schema electric a plcii de dezvoltare [7]

Introducere

13

1.5. Layout - Low Pin Count Demo Board


Figura 1-15: Amplasarea componentelor [7]

1.6. Lista de materiale - Low Pin Count Demo Board


Tabelul 1-1: Lista de materiale
Nume component
Cantitate Descriere
C1,C2
2
Condensator ceramic THT, 0.1uF,
16V, 5%
R3-R6
4
Rezistor, 470, 5%, 1/8W
R2,R7
2
Rezistor, 1K, 5%, 1/8W
R1
1
Rezistor, 10K, 5%, 1/8W
RP1
1
Poteniometru 10K
DS1-DS4
4
LED, Red
SW1
1
Push buton

14
U1-Microcontroler
P1
J1
JP1-JP5

Introducere
1
1
1
5

20-pin MCU (PIC16F690)


Conector, 6 pini, 100 mils
Conector, 14 pini, 100 mils
Jumperi, 2 pini, 100 mils

1.7. Probleme propuse


a) Identificai urmtoarele componente din tabelul 6-1, pe schema electric
a plcii de dezvoltare Low Pin Count Demo Board ct i pe PCB-ul
plcii de dezvoltare. Care e rolul componentelor: C1, C2, R3-R6, R2,
R7, R1, RP1, DS1 - DS4?
b) Creai un proiect cu numele ProiectTest ntr-un director cu acelai nume
i adugai un fiier main.c care sa conin scheletul unui fiier *.c.
c) Realizai urmtoarele transformri
12310= .......................................2
011000112=...........10=..............16
D616=.......................2=..............10
F13B16=.....................................10
110101102=..............10=............16
5410=..........................2=............16
5416=..........................2=............10
d) Scriei tabelul de adevr pentru urmtoarele pori logice cu 2 intrri: I,
SAU i SAU-EXCLUSIV.

2. Embedded C
2.1. Introducere
Pentru a realiza controlul unui sistem incorporat cu microcontroler, avem
nevoie de un cod software care s ruleze pe acesta. Programul trebuie s se
foloseasc de resursele hardware disponibile, colectnd informaii prin
intermediul intrrilor (push-buttons, senzori digitali sau analogici, reele de
comunicaie .a.), n funcie de acestea controlnd ieirile (leduri, display
LCD, motoare .a.). Pentru a realiza acest lucru, fiecare procesor ofer un
set de instruciuni de baz, numite instruciuni main, cu ajutorul crora se
pot crea aplicaii. Dei aplicaiile pot fi scrise direct, folosind instruciuni
main, numrul redus de instruciuni existente duce la o complexitate mare
a codului. Din acest motiv, majoritatea aplicaiilor sunt scrise n limbaje de
programare de nivel nalt, folosindu-se un compilator pentru a transforma
codul scris de noi, n limbaj main. Cel mai rspndit limbaj folosit n
aplicaiile embedded este ANSI C.
Pentru a ne familiariza cu sintaxa limbajului C i cu elementele specifice
programrii embedded, n cele ce urmeaz vom analiza i explica un scurt
exemplu de cod. Mai multe informaii despre limbajul C i particulariti ale
programrii embedded putei gsi n Anexa 1.

16
EXEMPLUL 01:
#include "SI_L03_ex_01.h"
/* defines of constants and macros */
#define NUMAR_MAGIC 32
#define SUMA(a,b) ((a)+(b))
/* variable definitions */
unsigned int suma_01, suma_02;
/* function declarations */
void functie_01(void);
unsigned int suma(unsigned char b, unsigned int a);
/* function definitions */
void main()
{
unsigned char numar_01;
unsigned int numar_02;
numar_01 = 7;
numar_02 = 15;
suma_01 = SUMA(7,NUMAR_MAGIC);
suma_02 = suma(numar_01, numar_02);
if(suma_01 > suma_02)
{
functie_01();
}
else
{
suma_01 = suma_02 + NUMAR_MAGIC;
}
while(1)
{
;
}
} /* end main() function */

Embedded C

Embedded C

17

void functie_01(void)
{
; /* do nothing */
}
unsigned int suma(unsigned char b, unsigned int a)
{
unsigned int c;
c = a + b;
return c;
}
2.2. Sintaxa limbajului C
2.2.1. Comentarii
Folosindu-ne de exemplul anterior, putem ncepe s analizm codul i s
identificm componentele principale.
Probabil cel mai la ndemn element al sintaxei C sunt comentariile. Un
comentariu este un text introdus n cod pentru a aduga explicaii
suplimentare sau pentru a delimita prile componente ale unui cod. n
exemplul anterior se pot observa mai multe comentarii, acestea fiind textele
ncepute cu /* i ncheiate cu */. Comentariile de aceast form se pot
ntinde pe mai multe rnduri, atta timp ct sunt cuprinse ntre cele dou
delimitatoare:
/* tot acest text
este un comentariu pe mai multe rnduri */
Mai exist i posibilitatea de a folosi comentarii de o linie. Acestea sunt
ncepute cu // i se ncheie unde se termin rndul respectiv:
// acesta este un comentariu de un rnd
// pe noul rnd, delimitatorul fiind folosit din nou
Se recomand folosirea comentariilor pentru a aduga explicaii
suplimentare asupra funcionalitii implementate ntr-un cod. O
documentare bun a codului duce la o nelegere mai uoar i mai rapid n

18

Embedded C

cazul n care codul este folosit de o alt persoan sau dac este revizuit dup
o perioad mai lung de timp.
2.2.2. Directive de pre-procesare
Continum analiza exemplului cu codul folosit pe primul rnd:
#include "SI_L03_ex_01.h"
Acest rnd este o directiv de pre-procesare. nainte ca un fiier s fie
compilat, are loc etapa de pre-procesare. n acest moment, toate directivele
de pre-procesare, adic toate rndurile ce ncep cu #, sunt nlocuite cu cod C
normal. Spre exemplu, directiva #include va fi nlocuit cu ntreg coninutul
fiierului scris ntre ghilimele. La includerea unui fiier, n loc de ghilimele,
se pot folosi i semnele mai mare i mai mic dup cum urmeaz:
<SI_L03_exemplu_01.h>.
n codul din exemplu se mai pot observa alte directive de preprocesare:
#define NUMAR_MAGIC 32
Acest tip de instruciune (#define) duce la nlocuirea numelui simbolic din
stnga (NUMAR_MAGIC) cu codul din dreapta (32). Astfel, codul a =
NUMAR_MAGIC este echivalent cu a = 32. i atunci, ntrebare evident
este de ce s mai complicm codul folosind un nume simbolic n locul
valorii numerice? S presupunem c, spre deosebire de exemplul anterior,
constanta 32 este folosit n mai multe locuri n cod, n mai multe fiiere.
Dac, dup un anumit timp, decidem s schimbm valoarea 32 cu 77? n
acest moment, va trebui s cutm prin tot codul locurile unde am folosit
numrul 32 i s l nlocuim cu 77. Dac definim un nume simbolic pentru
valoarea 32, precum n exemplu, este suficient s schimbm valoarea ntr-un
singur loc, pre-procesarea nlocuind apoi n tot codul. Cnd folosim acest tip
de definire spunem despre numele simbolic asignat c este o constant.
Alt mod pentru a crea constante este prin folosirea calificativului const.
Explicaii despre acest calificativ se pot gsi n Anexa 1. n cele ce urmeaz
vom analiza un scurt exemplu n care sunt folosite cele dou tipuri de
constante. n imaginile de mai jos putem observa n partea stng codul C
iar n partea dreapt instruciunile n cod main rezultate dup compilare.

Embedded C

19
Figura 2-1: Comparaie ntre #define i const

Din acest exemplu (imaginea de mai sus) este evident c folosirea unei
constante prin #define produce un cod mai rapid, att n cazul n care
constantele se adun cu variabile care au 16 bii (cazul de sus) ct i n cazul
n care se adun cu variabile pe 8 bii (cazul de jos).
Ca i exemplu, pentru lucrul cu variabile pe 8 bii, instruciunea C:
sum_01 = variable + MACRO;

20

Embedded C

este alctuit din 5 instruciuni de asamblare n timp ce intruciunea


sum_02 = variable + constant;
este alctuit din 9 instruciuni de asamblare. Acest lucru se datoreaz
faptului c valoarea constantei constant trebuie adus de la adresa din
memorie de unde este salvat, n timp ce valoarea MACRO este prezent in
op-codul instruciunii. Iat deci c rularea primei variante este aproape de
dou ori mai rapid.
n schimb, aceste constante au i dezavantajul de a nu avea un tip de date
(ex: unsigned int) i deci compilatorul nu poate verifica dac sunt folosite n
mod corespunztor.
n exemplul iniial se mai poate observa un loc unde este folosit directiva
#define:
#define SUMA(a,b)

((a)+(b))

Aceasta are acelai rezultat prezentat anterior, doar c macroul definit


primete i parametrii. De exemplu, linia de cod:
suma_01 = SUMA(7,NUMAR_MAGIC);
va arta astfel dup preprocesare:
suma_01 = ((7)+(32));
Spunem despre SUMA c este un macro precum o funcie (function-like
macro) i are ca avantaje o execuie mai rapid fa de o funcie normal.
2.2.3. Variabile
Un alt element de baz al sintaxei C sunt variabilele. O variabil este, de
fapt, un spaiu alocat n memoria volatil (RAM) ce poate fi accesat de-a
lungul aplicaiei printr-un nume simbolic. nainte de a putea folosi o
variabil, aceasta trebuie declarat. n exemplul prezentat, sunt declarate
mai mult variabile:
unsigned int suma_01, suma_02;
unsigned char numar_01;
unsigned int numar_02;

Embedded C

21

Pentru a declara o variabil, trebuie specificat tipul acesteia i un nume


simbolic. Variabilele declarate de noi sunt de tip unsigned int i unsigned
char. De fapt, tipul lor este fie int fie char, calificativul unsigned nsemnnd
c acestea nu au semn. Atribuirea unei valori negative unei variabile
unsigned nu are sens i va produce rezultate neateptate. Declarnd o
variabil de tip char, compilatorul va rezerva n memorie un spaiu de 8 bii.
Dac acea variabil primete calificativul unsigned, ea va putea primi valori
n intervalul 0 - 255 (0x00 - 0xFF). Aceeai variabil declarat signed va
avea valori cuprinse ntre -128 i 127. O variabil signed char va folosi doar
7 bii pentru a salva valoarea i un bit pentru semn. Astfel, valoarea 0x8F
(0b1000_1111) pentru o variabil fr semn reprezint 143 n decimal, n
timp ce pentru o variabil cu semn este -113. Prin analogie, aceste reguli se
aplic i variabilelor ce ocup mai muli bii n memorie.
n tabelul urmtor sunt prezentate tipurile de date ntregi i valorile limit:

Tip de date
char
short
int
long

Tabel 2-1: Tipuri de date ntregi


Numr bii unsigned range signed range
8 bii
0 - 255
-128 - 127
16 bii
0 - 65535
-32768 - 32767
16 bii
0 - 65535
-32768 - 32767
32 bii
0 - 4294967295 -2147483648 2147483647

Observaie 1: Calificativul signed este unul implicit. Astfel, declarnd o


variabil folosind doar tipul de date, de exemplu char, este echivalent cu a o
declara signed char.
Observaie 2: Mrimea variabilelor int poate s difere n funcie de
platforma pentru care scriem codul i de compilatorul folosit, avnd fie 16,
fie 32 de bii. Pentru a evita rezultatele neateptate, este recomandat
cunoaterea exact a mrimii variabilelor int sau folosirea variabilelor short
sau long. Pentru platforma folosit n acest material, variabilele int ocup 16
bii.
Pentru operaii mai complexe exist i posibilitatea de a declara variabile cu
virgul mobil. Aceste tipuri sunt float i double i mrimea lor este, de
regul, 32 respectiv 64 de bii. Reprezentarea numerelor n virgul mobil

22

Embedded C

este mai complex dect cea a numerelor ntregi, motiv pentru care nu va fi
explicat n acest material.
2.2.4. Funcii
O funcie este o bucat delimitat de cod ce ndeplinete o sarcin specific
i poate fi executat din mai multe puncte ale aplicaiei. Funciile sunt
folosite pentru a mpri codul aplicaiei n mai multe subrutine generice.
Spre exemplu, dac ntr-un program avem nevoie s calculm de mai multe
ori rdcinile unei ecuaii de gradul al doilea, n loc s scriem de fiecare
dat toate calculele pentru aflarea acestora, vom crea o funcie generic ce
primete ca parametri de intrare ecuaia i returneaz rdcinile, aceasta
urmnd s fie chemat din codul principal de cte ori este nevoie.
n exemplul dat, se pot observa trei funcii: functie_01, suma i main. Putem
observa pentru functie_01 i suma c acestea apar de mai multe ori n cod.
Prima folosire a acestora este momentul n care sunt declarate:
void functie_01(void);
unsigned int suma(unsigned char b, unsigned int a);
Se observ c n momentul n care funciile sunt declarate, nu este specificat
i codul acestora. Declaraia unei funcii implic doar stabilirea numelui
acesteia, tipului returnat i tipurile datelor primite ca i parametri de intrare.
Tipul de date returnat este specificat nainte de numele generic al funciei iar
parametri sunt specificai n interiorul parantezelor, dup numele funciei.
Dac dorim ca o funcie s primeasc mai muli parametri, acetia vor fi
separai prin virgul.
Pentru prima funcie, numele este functie_01, tipul de date returnat este
void, iar funcia primete ca i parametru de intrare tot tipul void. Prin void
ca tip returnat nelegem c funcia nu returneaz nici o valoare iar void ca i
parametru de intrare nseamn c funcia nu primete nici un parametru.
Spre deosebire de functie_01, suma returneaz o variabil de tip unsigned
int i primete doi parametri, unul unsigned char iar al doilea unsigned int.
Al doilea moment n care ntlnim cele dou funcii, putem observa c
suntem n codul propriu-zis. Aici spunem despre funcii c sunt apelate sau
chemate. Chiar dac nc nu am definit codul funciilor, acestea au fost
declarate n prealabil i astfel compilatorul poate verifica dac ele sunt

Embedded C

23

apelate cu tipurile de date corecte. Fr declaraiile de la nceputul codului,


acest lucru nu ar fi fost posibil, compilatorul returnnd erori la ntlnirea
funciilor.
Al treilea loc n care funciile sunt ntlnite este momentul n care acestea
sunt definite. Se observ c numele, tipul returnat i cel al parametrilor sunt
specificai i aici, fiind identice cu declaraia. n cazul n care, din greeal,
apar diferene ntre declaraie i definiie, compilatorul ne returneaz o
eroare specificnd acest lucru. Definiia unei funcii difer de declaraie prin
faptul c este dat i corpul funciei. Codul ce compune corpul unei funcii
este cuprins ntre dou acolade { }. n cazul n care avem o funcie care
returneaz un tip de dat, ultima instruciune a funciei trebuie s fie
instruciunea return urmat de o variabil sau valoare de tipul specificat.
O a treia funcie poate fi observat n cod:
void main()
Aceasta este o funcie special, reprezentnd locul de unde pornete
aplicaia. Orice aplicaie trebuie s aib o funcie main, aceasta fiind prima
care se cheam cnd aplicaia ruleaz. Se poate observa c aceast funcie
este direct definit, fr s fie i declarat. Acest lucru este posibil deoarece
funcia nu este chemat explicit din alte pri ale programului.
2.2.5. Operatori
Pentru a realiza diversele sarcini ale unei aplicaii, limbajul de programare
pune la dispoziie un set fix de operatori. Cel mai des folosii sunt operatorii
aritmetici, acetia fiind foarte asemntori cu operaiile matematice
elementare:

24

Embedded C

Tabelul 2-2: Operatori aritmetici


Operaie
Simbol
Sintax
Atribuire
=
a=b
Adunare
+
a+b
Scdere
a-b
nmulire
*
a*b
mprire
/
a/b
Modulo
%
a%b
pre-incrementare
++
++a
post-incrementare
++
a++
pre-decrementare
---a
post-decrementare
-a-Atribuirea este cea mai simpl operaie disponibil, prin aceasta asignnduse valoarea din dreapta semnului egal, variabilei din stnga acestuia. n
partea dreapt putem avea fie o valoare direct, fie o variabil, fie o expresie
compus din mai multe operaii.
Adunarea, scderea i nmulirea sunt asemenea operaiilor matematice, cu o
singur meniune: n momentul n care acestea sunt folosite trebuie s se
in cont de mrimea operanzilor. n cazul n care se face, spre exemplu, o
adunare ntre dou numere pe 16 bii, rezultatul ar putea depi limita
maxim a unei variabile pe 16 bii. n cazul n care rezultatul nu este salvat
ntr-o variabil cu dimensiuni mai mari, parte din acesta se va pierde.
mprirea pe ntregi atribuit tot unui ntreg va duce doar la pstrarea prii
ntregi a rezultatului. mprind pe ntregi 10 la 3 va avea ca rezultat
valoarea 3. Strns legat de mprire este i operaia modulo, care are
acelai rezultat ca i operaia matematic. Astfel, 10 modulo 3 va avea ca
rezultat valoarea 1.
Ultimii operatori rmai se comport asemntor i sunt numii operatori
unari, deoarece se aplic unui singur operand. Folosirea operatorilor de
incrementare sau decrementare duce la adunarea sau scderea valorii 1 din
operand iar poziionarea operatorului, post sau pre operand, duce la
schimbarea ordinii operaiilor ntr-o expresie. De exemplu, preincrementarea duce mai nti la modificarea operandului i apoi la folosirea

Embedded C

25

acestuia n expresie, n timp ce post-incrementarea duce la folosirea


operandului n expresie i doar apoi la modificarea valorii acestuia.
Pe lng operatorii aritmetici, limbajul mai pune la dispoziie i operatori de
comparaie i operatori logici:
Tabelul 2-3: Operatori de comparaie i operatori logici
Operaie
Simbol
Sintax
Egal
==
a == b
nu este egal
!=
a != b
mai mare
>
a>b
mai mic
<
a<b
mai mare sau egal
>=
a >= b
mai mic sau egal
<=
a <= b
Negare
!
!a
I logic
&&
a && b
SAU logic
||
a || b
Operatorii de comparaie pot fi folosii pentru a lua decizii pe parcursul
aplicaiei. Acetia pot fi folosii att pentru a compara variabile ct i
constante sau direct expresii. Rezultatul unei operaii de comparaie este
egal cu 1 dac rezultatul este adevrat sau 0 dac rezultatul este fals.
Operatorii logici sunt folosii pentru a nlnui mai multe expresii de
comparaie. Un I logic ntre mai multe expresii are rezultatul 1 doar dac
toate rezultatele acelor expresii sunt 1. Un SAU logic ntre mai multe
expresii va avea rezultatul 0 doar dac toate rezultatele expresiilor sunt 0.
A treia categorie de operatori este cea a operatorilor pe bii.
Tabel 2-4: Operatori pe bii
Operaie
Simbol
Sintax
negare pe bii
~
~a
I pe bii
&
a&b
SAU pe bii
|
a|b
XOR pe bii
^
a^b
Deplasare la stnga pe bii
<<
a << b

26
Deplasare la dreapta pe bii

Embedded C
>>

a >> b

Primii patru operatori din tabel produc rezultatele operaiilor logice


reprezentate dar se ntmpl la nivelul fiecrui bit al operanzilor. Avnd
valoarea pe 8 bii 0b1010_1010, rezultatul unei negri pe bii va fi
~(0b1010_1010) = 0b0101_0101.
Dac realizm un I pe bii ntre valorile:
0b1100_1100 &
0b1010_1010, rezultatul va fi
------------------0b1000_1000.
Dac realizm un SAU pe bii ntre valorile:
0b0100_1100 |
0b1010_0010, rezultatul va fi
------------------0b1110_1110.
Operaiile logice I i SAU sunt des folosite n lucrul cu anumii bii ai unui
registru prin aa numitele mti. De exemplu, dac dorim s setm doar
bitul 3 de la o anumit adres, fr a modifica starea celorlali bii, vom
folosi operaia SAU:
registru = registru | 0b0000_1000;
Dac dorim s tergem doar bitul 5, fr a modifica valoarea celorlali bii
din registru, vom face o masc cu operaia I:
registru = registru & 0b1101_1111;
n ultimul exemplu vom face o masc folosind operaia I pentru a verifica
doar starea bitului 4 dintr-un registru (care poate fi, spre exemplu, un flag):
if ( ( registru & 0b0001_0000) == 0b0001_0000)
{ ... }

Embedded C

27

Operaiile pentru deplasare pe bii au ca rezultat mutarea biilor primului


operand cu numrul de poziii egal cu al doilea operand. Astfel, valoarea
0b0000_0101 deplasat la stnga cu 3 va avea ca rezultat:
(0b0000_0101)<<3 = 0b0010_1000.
La folosirea acestor operanzi trebuie inut cont de mrimea variabilelor. n
exemplul anterior, o deplasare cu mai mult de 8 poziii pe o variabil pe 8
bii va avea ca rezultat 0.
Observaie: Deplasarea la stnga sau dreapta cu un anume numr de bii
este echivalent cu nmulirea sau mprirea cu puteri ale lui 2.
2.2.6. Instruciuni de control
Datorit faptului c o aplicaie nu poate rula doar secvenial, avem nevoie
de instruciuni care s modifice cursul de execuie al unui program. Cele
mai uzuale astfel de instruciuni vor fi prezentate n continuare.
Instruciunile if i else sunt folosite de regul n pereche dup cum urmeaz:
if( expresie )
{
... /* cod_01 */
}
else
{
... /* cod_02 */
}
n cazul n care expresia din dreptul instruciunii if este adevrat, codul
cuprins ntre primele dou acolade se va executa (cod_01). n caz contrar se
va executa al doilea bloc (cod_02). Instruciunile if else se pot combina
pentru a forma multiple ci de execuie dup cum urmeaz:
if( expresie_01 )
{ ... /* cod_01 */ }
else if( expresie_02)
{ ... /* cod_02 */ }
else
{ ... /* cod_03 */ }

28

Embedded C

Asemntor instruciunilor if else, este instruciunea switch, aceasta


deosebindu-se ns prin faptul c n loc de o expresie care s determine
calea de execuie, este folosit o valoare ntreag.
switch( valoare )
{
case 0: ... /* cod_01 */
break;
case 1: ... /* cod_02 */
break;
..........
default: ... /* cod_default */
break;
}
Dac valoarea din dreptul instruciunii switch este 0, atunci cod_01 se va
executa. Dac valoarea este 1, cod_02 va rula. n cazul n care valoarea nu
este printre cele specificate n dreptul instruciunilor case, se va executa
cod_default. De observat este faptul c fiecare caz se ncheie cu o
instruciune break. Dac aceasta nu este prezent, codul va rula n
continuare (trecnd i prin alte cazuri) pn la ntlnirea primului break sau
pn la ncheierea blocului instruciunii switch.
n cadrul instruciunilor de control ntlnim i instruciuni de bucl precum
instruciunea while.
while( expresie )
{
... /* cod */
}
Aceast instruciune permite executarea codului din blocul delimitat de
acolade atta timp ct expresia din paranteze este adevrat. Dac la prima
trecere prin bucl expresia nu este adevrat, codul nu se va executa
niciodat. Expresia este reevaluat de fiecare dat dup ce codul dintre
acolade a fost executat. Dac dorim cel puin o execuie a codului, putem
folosi instruciunea do while dup cum urmeaz:

Embedded C

29

do
{
... /* cod */
} while( expresie );
Alt instruciune ce poate fi folosit pentru a crea bucle este instruciunea
for dup cum urmeaz:
int i;
for(i = 0; i < 10; i++)
{
... /* cod */
}
Prima observaie n ceea ce privete aceast instruciune este faptul c avem
nevoie de o variabil declarat pentru a realiza bucla. La nceputul buclei,
variabilei i i este atribuit valoarea 0. Condiia de execuie a buclei este i <
10 iar dup execuia codului, se incrementeaz variabila de control i++.
Astfel, codul din interiorul acoladelor se va executa atta timp ct i este mai
mic dect 10 i anume de 10 ori.
2.3. Programare embedded
Limbajul C este un limbaj general, menit s ruleze pe orice platform. Din
aceste motive, n funcie de locul unde este folosit, apar anumite
particulariti.
n aplicaiile create pentru sisteme incorporate se pot observa o serie de
particulariti ce vor fi prezentate n cele ce urmeaz.
2.3.1. Bucla infinit
n cazul unui program scris special pentru un PC, nu trebuie acordat mare
atenie asupra contextului unde acesta va rula, deoarece sistemul de operare
se va ocupa de aceste detalii. n cazul unui sistem incorporat, unde gestiunea
aceasta nu este realizat, avem nevoie s introducem n cod diverse
mecanisme de control. Bucla infinit este unul din aceste mecanisme i prin
folosirea ei se evit rechemarea funciei main de fiecare dat dup ce
execuia a ajuns la captul acesteia. Spre exemplu, dac n codul prezentat la
nceputul capitolului nu am fi adugat o bucl infinit la captul funciei
main, programul ar fi fost reluat la nesfrit. Dac, spre exemplu, primele

30

Embedded C

aciuni fcute de aplicaie n funcia main ar fi fost iniializri hardware,


acestea ar fi fost i ele reluate de fiecare dat. Este evident c acest lucru nu
este un comportament adecvat. Din acest motiv, de regul, funcionalitatea
unui sistem incorporat este realizat n cadrul unui bucle infinite.
while( 1 ){ ... /* cod aplicaie */ }
2.3.2. ntreruperile
O ntrerupere este definit ca un mecanism hardware oferit de ctre
platforma pe care ruleaz aplicaia, prin care se ntrerupe irul curent de
execuie i se ruleaz o alt bucat de cod n funcie de anumii stimuli
externi. Spre exemplu, o aplicaie ar putea fi ntrerupt n momentul n care
este apsat un buton pentru a executa alt bucat de cod ce trateaz acest
eveniment. Pentru a ne folosi de acest mecanism, trebuie mai nti s
configurm sursa respectiv de ntrerupere, n funcie de platforma folosit,
iar apoi s scriem codul ce se va executa la activarea ntreruperii.
O rutin de tratare a unei ntreruperi este o bucat de cod, asemntoare unei
funcii, care se cheam prin intermediul unor mecanisme hardware. Aceast
funcie nu primete argumente i nici nu returneaz nici o valoare. De obicei
se urmrete ca ntreruperile s se execute ct mai repede, pentru a deranja
ct mai puin aplicaia principal.
Pentru platforma folosit n acest material, avem posibilitatea de a defini o
singur rutin de tratare a tuturor surselor de ntrerupere dup cum urmeaz:
void interrupt isr(void)
2.3.3. Operaii pe bii
Datorit faptului c muli regitri de configurare necesit setarea doar a
anumitor bii, n aplicaiile incorporate sunt foarte importante operaiile pe
bii. De exemplu, dac dorim s scriem 1 doar n bitul trei al unui registru pe
8 bii i s lsm neschimbate valorile celorlali bii, n loc s citim registrul
i s l rescriem n funcie de valoarea acestuia, e suficient s realizm un
SAU logic cu valoarea 0b0000_1000. Astfel, toate valorile n afar de cea a
bitului trei vor rmne neschimbate iar bitul trei va lua valoarea 1 indiferent
de ce valoare are.

Embedded C

31

Operaiile pe bii sunt att de des folosite nct exist i denumiri specifice
pentru scrierea unui bit cu o anumit valoare. Se spune despre un bit n care
se scrie 1 c acesta este setat, iar cnd scriem 0 c este resetat.
Alt denumire des folosit este aceea de flag. Un flag este un bit, un registru
sau o variabil indicatoare de stare. Dac spunem c flag-ul unei anumite
ntreruperi a fost setat, nseamn c bitul indicator de stare corelat acelei
ntreruperi a luat valoarea 1.
2.4. Aplicaie propus
Pentru a putea vedea cum se comport codul din exemplul prezentat, avem
opiunea de a l rula folosind un debugger simulat de ctre mediul de
dezvoltare MPLAB. Pentru a realiza acest lucru, trebuie urmai paii:
a) Creai un proiect i adugai un fiier ce conine codul prezentat la
nceputul acestui capitol. Compilai proiectul accesnd meniul Project /
Build sau butonul

din bara principal.

b) Din meniul principal, selectai Debugger, apoi Select Tool iar apoi
opiunea 4.MPLAB SIM. Observai noul panou de comand aprut.
c) Pentru a opri execuia unui program, avem posibilitatea de a selecta
breakpoints. Acestea se adaug prin click dublu pe o anumit linie de
cod. Adugai un breakpoint pe linia 18 (numar_01 = 7;).
d) Din meniul debugger-ului, apsai butonul Run
aplicaia.

pentru a porni

e) Din bara de meniu principal, selectai View iar apoi Watch. Noua
fereastr deschis ne ofer un mod de a vedea valorile variabilelor sau a
regitrilor. Din dreptul butonului Add Symbol, selectai variabilele
folosite n codul principal: numar_01, numar_02, suma_01 i suma_02,
ct i cele folosite n funcia suma: a, b i c. Dup selectarea fiecrei
variabile, trebuie apsat butonul Add Symbol.
f) Folosind butonul Step Into
din panoul debugger-ului, rulai
aplicaie pn la bucla infinit i observai irul de execuie al acesteia
ct i valorile luate de ctre variabile.

32

Embedded C

g) ncercai i celelalte butoane de pe panoul debugger-ului i


experimentai aciunile acestora.
2.5. Probleme propuse
a) Descriei ce efect are urmtoarea linie de cod:
const unsigned char a = 10;
b) Scriei rezultatul urmtoarelor operaii cu a = 3 i b = 4:
c = a+++b; a =
c = ++a+b; a =

b=
b=

c=
c=

c) Folosind proiectul oferit ca exemplu, declarai n funcia main nc trei


variabile de tip unsigned int a, b i c. Primele dou iau valorile 0xFF00
i 0x0101. Atribuii variabilei c rezultatul sumei dintre a i b. Ce valoare
ia c?

3. Prezentare C
3.1. Introducere
n cadrul acestui capitol va fi prezentat pe scurt microcontrolerul
PIC16F690.
3.2. Caracteristici principale PIC16F690
a) RISC CPU:
35 instruciuni single-word.
Toate instruciunile sunt single-cycle, exceptnd instruciunile de
salt (program branch) care sunt two-cycle.
Frecvena maxim de funcionare: DC 20MHz clock input; DC 200ns ciclul de instruciune.
Memorie program (flash) 4Kx14 words. 4K de cuvinte a cte 14 bii
pentru codificarea instruciunilor, ceea ce nseamn o memorie
program de 7K.
Memorie de date (RAM) 256x8 bytes. Adic, 265 de bytes (octei) a
cte 8 bii fiecare, memorie folosit pentru salvarea variabilelor.
Configuraia pinilor compatibil fie pentru capsul de 20 pini PDIP,
fie pentru SOIC, SSOP i QFN.
b) Periferice digitale:
Timer 0: 8-bit timer/counter cu pre-scalar pe 8 bii.
Timer 1: 16-bit timer/counter cu pre-scalar. Numrtorul (counter)
poate fi incrementat i n modul Sleep.
Timer 2: 8-bit timer/counter cu registru de perioad pe 8 bii, prescalar i post-scalar.
Dou module Enhanced Capture/Compare/PWM: Capture pe 16 bii
cu rezoluie maxim 12.5ns; Compare pe 16 bii cu rezoluie maxim
200ns; PWM cu rezoluie pe 10 bii i frecven maxim de 20KHz.
Comunicare serial sincron prin SPI (Master mode sau Slave mode) i
I2C (Master/Slave mode).
Comunicare serial asincron/sincron prin UART/SCI cu posibilitatea
de detecie 9-bit address mode. Suport modul RS-232, RS-485 i
LIN2.0.

Prezentare C

34

Memorie de date EEPROM 256x8 bytes. 256 de bytes a cte 8 bii


pentru salvarea datelor in EEPROM.
Circuit de detecie Brown-out detection pentru Brown-out Reset
(BOR).
c) Periferice analogice:
Convertor analog-digital (A/D) pe 10 bii, pe 12 canale.
Brown-out Reset.
Dou comparatoare analogice cu tensiune de referin programabil
i intrrile selectabile printr-un multiplexor.
d) Caracteristici specifice:
100.000 de cicli erase/write pentru memoria de program (flash).
1.000.000 de cicli erase/write pentru memoria de date EEPROM.
Memoria EEPROM menine datele nealterate (data retention) > 40 de
ani.
Programare In-circuit-serial-programming (ICSP) via doi pini.
Necesit o singur tensiune de alimentare de 5V pentru ICSP.
Watch Dog Timer (WDT) cu propriul circuit de oscilaie on-chip de
tip RC.
Cod de protecie programabil.
Sleep mode pentru reducerea consumului de energie.
Diverse surse selectabile pentru oscilator.
In-circuit-debug (ICD) via doi pini.

Prezentare C

35

3.3. Diagrama pinilor i descrierea acestora:


Figura 3-1: Diagrama pinilor pentru capsula 20-pin PDIP, SOIC, SSOP [6]

Placa de dezvoltare Low Pin Count Demo Board dispune de un


microcontroler PIC16F690 cu capsul 20-pin PDIP, n tehnologie THT
(Through Hole Tehnology).
Tabel 3-1: Descrierea funcionalitii pinilor [6]
Nume

RA0/AN0/C1I
N+
/ICSPDAT/UL
PWU

RA1/AN1/C12I
N0/VREF/ICSPCL
K

RA2/AN2/T0C
LK
/INT/C1OUT

RA3/MCLR/VP
P

Funcie

Tip
intrare

Tip ieire

RA0

TTL

CMOS

AN0
CIN+
ICSPDAT
ULPWU

AN
AN
TTL
AN

CMOS
-

RA1

TTL

CMOS

AN1
C12IN0-

AN
AN

VREF

AN

ICSPCLK

ST

RA2

ST

CMOS

AN2
T0CLK
INT
C1OUT

AN
ST
ST
-

CMOS

RA3

TTL

MCLR
VPP

ST
HV

Descriere
Pin general de intrare ieire. Activare
individual de pull-up.
Intrarea 0 A/D.
Intrarea pozitiv a comparatorului C1.
ICSP DATA I/O.
Intrare de Wake-up Ultra Low-Power.
Pin general de intrare ieire. Activare
individual de pull-up.
Intrarea 1 A/D.
Intrarea negativ a comparatorului C1 sau C2.
Tensiune de referin extern pentru
convertorul A/D.
Ceas pentru ICSP.
Pin general de intrare ieire. Activare
individual de pull-up.
Intrarea 2 A/D.
Ceas de intrare pentru Timer0.
Pin pentru ntrerupere extern.
Ieirea comparatorului C1.
Pin general de intrare ieire. Activare
individual de pull-up.
Pin de RESET general cu pull-up intern.
Tensiunea de programare.

Prezentare C

36

RA4/AN3/T1G
/OSC2/CLKOU
T

RA5/T1CLK/
OSC1/CLKIN

RB4/AN10/
SDI/SDA

RB5/AN11/RX/
DT

RB6/SCK/SCL

RB7/TX/CK

RC0/AN4/C2I
N+

RC1/AN5/C12I
N1-

RC2/AN6/C12I
N2-/P1D

RC3/AN7/C12I
N3-/P1C

RC4/C2OUT/P
1B

RA4

TTL

CMOS

AN3
TIG
OSC2
CLKOUT

AN
ST
-

XTAL
CMOS

RA5

TTL

CMOS

T1CLK
OSC1
CLKIN

ST
ST

XTAL
-

RB4

TTL

CMOS

AN10
SDI
SDA

AN
ST
ST

OD

RB5

TTL

CMOS

AN11
RX
DT

AN
ST
ST

CMOS

RB6

TTL

CMOS

SCK
SCL

ST
ST

CMOS
OD

RB7

TTL

CMOS

TX
CK

ST

CMOS
CMOS

RC0

ST

CMOS

AN4
C2IN+

AN
AN

RC1

ST

CMOS

AN5
C12IN1-

AN
AN

RC2

ST

CMOS

AN6
C12IN2P1D

AN
AN
-

CMOS

RC3

ST

CMOS

AN7
C12IN3P1C

AN
AN
-

CMOS

RC4

ST

CMOS

C2OUT
P1B

CMOS
CMOS

Pin general de intrare ieire. Activare


individual de pull-up.
Intrarea 3 A/D.
Intrare de validare a Timer1.
Quartz/Rezonator.
Pin de iesire frecventa Fosc/4.
Pin general de intrare ieire. Activare
individual de pull-up.
Ceas de intrare pentru Timer1.
Quartz/Rezonator.
Intrare de ceas extern/ Oscilator RC.
Pin general de intrare ieire. Activare
individual de pull-up.
Intrarea 10 A/D.
Pin intrare SPI.
Pin de date intrare/iesire I2CTM.
Pin general de intrare ieire. Activare
individual de pull-up.
Intrarea 11 A/D.
Intrarea asincron EUART.
Pin de date sincron EUART.
Pin general de intrare ieire. Activare
individual de pull-up.
Ceas pentru SPI.
Pin de ceas I2CTM.
Pin general de intrare ieire. Activare
individual de pull-up.
Iesire asincron EUART.
Pin de ceas sincron EUART.
Pin general de intrare ieire. Activare
individual de pull-up.
Intrarea 4 A/D.
Intrarea pozitiv a comparatorului C2.
Pin general de intrare ieire. Activare
individual de pull-up.
Intrarea 5 A/D.
Intrarea negativ a comparatorului C1 sau C2.
Pin general de intrare ieire. Activare
individual de pull-up.
Intrarea 6 A/D.
Intrarea negativ a comparatorului C1 sau C2.
Iesire PWM.
Pin general de intrare ieire. Activare
individual de pull-up.
Intrarea 7 A/D.
Intrarea negativ a comparatorului C1 sau C2.
Ieire PWM.
Pin general de intrare ieire. Activare
individual de pull-up.
Ieirea comparatorului C2.
Ieire PWM.

Prezentare C
RC5/CCP1/P1
A

RC6/AN8/SS

RC7/AN9/SDO

37
RC5

ST

CMOS

CCP1
P1A

ST
-

CMOS

RC6

ST

CMOS

AN8
SS

AN
ST

RC7

ST

CMOS

AN9
AN
SDO
CMOS
VSS
VSS
Power
VDD
VDD
Power
Legend: AN intrare sau ieire analogic
TTL pin de intrare compatibil TTL
HV tensiune ridicat (high voltage)
CMOS pin de intrare sau ieire compatibil CMOS
ST pin de intrare de tip Trigger Schmitt cu nivele logice CMOS
XTAL cristal
OD open drain

Pin general de intrare ieire. Activare


individual de pull-up.
Intrare de captur/comparare.
Ieire PWM.
Pin general de intrare ieire. Activare
individual de pull-up.
Intrarea 8 A/D.
Pin de intrare Slave Select.
Pin general de intrare ieire. Activare
individual de pull-up.
Intrarea 8 A/D.
Pin de ieire date SPI.
Referin mas.
Alimentare pozitiv.

Prezentare C

38
3.4. Arhitectura microcontrolerului PIC16F690
Figura 3-2: Arhitectura PIC16F690 [6]

Prezentare C

39

n figura de mai sus se observ:


Este o arhitectur de tip Harward.
Bus-ul de date are o lime de 8 bii i la el sunt conectate CPU-ul,
perifericele (porturile, modulele timer, memoria EEPROM, ADC,
USART, etc...) i memoria RAM.
Bus-ul de instruciuni are o lime de 14 bii i este situat ntre
memoria Flash (care conine instruciunile codate pe 14 bii) i
procesor (CPU).
CPU-ul are o stiv cu o adncime de 8 cuvinte a cte 13 bii.
ALU realizeaz operaii aritmetice ntre 2 operanzi. Primul operand
este registrul de lucru W iar al doilea operand poate fi furnizat fie de
bus-ul de date, fie direct din coninutul instruciunii.
3.5. Harta memorie
Figura 3-3: Harta memoriei [6]

40

Prezentare C

PIC16F690 are un PC (Program Counter) pe 13 bii, capabil s acceseze


locaiile unei memorii de 8k. Memoria Flash conine cuvinte pe 14 bii i are
4K adrese. Memoria total este de 4K x 14bii = 7KByte.
Adresa de reset este 0h, iar vectorul de ntreruperi este mapat la adresa 4h.
3.6. Probleme propuse
a) Cutai n documentaia microcontrolerului PIC16F690 adresa i
coninutul urmtorilor regitri: PORTA, PORTC, TRISB.
Not: Documentaia microcontrolerului se gsete pe site-ul firmei
Microchip. Adresa regitrilor este notat n capitolul Memory Organization.
Pentru a afla coninutul unui registru, putem accesa capitolul INDEX din
documentaie, unde avem referine directe la descrierea regitrilor.
b) Notai numrul i numele pinilor la care sunt conectate ledurile pe placa
de dezvoltare (DS1 - DS4). Care regitri trebuie modificai pentru a seta
portul respectiv?
Not: Pentru a controla un pin digital de intrare/ieire trebuie modificai doi
regitri iar n cazul pinilor implicit asignai modulului ADC, trei.
c) Ce spaiu de memorie ocup 64 de variabile declarate char, mpreun cu
32 de variabile declarate int?
d) Cte variabile mai pot fi declarate float, ntr-o memorie de 1kB, dac
deja au fost declarate variabilele de la punctual anterior?
Not: Un kilobyte este egal cu 1024 de bytes (sau octei).
e) n care memorie (de date RAM/program Flash) aloc compilatorul
spaiu de memorie n cazul n care declarm o variabil? Dar dac
declarm o constant?
f) Cte tipuri de memorie are microcontrolerul PIC16F690? Care este rolul
lor?
g) Ce se ntmpl cu datele salvate ntr-o memorie RAM, dup
ndeprtarea tensiunii de alimentare? Dar cu datele dintr-o memorie
Flash?

Prezentare C

41

h) Care din cele dou tipuri de memorie RAM/Flash are un consum mai
mare de curent? Care credei c este mai rapid i de ce?
i) Dac declarm 20 de constante pe 2 octei (16 bii), cte variabile int
mai putem declara dac memoria are 256 de octei?
j) Scriei rezultatul urmtoarelor operaii:
0xAE+0x2A = 0x.. = 0b..
0b01001110 + 0b01100010 = 0b.= 0x
0b00110011 & 0b00100000 = 0b. ..= 0x
0b00001100 | 0xA1 = 0b= 0x

4. Pinul de ieire (Output pin)


4.1. Introducere
n cadrul acestui capitol va fi prezentat perifericul GPIO PORT (General
Purpose Input Output Port). Microcontrolerul PIC16F690 are 3 astfel de
porturi: PORTA, PORTB i PORTC. PORT este un grup de k pini asociai
informatic unui registru PORTx. Trebuie totui menionat un aspect
important: toate microcontrolerele din familia PIC16F6xx au n arhitectura
lor astfel de porturi.
Din punct de vedere al porturilor, trei aspect majore care sunt strns legate,
stau la baza alegerii microcontrolerului pentru aplicaia noastr:
a) Numrul de pini necesari: dac PIC16F690, care conine trei porturi, nu
este suficient din punct de vedere al numrului de pini, vom fi nevoii s
alegem un alt microcontroler.
b) Spaiu: dac microcontrolerul dispune de mai multe tipuri de
configuraii de porturi (i capsule) vom alege configuraia cu cei mai
puini pini, care s satisfac nevoile proiectului. Astfel se poate reduce
suprafaa ocupat pe PCB.
c) Tehnologie: dac tehnologia permite cositorirea capsulei SMD, vom
alege acest tip de capsul n defavoarea capsule THT datorit suprafeei
reduse de pe PCB i a unui cost mai mic.
4.2. Pinul de ieire
Aproape orice pin poate fi asignat mai multor periferice, deci poate avea
funcii multiple. Funcia dorit se asigneaz pinului printr-o configurare
hardware corect. De exemplu, pinul 2 poate avea urmtoarele funcii:
RA5: pinul 5 din PORTA. Pin digital de intrare sau ieire. Nivel TTL
ca i pin de intrare i CMOS pentru configuraia pin de ieire.
T1CKI: pin extern de ceas (clock) pentru TIMER1. Pin digital de
intrare.
OSC2: quartz (XTAL).
CLKOUT: pin de ieire pe care se poate vizualiza Fosc/4 (frecvena de
tact/4).

Pinul de ieire (Output pin)

43

Dup cum am precizat anterior, pinii GPIO pot fi configurai de intrare sau
de ieire. Aceast setare se face cu ajutorul registrului TRISx:
Dac bitul K aferent pinului K este setat 1 atunci pinul K va fi pin de
intrare.
Daca bitul K aferent pinului K este setat 0 atunci pinul K va fi pin de
ieire.
Cnd pinul K este configurat ca i ieire, atunci scriind n registrul PORTx
la poziia bitului K, vom modifica starea electric a pinului.
Scriind 1 n registru, pe pin vom citi cu ajutorul unui multimetru 5V
(1 logic).
Scriind 0 n registru, pe pin vom citi cu ajutorul unui multimetru 0V
(0 logic)
Cnd este configurat ca i pin de ieire, din punct de vedere electric pinul
poate fi echivalat cu urmtorul circuit tri-state:
Figura 4-1: Echivalarea electric a unui pin de ieire (Digital Output)

Pinul de ieire (Output pin)

44
Vom avea urmtoarele cazuri:

Contactul A nchis, B deschis: La ieirea pinului vom avea 1, sau cu


alte cuvinte vom citi Vdd cu ajutorul unui multimetru.
Contactul A deschis, B nchis: La ieirea pinului vom avea 0, sau cu
alte cuvinte vom citi 0V cu ajutorul unui multimetru. Pinul e tras la
mas.
Contactele A i B deschise: Pinul se afl n cea de a treia stare tristate, sau stare de nalt impedan hi-Z.
Contactele A i B nchise: INTERZIS! Se va produce scurt-circuit
care duce la distrugerea perifericului sau chiar a microcontrolerului.
Aceast configuraie nu este posibil, deoarece hardware-ul din
microcontroler nu permite acest lucru.
Tabel 4-1: Funciile pinilor din PORTC [6]
PORTC: conine 8 pini RC0-RC7. Acetia pot avea urmtoarele funcii:
Nume

Funcie

RCO/AN4/C2IN+

RC1/AN5/C12IN1-

RC2/AN6/C12IN2/P1D

RC3/AN7/C12IN3/P1C

RC4/C2OUT/P1B

RC5/CCP1/P1A

RC6/AN8/SS

RC7/AN9/SDO

Tip Ieire

Descriere

RC0
AN4
C2IN+
RC1
AN5
C12IN1-

Tip
Intrare
ST
AN
AN
ST
AN
AN

CMOS
CMOS
-

RC2
AN6
C12IN2-

ST
AN
AN

CMOS
-

P1D
RC3
AN7
C12IN3-

ST
AN
AN

CMOS
CMOS
-

P1C
RC4
C2OUT
P1B
RC5
CCP1
P1A
RC6
AN8
SS
RC7
AN9

ST
ST
ST
ST
AN
ST
ST
AN

CMOS
COMS
CMOS
CMOS
COMS
CMOS
CMOS
CMOS
-

Pin digital de intrare/ieire.


Pin analogic de intrare al A/D. Pinul 4.
Intrarea pozitiv a comparatorului C2.
Pin digital de intrare/ieire.
Pin analogic de intrare al A/D. Pinul 5.
Intrarea negativ a comparatorului C1
sau C2.
Pin digital de intrare/ieire.
Pin analogic de intrare al A/D. Pinul 6.
Intrarea negativ a comparatorului C1
sau C2.
Pin de ieire PWM.
Pin digital de intrare/ieire.
Pin analogic de intrare al A/D. Pinul 7.
Intrarea negativ a comparatorului C1
sau C2.
Pin de ieire PWM.
Pin digital de intrare/ieire.
Pinul de ieire al comparatorului C2.
Pin de ieire PWM.
Pin digital de intrare/ieire.
Pinul de intrare captur.
Pin de ieire PWM.
Pin digital de intrare/ieire.
Pin analogic de intrare al A/D. Pinul 8.
Pin de selecie pentru SPI.
Pin digital de intrare/ieire.
Pin analogic de intrare al A/D. Pinul 9.

Pinul de ieire (Output pin)


SDO
CMOS
Legend: AN intrare sau ieire analogic
TTL pin de intrare compatibil TTL
HV tensiune ridicat (high voltage)
CMOS pin de intrare sau ieire compatibil CMOS
ST pin de intrare de tip Trigger Schmitt cu nivele logice CMOS
XTAL cristal
OD open drain

45
Pin de ieire de date pentru SPI.

Pinii sunt asignai implicit perifericului ADC (convertorul analog-numeric)


mai puin pinul RC4 i RC5, iar direcia lor este de intrare. Dac se dorete
configurarea pinului ca i pin digital, bitul aferent din registrul ANSEL sau
ANSELH (dup caz), trebuie scris cu valoarea 0. Astfel semnalul aplicat pe
pin va ajunge i la circutul digital (poarta logic de tip Trigger Schmitt este
validat i va avea la ieire starea logic a semnalului aplicat pe pin).
Datorit faptului c sunt 11 pini analogici i fiecare pin are un bit asignat,
cei 11 bii nu vor avea loc ntr-un singur registru de 8 bii. Acesta este
motivul pentru care exist registrul ANSEL (conine primii 8 bii) i
ANSELH (conine restul de bii).
Figura. 4-2: Selecia pin digital/analog

Un pin de ieire (bitul aferent din registrul TRIS este 0) funcioneaz ca i


pin digital i fr ca bitul aferent din registrul ANSEL s fie 0, dar este
recomandat ca i n acest caz, pinul s fie setat cu funcie digital cu ajutorul
registrului ANSEL.

Pinul de ieire (Output pin)

46

Figura 4-3: Schema bloc a pinilor RC0 i RC1 [6]

Pentru a seta direcia pinilor se utilizeaz registrul TRISC, iar pentru citirea
sau scrierea portului registrul PORTC.
Tabel 4-2: Regitri asociai cu PORTC [6]
Nume

Bit7

Bit6

Bit5

Bit4

Bit3

Bit2

Bit1

Bit0

ANSEL

ANS7

ANS6

ANS5

ANS4

ANS3

ANS2

ANS1

ANS0

ANSELH

ANS11

ANS10

ANS9

ANS8

CCP1CON

P1M1

P1M0

DC1B1

DC1B0

CCP1M3

CCP1M2

CCP1M1

CCP1M0

CM2CON0

C2ON

C2OUT

C2OE

C2POL

C2R

C2CH1

C2CH0

CM2CON1

MC1OUT

MC2OUT

T1GSS

C2SYNC

PORTC

RC7

RC6

RC5

RC4

RC3

RC2

RC1

RC0

PSTRCON

STRSYNC

STRD

STRC

STRB

STRA

SRCON

SR1

SR0

C1SEN

C2REN

PULSS

PULSR

SSPCON

WCOL

SSPOV

SSPEN

CKP

SSPM3

SSPM2

SSPM1

SSPM0

TRISC

TRISC7

TRISC6

TRISC5

TRISC4

TRISC3

TRISC2

TRISC1

TRISC0

VRCON

C1VREN

C2VREN

VRR

VP6EN

VR3

VR2

VR1

VR0

Legend: x=necunoscut, u=nemodificat, -=bitul se citete ca 0. Biii nchii la culoare nu sunt folosii de PORTC.

Pinul de ieire (Output pin)

47

4.3. Limitri electrice:


Curent maxim prin pinul Vss = 300mA
Curent maxim prin pinul Vdd = 250mA
Curent maxim absorbit de un pin I/O = 25mA
Curent maxim generat de un pin I/O = 25mA
Curent maxim absorbit de PORTA, PORTB si PORTC = 200mA
Curent maxim generat de PORTA, PORTB si PORTC = 200mA
4.4. Probleme propuse
a) Studiai cazul n care legm doi pin de ieire ntre ei printr-o srm. Ce
se ntmpl? Este permis?
Not: Urmrii Figura 2.1 n cazul n care unul dintre pini e legat la mas
iar al doilea la Vdd.
b) Studiai cazul n care legm un pin de ieire cu unul de intrare ntre ei
printr-o srm. Este permis?
c) Cte leduri putem lega n paralel la un pin, dac pentru a lumina este
nevoie s fie strbtute de un curent de 7 mA?
Not: Trebuie considerat curentul maxim generat de un pin.
d) Cte leduri putem lega la un microcontroler, n funcie de configuraie
(Catodul sau Anodul legate la pinul portului), dac pentru a lumina
trebuie s fie strbtute de un curent de 10mA?
Not: Dac legm Catodul la pinul portului, ledul se va aprinde cnd ieirea
acestuia e legat la mas (zero logic). n acest caz trebuie considerat
curentul maxim prin pinul Vss.
4.5. Aplicaie propus
Scriei un mic program n care s setai pinii RC0-RC3 pini de ieire i pinii
RC4-RC7 pini de intrare. Salvai valoarea pinilor RC4-RC7 ntr-o variabil
(care trebuie declarat n prealabil) i aprindei ledurile legate la pinii RC0
i RC2.

48

Pinul de ieire (Output pin)

Not: Paii necesari scrierii programului n memoria microcontrolerului


(flashing) se gsesc n Anexa 2.
n figura de mai jos se poate vizualiza rezultatul ateptat al programului.
Microcontrolerul iese din reset (pinul MCLR este 1 logic) i la intrarea n
funcia main, pinul RC0 va trece n starea 1 logic, care duce la aprinderea
ledului DS1.
Figura 4-4: Setarea pinului RC0 dup ieirea din reset

Not: Pe parcursul acestui material, revolvarea diverselor aplicaii va fi


nsoit i de oscilograme care s exemplifice, ntr-un mod practic,
comportamentul corect i ateptat al microcontrolerului pe care ruleaz
programul dat ca i exemplu (versiunea complet a acestuia). Cei care nu
sunt familiarizai cu interpretarea unei oscilograme pot gsi mai multe
detalii n Anexa 3.

Pinul de ieire (Output pin)

49

4.6. Model Software


/* include files */
#include "pic.h"
/* variables */
unsigned char portRead; /* for reading the port C pin values */
/* function declarations */
void init();
/* function definitions */
void main()
{
init();
portRead = ??? & ???; /* use mask for reading only RC4 - RC7 pins */
PORTC = ???; /* set RC0 and RC2 - turn on LEDS */
while(1)
{
;
}
}
void init()
{
ANSEL = ???; /* set RC0 to RC3 as digital pins */
ANSELH = ??? ; /* set RC6 and RC7 as digital pins */
TRISC = ???; /* RC4 to RC7 input. RC0 to RC3 output */
PORTC = 0x00; /* port C pins reset value */
}
Not: Modelul software este oferit doar ca punct de plecare. Pentru
realizarea aplicaiei, codul trebuie completat, nlocuind semnele de ntrebare
cu valorile corecte.

Pinul de ieire (Output pin)

50
4.7. Problem propus

Scriei un program prin care s setai portul C astfel nct ledurile s afieze
alternative valoarea 0xA i 0x5 ntr-o bucl infinit.
n Figura 4-5 se poate vizualiza rezultatul dorit al temei. ntr-o bucl
infinit n funcia main, pinii RC0-RC3 vor indica alternativ valorile 0x5 i
0xA.
Figura 4-5: Alternarea valorii 0x5 i 0xA pe pinii din PORTC

5. Pinul de intrare (Input pin)


5.1. Introducere
n cadrul acestui capitol va fi prezentat n continuare perifericul GPIO
PORT (General Purpose Input Output Port).
Toi pinii asignai perifericelor PORTx, sunt, dup reset, pini de intrare.
Acest lucru se datoreaz faptului c, n aplicaii, la pinii microcontrolerului
pot fi legai senzori, ieirile digitale ale altor microcontrolere, circuite
integrate, etc. Dac pinii ar fi implicit de ieire, exist riscul s se produc
scurt-circuite la punerea sub tensiune a circuitului, care s duc la
distrugerea microcontrolerului, aa cum se va ilustra n figurile de mai jos.
Exemplu: la pinul RB4 se leag un senzor digital care are starea logic 1 ca
n Figura 5-1. Presupunem c pinul este implicit de ieire i starea logic
este 0. n acest caz s-ar produce un scurt-circuit care ar duce la distrugerea
microcontrolerului pn ce aplicaia s ruleze pentru a schimba direcia
pinului, fcndu-l de intrare.
Evident, acest caz poate aprea chiar i dac pinul este implicit de intrare,
printr-o eroare software, dac pinul RB4 este declarat pin de ieire n
program. Pentru a preveni astfel de situaii, legtura electric corect este
prezentat in Figura 5-2. Se observ c rezistena are rolul de a limita
valoarea curentului n situaia nedorit. Rezistena trebuie aleas astfel nct
valoarea curentului s nu depeasc valoarea maxim admis (25mA
pentru un pin digital). n cazul n care pinul este declarat corect, de intrare,
rezistena nu modific funcionarea circuitului, deoarece cderea de tensiune
pe ea va fi neglijabil (curentul absorbit de pinul de intrare este aproape 0)
i pe pinul microcontrolerului vom putea msura 5V.
ntrebare: ntlnim i pe schema electric a plcii de dezvoltare astfel de
protecii? Dac da, unde anume? Ce situaie nedorit se evit?

52

Pinul de ieire (Output pin)


Figura 5-1: Conexiune nedorit

Figura 5-2: Conexiune corect

5.2. Pinul de intrare


Dup cum am precizat i n capitolul anterior, pinii GPIO pot fi configurai
de intrare sau de ieire. Aceasta setare se face cu ajutorul registrului TRISx:

Pinul de intrare (Input pin)

53

Dac bitul K aferent pinului K este setat 1 atunci pinul K va fi pin de


intrare.
Dac bitul K aferent pinului K este setat 0 atunci pinul K va fi pin de
ieire.
Cnd pinul K este configurat ca i intrare, citind registrul PORTx la poziia
bitului K, vom regsi starea electric (logic) a pinului de intrare.
Cnd n registru PORTx bitul k are valoarea 1, pe pinul de ieire va fi
o tensiune de 5V, msurabil cu un multimetru sau un osciloscop.
Cnd n registru PORTx bitul k are valoarea 0, pe pinul de ieire va fi
o tensiune de 0V, msurabil cu un multimetru sau un osciloscop.
Figura 5-3: Setarea direciei pinilor unui port (ex: PORTC) [3]

n exemplul de mai sus ntlnim urmtoarele situaii:


Pinul RC0 trebuie setat ca i intrare pentru a citi starea butonului
Btn2. Acest lucru se face scriind 1 pe poziia bitului 0 din registrul
TRISC. Pe poziia bitului 0 din registrul PORTC se poate citi starea
logic a pinului.
Pinul RC1 trebuie setat ca i ieire pentru a aprinde ledul. Acest lucru
se face scriind 0 pe poziia bitului 1 din registrul TRISC. La poziia
bitului 1 din registrul PORTC se poate scrie starea logic pe care

54

Pinul de ieire (Output pin)


dorim s o aib pinul. Pentru a aprinde ledul trebuie s scriem 1
logic. Pentru stingere vom scrie 0.
Pinul RC2 trebuie setat ca i intrare pentru a citi starea butonului
Btn1. Acest lucru se face scriind 1 pe poziia bitului 2 din registrul
TRISC. Pe poziia bitului 2 din registrul PORTC se poate citi starea
logic a pinului.

Cnd pinul K este configurat ca pin de intrare, operaiile de scriere n


registrul PORTx, la poziia bitului K nu vor avea nici un efect (vor fi
ignorate). Acest lucru se datoreaz faptului c scrierea afecteaz lach-ul, pe
cnd la citire, registrul conine informaii despre starea pinilor. Cu alte
cuvinte, cnd pinii sunt declarai de intrare, chiar dac scriem o valoare n
registrul PORTx, la citire, acesta va conine starea real a pinilor.
Figura 5-4: Accesul de scriere i citire al unui port

Cnd este configurat ca i pin de intrare, din punct de vedere electric, pinul
poate fi echivalat cu o rezisten de valoare foarte mare legat la mas.

Pinul de intrare (Input pin)

55

Figura 5-5: Echivalarea electric a unui pin Digital Input

Figura 5-6: Comportamentul electric al pinilor de intrare [3]


+5V

+5V
R3

+Vcc

+5V

Btn1

PA2
I~0

I~0

RIN

Gnd

RIN

PA0

R1
Btn2
LED

Dup cum se observ n figurile de mai sus, curentul absorbit de un pin de


intrare este neglijabil, fiind aproape 0. Cu alte cuvinte, un pin de intrare
legat ntr-un circuit nu modific funcionarea electric a acestuia.

Pinul de ieire (Output pin)

56

Tabel 5-1: Funciile pinilor din PORTA [6]


PORTA: conine 6 pini - RA0-RA5. Acetia pot avea urmtoarele funcii:
Nume

Funcie

RAO/AN0/C1IN+/
ICSPDAT/ULPWU

RA1/AN1/C12IN0/VREF/ICSPCLK

RA0
AN0
C1IN+
ICSPDAT
ULPWU
RA1
AN1
C12IN0-

Tip
Intrare
ST
AN
AN
TTL
AN
ST
AN
AN

Tip
Ieire
CMOS
CMOS
CMOS
-

VREF

AN

ICSPCLK
TTL
RA2
ST
CMOS
AN2
AN
T0CLK
ST
INT
ST
C1OUT
CMOS
RA3/MCLR/VPP
RC3
ST
CMOS
MCLR
ST
VPP
HV
RA4/AN3/T1G/
RC4
ST
COMS
OCS2/CLKOUT
AN3
AN
T1G
ST
OSC2
XTAL
CLKOUT
CMOS
RA5/T1CLK/
RA5
ST
COMS
OSC1/CLKIN
T1CLK
ST
OSC1
XTAL
CLKIN
ST
Legend: AN intrare sau ieire analogic
TTL pin de intrare compatibil TTL
HV tensiune ridicat (high voltage)
CMOS pin de intrare sau ieire compatibil CMOS
ST pin de intrare de tip Trigger Schmitt cu nivele logice CMOS
XTAL cristal
OD open drain
RA2/AN2/T0CLK/
INT/C1OUT

Descriere
Pin digital de intrare/ieire.
Pin analogic de intrare al A/D. Pinul 0.
Intrarea pozitiv a comparatorului C1.
Pin de date intrare/ieire ICSPTM
Pin de intrare ultra-low Wake-up.
Pin digital de intrare/ieire.
Pin analogic de intrare al A/D. Pinul 1.
Intrarea negativ a comparatorului C1 sau
C2.
Tensiune extern de referin pentru
convertorul ADC.
Ceas pentru ICSPTM.
Pin digital de intrare/ieire.
Pin analogic de intrare al A/D. Pinul 2.
Pin de ceas pentru Timer 0.
Pin de ntrerupere extern.
Pin de ieire al comparatorului C1.
Pin digital de intrare/ieire.
Pin de reset cu pull-up intern.
Tensiune de programare.
Pin digital de intrare/ieire.
Pin analogic de intrare al A/D. Pinul 2.
Intrare de validare a Timer 1.
Quartz/Rezonator.
Pin de ieire frecventa Fosc/4.
Pin digital de intrare/ieire.
Ceas de intrare pentru Timer 1.
Quartz/Rezonator.
Intrare de ceas extern / Oscilator RC.

Pinii portului A sunt asignai implicit perifericului ADC (convertorul


analog-numeric) mai puin pinul RA3 i RA5, iar direcia lor este de intrare.
Dac se dorete configurarea pinului ca i pin digital, bitul aferent din
registrul ANSEL trebuie scris cu valoarea 0. Dac se folosete ca i pin
digital, setarea direciei pinilor se face cu ajutorul registrul TRISA, iar
pentru citirea sau scrierea portului, registrul PORTA.

Pinul de intrare (Input pin)

57

Tabel 5-2: Regitri asociai cu PORTA [6]


Nume

Bit7

Bit6

Bit5

Bit4

Bit3

Bit2

Bit1

Bit0

ANSEL

ANS7

ANS6

ANS5

ANS4

ANS3

ANS2

ANS1

ANS0

ADCON

ADFM

VCFG

CHS3

CHS2

CHS1

CHS0

GO/DONE

ADON

CM1CON0

C1ON

C1OUT

C1OE

C1POL

C1R

C1CH1

C1CH0

INTCON

GIE

PEIE

T0IE

INTE

RABIE

TOIF

INTF

RABIF

IOCA

IOCA5

IOCA4

IOCA3

IOCA2

IOCA1

IOCA0

PORTC

RA5

RA4

RA3

RA2

RA1

RA0

OPTION_REG

RABPU

INTEDG

TOCS

TOSE

PSA

PS2

PS1

PS0

T1CON

T1GINV

TMR1GE

T1CKPS1

T1CKPS0

T1OCSEN

T1SYNC

TMR1CS

TMR1ON

SSPCON

WCOL

SSPOV

SSPEN

CKP

SSPM3

SSPM2

SSPM1

SSPM0

TRISC

TRISA5

TRISA4

TRISA3

TRISA2

TRISA1

TRISA0

WPUA

WPUA5

WPUA4

WPUA2

WPUA1

WPUA0

Legend: x=necunoscut, u=nemodificat, -=bitul se citete ca 0. Biii nchii la culoare nu sunt folosii de PORTA.

5.3. Pull-up/Pull-down:
Dac intrarea pinului este lsat n aer, starea logic a pinului poate fi
influenat de cmpuri electromagnetice. Pentru a evita aceast situaie
nedorit, pinul trebuie legat fie la VSS, fie la VDD. Exist dou posibiliti:
a) Pull-down (legarea la mas)
Figura 5-7: Conexiune pull-down

Dup cum se observ, atta timp ct butonul nu este apsat, potenialul pe


pin este 0, deci starea logic este 0, pinul nefiind lsat n aer. n momentul
n care butonul este apsat, potenialul pe pin devine +5V, deci starea logic
ce va fi citit pe pin este 1 logic. Valoarea rezistenei trebuie s fie de
ordinul K..

Pinul de ieire (Output pin)

58
b) Pull-up (legarea la +5V)

Figura 5-8: Conexiunea pull-up

Dup cum se observ, atta timp ct butonul nu este apsat, potenialul pe


pin este +5V, deci starea logic este 1, deoarece cderea de tensiune pe
rezisten este 0V (U=I*R, unde I=0). n momentul n care butonul este
apsat, potenialul pe pin devine 0V, deci starea logic ce va fi citit pe pin
este 0 logic. Valoarea rezistenei trebuie s fie de ordinal K, ca i n cazul
rezistenei de pull-down.
Trebuie menionat c PORTA si PORTB dispun de conexiune pull-up
intern, care poate si activat pentru pinii de intrare cu ajutorul biilor din
registrul WPUA pentru pinii ce alctuiesc PORTA sau WPUB pentru pinii
ce alctuiesc PORTB.
5.4. Switch Debounce
Dei sunt foarte des folosite n aplicaii datorit costului redus i a
simplitii, comutatoarele mecanice (push-button) au un mare dezavantaj:
sunt foarte zgomotoase. Datorit nchiderii i deschiderii contactelor apar
oscilaii i se formeaz trenuri de impulsuri parazite (Figura 5-9). Problema
se numete switch bounce i ncercarea de eliminare a acestor impulsuri
parazite se numete switch debounce.

Pinul de intrare (Input pin)

59

Figura 5-9: Switch bounce

Practic o apsare fizic a unui push-button este vzut din punct de vedere
electric ca o serie de apsri. Empiric se poate determina durata acestor
oscilaii, ea fiind in jur de 10ms. Exist mai multe soluii, fie hardware fie
software, pentru switch debouncing. Cea mai convenabil i care va fi
prezentat n continuare este soluia software.
Este prezentat un algoritm pentru schimbarea strii unui led la fiecare
apsare a unui push-button.
Figura 5-10: Algoritm debounce

Pinul de ieire (Output pin)

60

n figura urmtoare se poate vedea c dup apsarea push-button-ului


conectat la pinul de intrare RA3, pinul RC0 i va schimba starea logic
doar dup 10ms, ntrziere fiind dat de algoritmul prezentat anterior.
Figura 5-11: Debounce software 10ms

5.5. Probleme propuse


a) Studiai cazul n care legm doi pini de intrare ntre ei printr-o srm.
Este permis?
b) Studiai cazul n care legm un pin de ieire cu unul de intrare ntre ei
printr-o srm. Ce se ntmpl? Este permis?
c) Studiai cazul n care legm un pin de ieire cu doi pini de intrare printro srm. Ce se ntmpl? Este permis?
5.6. Aplicaie propus
Scriei un mic program n care s setai pinul RA3 pin de intrare i pinii
RC0-RC3 pini de ieire. Schimbai starea ledului conectat la pinul RC0 la
fiecare apsare a butonului conectat la pinul RA3.

Pinul de intrare (Input pin)

61

n figura de mai jos se poate vedea c la fiecare nou apsare a push-buttonului conectat la pinul de intrare RA3, pinul RC0 i va schimba starea
logic, lucru care se observ i prin aprinderea sau stingerea ledului DS1.
Figura 5-12: Trecea din starea 0 logic n starea 1 logic la prima acionare a
push-button-ului

Figura 5-13: Trecea din starea 1 logic n starea 0 logic la o nou acionare a
push-button-ului

62

Pinul de ieire (Output pin)

5.7. Model software


/* include files */
#include "pic.h"
/* constant and macro defines */
#define PUSH
???
#define LED
???
#define ON
1
#define OFF
0
#define PRESSED 0

/* function declarations */
void init();
void delayMs(unsigned int ms);
/* function definitions */
void main()
{
init();
LED = OFF;
/* delay before entering infinite loop */
delayMs(1000);
while(1)
{
/* check if push button has been pressed */
if(PUSH == ???)
{
delayMs(10); /* 10ms delay */
if(PUSH == ???) /* if push button is still pressed */
{
???
}
}
}
}

Pinul de intrare (Input pin)

63

void init()
{
ANSEL = 0x0F; /* set RC0 to RC3 as digital pins */
ANSELH = 0x0C ; /* set RC6 and RC7 as digital pins */
TRISA = ???; /* set all pins on port A as input */
TRISC = ???; /* RC4 to RC7 input. RC0 to RC3 output */
PORTC = ???; /* port C pins reset value */
}
void delayMs(unsigned int ms)
{
unsigned int i,j;
for(i = 0; i< ms; i++)
{
/* delay for 1 ms - empirically determined */
for(j=0; j<62; j++)
{
;
}
}
}
Observaie 1: Pinul RA3, pe lng funcia de intrare-ieire digital, mai
poate fi folosit i ca pin de reset (MCLR). Pentru a putea folosi push-buttonul de pe plac pentru alt funcie dect cea de reset, trebuie modificai biii
de configurare ai microcontrolerului dup cum am prezentat n primul
capitolul la punctul 1.2.6 (Pin Function Select bit ia valoarea MCLR pin
function is digital input).
Observaie 2: n momentul n care programatorul PICKIT 2 este conectat la
placa de dezvoltare, starea electric a pinului RA3 (MCLR) este controlat
din mediul de dezvoltare MPLAB (pentru a putea ine sau scoate din reset
microcontrolerul). Datorit faptului c n aplicaia noastr alimentarea se
face prin PICKIT 2, programatorul nu poate fi deconectat dup scrierea
programului aa c starea pinul RA3 nu poate fi modificat prin apsarea
push-button-ului. Pentru a putea totui folosi push-button-ul n timp ce
programatorul este conectat trebuie fcut urmtoarea setare din meniul
Programmer / Settings: csua 3-State on Release from Reset trebuie
bifat precum n figura de mai jos:

64

Pinul de ieire (Output pin)


Figura 5-14: Setarea programatorului pentru folosirea push-button-ului
conectat la RA3

Pinul de intrare (Input pin)

65

5.8. Problem propus


Scriei un program prin care s aprindei succesiv ledurile (doar un led
aprins la un moment dat), de la DS1 la DS3, la fiecare apsare nou a
butonului legat la pinul RA3.
n figura de mai jos se poate observa c la fiecare apsare nou a pushbutton-ului conectat la pinul de intrare RA3, pinii RC0-RC3 i vor schimba
starea logic succesiv.
Figura 5-15: Acionarea repetat a push-button-ului

6. Timer 1
6.1. Introducere
Pentru realizarea sarcinii de a funciona n timp real, aplicaiile embedded
au nevoie de mecanisme specifice pentru a determina intervale precise de
timp. Microcontrolerele ofer astfel de mecanisme incorporate n modulul
numit Timer. Cea mai important funcie a modulului Timer este aceea de
numrtor intern (internal counter). Un registru (counter register) este
incrementat la intervale fixe, frecvena de incrementare fiind egal cu
frecvena la care ruleaz aplicaia (frecvena sistemului) sau este divizat (n
funcie de setrile modulului) din frecvena sistemului. Pentru a folosi
aceast funcie, putem fie citi registrul intern, determinnd din numrul de
incremente timpul trecut, fie putem folosi ntreruperile hardware generate de
ctre modul n momentul n care contorul atinge o valoare prestabilit.
Microcontrolerul PIC16F690 dispune de 3 module Timer:

Un timer pe 16 bii (Timer 1).


Dou module de timer pe 8 bii (Timer 0 i Timer 2).
Modulul Timer 2 dispune i de post-scalare programabil.
Oricare din cele trei module poate fi folosit ca surs de ntrerupere.
Toate cele trei module de timer dispun de pre-scalare programabil.

6.2. Descriere Timer 1


Timer pe 16 bii compus din doi regitri de 8 bii: TMR1H i TMR1L
care se pot scrie i citi.
Pre-scalare programabil (factor de divizare 1, 2, 4 sau 8).
Perechea de regitri se incrementeaz de la 0x0000 pn la 0xFFFF.
n momentul n care se atinge valoarea maxim se produce un
overflow i se reia incrementarea de la valoare 0x0000.
n momentul n care se produce un overflow, modulul de timer poate
genera o ntrerupere.
Pentru controlul i indicarea strii ntreruperii, modulul are asignai
doi bii: bitul TMR1IE pentru activarea ntreruperii i bitul TMR1IF
pentru indicarea strii ntreruperii.

Timer 1

67
Figura 6-1: Schema bloc a modulului Timer 1 [6]

Principiul de funcionare al acestui tip de timer este urmtorul:


Modulul conine doi regitri de 8 bii care mpreun formeaz un contor de
16 bii. n timpul aplicaiei, n aceti regitri se poate scrie o valoare ce va
reprezenta valoarea de pornire a contorului. Dup activarea modulului,
valoarea din cei doi regitri se va incrementa cu fiecare impuls sosit la
intrarea sa, timpul de incrementare fiind influenat de configuraia folosit.
Cnd valoare din contor atinge maximul (0xFFFF), se produce o depire a
valorii maxime a registrului TMR1 pe 16 bii (format din cei doi regitri pe
8 bii TMR1H si TMR1L) i valoarea din registru se reseteaz la 0x0000
(overflow). n acest moment, bitul de stare al ntreruperii (bitul flag
TMR1IF) se va seta. n cazul n care i bitul de activare al ntreruperii
(TMR1IE) este setat, se va genera o ntrerupere i aplicaia va sri n rutina
de tratare a ntreruperii. Pentru ca o nou ntrerupere s se poat genera,
bitul indicator de stare (TMR1IF) trebuie resetat.
Frecvena de intrare n modulul de timer (n cazul configuraiei prezentate n
aceast lucrare) este Fosc/4, unde Fosc este frecvena oscilatorului folosit (n
acest caz 4MHz). Aceasta poate fi divizat cu ajutorul pre-scalarului setat

68

Timer 1

din registrul de configuraie T1CON. Practic, dac vom folosi un pre-scalar


de 1:8, valoarea contorului se va incrementa doar la al 8-lea impuls sosit la
intrarea modulului. Astfel, intervalul de timp ce poate fi capturat pe acelai
numr de bii va fi de 8 ori mai mare. O valoare mic a pre-scalarului duce
la o precizie mai mare a timpului msurat dar valoarea maxim pentru
generarea ntreruperilor este mai mic. n contradicie, un pre-scalar mai
mare duce la o precizie mai mic dar aduce beneficiul unui timp mai mare
ntre ntreruperi. n funcie de aplicaia dorit, se pot alege urmtoarele
valori pentru pre-scalare: 1:1, 1:2, 1:4, 1:8.
n urmtoarele tabele vom descrie regitri cei mai uzuali ai modulului.
Tabel 6-1: Descrierea regitrilor afereni modulului Timer 1 [6]
Nume

Bit7

Bit6

Bit5

Bit4

Bit3

Bit2

Bit1

Bit0

CM2CON1

MC1OUT

MC2OUT

T1GSS

C2SYNC

INTCON

GIE

PEIE

T0IE

INTE

RABIE

T0IF

INTF

RABIF

PIE1

ADIE

RCIE

TXIE

SSPIE

CCP1IE

TMR2IE

TMR1IE

PIR1

ADIF

RCIF

TXIF

SSPIF

CCP1IF

TMR2IF

TMR1IF

TMR1H

Conine cei mai semnificativi 8 bii ai TMR1

TMR1L

Conine cei mai puin semnificativi 8 bii ai TMR1

T1CON

T1GINV

T1CKPS0

T1OSC

T1SYNC

TMR1CS

TMR1ON

TMR1GE

T1CKPS1

Legenda: x=necunoscut, u=nemodificat, -=bitul se citete ca 0. Biii nchii la culoare nu sunt folosii de TIMER1.

INTCON: registrul de configurare al ntreruperilor. Se activeaz


ntreruperile generale i ale perifericelor.
PIR1: registrul de flag-uri al perifericelor. Conine flag-urile individuale de
ntrerupere pentru periferice.
PIE1: registrul de activare al ntreruperilor pentru periferice. Conine bii
individuali de activare a ntreruperilor pentru periferice.
CM2CON1: registrul de control al modulului comparator 2. Este folosit
pentru activarea funciei gate control pentru Timer 1. Aceast
funcionalitate nu este prezentat n aceast lucrare.

Timer 1

69

Tabel 6-2: Registrul T1CON - registrul de configurare pentru Timer 1

Legend: R - bitul poate fi citit; W - bitul poate fi scris; U - bit neimplementat, se va citi 0; n valoare dup POR;
1 - bitul e setat; 0 - bitul e ters; X - valoare necunoscut;

Bit 7 T1GINV: Timer1 Gate Invert bit(1)


1 = Timer 1 se va incrementa cnd semnalul de Gate este 1 logic
0 = Timer 1 se va incrementa cnd semnalul de Gate este 0 logic
Bit 6 TMR1GE: Timer 1 Gate control bit(2)
Dac TMR1ON este 0:
Bitul TMR1ON este ignorat
Dac TMR1ON este 1:
1 = Incrementarea Timer 1 este controlat de semnalul de Gate
0 = Timer 1 se va incrementa in permanen
Bit 5-4 T1CKPS<1:0>: Timer 1 Input Clock Prescale Select bit
11 = valoare pre-scalar 1:8
10 = valoare pre-scalar 1:4
01 = valoare pre-scalar 1:2
00 = valoare pre-scalar 1:1
Bit 3 T1OSCEN: LP Oscillator Enable Control bit
Dac INTOSC este activat fr oscilator pe CLKOUT:
1 = Oscilatorul LP e activat ca i surs de ceas pentru TIMER 1
0 = Oscilatorul LP e dezactivat
Altfel bitul este ignorat
Bit 2 T1SYNC: Timer 1 External Clock Input Synchronization Control bit TMR1CS = 1:
1 = Nu se va sincroniza cu semnalul extern
0 = Se va sincroniza cu semnalul extern
Bit 1 TMR1CS: Timer 1 Clock Source Select bit
1 = Sursa de ceas va fi semnalul extern de pe pinul T1CKI (frontul cresctor)
0 = Sursa de ceas va fi semnalul intern FOSC/4
Bit 0 TMR1ON: Timer 1 On bit
1 = Timer 1 este activat/pornit
0 = Timer 1 este dezactivat/oprit
Not 1: Bitul T1GINV inverseaz logica de Gate indiferent de sursa de ceas.
Not 2: Bitul TMR1GE trebuie setat s foloseasc fie pinul T1G fie C2OUT ca i surs de
Gate pentru Timer 1, dup cum este selectat de ctre bitul T1GSS din registrul
CM2CON1.

n ceea ce privete generarea de ntreruperi, utilizatorul trebuie s fac


urmtorii pai:

70

Timer 1
Figura 6-2: Logica generrii de ntreruperi [6]

Biii GIE i PEIE din registrul INTCON trebuie setai pentru a activa
ntreruperile generale i ale perifericelor.
Tabel 6-3: Registrul INTCON

Legend: R - bitul poate fi citit; W - bitul poate fi scris; U - bit neimplementat, se va citi 0; n valoare dup POR;
1 - bitul e setat; 0 - bitul e ters; X - valoare necunoscut;

Bit 7 GIE: Global Interrupt Enable bit


1 = Activeaz toate sursele de ntrerupere
0 = Dezactiveaz toate sursele de ntrerupere
Bit 6 PEIE: Peripheral Interrupt Enable bit
1 = Activeaz toate sursele de ntrerupere ale perifericelor
0 = dezactiveaz toate sursele de ntrerupere ale perifericelor

Timer 1

71

Bitul flag TMR1IF din registrul PIR1 trebuie ters nainte de a valida sursa
de ntrerupere prin setarea bitului de activare a ntreruperii. n caz contrar,
riscm ca bitul flag sa aib valoarea 1, iar n momentul activriii
ntreruperii, programul s sar n rutina de tratare a ntreruperii, lucru
nedorit de noi n acel moment. Aceasta ar trebui s fie o regul de la care s
nu ne abatem niciodat n timpul scrierii programului pentru microcontroler:
bitul flag trebuie ters nainte de a activa sursa de ntrerupere.
Tabel 6-4: Registrul PIR1

Legend: R - bitul poate fi citit; W - bitul poate fi scris; U - bit neimplementat, se va citi 0; n valoare dup POR;
1 - bitul e setat; 0 - bitul e ters; X - valoare necunoscut;

Bit 0 TMR1IF: Timer 1 Overflow Interrupt Flag bit


1 = Registrul numrtor Timer 1 a atins valoarea maxim
0 = Registrul numrtor Timer 1 nu a atins valoarea maxim

ntreruperea Timer 1 trebuie activat prin setarea bitului TMR1IE din


registrul PIE1.
Tabel 6-5: Registrul PIE1

Legend: R - bitul poate fi citit; W - bitul poate fi scris; U - bit neimplementat, se va citi 0; n valoare dup POR;
1 - bitul e setat; 0 - bitul e ters; X - valoare necunoscut;

Bit 0 TMR1IE: Timer 1 Overflow Interrupt Enable bit


1 = Activeaz ntreruperea generat de Timer 1
0 = Dezactiveaz ntreruperea generat de Timer 1

6.3. Aplicaie propus


S se scrie un program care s schimbe starea ledului DS2 de pe plac, la
fiecare 2 secunde, folosind ca baz de timp modulul Timer 1.

72

Timer 1

n Figura 6-3 este prezentat semnalul dreptunghiular cu factor de umplere


50%, generat prin schimbarea strii logice a pinului RC1 (led DS2) la
fiecare 2s.
Figura 6-3: ntrerupere generata la 2s cu Timer 1

6.4. Configurarea timer-ului


Timer 1 va fi configurat astfel nct s genereze ntreruperi la fiecare
500ms.
n primul rnd trebuie calculat durata maxim ce poate fi msurat pe 16
bii pentru frecvena de oscilator.
Fosc = 4MHz
Ftimer = Fosc/4 = 1MHz
Tosc = 250ns (1/Fosc)
Ttimer = 1000ns =1us.
Asta nseamn c pentru un pre-scalar de 1:1 registrul TMR1
(TMR1H+TMR1L) se va incrementa la fiecare 1us.
Tdorit = 500ms

Timer 1

73

NRincrementari = Tdorit/Ttimer
NRincrementari = 500ms/1us
NRincrementari = 500 000
Valoarea maxim ce poate fi scris n registrul TMR1 este 65535 (0xFFFF),
deci perioada de timp maxim ce poate fi msurat este aproximativ
65.5ms. Vom fi nevoii s folosim un pre-scalar diferit de 1:1.
Dac vom folosi un pre-scalar 1:8 Ttimer va deveni 8us, deoarece registrul
TMR1 se va incrementa doar la fiecare al optulea impuls de la intrare.
Atunci:
NRincrementari = Tdorit/Ttimer
NRincrementari = 500ms/8us
NRincrementari = 62 500 = 0xF424
Din numrul de incrementri rezult valoarea ce trebuie scris n TMR1H i
TMR1L. Ea este 0xFFFF- 0xF424 = 0xBDB. Adic timer-ul se va
incrementa de la 0xBDB la 0xFFFF, adic de 62 500 de ori. TMR1H =
0x0B; TMR1L = 0xDB.
Dup stabilirea valorii pre-scalarului i a registrului TMR1H i TMR1L,
vom trece la setarea celorlali bii din registrul de configurare T1CON:
Bitul 7 i 6 (T1GINV i TMR1GE) vor rmne zero deoarece nu
folosim funcia de Gate a timer-ului.
Bitul 5 i 4 (T1CKPS1:T1CKPS2) sunt bii pentru setarea prescalarului. Pentru pre-scalare de 1 la 8 avem nevoie de valoarea 0b11.
Bitul 3 (T1OSCEN) este folosit doar n cazul n care folosim
oscilator intern pentru low-power. Pentru configuraia folosit,
acest bit este ignorat.
Bitul 2 (T1SYNC) este valid doar dac modulul folosete un ceas
extern pentru configuraia folosit, acest bit este ignorat.
Bitul 1 (TMR1CS) alege sursa ceasului folosit. Pentru a avea ceas
intern Fosc/4, acesta ia valoarea zero.
Bitul 0 (TMR1ON) este folosit pentru activarea modulului. Timer 1
este activ/pornit cnd acesta ia valoarea 1.
Pentru activarea ntreruperii, setm biii GIE i PEIE din registrul INTCON.
n final, trebuie ters bitul de stare (flag) TMR1IF i apoi setat bitul
TMR1IE pentru activarea ntreruperii.

74

Timer 1

Folosind aceast configuraie, schema bloc a modulului va arta ca n figura


de mai jos.
Figura 6-4: Configurare Timer 1

6.5. Model software


n programul scris de noi va trebui s avem n vedere urmtoarele:
Configurarea modulului Timer 1.
Configurarea pinului RC2 (la care este legat ledul 3) ca pin de ieire.
Scrierea rutinei de tratare a ntreruperii.
Exemplu de cod:
/* include files */
#include "pic.h"
/* constant and macro defines */
#define LED
???
#define ON
1
#define OFF
0
/* variables */
volatile unsigned int counter;

Timer 1

/* function declarations */
void init();
/* function definitions */
void main()
{
init();
while(1)
{
/* switch LED after m seconds */
if(counter == ???)
{
if(LED == ON)
{
LED = OFF;
}
else
{
LED = ON;
}
counter = 0; /* reset counter */
}
}
}
void init()
{
ANSEL = ??? ; /* set RC0 to RC3 as digital pins */
ANSELH = ??? ; /* set RC6 and RC7 as digital pins */
TRISC = ??? ; /* RC4 to RC7 input. RC0 to RC3 output */
PORTC = 0x00; /* port C pins reset value */
/* timer 1 settings */
TMR1L = ??? ;
TMR1H = ??? ;
T1CON = ??? ;

75

76

Timer 1

/* interrupt settings */
GIE = 1; /* global interrupt enable */
PEIE = 1; /* peripheral interrupt enable */
TMR1IF = 0; /* clear TMR1 interrupt flag */
TMR1IE = 1; /* TMR1 interrupt enabled */
/* start TMR1 */
TMR1ON = 1;
/* variable intializations */
counter = 0;
}
/* Interrupt function */
void interrupt isr(void)
{
/* check if THR1 interrupt enable and flag are set */
if((TMR1IE == 1) && (TMR1IF == 1))
{
TMR1L = ??? ;
TMR1H = ??? ;
counter ++;
/* increment counter every 500ms */
TMR1IF=0;
/* clear TMR1 interrupt flag*/
}
}
Observaie: Implementnd aplicaiile prezentate n aceast lucrare pe
diverse calculatoare s-a observat c, n mediile unde sunt instalate mai multe
compilatoare, folosind anumite compilatoare n combinaie cu definirea
funciei de tratare a ntreruperilor duce la un comportament eronat: dup
ieirea din reset, n loc s se execute funcia main, aplicaia sare direct n
rutina de tratare a ntreruperilor. Dac, dup scrierea programului n
microcontroler, aplicaia pare s nu ruleze, acest comportament se poate
datora compilatorului activ folosit n proiect. Aceast problem este
prezent chiar dac selectm compilatorul potrivit cnd crem proiectul
(capitolul 1, punctul 2.3). Pentru a verifica dac folosim compilatorul
potrivit, accesai meniul Project / Build Options / Project i n fereastra
Driver, asigurai-v c primul compilator din list este Compiler for

Timer 1

77

PIC10/12/16 MCUs (Lite Mode) Vx.yy precum n figura de mai jos.


Folosii butonul Move Up dac acesta nu e primul.

Figura 6-5: Selectarea compilatorului folosit la Build

78

Timer 1

6.6. Problem propus


S se genereze un semnal dreptunghiular cu frecven 2Hz i factor de
umplere 60% pe pinul digital de ieire conectat la ledul 1 de pe plac, cu
ajutorul Timer 1.
n figurile urmtoare este prezentat semnalul dreptunghiular cu frecvena
2Hz i factor de umplere de 60% generat cu ajutorul Timer1, pe pinul RC2.
n Figura 6-6 este pus n eviden, ntre cele dou cursoare prezente pe
oscilogram, valoarea perioadei semnalului.
Figura 6-6: Semnal dreptunghiular cu frecventa de 2Hz

n Figura 6-7 este pus n eviden, ntre cele dou cursoare prezente pe
oscilogram, valoarea pulsului high a semnalului (factorul de umblere
60%).

Timer 1
Figura 6-7: Semnal dreptunghiular cu factor de umplere 60%

79

7. Timer 2
7.1. Descriere Timer 2
Timer pe 8 bii, compus dintr-un registru contor (TMR2) i un
registru pentru perioad (PR2).
pre-scalar programabil (1:1,1:4,1:16).
post-scalar programabil (1:1 pn la 1:16).
valoarea pre-scalarului i post-scalarului se reseteaz la orice scriere
n regitri TMR2 sau T2CON.
registrul TMR2 se incrementeaz pornind de la valoarea 0x00 pn
atinge valoarea setat n registrul perioad PR2. Dup acest moment,
la urmtorul impuls, incrementarea se reia de la 0x00.
dup reset, registrul PR2 este iniializat cu valoarea 0xFF. n acest
registru, nainte de activarea modulului, trebuie scrisa valoarea
calculat pentru a msura perioada de timp dorit.
cnd avem condiie de egalitate ntre contorul TMR2 i valoarea
scris n PR2, se genereaz o ntrerupere.
biii asociai ntreruperilor sunt: TMR2IE pentru activarea
ntreruperii; TMR2IF bitul flag al ntreruperii; GIE bitul pentru
activarea ntreruperilor globale; PEIE bitul pentru activarea
ntreruperilor de la periferice.
Figura 7-1: Schema bloc a Timer2 [6]

Timer 2

81

Principiul de funcionare al acestui tip de timer este urmtorul:


Modulul timer conine doi regitri: unul de incrementare (TMR2) i unul
pentru definirea perioadei de timp ce se dorete a fi msurat (PR2). n
registrul de perioad PR2 se ncarc o valoare dorit de noi (calculat n
prealabil). Registrul TMR2 se incrementeaz dup activarea modulului, la
fiecare impuls sosit la intrarea timer-ului (cu frecvena Fosc/4), de la valoarea
0 pn va ajunge la valoarea scris n registrul de perioad PR2.
La urmtorul impuls sosit la intrarea n timer, registrul TMR2 se va reseta la
valoarea 0 i va ncepe din nou s se incrementeze. Dac circuitul de postscalare este setat altfel dect 1:1, bitul flag TMR2IF nu se va seta la prima
egalitate dintre TMR2 i PR2. Cu alte cuvinte, dac circuitul de post-scalare
este setat 1:n, bitul de ntrerupere TMR2IF se va seta doar la a n-a egalitate
dintre registrul TMR2 i PR2. Spre exemplu, pentru o setare a postscalarului 1:6, doar la a 6-a egalitate se va seta flag-ul TMR2IF (TMR2 se
incrementeaz pn la valoarea PR2 de la 6 ori).
Dac i bitul TMR2IE (bitul de activare al ntreruperii) este setat, se va
genera o ntrerupere (cu condiia ca i biii GIE i PEIE s fie setai).
Microcontrolerul va sri n rutina de tratare a ntreruperii, unde bitul
TMR2IF trebuie ters, pentru ca o nou ntrerupere s fie posibil.
Frecvena impulsurilor de intrare n modulul timer este Fosc/4, unde Fosc este
frecvena oscilatorului folosit (4MHz n cazul aplicaiei noastre). Ea poate fi
divizat cu ajutorul pre-scalarului setat din registrul de configurare T2CON.
Practic, dac vom folosi un pre-scalar 1:4, valoarea registrului TMR2 se va
incrementa doar la al 4-lea impuls sosit la intrarea modulului. Astfel,
intervalul de timp ce poate fi msurat pe acelai numr de bii va fi de 4 ori
mai mare. Valorile posibile pentru pre-scalar sunt 1:1, 1:4, 1:8.
Tabel 7-1: Descrierea regitrilor afereni modulului Timer 2 [6]
Nume

Bit7

Bit6

Bit5

Bit4

Bit3

Bit2

Bit1

Bit0

INTCON

GIE

PEIE

T0IE

INTE

RABIE

T0IF

INTF

RABIF

PIE1

ADIE

RCIE

TXIE

SSPIE

CCP1IE

TMR2IE

TMR1IE

PIR1

ADIF

RCIF

TXIF

SSPIF

CCP1IF

TMR2IF

TMR1IF

TMR2

Registru de incrementare pe 8 bii

PR2

Registru de perioad a Timer 2

T2CON

TOUTPS1

TOUTPS0

TMR2ON

T2CKPS1

T2CKPS0

TOUTPS3

TOUTPS2

Legend: x=necunoscut, u=nemodificat, -=bitul se citete ca 0. Biii nchii la culoare nu sunt folosii de TIMER2.

82

Timer 2

INTCON: registrul de configurare al ntreruperilor. Se activeaz


ntreruperile generale i ale perifericelor.
PIE1: registrul de activare al ntreruperilor pentru periferice. Conine bii
individuali de activare a ntreruperilor pentru periferice.
PIR1: registrul de flag-uri al perifericelor. Conine flag-urile individuale de
ntrerupere pentru periferice.
T2CON: registru de configurare a modulului Timer 2.
Tabel 7-2: Descriere T2CON - registrul de configurare pentru Timer 2

Legend: R - bitul poate fi citit; W - bitul poate fi scris; U - bit neimplementat, se va citi 0; n valoare dup POR;
1 - bitul e setat; 0 - bitul e ters; X - valoare necunoscut;

Bit 7 Neimplementat: Se citete 0


Bit 6-3 TOUTPS<3:0>: Biii de selecie a post-scalarului
0000 = 1:1 Post-scalar
0001 = 1:2 Post-scalar
0010 = 1:3 Post-scalar
0011 = 1:3 Post-scalar
1110 = 1:15 Post-scalar
1111 = 1:16 Post-scalar
Bit 2: TMR2ON: Bit de activare a modulului
1 = TMR2 este activ
0 = TMR2 este dezactivat/oprit
Bit 1-0 T2CKPS<1:0>: Bit de selecie a pre-scalarului
00 = Pre-scalar 1
01 = Pre-scalar 4
1X = Pre-scalar 16

n ceea ce privete generarea de ntreruperi, utilizatorul trebuie s fac


urmtorii pai:

Timer 2

83
Figura 7-2: Logica generrii de ntreruperi [6]

Biii GIE i PEIE din registrul INTCON trebuie setai pentru a activa
ntreruperile generale i a perifericelor.
Tabel 7-3: Registrul INTCON

Legend: R - bitul poate fi citit; W - bitul poate fi scris; U - bit neimplementat, se va citi 0; n valoare dup POR;
1 - bitul e setat; 0 - bitul e ters; X - valoare necunoscut;

Bit 7 GIE: Bit de activare a ntreruperilor globale


1 = Activarea tuturor ntreruperilor nemascabile
0 = Dezactivarea tuturor ntreruperilor
Bit 6 PEIE: Bit de activare a ntreruperilor de la periferice
1 = ntreruperile perifericelor sunt active
0 = ntreruperile perifericelor sunt dezactivate

84

Timer 2

Bitul flag TMR2IF din registrul PIR1 trebuie ters.


Tabel 7-4: Registrul PIR1

Legend: R - bitul poate fi citit; W - bitul poate fi scris; U - bit neimplementat, se va citi 0; n valoare dup POR;
1 - bitul e setat; 0 - bitul e ters; X - valoare necunoscut;

Bit 1 TMR2IF: Bit de stare a ntreruperi TMR2


1 = O ntrerupere a TMR2 a fost generat
0 = Nici o ntrerupere a TMR2 nu a fost generat

ntreruperea timer-ului 2 trebuie activat prin setarea bitului TMR2IE din


registrul PIE1.
Tabel 7-5: Registrul PIE1

Legend: R - bitul poate fi citit; W - bitul poate fi scris; U - bit neimplementat, se va citi 0; n valoare dup POR;
1 - bitul e setat; 0 - bitul e ters; X - valoare necunoscut;

Bit 1 TMR2IE: Bit de activare a ntreruperii Timer 2


1 = ntreruperea modulului TMR2 este activat
0 = ntreruperea modulului TMR2 este dezactivat

7.2. Aplicaii propuse


a) S se scrie un program care s schimbe starea ledului DS2 de pe plac la
fiecare 2 secunde, folosind ca i baz de timp Timer 2.
n Figura 7-3 este prezentat semnalul dreptunghiular cu factor de umplere
50% generat prin schimbarea strii logice a pinului RC1 (led DS2) la fiecare
2s.

Timer 2

85
Figura 7-3: ntrerupere generat la 2s cu Timer 2

b) S se scrie un program care s schimbe starea ledului DS3 de pe plac la


fiecare o secund, folosind ca i baz de timp Timer 2, cu urmtoarele
condiii impuse: post-scalar 1:2 i pre-scalar 1:16.
n Figura 7-4 este prezentat semnalul dreptunghiular cu factor de umplere
50% generat prin schimbarea strii logice a pinului RC2 (led DS3) la fiecare
2s.
Figura 7-4: ntrerupere generat la 1s cu Timer2

86

Timer 2

7.3. Configurarea timer-ului


Timer 2 va fi configurat astfel nct s genereze ntreruperi la fiecare 10ms.
n primul rnd trebuie calculat durata maxim ce poate fi msurat pe 8 bii
pentru frecvena de oscilator:
Fosc =4MHz
Ftimer = Fosc/4 = 1MHz
Tosc = 250ns
Ttimer = 1000ns =1us.
Asta nseamn c pentru un pre-scalar de 1:1 registrul TMR2 se va
incrementa la fiecare 1us.
Tdorit = 10ms
NRincrementari = Tdorit/Ttimer
NRincrementari = 10ms/1us
NRincrementari = 10 000
Valoarea maxim care poate fi scris n registrul TMR2 este 255, deci
perioada de timp maxim ce poate fi msurat este aproximativ 256us. Vom
fi nevoii s folosim un pre-scalar diferit de 1:1.
Dac vom folosi un pre-scalar 1:16, Ttimer va deveni 16us, deoarece registrul
TMR2 se va incrementa doar la fiecare al 16-lea impuls. Atunci:
NRincrementari = Tdorit/Ttimer
NRincrementari = 10ms/16us
NRincrementari = 625 = 0x271
Din numrul de incrementri rezult valoarea ce trebuie scris in TMR2. n
acest moment valoarea este nc mai mare de 256. n acest caz vom folosi i
post-scalarul, astfel nct numrul de incrementri s fie mai mic de 256.
Vom alege un post-scalar 1:5. Adic doar a 5-a egalitate va genera o
ntrerupere. Atunci:
NRincrementari = Tdorit/Ttimer
NRincrementari = 10ms/80us
NRincrementari = 125 = 0x7D
Cu alte cuvinte, pentru a afla valoarea maxim ce poate fi msurat cu
modulul Timer 2, nmulim valorile maxime pentru pre-scalar i post-scalar
(16), cu numrul maxim de incremente al contorului (8 bii = 256
incremente), totul mprit la frecvena oscilatorului folosit.

Timer 2

87

Tmax = (256 * 16 * 16)/(4MHz/4)


Se poate observa c, folosind valorile maxime pentru pre i post scalar,
modulul Timer 2 are valoarea maxim ct un timer pe 16 bii (256*16*16 =
65536)
Dup stabilirea valorilor pentru pre i post scalar, se trece la setarea
registrului de control T2CON:
Bitul 7 bit rezervat.
Biii 6 pn la 3 (TOUTPS3:TOUTPS0) conin valoarea postscalarului. Pentru a obine raportul dorit de 1 la 5, trebuie s scriem
n aceti bii valoarea 0b0100.
Bitul 2 (TMR2ON) este bitul de activare al modulului. Timer 2 este
activat cnd acesta are valoarea 1.
Biii 1 i 0 (T2CKPS1-T2CKPS0) seteaz valoarea pre-scalarului.
Pentru un raport de 1 la 16, avem nevoie de valoarea 0b11 sau 0b10.
Pentru activarea ntreruperii setm biii GIE i PEIE din registrul INTCON.
La sfrit trebuie ters bitul TMR2IF i apoi setat bitului TMR2IE pentru
activarea ntreruperii.
7.4. Model software
n programul scris de noi va trebui s avem n vedere:
Configurarea modulului Timer 2.
Configurarea ca i ieire a pinului RC1 la care este legat ledul DS2.
Scrierea rutinei de tratare a ntreruperii.
Exemplu de cod:
/* include files */
#include "pic.h"
/* constant and macro defines */
???
/* variables */
???

88
/* function declarations */
void init();
/* function definitions */
void main()
{
init();
while(1)
{
/* switch LED after m seconds */
if(counter == ???)
{
??? /* insert code here */
}
}
}
void init()
{
/* pin settings */
???
/* timer 2 settings */
TMR2 = 0x00; /* reset TMR2 counter */
PR2 = ??? ; /* overflow value */
T2CON = ??? ; /* TMR 2 settings */
/* interrupt settings */
???
/* start TMR2 */
???
/* variable intializations */
counter = 0;
}

Timer 2

Timer 2

89

/* Interrupt function */
void interrupt isr(void)
{
/* check if TMR2 interrupt enable and flag is set */
if((???) && (???))
{
??? /* insert code here */
}
}
7.5. Problem propus
Descriei pe scurt un proiect n care poate fi folosit un timer. Ce rol ar avea?
Pe care din cele dou module de timer (Timer 1 sau Timer 2) le-ai folosi i
de ce?

8. Servomotor
8.1. Introducere
Multe aplicaii embedded presupun comanda unui motor cu scopul de
acionare mecanic a unui sistem. n astfel de aplicaii, alegerea corect a
motorului constituie de multe ori o sarcin dificil. Trebuie luate n calcul
mai multe aspecte, dintre care cele mai importante, n funcie de aplicaie,
sunt:
Gabarit: motorul trebuie s poat fi amplasat n spaiul dedicat
produsului. De exemplu, pentru cutiile de vitez automate,
ambreiajul este acionat de un motor electric, iar dimensiunile sunt
impuse de cerinele clienilor (gabaritul cutiei de vitez).
Cuplu: n funcie de sistemul ce trebuie acionat este nevoie de un
anumit cuplu. Fiecare tip de motor are un anumit cuplu n funcie de
gabarit, tensiune de alimentare, turaie i tip constructiv. Cuplul
motorului ales trebuie sa satisfac cerinele proiectului.
Comanda motorului: comanda electric a motorului este un criteriu
important, deoarece difer mult de la motor la motor, fiind fie simpl
(servomotor), fie foarte complex (motor brushless).
Tensiunea de alimentare: ca exemplu, la autoturisme, tensiunea de
alimentare este 12V. Un motor cu o tensiune de alimentare diferit de
12V poate introduce n proiect necesitatea unei surse n comutaie sau
altor soluii hardware, care cresc preul produsului i complexitatea
acestuia.
Durata de via: un motor de curent continuu are perii colectoare
care, n timp, se deterioreaz, pe cnd un motor brushless nu
ntmpin acest impediment. Din acest punct de vedere, un sistem cu
motor brushless este indicat n locuri greu accesibile sau n produse
crora li se impune o durat de via lung i fr defecte.
Preul: preul motorului este un procent important din costul total al
produsului i astfel trebuie s se ncadreze n nite limite foarte bine
stabilite. Preul poate varia de la civa EURO (servomotoare
analogice RC) la sute de EURO (motor de curent continuu cu
encoder i cutie reductoare).
S lum n continuare un caz particular, o posibil aplicaie. S plecm de la
ideea c trebuie s realizm pentru bordul unui automobil un vitezometru

Servomotor

91

care s par analogic, adic s aib o scal i un ac indicator, dar care s fie
acionat de un motor electric comandat de sistemul care msoar viteza
autovehiculului. Pentru alegerea motorului trebuie s inem cont de criteriile
de mai sus i am putea lua n calcul cteva tipuri de motoare:
Motor de curent continuu: din punct de vedere al gabaritului, al
cuplului dezvoltat i al preului poate fi o variant. Mari dezavantaje
ar fi comanda complicat cu bucl nchis (avem nevoie de comand
cu feedback pentru a fi siguri c acul este la poziia dorit) i durata
de via a periilor.
Motorul pas cu pas: motorul pas cu pas n conexiune bipolar are de
asemenea dezavantajul complexitii driverului hardware pentru
comand. n schimb, motorul pas cu pas n conexiune unipolar
depete acest dezavantaj, comanda fiind una relativ simpl. Pentru
cuplul necesar acionrii acului indicator n aceast aplicaie, motorul
are de asemenea un gabarit relativ redus. Durata de via este foarte
mare dar preul poate fi considerat mare.
Motorul brushless: nu corespunde din mai multe puncte de vedere.
Preul este ridicat comparativ cu alte tipuri de motoare. Comanda este
complex. n plus, un alt dezavantaj este consumul mai mare de
curent.
Servomotorul: la baz are tot un motor de curent continuu dar de
dimensiuni foarte mici. Este cel mai simplu de comandat, deoarece
include un sistem de feedback cu poteniometru iar poziia la care
trebuie s se deplaseze rotorul se d prin comand PWM pe un singur
fir. Include i un reductor, deci cuplul este ridicat comparativ cu
gabaritul lui i consumul de curent. Preul este de asemenea un
avantaj, acest tip de motor fiind mai ieftin dect un motor pas cu pas.
8.2. Comanda unui servomotor
Servomotorul este compus din mai multe pri: un motor (DC de regul), un
reductor mecanic, un traductor de poziie (cel mai adesea un poteniometru),
un driver de motor, un amplificator de eroare i un circuit pentru
decodificarea poziiei dorite.
n Figura 8-1 putem observa schema bloc a unui astfel de sistem.

92

Servomotor
Figura 8-1: Schema bloc a unui servomotor analogic

Comanda unui servomotor analogic se face cu ajutorul unui semnal PWM


(Pulse Width Modulation), generat de ctre microcontroler.
Figura 8-2: Forma unui semnal PWM

Unde: TON = durata pulsului high (poate varia)


TP = perioada semnalului (rmne constant)
VPK = amplitudinea semnalului
DC = TON/TP (%) - Factor de umplere (Duty Cycle)
Perioada semnalului este 20ms i durata pulsului high variaz, n general,
ntre 1ms i 2ms, n funcie de poziia dorit pentru rotor. Durata pulsului

Servomotor

93

este folosit de ctre servomotor pentru a determina poziia la care s se


roteasc.
Semnalul PWM ajunge la intrarea unui circuit care convertete limea
pulsului high n tensiune. Practic, prin modificarea Duty Cycle a semnalului
PWM, se modific tensiunea de la ieirea convertorului (care este aplicat la
intrarea amplificatorului de eroare).
Senzorul de poziie este un poteniometru a crui tensiune de ieire este
proporional cu poziia absolut a axului. Tensiunea de pe poteniometru
ajunge la una din intrrile amplificatorului de eroare, iar la cealalt intrare
se aplic tensiunea de la ieirea circuitului ce convertete factorul de
umplere al semnalului de comand PWM ntr-o tensiune analogic.
Circuitul se numete convertor pulse width to voltage i tensiunea de la
ieire este proporional cu limea pulsului PWM (cu ct limea pulsului
de la intrare e mai mare cu att tensiunea va fi mai mare la ieire). Cu alte
cuvinte, la una din intrri vom regsi poziia curent, iar la cealalt poziia
dorit.
Amplificatorul de eroare este un amplificator operaional (folosit ca i
comparator), care va ncerca n permanen s aduc la zero diferena dintre
cele dou intrri. Ieirea amplificatorului operaional este o tensiune fie
negativ, fie pozitiv, n funcie de diferena celor doua tensiuni de la
intrare.
Dac tensiunea este pozitiv, motorul se va roti ntr-un sens, iar dac este
negativ se va roti n sensul opus. Acest lucru i permite amplificatorului
operaional s reduc diferena dintre cele dou tensiuni de la intrare sa,
cauznd astfel axul s ajung la poziia dorit.
8.3. Aplicaie propus
Pentru ncaput stabilii cu ajutorul unui generator de semnal, limea
impulsului ce trebuie trimis ctre servomotor la fiecare 20ms, pentru poziia
de 0 grade, 90 de grade i 180 de grade.
Poziia axului servomotorului
0 grade
90 grade
180 grade
Limea pulsului
[ms]

94

Servomotor

Se consider c aplicaia ce trebuie realizat cu ajutorul unui servomotor


este un indicator de vitez pentru un autoturism (0Km/h corespunde cu
poziia de 0 grade a servomotorului i viteza de 180Km/h cu poziia de 180
de grade a servomotorului). S se scrie un program n care, cu ajutorul
timerelor 1 i 2, microcontrolerul s comande servomotorul astfel nct
acesta s indice viteza de 85Km/h. Pinul folosit pentru comand este pinul
la care este conectat i ledul DS4.
n Figura 8-3 este prezentat semnalul PWM cu perioada 20 ms i cu factor
de umplere 10%, generat pe pinul RC3 (led DS4).
Figura 8-3: Semnal PWM cu perioada 20 ms.

Servomotor

95

8.4. Model software


n programul scris de noi va trebui s avem n vedere, conform figurii de
mai jos, urmtoarele:
Figura 8-4: Program flow

Configurarea Timer 1 ca i baz de timp de 20ms (perioada constant


a semnalului PWM).
Configurarea Timer 2 ca i baz de timp pentru limea pulsului
pozitiv (Duty Cycle).
Configurarea ca ieire a pinului la care este legat ledul DS4.
Scrierea rutinei de tratare a ntreruperilor pentru ambele surse de
ntrerupere.
Exemplu de cod:
/* include files */
#include "pic.h"
/* constant and macro defines */
???
/* function declarations */
void init();

96
/* function definitions */
void main()
{
init();
while(1)
{
; /* further development */
}
}
void init()
{
/* pin configuration */
???
/* timer 1 settings */
???
/* timer 2 settings */
???
/* interrupt settings */
???
/* other initializations */
???
}
/* Interrupt function */
void interrupt isr(void)
{
/* check if TMR1 interrupt enable and flag are set */
if((TMR1IE == 1) && (TMR1IF == 1))
{
??? /* insert code here */
}
/* check if TMR2 interrupt enable and flag are set */

Servomotor

Servomotor

97

if((TMR2IE == 1) && (TMR2IF == 1))


{
??? /* insert code here */
}
}
8.5. Problem propus
Generai un semnal PWM cu frecven de 5KHz i factor de umplere 20%
folosind aceleai 2 periferice (Timer 1 i Timer 2). Pinul pe care semnalul
trebuie generat este RC0.
n Figura 8-5 este prezentat semnalul PWM cu frecven 5KHz i cu factor
de umplere 20% generat pe pinul RC3 (led DS4).
Figura 8-5: Semnal PWM cu perioada 20 ms

9. Convertor Analog Numeric


9.1. Introducere
Conversia analog-numeric reprezint operaia de obinere a unei secvene
numerice de valoare proporional cu o mrime analogic. n funcie de
tipul constructiv, vitez i precizie, un circuit ADC se clasific n:
ADC cu comparare:
de tip paralel
cu tensiune de comparat cresctoare
cu urmrire
cu aproximri succesive
ADC tensiune timp
cu integrarea unei tensiuni de referin
cu dubl integrare
ADC tensiune-frecven
Indiferent de tipul convertorului, mrimea analogic de la intrarea n
convertor este discretizat ntr-un numr de trepte elementare. Acest numr
elementar de trepte este dat de numrul de bii pe care se obine rezultatul
conversiei i este egal cu 2N. Cea mai mic valoare convertit diferit de
zero este treapta elementar (cuanta): q = UR2-N
Figura 9-1: Codarea tensiunii de intrare [6]

Convertor Analog Numeric

99

Dou valori posibile consecutive difer ntre ele cu q. Cuanta reprezint, de


fapt, chiar rezoluia convertorului.
Pentru o precizie ct mai bun, q trebuie s fie ct mai mic. Cu ct N
(numrul de bii pe care se obine rezultatul) este mai mare, pentru aceeai
tensiune de referin UR a convertorului, q va fi mai mic. Inconvenientul
care apare la creterea lui N este creterea timpului necesar realizrii
conversiei analog numerice. n practic, de cele mai multe ori, trebuie fcut
un compromis ntre precizie i viteza de realizare a conversiei, n funcie de
cerinele aplicaiei.
O alta modalitate de a mbunti precizia, fr a crete N, este alegerea
corespunztoare a tensiunii de referin UR. De exemplu, dac prin natura
proiectrii aplicaiei, tim c tensiunea maxim de intrare n convertor este
2.8V, atunci vom impune o tensiune de referin UR = 3V (cu alte cuvinte,
ct mai apropiat de tensiunea maxim de convertit).
Exemplul 1: Dac avem o tensiune de referin de 5V i un convertor pe 10
bii (1024 de valori posibile), rezoluia este de 4.88mV. Pentru aceeai
tensiune de referin, dar de aceast dat convertorul este pe 8 bii (256 de
valori posibile), rezoluia este de 19.53mV.
Exemplul 2: Avem un convertor pe 10 bii, iar tensiunea maxim la intrarea
n convertor este de 2.9V. Putem alege o tensiune de referin de 5V,
rezoluia fiind n acest caz 4.88mV. Putem mbunti precizia, dac
modificm tensiunea de referin la o valoare de 3V, rezoluia devenind
2.92mV. Acest lucru va duce i la scderea timpului necesar eantionrii (n
proporii mici).
Eantionarea semnalului analogic se face la intervale de timp bine definite.
Cu ct frecvena de eantionare este mai mare, cu att se vor pierde mai
puine informaii din semnalul analogic ce se vrea convertit (vom obine mai
multe mostre). Timpul minim ntre dou eantionri Te trebuie totui s
permit circuitului digital s realizeze conversia analog-numerica. Acest
timp depinde n mare msura de numrul de bii pe care se obine rezultatul
conversiei i de tipul constructiv al convertorului.
Conform teoremei eantionrii, este necesar ca valoarea minim a
frecvenei de eantionare s satisfac relaia:
fe 2fxmax condiia Nyquist.

100

Convertor Analog Numeric

Unde fxmax este frecvena maxim a spectrului semnalului analogic de


intrare UX, iar fe este frecvena de eantionare.
Figura 9-2: Modelul unui pin de intrare analogic [6]

Un pin de intrare analogic are o impedan foarte mare, pentru a nu


modifica funcionarea circuitului n care este conectat. Acest lucru se
realizeaz folosind la intrare un amplificator operaional repetor (prin care
se ncarc condensatorul CHOLD). Practic, la nchiderea ntreruptorului se
realizeaz eantionarea, prin ncrcarea condensatorului CHOLD pn la
valoarea tensiunii aplicat pe pinul respectiv. Acest condensator este
conectat la intrarea n convertorul analog numeric i el va menine tensiunea
constant pe durata conversiei.
9.2. Descriere ADC pe 10 bii
Microcontrolerul PIC16F690 dispune de un convertor pe 10 bii care are
urmtoarele caracteristici:

Convertor analog numeric cu aproximri succesive.


12 intrri analogice (AN0 AN11).
Pini externi pentru tensiunea de referin (selectabil prin software).
Dou tipuri de aliniere a rezultatului conversiei.

n figura de mai jos este prezentat o schem bloc a convertorului analog


numeric.

Convertor Analog Numeric

101

Figura 9-3: Schema bloc a modulului ADC [6]

Modulul ADC are 15 regitri asociai, care vor fi descrii n continuare.


Dintre acetia, 2 regitri sunt pentru salvarea rezultatului conversiei i 2
pentru configurarea modului ADC.
Tabel 9-1: Regitri asociai modulului ADC [6]
Nume

Bit7

Bit6

Bit5

Bit4

Bit3

Bit2

Bit1

Bit0

ADCON0

ADFM

VCFG

CH3

CH2

CH1

CH0

GO/DONE

ADON

ADCON1

ADCS2

ADCS1

ADCS0

ANSEL

ANS7

ANS6

ANS5

ANS4

ANS3

ANS2

ANS1

ANS0

ANSELh

ANS11

ANS10

ANS9

ANS8

ADRESH

Rezultatul conversiei A/D. Cel mai semnificativ octet.

ADRESL

Rezultatul conversiei A/D. Cel mai putin semnificativ octet.

INTCON

GIE

PEIE

T0IE

INTE

RABIE

T0IF

INTF

RABIF

PIE1

ADIE

RCIE

TXIE

SSPIE

CCP1IE

TMR2IE

TMR1IE

PIR1

ADIF

RCIF

TXIF

SSPIF

CCP1IF

TMR2IF

TMR1IF

PORTA

RA5

RA4

RA3

RA2

RA1

RA0

PORTB

RB7

RB6

RB5

RB4

PORTC

RC7

RC6

RC5

RC4

RC3

RC2

RC1

RC0

TRISA

TRISA5

TRISA4

TRISA3

TRISA2

TRISA1

TRISA0

102

Convertor Analog Numeric

TRISB

TRISB7

TRISB6

TRISB5

TRISB4

TRISC

TRISC7

TRISC6

TRISC5

TRISC4

TRISC3

TRISC2

TRISC1

TRISC0

Legend: x=necunoscut, u=nemodificat, -=bitul se citete ca 0. Biii nchii la culoare nu sunt folosii de ADC.

Regitri TRISA, TRISB i TRISC se folosesc pentru alegerea direciei


pinilor. Dac acetia sunt configurai ca i pini analogici, asignai modulului
ADC, direcia pinilor selectabil din regitri de direcie TRISx trebuie s fie
input. Regitri PORTA, PORTB i PORTC se folosesc doar n cazul n care
pinii din cele trei porturi sunt setai ca i pini digitali.
Figura 9-4: Asignarea pinilor [3]
+5V
Btn1
PA2
D/A
PA1
+5V
PA0

R2

D/A
P
CAN

x x x x x 0 1 x
PORTA

LED

x x x x x 1 0 1
ADCON0 & ADCON1

- -

- - - - 0 0
ADRESH

TRISA

0 1 1 0 0 1 0 1
ADRESL

Regitri ADCON0 i ADCON1 sunt regitri de configurare ai modulului


ADC. Cu ajutorul regitrilor ANSEL i ANSELH se asigneaz pinii fie
modulului ADC, fie portului I/O. Regitri ADRESH i ADRESL sunt
regitri n care se salveaz rezultatul conversiei numrul cuantelor q
coninute de tensiunea de convertit. Exist 2 moduri de aliniere a
rezultatului pe 10 bii.
INTCON, PIR1 i PIE1 sunt regitri folosii pentru activarea i lucrul cu
ntreruperea generat la finalul conversiei analog numerice.

R1

Convertor Analog Numeric

103

Tabel 9-2: Registrul ADCON0

Legend: R - bitul poate fi citit; W - bitul poate fi scris; U - bit neimplementat, se va citi 0; n valoare dup POR;
1 - bitul e setat; 0 - bitul e ters; X - valoare necunoscut;

Bit 7 ADFM: Formatul conversiei A/D


1 = Aliniat la dreapta
0 = Aliniat la stanga
Bit 6 VCFG: Tensiunea de referin
1 = Pinul VREF
0 = VDD
Bit 5-2 CHS<3:0>: Biii pentru selectarea canalul analogic
0000 = AN0
0001 = AN1
0010 = AN2
0011 = AN3
0100 = AN4
0101 = AN5
0110 = AN6
0111 = AN7
1000 = AN8
1001 = AN9
1010 = AN10
1011 = AN11
1100 = CVREF
1101 = Referin fixa de 0.6V
1110 = Nu este implementat
1111 = Nu este implementat
Bit 1 GO/DONE: Bitul de start a conversiei
1 = Conversie A/D n execuie. Setarea acestui bit pornete o conversii A/D. Acest bit
este ters (devine 0) automat de ctre hardware la finalul unei conversii.
0 = Conversie A/D oprit.
Bit 0 ADON: Bit de activare a modulului
1 = Modulul ADC este activat
0 = Modulul ADC este dezactivat

Tabel 9-3: Registrul ADCON1

104

Convertor Analog Numeric

Legend: R - bitul poate fi citit; W - bitul poate fi scris; U - bit neimplementat, se va citi 0; n valoare dup POR;
1 - bitul e setat; 0 - bitul e ters; X - valoare necunoscut;

Bit 7 Neimplementat: Se citete 0.


Bit 6-4 ADCS<2:0>: Bit de selecie a ceasului pentru conversia A/D
000 = FOSC/2
001 = FOSC/8
010 = FOSC/32
X11 = FRC(oscilator intern dedicat = 500kHz max)
100 = FOSC/4
101 = FOSC/16
110 = FOSC/64
Bit 3-0 Neimplementat: Se citete 0.

Salvarea rezultatului conversiei poate fi fcut n dou feluri: right sau left
justified. Dac alegem modul right justified, cei mai puin semnificativ 8 bii
vor fi scrii n ADRSEL, iar cei mai semnificativi 2 bii in ADRSEH. n
cazul selectrii modului left justified, cei mai puin semnificativ 2 bii vor fi
salvai n ADRSEL, iar cei mai semnificativ 8 bii n ADRESH.
Figura 9-5: Alinierea rezultatului conversiei [6]

Convertor Analog Numeric

105

n ceea ce privete generarea de ntreruperi, utilizatorul trebuie s fac


urmtorii pai:
INTCON: registrul de configurare al ntreruperilor. Se activeaz
ntreruperile generale i a perifericelor prin setarea biilor GIE i PEIE.
PIR1: registrul de flag-uri al perifericelor. Conine flag-urile individuale de
ntrerupere pentru periferice. Se va terge bitul ADIF (6). Acest bit se va
seta automat la finalul conversiei analog numerice.
PIE1: registrul de activare al ntreruperilor pentru periferice. Conine bii
individuali de activare a ntreruperilor pentru periferice. Se va seta bitul
ADIE (6), pentru activarea ntreruperii generate de modulul ADC.
Modul de lucru al convertorului este simplu. Dup ce setrile sunt realizate
(se alege pinul de pe care are loc conversia, frecvena de conversie, etc.)
procesul de conversie este pornit efectiv cu trigger software prin scrierea
bitului GO (bit 2) din registrul ADCON0. La finalul conversiei, bitul GO va
fi ters automat de ctre hardware i va returna n regitrii ADRSEH i
ADRSEL valoarea conversiei, adic o valoare corespunztoare cu tensiunea
de pe pin. Aceast valoare reprezint chiar numrul cuantelor q cuprinse n
tensiunea de convertit.
Dac rezoluia conversiei este de 5mV, i valoarea conversiei este
0b000000_1000, atunci tensiunea pe pin este cuprins intre 40mV si
44.9mV. Aceai regul (nmulim numrul de cuante rezultat cu valoarea
rezoluiei) o aplicm i pentru valoarea conversiei: 0b010000_1000.
Tensiunea pe pin este cuprins ntre 1320mV i 1324.9mV.
9.3. Aplicaie propus
S se scrie un program care s aprind ledul DS3 de pe plac, dac
tensiunea electric la intrarea pinului de conversie analog numeric
AN0 este mai mare de 3V.
Folosind Timer 1, conversia analog numeric se va realiza la fiecare
500ms.
ntreruperea modulului ADC trebuie generat la finalul fiecrei
conversii.
Sursa de trigger software a conversiei: setarea bitului GO (prezentat
la punctul 9.4).
Tensiunea de referin s provin de la pinii VDD i VSS.

106

Convertor Analog Numeric


Figura 9-6: Diagram cerine

n Figura 9-7 este prezentat starea ledului DS3 pentru o tensiune la intrarea
convertorului ADC care depete pragul de 3V (moment n care pinul RC2
devine 1 logic) i care, dup un timp, revine sub pragul de 3V (pinul revine
i el n starea de 0 logic).
Figura 9-7: Starea pinului RC2 n funcie de tensiunea de pe pinul RA0

Convertor Analog Numeric

107

9.4. Configurarea ADC


Configurarea modulului ADC presupune urmtorii pai:
Selectarea pinilor analogici AN0-AN11:
Deoarece dorim s citim tensiunea aplicat pe pinul AN0, acesta trebuie
setat ca i pin de intrare analogic. Bitul ANS0 din registrul ANSEL are
valoarea 1, adic AN0 pin analogic (buffer-ul digital de intrare este oprit i
orice citire din PORTx va returna valoarea 0 la poziia bitului asignat
pinului). Trebuie avut grij ca i direcia pinului din registrul de direcie
TRISA s fie de input. Bitul 0 din acest registru va avea valoarea 1.
Selectarea sursei tensiunii de referin ADC:
Aceast tensiune trebuie s fie cel puin egal cu valoarea maxim ce se
vrea a fi convertit. Deoarece tensiunea pe pinul AN0 este aplicat cu
ajutorul unui poteniometru conectat la 5V (deci poate varia ntre 0V i 5V),
tensiunea de referin trebuie s fie 5V. n aceast aplicaie va fi chiar
tensiunea de alimentare a modulului ADC de pe pinii VDD i VSS. Setarea
se face cu ajutorul bitului VCFG din registrul ADCON0<6>.
Observaie: Trebuie precizat c tensiunea de referin poate fi aplicat i pe
pinul extern VREF+ din mai multe motive. Unul este legat de creterea
preciziei i a fost prezentat n paragrafele anterioare. Un alt motiv important
este legat de faptul c n multe aplicaii, temperatura de lucru a circuitului
poate varia mult, astfel variind i tensiunea de referin. n astfel de situaii
sunt folosite circuite externe de stabilizare a tensiunii (mai puin influenate
de variaia cu temperatura) pentru asigurarea tensiunii de referin a
circuitului ADC.
Selectarea tactului pentru conversie. Biii ADCS<0:2> din registrul
ADCON1:
Tactul TAD al modulului analogic ADC controleaz timpul de conversie. O
conversie complet necesit 12 perioade TAD. Perioada unei conversii
analog-numerice se poate configura cu ajutorul biilor ACSD<2:0> i
trebuie s aib o valoare minima de 4.6 s (pentru 5V). Astfel vom alege
ADCS2 = 1 i ACSD<1:0> = 0b00.
Alegerea formatului rezultatului conversiei (ADFM din registrul
ADCON0):
Exist dou moduri de format. Cel utilizat n aceast aplicaie este de tip
right justify, adic bitul ADFM = 1.

108

Convertor Analog Numeric

Activarea modulului:
Activarea modulului se face prin setarea bitului ADON din registrul
ADCON0 (bitul 0). Urmtorul pas ar fi declanarea n software a conversiei
prin setarea bitului GO, bitul 2 din ADCON0. n momentul scrierii acestui
bit, modulul ADC va incepe conversia analog numeric a tensiunii regsite
pe pinul analogic de intrare. La finalul conversiei modulul ADC va returna
n regitri ADRSEH si ADRSEL o valoare corespunztoare cu tensiunea de
pe pin (numrul cuantelor q coninute de tensiunea de convertit).
Activarea ntreruperilor, att pentru Timer 1 ct i pentru modulul
ADC:
Trebuie setai biii GIE i PIE din registrul INTCON, biii TMR1IE i ADIE
din registrul PIE1. Flag-urile ambelor surse de ntrerupere trebui terse i
anume biii TMR1IF i ADIF din registrul de flag-uri PIR1.
9.5. Model software
n programul scris de noi va trebui s avem n vedere:

Configurarea Timer 1
Configurarea modulului ADC
Configurarea ca i ieire a pinului la care este legat ledul DS3
Scrierea rutinei de tratare a ntreruperii.

Exemplu de cod:
/* include files */
#include "pic.h"
/* constant and macro defines */
???
#define THRESHOLD 3000 /* threshold for turning the LED ON */
#define ADC_TO_mV 5 /* rounded from 4.88 */
/* variables */
volatile unsigned int ADCValue, lastADCValue;
volatile unsigned int milliVolts;
/* function declarations */
void init();

Convertor Analog Numeric

109

/* function definitions */
void main()
{
init();
while(1)
{
/* check if last ADC value is different from current read - only if true
execute code */
if(ADCValue != lastADCValue)
{
milliVolts = ADCValue * ADC_TO_mV; /* convert from ADC value
to mV */
/* turn LED ON if greater than set threshold */
???
/* save last ADC value */
lastADCValue = ADCValue;
}
}
}
void init()
{
/* pin configuration */
???
/* timer 1 settings */
???
/* ADC configuration */
ADCON0 = 0x80; /* right justify; Vref = Vdd; AN0; module turned off */
ADCON1 = 0x40; /* Fosc/4 */
ADON = 1; /* turn module on */
/* interrupt settings */
???

110

Convertor Analog Numeric

/* start TMR1 */
TMR1ON = 1;
/* initialize variables */
lastADCValue = 0;
ADCValue = 0;
milliVolts = 0;
}
/* Interrupt function */
void interrupt isr(void)
{
/* check if TMR1 interrupt enable and flag are set */
if((TMR1IE == 1) && (TMR1IF == 1))
{
TMR1L = ??? ;
TMR1H = ??? ;
ADCON0 |= 0x02; /* set GO bit to start ADC conversion */
TMR1IF = 0;
/* clear TMR1 interrupt flag*/
}
else if((ADIE == 1) && (ADIF == 1))
{
ADCValue = (ADRESH << 8) + ADRESL;
ADIF = 0; /* clear ADC ISR flag */
}
}

10. UART
10.1. Introducere
UART (Universal Asynchronous Receiver Transmitter) este o interfa de
comunicare asincron serial. Fiecare dintre participani are propriul circuit
de generare a ceasului necesar comunicrii i astfel protocolul este asincron
(nu exist semnal de ceas transmis ntre participani). Se mai numete i SCI
(Serial Communications Interface).
UART este un protocol de comunicare pe 2 fire, nu necesit master i
comunicarea poate fi iniiat simultan de oricare dintre noduri. Acest mod se
numete full-duplex. Protocolul poate fi folosit pentru comunicaia dintre
dou microcontrolere aflate la civa metri distan (dac se folosete cablu
torsadat). Ambii participani la comunicare trebuie s aib aceleai setri
(numr de bii, frecvena semnalului de ceas sau paritatea).
10.2. Descriere modul UART
n funcie de implementarea hardware, modulul UART poate avea diferite
caracteristici. Cele mai importante la PIC16F690 sunt:
Datele transmise pot avea o lungime de 8 sau 9 bii, n funcie de
setrile fcute.
Datele ce se doresc a fi transmise sunt mpachetate de ctre
hardware pentru a corespunde cu protocolul, fiind adugai un bit de
start i unul de stop.
Modulul dispune de pini dedicai de transmisie i de recepie.
ntreruperi dedicate att pentru transmisie ct si pentru recepie.
Un buffer de transmisie i unul de recepie (de tip FIFO cu
adncime 2).
Modulul dispune de bii de stare care indic eroarea de format i
eroarea de recepie a unui nou mesaj (cnd buffer-ul de recepie este
plin).
Cnd bitul SPEN este setat, pinul RX este configurat ca si pin de
intrare, indiferent de starea bitului din registrul TRIS, chiar dac
blocul de recepie nu este activat.
Trebuie adugat c n unele implementri hardware (nu este cazul
microcontrolerului PIC16F690) exist i un bit de paritate (par sau impar)

112

UART

care face parte (opional) din formatul mesajului trimis. Acest bit de paritate
este calculat i mpachetat alturi de biii de date n formatul mesajului de
ctre participantul care trimite datele. La recepie, acest bit este
despachetat i comparat cu valoarea de paritate calculat la recepie. n
cazul n care difer, se genereaz eroare de paritate.
Exist i implementri hardware unde, n funcie de setri, putem alege unul
sau doi bii de stop.
Figura 10-1: Formatul protocolului UART

n figurile de mai jos se poate observa un mesaj cu data 0x66 (0b01100110)


i cu o rat de transfer de 9600 bit/secund (adic 140.1 s pentru fiecare
bit). Mesajul conine un bit de start, primul bit (cu o lime de 140.1 s) ce
va fi 0 logic, 8 bii de date (cu o lime de 8*104.1 s i valoarea 0x66) i
un bit de stop (cu o lime tot de 140.1s) ce va fi 1 logic. Limea total a
mesajului va fi 1041s (adic 10 bii).
Figura 10-2: Valoarea 0x66 trimis cu 9600 bit/secunda

UART

113

Se poate observa n continuare modul n care datele sunt mpachetate n


formatul mesajului. Primul este bitul de start, cuprins ntre cursoare.
Figura 10-3: Bit de start pentru un mesaj trimis cu 9600 bit/secunda

Urmeaz datele, adic valoarea 0x66 (0b01100110), cu cel mai puin


semnificativ bit trimis primul. Data va avea o lime de 832.8 s, adic 8
bii a cte 104.2 s.
Figura 10-4: Datele (0x66) ntr-un mesaj trimis cu 9600 bit/secunda

114

UART

Ultimul bit mpachetat n formatul mesajului este bitul de stop care are
valoarea de 1 logic. n figura urmtoare bitul de stop este cuprins ntre
cursoare i are o lime de 104.1 s.
Figura 10-5: Bit de stop pentru un mesaj trimis cu 9600 bit/secunda

10.2.1. Blocul de transmisie


Modulul UART are un pin dedicat de transmisie notat TX. Pe acest pin
datele se vor transmite n mod serial, bit dup bit, de la cel mai puin
semnificativ, la cel mai semnificativ bit. Schema blocului de transmisie este
prezentat in imaginea de mai jos. Dup ce setrile necesare au fost fcute,
transmisia ncepe n momentul n care utilizatorul va scrie n registrul
TXREG. Se poate observa c datele scrise n registrul de transmisie TXREG
sunt mutate hardware (nu de ctre o instruciune scris n software) n
Transmit Shift Register, unde vor fi i mpachetate alturi de biii de start
i stop, moment n care transmisia va ncepe i bitul de stare TXIF se va
seta.
Dup scrierea datelor n registrul TXREG se va iniializa trimiterea datelor.
Primul bit trimis pe bus-ul TX este bitul de START. Vor urma biii de date
(8 sau 9 n funcie de setri) i mesajul se va ncheia cu bitul de STOP. Pinul
de TX va reveni la finalul transmisiei n starea de ateptare IDLE (va avea
starea 1 logic).

UART

115

Blocul de transmisie este activat prin setarea bitului TXEN. Pentru a


transmite date n format de 8 bii, bitul TX9 trebuie s fie 0. Pinul TX (RB7)
nu are i funcie analogic, aa c prin activarea modulului (setarea bitului
SPEN din registrul RCSTA), pinul va fi asignat modulului UART i va fi
pin de ieire, indiferent de setrile fcute n registrul TRISB (la poziia
bitului 7).
Dac se dorete folosirea ntreruperilor, bitul TXIE trebuie setat n registrul
PIE1, ct i biii PEIE i GIE, din registrul INTCON.
Figura 10-6: Schema blocului de transmisie UART [6]

10.2.2. Blocul de recepie


Modulul UART are un pin dedicat de recepie notat RX. Pe acest pin datele
se vor recepiona n mod serial, bit dup bit, de la cel mai puin
semnificativ, la cel mai semnificativ bit. Schema blocului de recepie este
prezentat n imaginea de mai jos. Dup ce setrile necesare au fost fcute,
recepia poate ncepe dac cellalt participant la comunicaie va transmite
date. Dup ce datele mpachetate sunt recepionate, ele vor fi
despachetate (se ndeprteaz bitul de start i cel de stop) i se vor regsi
n buffer-ul de recepie RSR. Biii de date sunt mutai de ctre hardware n
registrul RCREG (de tip FIFO cu adncime 2). Chiar dac primul mesaj
recepionat nu este citit, un al doilea poate fi recepionat, deoarece FIFO-ul
are dou intrri disponibile. Dac un al treilea mesaj sosete, acesta nu va fi
mutat n FIFO (deoarece este plin) i va rmne n Shift Register. Mesajele
ulterioare nu vor mai fi recepionate pn nu se citete RCREG.

116

UART

Cnd datele sunt mutate (automat de ctre hardware) dup recepie din
buffer n registrul RCREG, bitul de stare RXIF va fi setat. Dac i bitul
RXIE este setat, o ntrerupere va fi generat.
Blocul de recepie este activat prin setarea bitului SPEN i CREN. Pentru a
recepiona date n format de 8 bii, bitul RX9 trebuie sa fie 0. Pinul RX
(RB5) are i funcie analogic AN11, aa c pe lng activarea modulului
(setarea bitului SPEN din registrul RCSTA) i activarea blocului de recepie
(setarea bitului CREN din registrul RCSTA), pinul trebuie asignat
modulului UART (devine pin digital) prin scrierea bitului ANS11 din
registrul ANSELH cu 0 logic.
Dac se dorete folosirea ntreruperilor, bitul RXIE trebuie setat n registrul
PIE1, ct i biii PEIE i GIE, din registrul INTCON.
Figura 10-7: Schema blocului de recepie UART [6]

Blocul de recepie dispune i de bii de stare care s indice posibilele erori


de comunicare. Unul din bii este bitul FERR, care indic o posibil eroare
de format a mesajului recepionat. Al doilea bit de stare, numit OERR,
indic o eroare de umplere a FIFO de recepie (mai mult de trei mesaje au
fost recepionate fr ca registrul RCREG s fie citit).
10.2.3. Setarea ceasului (rata de transfer)
Pentru o comunicare corect ntre doi participani, ambii trebuie s aib
aceeai rat de transfer, adic s transmit la fel de muli bii pe secund.

UART

117

Aceasta este i unitatea de msur, bii pe secund. n limba englez rata de


transfer se numete baud rate.
Exemplu: Dac rata de transfer este 9600, atunci, intr-o secund, vor fi
trimii 9600 de bii, iar limea unui bit este 104.1 s.
Figura 10-8: Limea unui bit pentru o rat de transfer 9600

Rata de transfer poate fi generat cu ajutorul a doi regitri: SPBRGH i


SPBRG, fie pe 8 bii, fie pe 16 bii, n funcie de valoarea biilor BRG16 i
BRGH. Dac bitul BRG16 este 0, atunci blocul de generare a ceasului
folosit pentru rata de transfer va funciona ca i un timer pe 8 bii i doar
registrul SPBRG este folosit. Dac bitul BRG16 este setat, atunci ambii
regitri vor fi folosii i se vor comporta ca un timer pe 16 bii.
n documentaia microcontrolerului este dat, n funcie de setrile fcute i
de frecvena oscilatorului, valoarea ce trebuie scris n registrul SPBRG
pentru rata de transfer dorit.

118

UART

Biii folosii pentru setarea ceasului sunt:


SYNC: cu care selectm dac modulul funcioneaz asincron sau
sincron.
BRGH: cu care alegem multiplicatorul (16 sau 64).
BRG16: cu care alegem 8 sau 16 bii pentru generarea ceasului.

Tabel 10-1: Biii de configurare ai ratei de transfer [6]


Bii de configurare
SYNC
BRG16
0
0
0
0
0
1
0
1
1
0
1
1

Mod de
funcionare UART
8 bit/ Asincron
8 bit/ Asincron
16 bit/ Asincron
16 bit/ Asincron
8 bit/ Asincron
16 bit/ Sincron

BRGH
0
1
0
1
X
X

Formul calcul
FOSC/[64*(n+1)]
FOSC/[16*(n+1)]
FOSC/[4*(n+1)]

Pentru calculul valorii registrul SPBRG pentru o anumit rat de transfer se


pot folosi formulele din Tabelul 10-1.
10.2.4. Regitri de configurare ai modulului UART
Tabel 10-2 Regitri modulului UART [6]
Nume

Bit7

Bit6

Bit5

Bit4

Bit3

Bit2

Bit1

Bit0

INTCON

GIE

PEIE

T0IE

INTE

RABIE

T0IF

INTF

RABIF

PIE1

ADIE

RCIE

TXIE

SSPIE

CCP1IE

TMR2IE

TMR1IE

PIR1

ADIF

RCIF

TXIF

SSPIF

CCP1IF

TMR2IF

TMR1IF

RCSTA

Registrul de recepie a datelor

TXREG

Registrul de transmisie a datelor

RCSTA

SPEN

RX9

SREN

CREN

ADDEN

FERR

OERR

RX9D

TXSTA

CSRC

TX9

TXEN

SYNC

SENDB

BRGH

TRMT

TX9D

BAUDCTL

ABDOVF

RCIDL

SCKP

BRG16

WUE

ABDEN

SPBRG

Registrul pentru calculul ratei de transfer. Cei mai puin semnificativi 8 bii.

SPBRGH

Registrul pentru calculul ratei de transfer. Cei mai semnificativi 8 bii.

TRISB

TRISB7

TRISB6

TRISB5

TRISB4

ANSELH

ANS11

ANS10

ANS9

ANS8

Legend: x=necunoscut, u=nemodificat, -=bitul se citete ca 0. Biii nchii la culoare nu sunt folosii de UART.

UART

119

Regitri INTCON, PIE1 i PIR1 sunt regitri asociai ntreruperilor pentru


transmisie sau recepie ce pot fi generate de modulul UART. Aceti regitri
au fost prezentai i n capitolele anterioare. n cadrul acestui capitol nu se
vor folosi sursele de ntrerupere ale modulului. Regitri TRISB i ANSELH
sunt i ei regitri ce au fost prezentai anterior i sunt folosii pentru
configurarea direciei i modului digital/analog a pinilor.
Registrul TXREG este registrul de transmisie. Dac modulul este activ i
corect iniializat, fiecare scriere n TXREG va genera o transmise a datelor
scrise. Registrul RCREG este registrul de recepie. Datele recepionate pe
pinul RX se vor regsi n registrul RCREG de unde pot fi citite. Regitri
SPBRG i SPBRGH sunt regitri ce conin valoarea pre-scalarului ce intr
in formula de calcul a ratei de transfer. Dac bitul BRG16 din registrul
BAUDCTL este setat 0 logic atunci n calcului formulei va intra doar
valoarea scris n registrul SPBRG.
Rata transfer = Fosc/[64 * (SPBRGH:SPBRG+1) ]
n continuare vor fi prezentai regitri de configurare ai modulului pentru
modul asincron i transfer pe 8 bii. Unii bii pot avea funcii i pentru
modul de lucru sincron dar, dac se dorete folosirea acestui mod, trebuie
consultat documentaia microcontrolerului pentru informaii complete
asupra acestor bii.
Tabel 10-3: Descriere registrului TXSTA

Legend: R - bitul poate fi citit; W - bitul poate fi scris; U - bit neimplementat, se va citi 0; n valoare dup POR;
1 - bitul e setat; 0 - bitul e ters; X - valoare necunoscut;

Bit 7 CSRC: Bit de selecie a ceasului


n mod asincron acest bit este ignorat
Bit 6 TX9: Bit pentru activarea transmisiei bitului 9
1 = Transmisie pe 9 bii
0 = Transmisie pe 8 bii
Bit 5 TXEN: Bit de activare a blocului de transmisie (1)
1 = Blocul de transmisie e activ
0 = Blocul de transmisie e dezactivat
Bit 4 SYNC: Bit de selecie a modului de funcionare
1 = Mod sincron
0 = Mod asincron

120

UART

Bit 3 SENDB: Transmisia caracterului Break


1 = Urmtoarea transmisie va fi un mesaj de tip Break (bitul este ters automat de
ctre hardware dup transmisia mesajului)
0 = Nu se va transmite un mesaj de tip Break
Bit 2 BRGH: Bit de selecie a ratei de transfer ridicat
1 = Vitez ridicat
0 = Vitez sczut
Bit 1 TRMT: Bit de stare a registrului de transmisie TSR
1 = TSR este plin (conine un mesaj ce urmeaz a fi transmis)
0 = TSR este gol (poate fi scris pentru a iniia o transmisie)
Bit 0: TX9D: Bitul 9 de date
Conine valoarea celui de al-9-lea bit. Poate fi bit de adres, date sau paritate
(1)

SREN/CREN suprascrie TXEN n mod sincron

Tabel 10-4: Descriere registrului RCSTA

Legend: R - bitul poate fi citit; W - bitul poate fi scris; U - bit neimplementat, se va citi 0; n valoare dup POR;
1 - bitul e setat; 0 - bitul e ters; X - valoare necunoscut;

Bit 7 SPEN: Bit de activare a portului serial


1 = Portul serial este activ (pinii RX i TX sunt asignai portului serial)
0 = Portul serial nu este activ (este inut in Reset)
Bit 6 RX9: Bit pentru activarea recepiei bitului 9
1 = Recepie pe 9 bii
0 = Recepie pe 8 bii
Bit 5 SREN: Bit de activare a unei singure recepii
Bitul este ignorat n mod asincron
Bit 4 CREN: Bit de activare a recepiei n mod continuu
n mod asincron:
1 = Blocul de recepie este activ
0 = Blocul de recepie este inactiv
Bit 3 ADDEN: Activarea deteciei bitului de adres
n mod asincron cu transmisie pe 9 bii (RX9 = 1)
1 = Detecia adresei este activat
0 = Detecia adresei este inactiv. Al-9-lea bit este recepionat i poate fi folosit ca i
bit de paritate (n software).
n mod asincron cu transmisie pe 8 bii (RX8 = 1) bitul este ignorat
Bit 2 FERR: Eroare de format
1 = O eroare de format a fost detectat
0 = Nici o eroare de format nu a fost detectat

UART

121

Bit 1 OERR: Eroare de Overrun


1 = O eroare de Overrun a fost detectat
0 = Nici o eroare de Overrun nu a fost detectat
Bit 0: RX9D: Bitul 9 de date
Conine valoarea celui de al-9-lea bit. Poate fi bit de adres, date sau paritate

Tabel 10-5: Descriere registrului BAUDCTL

Legend: R - bitul poate fi citit; W - bitul poate fi scris; U - bit neimplementat, se va citi 0; n valoare dup POR;
1 - bitul e setat; 0 - bitul e ters; X - valoare necunoscut;

Bit 7 ABDOVF: Bit de stare a circuitului de detecie automat a ratei de transfer


1 = Timer-ul circuitului a ajuns la valoarea maxim (Overflow)
0 = Timer-ul circuitului nu a ajuns la valoarea maxim
Bit 6 RCIDL: Bit de stare a blocului de recepie
n mod asincron:
1 = Recepia este n ateptare (nu se recepioneaz un mesaj)
0 = Un bit de start s-a recepionat i recepia este in curs
Bit 5: Neimplementat: Bitul se citete 0
Bit 4 SCKP: Bit de selecie a polaritii sincrone
n mod asincron:
1 = Datele transmise pe pinul TX sunt negate
0 = Datele transmise pe pinul TX nu sunt negate
Bit 3 BRG16: Generatorul ratei de transfer pe 16 bii
1 = Generatorul ratei de transfer folosete 16 bii (SPBRGH:SPBRG)
0 = Generatorul ratei de transfer folosete 8 bii (SPBRG)
Bit 2 Neimplementat: Bitul se citete 0
Bit 1 WUE: Bit de activare a wake-up
n mod asincron
1 = Blocul de recepie ateapt un front descresctor
0 = Blocul de recepie funcioneaz n mod normal
Bit 0 ABDEN: Bit de activare a circuitului de detecie automat a ratei de transfer
1 = Circuitul este activ
0 = Circuitul nu este activ

122

UART

10.3. Aplicaie propus


S se scrie un program care s trimit pe pinul TX, ntr-o bucla infinit,
toate valorile decimale de la 0 la 100. Pinul RX va fi legat printr-o srm de
pinul TX (loopback mode) iar la recepia valorii 90 decimal, ledul DS1 de
pe plac trebuie aprins, indicnd recepia. Transferul trebuie s fie realizat
pe 8 bii i cu o rata de transfer de 9600baud (9600 bii/secunda).
10.4. Configurarea modulului UART
Funcia de configurare a modulului UART trebuie s ndeplineasc
urmtorii pai:
a) Setarea corect a ratei de transfer. n paginile de catalog este dat
formula de calcul a ratei de transfer. n Tabelul 2-1 se gsete formula
de calcul n funcie de biii SYNC, BRGH i BRG16. Pentru cerina de
mai sus alegem urmtoarea configuraie:

SYNC = 0 pentru mod asincron


BRG16 = 1 pentru generarea ratei de transfer se folosesc 16 bii
BRGH = 0 pentru vitez sczut

Formula de calcul rezultat este: Rat de transfer = Fosc/[16*(n+1)].


innd cont de faptul c Fosc este 4MHz i c rata de transfer dorit este
9600, valoarea ce trebuie scris n registrul SPBRG este 25.
b) Alegerea modului asincron. Acest lucru se face prin scrierea bitului
SYNC din registrul TXSTA cu valoarea 0. Chiar din setarea ratei de
transfer acest pas a fost realizat.
c) Selecia transmisiei i recepiei pe 8 bii. Bitul TX9 din registrul TXSTA
i RX9 din RCSTA trebuie scrii cu valoarea 0.
d) Activarea blocului de transmisie prin setarea bitului TXEN din registrul
TXSTA. Direcia de ieire se selecteaz din registrul TRISB.
e) Activarea blocului de recepie prin setarea bitului CREN din registrul
CREN. Pentru ca datele ce ajung la pinul RX (RB5/AN11/RX) s
ajung i fizic n registrul de recepie, acest pin trebuie legat intern la
registru. Pinul trebuie s aib funcie digital pentru ca acest lucru s se
ntmple. Dup reset pinul are funcie analogic (AN11) i funciile sale

UART

123

digitale sunt blocate. Prin scrierea cu valoarea 0 a bitului ANS11 din


registrul ANSELH, pinul devine digital i biii care ajung la pinul RX se
vor regsi i in registrul RCREG.
f) Activarea modulului UART prin scrierea bitului SPEN din registrul
RCSTA. n acest moment orice scriere n registrul TXREG va iniia o
transmisie de data pe pinul TX. Se vor transmite ntr-o bucl toate
valorile decimale ntre 0 i 100.
Figura 10-9: Primele 5 mesaje trimise

Dac pinul TX este legat cu pinul RX printr-o srm, datele transmise pe


pinul TX prin scrierea in registrul TXREG vor fi recepionate pe pinul RX
i se pot citi din registrul RCREG. Bineneles c ntre scrierea n registrul
TXREG i citirea datelor din registrul RCREG trebuie un timp de ateptare
necesar realizrii fizice a transmisiei. Acest timp se poate elimina prin
folosirea ntreruperii la recepie i citirea datelor n rutina de tratare a
ntreruperii. n acest fel ne asigurm c datele sunt citite doar dup ce
recepia este complet. n cerin i exemplul dat nu se folosete
ntreruperea la recepie. Atta timp ct nu s-a recepionat valoarea 90, pinul
RC0 trebuie s rmn 0 logic. Acest lucru se poate observa n figura

124

UART

urmtoare. La recepia mesajului cu valoarea 90, pinul i schimb starea n


1 logic.
Figura 10-10: Recepia mesajului cu valoare 90

10.5. Model software


n programul scris de noi va trebui s avem n vedere:

Scrierea valorii n n registru SPBRG pentru rata de transfer 9600.


Selectarea modului asincron i formatului pe 8 bii.
Activarea blocului de transmisie TX i cel de recepie RX.
Activarea portului serial.
Scrierea datelor n registrul TXREG pentru a iniia transmisia.
Citirea datelor din registrul RCREG pentru detectarea mesajului cu
valoarea 90.

Exemplu de cod:

UART

125

/* include files */
#include "pic.h"
/* macro*/
#define LED ???
/* function declarations */
void init();
/* function definitions */
void main()
{
unsigned int i, j;
init();

/* local variables*/

while(1)
/* infinit loop*/
{
for (i = 0; i<101; i++)
/* loop to send 101 messages*/
{
TXREG = i; /* send all values from 0 to 100*/
for (j = 0; j<100; j++); /* small delay between messages*/
if (RCREG == 90) /* read the received data and compare it to 90*/
LED =???;
/* turn on DS1*/
}
}
}
void init()
{
/* Pin settings for LEDs*/
ANSEL = 0x0F; /* set RC0 to RC3 as digital pins */
TRISC = 0xF0; /* RC4 to RC7 input. RC0 to RC3 output */
PORTC = 0x00; /* port C pins reset value. LEDs off*/
/* Baud setting */

126

UART

/* SYNC = 0; BRG16 = 1; BRGH = 0 - find the SPBRG value in the


datasheet (Table 12-5)
|
|
|
|
|
---- low speed
|
---------- 16 bit Baud Rate Generator is used
----------------------------------------------- Asyncron mode */
BAUDCTL = 0x08; /* BRG16 = 1*/
SPBRG =?????; /* this value is from the datasheet or using the correct
formula*/
/* TX settings */
TRISB &= 0x7F; /* TX/RB7 output */
TXSTA = 0x20; /* TX enabled; asincron mode (SYNC = 0); 8-bits;
BRGH = 0 */
/* RX settings */
ANSELH = 0x07 ; /* set RB5 as digital pins. This is analogic by default*/
TRISB |= 0x20; /* RX/RB5 input */
RCSTA = 0x10; /* RX enabled; 8-bits */
/* Turn on UART*/
RCSTA |= 0x???; /*UART enabled*/
}

Anexa 1
Anexa 1 prezint cteva elemente ale limbajului C ce nu au fost explicate n
Capitolul 2. Acestea sunt descrise pe scurt, sub forma de list, avnd ca scop
familiarizarea cititorului cu ct mai mult elemente ale limbajului de
programare.
Const este un calificativ care, atribuit definiiei unei variabile, o transform
pe aceast ntr-o constant, adic devine read-only. Precum o variabil
normal, constanta creat va avea un tip, un nume generic i o adres,
diferena fiind c, o dat atribuit o valoare, aceasta nu mai poate fi
modificat.
const unsigned int a = 10;
Pe parcursul codului se poate folosi noua constant cu numele ei generic,
atribuirea unei alte valori fiind imposibile. n aplicaiile embedded o
constant va fi stocat n memoria de tip read-only (ROM, Flash) i nu n
RAM precum n cazul variabilelor.
Volatile este la rndul su un calificativ care se atribuie variabilelor i care
semnaleaz compilatorului s nu optimizeze accesele la acea variabil. n
aplicaiile embedded sunt dese momentele n care se citesc regitri de stare
care se pot schimba independent de aplicaia care ruleaz pe microcontroler.
Considerm exemplul urmtor:
while(reg_read == 0)
{ ; }
Presupunem c registrul pe care l citim n bucla anterioar este zero la
nceput, primind o valoare diferit doar dup un anumit timp (ex: se seteaz
un bit pentru un mesaj recepionat). Dac variabila reg_read nu este
declarat ca fiind volatile, compilatorul ar putea optimiza codul i n loc s
citeasc valoarea de la adresa registrului de fiecare dat, o va citi o singur
dat, la nceput i aceasta fiind 0, bucla va deveni infinit. Declarnd
variabila ca fiind volatile foreaz compilatorul s aduc de fiecare dat
valoarea din memorie, n cazul nostru, din registrul pe care dorim s l citim.

128

Anexa 1

Extern este un cuvnt cheie ce se atribuie variabilelor i funciilor n


contextul proiectelor formate din mai mult fiiere surs. n cazul proiectelor
complexe, este imposibil ca tot codul s fie n acelai fiier *.c. Din acest
motiv, se pot folosi mai mult fiiere *.c i *.h n care s se scrie codul
aplicaiei iar pentru a putea interaciona ntre ele, se folosesc variabilele i
funciile extern.
Dac declarm o variabil ca fiind extern (extern unsigned int a;) ntr-un
fiier test.h, aceasta va putea fi folosit n orice fiier *.c care include test.h.
Astfel, mai multe module software pot interaciona ntre ele prin valorile
salvate n variabila a. n mod asemntor, declarm o funcie ca fiind extern
ntr-un fiier *.h, apoi o definim ntr-un fiier *.c. Incluznd fiierul *.h (n
care funcia a fost definit), putem apela funcia respectiv din mai multe
module.
Static este, n mare msur, opusul lui extern. Declarnd o variabil sau
funcie ca fiind static le transform n membri locali ai modulului. Un
membru local nu poate fi accesat n afara fiierului unde a fost declarat
(static unsigned int b;). Pe lng acest neles, static mai este folosit i n
cadrul funciilor la declararea variabilelor. Considerm exemplu:
void function (void)
{ static unsiged int a = 0;
a++;
}
n cadrul funciei prezentate anterior am declarat o variabil static local
acelei funcii. O astfel de variabil are ca i proprietate de baz faptul c,
dup ce apelul funciei s-a ncheiat, ea i pstreaz valoarea. n exemplul
anterior, la al doilea apel al funciei, variabila a va avea valoarea 1 ea fiind
iniializat cu valoarea 0 doar la primul apel.
Un vector (tablou sau array) este o structura de date n care se pstreaz
informaie de acelai tip n locaii succesive de memorie. Pentru a accesa
diversele locaii de memorie e suficient s indexm vectorul respectiv.
unsigned int arr[10];
for(i=0;i<10;i++)
{
arr[i] = i;
}

Anexa 1

129

Codul prezentat anterior declar un vector numit arr de 10 locaii pentru


variabile unsigned int. Indexarea se face folosind parantezele ptrate arr[i].
Vectorii sunt un mod foarte eficient de a ine date ce se vor folosi n bucle
for sau while. Dac n exemplul anterior nu am fi folosit un vector, codul
rezultat ar fi fost mult mai complex, cu 10 declaraii de variabile i 10
iniializri diferite.
Pointerul este unul dintre cele mai puternice mecanisme ale limbajului C i
unul dintre motivele pentru care limbajul se folosete n aplicaiile
embedded. n cel mai simplu mod spus, un pointer este o variabil ce
conine o adres spre un alt element. Pentru a declara un pointer, trebuie s
specificm tipul de date spre care el ne trimite: unsigned int * ptr. Aceast
linie de cod declar un pointer ctre o variabil unsigned int. Dimensiunea
lui ptr nu este egal cu cea a variabilei spre care ne trimite (int - 16 bii) ci
are o mrime ce depinde de platforma pe care rulm codul. n exemplul
urmtor putem observa cum sunt folosii pointerii:
unsigned int * ptr;
unsigned int a = 10;
ptr = &a;
*ptr = 20;
ptr este declarat ca pointer la unsigned int i a este o variabil unsigned int
care primete valoarea 10. ptr nu este iniializat la declarare, dar el primete
adresa lui a prin folosirea operatorului &. Pentru a modifica valoarea spre
care ptr ne trimite, folosim operatorul * precum n linia *ptr = 20; . Dup
execuia acestui cod, n ptr vom gsi adresa lui a iar n a vom avea valoarea
20.
Pentru a demonstra modul n care pointerii sunt folosii n aplicaiile
embedded, vom considera un exemplu n care dorim s citim informaiile
dintr-un registru de 8 bii aflat la adresa 0x1000 i apoi s scriem n acest
registru valoarea 0xAA.
volatile unsigned char * ptr_reg;
unsigned char reg_read = 0;
ptr_reg = (unsigned char *) 0x1000;
reg_read = *ptr_reg;
*ptr_reg = 0xAA;

130

Anexa 1

n exemplul anterior se observ cum ptr_reg a fost declarat pointer ctre un


volatile unsigned char deoarece ne va trimite la un registru (volatile) de 8
bii (unsigned char). Spre deosebire de primul exemplu n care am folosit
operatorul & pentru a afla adresa dorit, n cazul de fa am scris direct
adresa dorit n ptr_reg, fr a folosi alt operator. Apoi, pentru a citi i scrie
la adresa respectiv, am folosit operatorul *.
Struct este un cuvnt cheie folosit pentru a crea noi structuri de date.
Presupunem c, n aplicaia noastr, dorim s folosim un calendar i avem
nevoie de variabile care s pstreze data unei zile. n loc s declarm trei
variabile pentru fiecare dat, vom crea un nou tip folosind structuri:
struct data
{
unsigned int anul:
unsigned char luna:
unsigned char ziua:
}
Dup ce am construit noul tip de dat putem s declarm variabile de acest
tip dup cum ureaz:
struct data test;
test.anul = 2012;
test.luna = 1;
test.ziua = 15;
n codul anterior se poate observa cum declarm o variabila numit test de
tip data. Apoi, folosind operatorul .(punct) accesm fiecare membru al
acelei variabile pentru a o iniializa cu o nou valoare.
Dat fiind faptul c lucrarea de fa nu are ca tem limbajului C, prezentarea
noastr se va opri aici. Pentru o mai bun nelegere a elementelor de
programare n acest limbaj, recomandm consultarea materialelor dedicate
acestui subiect.

Anexa 2
Anexa 2 va prezenta scrierea codului (fiierul *.hex) n memoria
microcontrolerului.
Dup scrierea codului n mediul de dezvoltare MPLAB i compilarea
acestuia, vom obine un fiier *.hex care conine codul main al
programului. Acesta trebuie scris in memoria program (Flash) a
microcontrolerului, de unde va fi rulat instruciune cu instruciune.
Trebuie urmai urmtorii pai:
a) Selectai meniul Programmer / Select Programmer / PICkit 2. Se va
deschide n bara de tool-uri un nou cmp, PICkit 2 Program Toolbar
care conine 9 butoane, fiecare avnd cte o funcie.
b) Apsai primul buton din partea stng, cel de scriere a memoriei, numit
Program the target device
. Ateptai ca scrierea s se finalizeze.
n urma acestui proces, codul main se va regsi n memoria Flash a
microcontrolerului.
c) Scoatei microcontrolerul din starea de reset (n care a fost introdus de
programatorul PICkit 2 n timpul scrierii memoriei) prin apsarea
butonului 7 din partea stng Bring target MCLR to Vdd
. Din
acest moment, microcontrolerul va ncepe execuia programul regsit in
memoria sa Flash pornind de la adresa 0x0.

Anexa 3
Privind urmtoarea oscilogram, este firesc s ne ntrebm: Cum putem
interpreta informai coninute de aceasta, i mai mult, unde regsim aceste
informai?
Figura 11-1: Principalele informai dintr-o oscilogram

Evident c rspusul la aceast ntrebare l vom regsi n imaginea de mai


sus. Pentru o mai bun interpretare am notat cu I, II si III urmtoarele
informai:

Anexa 3

133

I: reprezint cele 4 canale ale osciloscopului: C1 (Galben), C2 (Rou), C3


(Albastru) i C4 (Verde). Acestea pot fi vizibile sau nu, n funcie de
numrul de semnale ce trebuie msurat. Pentru a calcula amplitudinea
semnalului trebuie s cunoatem numrul de voli pe diviziune (pe
vertical). Aceast informaie se regsete n csua canalului respectiv:

Se poate observa uor c semnalul de pe canalul 1, dat ca exemplu n


oscilograma de mai sus, are o amplitudine de 5V (o diviziune nmulit cu
5V/div).
II: reprezint informaile despre baza de timp. Cu alte cuvinte, ce perioad
de timp este cuprins intr-o diviziune (pe orizontal).

Ce ne spune informaia de mai sus? Intr-o diviziune aveam o secund.


Astfel putem folosi aceast informaie pentru a calcula frecvena unui
semnal.
III: reprezint eticheta canalului. Este o opiune a osciloscopului folosit
care ne ajut s intelegem foarte uor ce pin (sau ce semnal) a fost aplicat pe
sonda canalului x. n imaginea de mai sus putem observa c C1 reprezint
semnalul de pe pinul RA0, C2 semnalul de pe pinul RC0 i asa mai departe.
n unele cazuri, mai ales pentru a afla limea unui puls sau perioada exact
a unui semnal, se pot folosi cursoare verticale, care permit stabilirea cu
exactitate a perioadei de timp cuprins ntre ele, dup cum se poate observa
n figura urmtoare.

134

Anexa 3
Figura 11-2: Folosirea cursoarelor verticale

IV: cursoarele verticale.


V: informaile despre cele dou cursoare, dup cum urmeaz:

Bibliografie
[1] Ioan P. Mihu, Dispozitive i Circuite Electronice, Volumul I,II, ISBN
973-95604-0-4, Ed. Alma Mater, Sibiu, 2004
[2] Ioan P. Mihu, Procesarea Numeric a Semnalelor. Noiuni Eseniale,
ISBN 973-632-195-1, Ed. Alma Mater, Sibiu, 2005
[3] Ioan P. Mihu, ANSI-C pentru microcontrolere, Note de curs, Sibiu,
2011
[4] Ilie Beriliu, Microcontrolere Aplicaii, ISBN 978-973-739-578-8, Ed.
Universitatea Lucian Blaga Sibiu, 2008
[5] Ilie Beriliu, Cu un PIC mai detept, Note curs, 2005
[6] PIC16F631/677/685/687/689/690 Data Sheet (DS41262E), Microchip
[7] Low Pin Count Demo Board Users Guide (DS51556A), Microchip
[8] *** http://publications.gbdirect.co.uk/c_book/
[9] *** http://microchip.com/

S-ar putea să vă placă și