93_96.PDF
(
190 KB
)
Pobierz
C dla mikrokontrolerów 8051, część 4
K U R S
O†sposobie, w†jaki przerwania s¹ obs³ugiwane
w†jÍzyku C,†pisa³em juø przy okazji omawiania podstaw
programowania. Dziú wykorzystamy programowanie przerwaÒ do budowy
prostego licznika. Wykorzystamy w†nim przerwanie generowane przez
Timer 1†do obs³ugi wyúwietlacza LED oraz przerwanie generowane przez
opadaj¹ce zbocze sygna³u na wejúciu INT0 do zliczania impulsÛw
zegarowych. W†programie wykorzystamy teø wskaüniki i†ich arytmetykÍ -
bÍdzie okazja co nieco siÍ nauczyÊ.
część 4
Budujemy licznik, czyli jêzyk C i przerwania
Licznik prezentowany w†artykule
jako przyk³ad zbudowa³em, korzysta-
j¹c z†p³ytki AVR Starter Kit oraz ka-
wa³ka p³ytki uniwersalnej. Oczywiú-
cie, jeúli uøywasz innego zestawu
eksperymentalnego - nie jest to øad-
n¹ przeszkod¹. Prawdopodobnie bÍ-
dziesz tylko musia³ zbudowaÊ sobie
wyúwietlacz LED.
wiÍc efektu migotania cyfr w†czasie
wpisywania danych do rejestrÛw. Po-
³¹czy³em szeregowo dwa uk³ady
74HCT595, tworz¹c w†ten sposÛb re-
jestr 16-bitowy. Jako pierwszy w†sze-
regu znajduje siÍ rejestr segmentÛw
cyfr, jako drugi rejestr za³¹czaj¹cy
poszczegÛlne cyfry. Wejúcie szerego-
we danych taktowane jest sygna³em
o†czÍstotliwoúci 4,8 kHz, natomiast
cyfry prze³¹czane s¹ z†czÍstotliwoúci¹
oko³o 300 Hz.
Uøy³em wyúwietlaczy LED ze
wspÛln¹ anod¹. Zasilanie anod za³¹-
czane jest przez tranzystory MOS
z†kana³em typu P (BS250). Ich sto-
sowanie jest bardzo wygodne, ponie-
waø nie wymagaj¹ øadnych dodatko-
wych elementÛw, takich jak na przy-
k³ad rezystory. Wartoúci rezystorÛw
pod³¹czonych do poszczegÛlnych seg-
mentÛw wyúwietlacza musisz dobraÊ
sobie do posiadanych cyfr. Numery
wyprowadzeÒ wyúwietlacza LED po-
traktuj jako orientacyjne. Istotne s¹
literowe oznaczenia segmentÛw. Na
wejúciach rejestrÛw szeregowych
znajduj¹ siÍ rezystory
pull-up
, tak
aby moøna by³o wyúwietlacz pod³¹-
czyÊ do dowolnego z†portÛw mikro-
kontrolera.
Wyúwietlacz do sterowania wyma-
ga trzech linii - jednej danych
i†dwÛch zegarowych. Ja wykorzysta-
³em P1.1, P1.2 i†P1.3 Oczywiúcie,
zmieniaj¹c program, moøesz uøyÊ do-
wolnych innych. RÛwnieø wykonuj¹c
drobne modyfikacje w†programie,
moøna pod³¹czyÊ do 8†wyúwietlaczy
LED o†wspÛlnej anodzie. W†skrÛcie
funkcjonowanie wyúwietlacza wygl¹-
da nastÍpuj¹co: dane za pomoc¹
opadaj¹cego zbocza sygna³u zegaro-
wego podawanego na wyprowadzenie
11 (SRCLK) wpisywane s¹ z†wejúcia
szeregowego na wyprowadzeniu 14
(SER) do wewnÍtrznego rejestru.
Mikrokontroler przesy³a pe³ne s³owo
16-bitowe tak, aby dzia³a³y oba uk³a-
dy rejestrÛw. NastÍpnie, po wpisa-
niu 16 bitÛw, na wyprowadzenie 12
(RCLK) podawany jest impuls zega-
rowy, ktÛrego opadaj¹ce zbocze po-
woduje przepisanie danych z†we-
wnÍtrznego szeregowo-rÛwnoleg³ego
rejestru do wyjúciowego rejestru ty-
pu zatrzask.
Program napisany zosta³ tak, øe
w†danym momencie úwieci tylko jed-
na cyfra. Jeúli prze³¹czanie cyfr bÍ-
dzie wystarczaj¹co szybkie, ludzkie
oko tego nie zauwaøy. Jest to typ
wyúwietlania zwany multipleksowa-
nym (wyúwietlanie dynamiczne).
Charakteryzuje siÍ on ma³ym pobo-
rem pr¹du - w†danym momencie za-
silana jest tylko jedna cyfra. Tyle na
temat zasady dzia³ania, zajmijmy siÍ
teraz programem.
P³ytka wyúwietlacza LED
Schemat po³¹czeÒ wyúwietlacza
LED pokazano na
rys. 1
. Niestety -
jeøeli chcesz eksperymentowaÊ z†tym
przyk³adem programowania, musisz
sobie taki uk³ad zbudowaÊ. Moim
zdaniem przyda on ci siÍ nie tylko
do eksperymentÛw, ale rÛwnieø moø-
na go uøyÊ w†dowolnym innym
uk³adzie wykorzystuj¹cym wyúwietla-
cze LED. Trzeba jednak uwaøaÊ -
obs³uga wyúwietlacza oparta jest
o†przerwanie generowane przez Ti-
mer 1, dlatego teø nie polecam ta-
kiego uk³adu na przyk³ad do czÍs-
toúciomierza. Chyba øe zgodzisz siÍ
na wy³¹czenie wyúwietlania w†czasie
pomiaru czÍstotliwoúci. Zaowocuje to
migotaniem przy pomiarze przebie-
gÛw o†niskiej czÍstotliwoúci. Jednak
tam, gdzie mikrokontroler nie jest
zbyt mocno obci¹øony i†gdzie nie
ma úcis³ych zaleønoúci czasowych -
úmia³o moøesz tego uk³adu uøyÊ.
Z†powodzeniem na przyk³ad stosujÍ
go w†uk³adzie termometru cyfrowego,
mimo rÛønic pogl¹dÛw na temat za-
wieszania transmisji z†DS1820 na
czas obs³ugi przerwaÒ - nie mam
z†tym k³opotu w†mojej aplikacji.
Do konstrukcji wyúwietlacza uøy-
³em rejestrÛw przesuwaj¹cych
74HCT595. Zrobi³em tak z†dwÛch po-
wodÛw. Po pierwsze, cena tych
uk³adÛw jest bardzo niska, a†obci¹-
øalnoúÊ ich wyjúÊ w†stanie niskim
jest wystarczaj¹ca do zasilania typo-
wego wyúwietlacza LED. Po drugie
zaú, uk³ad nie wyprowadza informa-
cji na wyjúcia do momentu pojawie-
nia siÍ osobnego impulsu zegarowe-
go, ktÛry j¹ tam przepisze. Nie ma
Mikrokontroler jako licznik
Program pokazano na
list. 1
.
Licznik wykorzystuje dwa przerwa-
nia. Pierwsze, zewnÍtrzne, powodo-
wane przez opadaj¹ce zbocze napiÍ-
cia na wejúciu INT0, uøywane jest
do zwiÍkszania wartoúci licznika.
Drugie - wewnÍtrzne, generowane
cyklicznie - pochodz¹ce od Timera
1, przepisuje stan bufora
display
do
rejestrÛw wyúwietlacza.
Program rozpoczyna siÍ od dekla-
racji. Linia danych wyúwietlacza za-
deklarowana zostaje jako P1^0, linia
zegara szeregowego jako P1^1, linia
zegara wyjúciowego rejestru latch ja-
ko P1^2. OprÛcz tego inicjujemy
zmienn¹ typu
unsigned int
zawiera-
j¹c¹ zliczane impulsy oraz sta³¹ ty-
pu
char
z†zawartoúci¹ inicjuj¹c¹ re-
jestr TH1 Timera 1. Sta³a ta to po-
úrednio czÍstotliwoúÊ, z†jak¹ wywo-
³ywane jest przerwanie obs³uguj¹ce
wyúwietlacz LED. Dalej znajduje siÍ
uporz¹dkowana w†kolejnoúci rosn¹cej
(od 0†do 9) tablica okreúlaj¹ca wy-
gl¹d wyúwietlanego znaku (
patterns
),
tablica z†kodami kolejnoúci za³¹cza-
nia cyfr (
digits
) oraz tablica - bufor
Elektronika Praktyczna 9/2002
93
K U R S
Rys. 1
wyúwietlacza w†RAM (
display
). Jak
³atwo zauwaøyÊ, dwie pierwsze
umieszczone s¹ w†obszarze pamiÍci
ROM mikrokontrolera (s³owo kluczo-
we
code
) i†maj¹ przypisane wartoúci.
Trzecia znajduje siÍ w†obszarze
RAM. Jest ona odwzorowaniem sta-
nu wyúwietlacza, abstrahuj¹c od nu-
meru wyúwietlanej aktualnie cyfry.
Kaøda z†tablic ma przypisany w³aú-
ciwy jej wskaünik, czyli zmienn¹,
ktÛra bÍdzie wskazywaÊ na element
tablicy. W†momencie zadeklarowania,
kaødy wskaünik ustawiany jest na
pierwszy element tablicy. Wyraøenie
Wskaünik = &Tablica
powoduje przy-
pisanie zmiennej
Wskaünik
adresu,
pod ktÛrym umieszczona jest
Tabli-
ca
. Wskaüniki to fantastyczne narzÍ-
dzie jÍzyka C!
Funkcja
Translate
zamienia argu-
ment
x
, ktÛrym jest dwubajtowa
liczba ca³kowita bez znaku, na od-
powiadaj¹c¹ tej liczbie zawartoúÊ bu-
fora
display
. Jednym s³owem, zamie-
nia liczbÍ na odpowiadaj¹cy jej wy-
gl¹d wyúwietlacza LED. Metoda jest
bardzo prosta, chociaø zapis pocz¹t-
kowo moøe siÍ wydaÊ niezrozumia-
³y. Po wywo³aniu funkcji wy³¹czane
s¹ przerwania Timera 1. Zosta³o to
zrobione w†celu unikniÍcia migotania
wyúwietlacza. PÛüniej, wskaünikowi
TDisplay
przypisywane jest wskaza-
nie na ostatni element bufora wy-
úwietlacza. Od niego to rozpocznie
siÍ translacja na kody LED. Przebie-
ga ona wed³ug nastÍpuj¹cego sche-
matu: do wartoúci wskaünika
TPat-
terns
dodaj resztÍ z†dzielenia argu-
mentu przez 10, a†nastÍpnie skopiuj
wskazywan¹ w†wyniku dzia³ania sta-
³¹ typu
char
z†tablicy
patterns
pod
adres wskazywany przez
TDisplay
.
Podziel liczbÍ przez 10, przesuÒ
wskazanie na nastÍpn¹ pozycjÍ w†bu-
forze wyúwietlacza i†powtÛrz opera-
cjÍ dla nastÍpnej cyfry. I†tak 6†razy
- dla kaødej z†cyfr LED.
Jako swego rodzaju rozszerzenie
funkcjonalnoúci, umieszczono wyga-
szanie zer nieznacz¹cych na pocz¹t-
ku cyfry. PÍtla - rozpoczynaj¹c od
pocz¹tku bufora - sprawdza znak
znajduj¹cy siÍ pod wskazanym przez
wskaünik bufora wyúwietlacza adre-
sem (
TDisplay)
i†porÛwnuje go ze
znakiem na pocz¹tku tablicy
digits
,
to znaczy wzorcem ì0î. Jeúli s¹ to
te same znaki, kod ì0î w†buforze
wyúwietlacza zostaje zamieniony na
0xFF, co odpowiada ca³kowitemu
wygaszeniu cyfry. Tak dzieje siÍ aø
do momentu napotkania wzorca rÛø-
nego od wzorca ì0î. WÛwczas to in-
strukcja
break
(spotkaliúmy j¹ w†kon-
strukcjach warunku
switch
) przerywa
dzia³anie pÍtli
for
. Po zakoÒczeniu
pÍtli za³¹czane jest wyúwietlanie -
odpowiada mu zezwolenie na przyj-
mowanie przerwaÒ Timera 1.
Dalej napotkamy procedury ob-
s³ugi przerwaÒ. WyrÛønia je s³owo
kluczowe
interrupt
umieszczone
w†nag³Ûwku funkcji. Funkcja
Incre-
mentCounter
obs³uguje przerwanie
zewnÍtrzne INT0. W†zasadzie nie ro-
bi nic za wyj¹tkiem zwiÍkszenia
stanu zmiennej
counter
i†wywo³ania
funkcji
Translate
. Druga z†nich to
procedura obs³ugi przerwania Time-
ra 1 -
DisplaySend
,
zajmuj¹ca siÍ
konstrukcj¹ i†przes³aniem s³owa do
wyúwietlacza LED. Przyjrzyjmy siÍ
dok³adniej stosowanym w†niej meto-
dom.
Timer 1†pracuje w†trybie 16-bito-
wym. Przerwanie zg³aszane jest przez
timer w†momencie przepe³nienia, to
znaczy zmiany stanu z†0xFFFF na
0x0000. WÛwczas to wywo³ywana
jest procedura obs³ugi przerwania.
Cykl odliczania rozpoczyna siÍ na
94
Elektronika Praktyczna 9/2002
K U R S
nowo od wartoúci 0†do 0xFFFF. Jeú-
li nie zdecydujemy inaczej, to od te-
go momentu do nastÍpnego przerwa-
nia up³ynie czas 65536 cykli maszy-
nowych (to jest 1/12 czÍstotliwoúci
oscylatora). W†przypadku mojego mo-
delu by³by to czas oko³o 100 mili-
sekund - z†ca³¹ pewnoúci¹ by³by on
powodem migotania cyfr, poniewaø
jest zbyt d³ugi. Moøna czas do wy-
wo³ania przerwania skrÛciÊ, ustawia-
j¹c na poø¹dan¹ wartoúÊ najpierw
m³odszy a†pÛüniej starszy bajt time-
ra. Poniewaø nie zaleøy mi na bar-
dzo dok³adnym odmierzaniu czasu,
zdecydowa³em siÍ na ustawienie (od-
úwieøenie) tylko starszego bajtu.
Dalej zwiÍkszane s¹ wartoúci
wskaünikÛw
TDisplay
(wskazanie na
cyfrÍ w†buforze wyúwietlacza) oraz
TDigits
, to znaczy wskaünik do tab-
licy z†kodami za³¹czenia cyfr. Oba te
wskaüniki zmieniane s¹ synchronicz-
nie co oznacza, øe przesuniÍcie siÍ
na nastÍpn¹ cyfrÍ musi powodowaÊ
rÛwnieø zmianÍ kodu za³¹czenia wy-
úwietlacza.
Warunek
if (TDisplay == 0)
s³u-
øy do zbadania, czy napotkano znak
koÒca bufora w†RAM. Jeúli tak, to
wskaüniki s¹ ustawiane ponownie na
pocz¹tek wskazywanych tablic.
Jako øe kod za³¹czenia musimy
wys³aÊ jako pierwszy, na pocz¹tek
zmiennej
x†
przypisywana jest war-
toúÊ kodu za³¹czenia cyfry. PÛüniej
przesuwana jest ona w†lewo o†8†po-
zycji, a†nastÍpnie sumowany jest
z†ni¹ wzorzec znaku do wyúwietle-
nia z†bufora
display
. To s¹ wszyst-
kie operacje, ktÛre musz¹ byÊ wyko-
nane w†celu poprawnej budowy s³o-
wa do sterowania wyúwietlaczem.
Teraz docieramy do pÍtli
for
, ktÛra
ma za zadanie wys³anie wszystkich
16 bitÛw s³owa do wyúwietlacza.
Znajduj¹ca siÍ wewn¹trz pÍtli
operacja przesuwania w†lewo zmien-
nej
x
ma na celu przeniesienie po-
jedynczego bitu s³owa do flagi C,
ktÛra to w†nastÍpnym poleceniu (
da-
taline =
CY) wp³ywa na stan bitu
portu - wyjúcia danych. Impuls ze-
garowy, zmiana stanu
shiftline
z†wy-
sokiego na niski, koÒczy proces wy-
s³ania bitu. PÍtla
for
powtarza ope-
racjÍ 16 razy, dla wszystkich bitÛw
zmiennej. TransmisjÍ koÒczy przepi-
sanie danych z†wewnÍtrznego rejest-
ru do rejestru wyjúciowego poprzez
zmianÍ stanu linii
latchline
. I†to jest
koniec obs³ugi przerwania Timera 1.
Program g³Ûwny
main()
zawiera
tylko proste ustawienia mikrokontro-
lera oraz, na samym pocz¹tku, zapi-
sanie znaku koÒca bufora wyúwietla-
cza. Ustawiane s¹:
List. 1.
//===============================================
// (C) Easy Soft 01/2002
// Raisonance RC-51, version 6.4.16
//===============================================
// rezonator 7,3728MHz
#include <reg52.h>
//definicje linii sterujących wyświetaniem
sbit dataline = P1^0;
sbit shiftline = P1^1;
sbit latchline = P1^2;
//licznik impulsów
int counter = 0;
//wartość rejestru timera TH1, TL1 nie jest modyfikowane liczy zawsze od 0
const char interval = 0xF8;
/* tutaj wzorce cyfr
d5
======
d1 | | d6
| d0 |
======
d7 | | d4
| |
======
d2
*/
char code patterns[10] = { 0x09,0xAF,0x1A,0x8A,0xAC,0xC8,0x48,0x8F,0x08,0x88 };
//przecinek = d3, wyłączenie cyfry = 0xFF
char *TPatterns = &patterns;
//tutaj kolejność załączania
char code digits[6] = { 0xFE,0xFD,0xFB,0xF7,0xEF,0xDF };
char *TDigits = &digits;
//bufor wyświetlacza w RAM
char data display[7];
char data *TDisplay = &display;
//zamiana zmiennej x na zawartość bufora do wyświetlenia
void Translate(unsigned int x)
{
char temp;
ET1 = 0; //wyłączenie na czas translacji wyświetlania
//(migotanie LED)
TDisplay = &display + 5; //zaczynamy translację od najmłodszej cyfry
for (temp=0; temp<6; temp++)
{
*TDisplay = *(TPatterns + x % 10); //adres wzorca + (reszta z dzielenia
//przez 10)
TDisplay-;
x /= 10;
}
TDisplay += 1; //po poprzedniej pętli TDisplay jest o 1 za małe
for (temp=0; temp<5; temp++) //wygaszenie zer nieznaczących od pozycji 1..5
{
if (*TDisplay == *TPatterns) *TDisplay = 0xFF; else break;
//jeśli napotkamy znak różny od 0,to koniec
TDisplay++;
}
ET1 = 1;
//załączenie wyświetlania
}
//procedura obsługi przerwania INT0
//zwiększanie licznika impulsów
void IncrementCounter(void) interrupt 0
{
counter++;
//zwiększenie licznika impulsów
Translate(counter);
//zamiana counter na liczby do wyświetlenia
}
Elektronika Praktyczna 9/2002
95
K U R S
List. 1. (ciąg dalszy)
//procedura obsługi przerwania od timer’a 1
//wysłanie zmiennej 2-bajtowej do wyświetlacza - 1 znak z bufora display
void DisplaySend(void) interrupt 3
{
char temp;
unsigned int x;
TH1 = interval;
//odświeżenie zawartości timera 1
TDisplay++;
//następna pozycja do wyświetlenia
TDigits++;
if (*TDisplay == 0)
//jeśli osiągnięto koniec bufora,
{
//to wróć do początku
TDisplay = &display;
TDigits = &digits;
}
x = *TDigits;
//x przyjmuje wartość liczby do wysłania
x <<= 8;
//składa się ona z bajtu wzorca cyfry
//i bajtu kolejności załączenia
x |= *TDisplay;
for (temp = 0; temp<16; temp++) //wysłanie cyfry poprzez przypisanie flagi C
//do wyjścia danych
{
x <<= 1;
dataline = CY;
shiftline = 1;
//impuls na wyjściu zegara przesuwającego
shiftline = 0;
}
latchline = 1;
//przepisanie danych do wyjść rejestrów
latchline = 0;
}
//program główny
void main(void)
{
*(TDisplay + 6) = 0x00;
//tutaj kod końca danych
Translate(counter);
//wyświetlenia 0.
TMOD = 0x11;
//oba timery jako 16 bitowe, kontrolowane
//wewnętrznie
TH1 = interval;
//przerwanie wywoływane z częstotliw.około 75Hz
ET1 = 1;
//zezwolenie na przerwanie od timer’a 1
TR1 = 1;
//uruchomienie timer’a 1
IT0 = 1;
//opadające zbocze na INT0 wyzwala przerwanie
EX0 = 1;
//załączenie przerwania INT0
EA = 1;
//zezwolenie na przyjmowanie przerwań
while (1);
//oczekiwanie na przerwania
}
- rejestr TMOD na wartoúÊ 0x11, to
znaczy oba Timery jako 16-bitowe,
a†impulsy pobierane s¹ z†wewnÍt-
rznego zegara,
- ustawiany jest starszy bajt licznika
Timera 1,
- w³¹czane s¹ przerwania.
Program g³Ûwny koÒczy pÍtla
while(1)
, w†ktÛrej mikrokontroler
oczekuje na impulsy przychodz¹ce
na INT0 oraz zajmuje siÍ obs³ug¹
wyúwietlania.
Pewnym zaskoczeniem by³ dla
mnie drobny fakt napotkany podczas
testowania programu. Jego pierwowzo-
rem by³ identycznie funkcjonuj¹cy
program w†jÍzyku asembler. Faktycz-
nie nie przejmowa³em siÍ mocno je-
go optymalizacj¹, ale gdy napisa³em
program w†C, mina mi zrzed³a. Pro-
gramy - mniej wiÍcej rÛwnowaøne
w†funkcjach - ten napisany w†asemb-
lerze zajmowa³ 169 bajtÛw, a†ten na-
pisany w†C - 119 bajtÛw. Sta³o siÍ
tak chyba z†jednego powodu. Po pier-
wsze, w†asemblerze dosyÊ trudno pi-
sze siÍ programy operuj¹ce na adre-
sach. Takie programy s¹ po prostu
ma³o czytelne. W†C†nie ma z†tym
wiÍkszego problemu. Moøna uøywaÊ
pewnych drÛg na skrÛty. I†co na to
wszyscy twierdz¹cy, øe programy na-
pisane w†jÍzykach wysokiego poziomu
zajmuj¹ duøo pamiÍci? Oczywiúcie,
moøesz teø powiedzieÊ, øe jestem
kiepskim programist¹...
Na koniec mam jeszcze ma³¹ su-
gestiÍ. A†moøe by tak do³oøyÊ prost¹
procedurÍ komunikacji, chociaøby przez
port RS232, i†nawet bez translacji po-
ziomÛw napiÍÊ zbudowaÊ alternatywÍ
dla uk³adÛw sterownikÛw wyúwietlaczy
LED, ktÛrych cena detaliczna jest - le-
kko mÛwi¹c - przeraøaj¹ca? Moøna by
by³o wykorzystaÊ tani mikrokontroler,
na przyk³ad AT89C2051. A†moøe AVR?
WÛwczas nie potrzeba rezonatora
kwarcowego. MyúlÍ, øe wraz z†cyfra-
mi bÍdzie on taÒszy niø jeden uk³ad
sterownika LED.
Jacek Bogusz, AVT
jacek.bogusz@ep.com.pl
Dodatkowe informacje
Ewaluacyjn¹ wersjê pakietu firmy Raisonance
prezentowanego w artykule zamieœciliœmy na
CD-EP8/2002B.
96
Elektronika Praktyczna 9/2002
Plik z chomika:
IZOPROPYL
Inne pliki z tego folderu:
Wentylatory.pdf
(1666 KB)
Star Wars. Katalizator. Wprowad - James Luceno.pdf
(1665 KB)
Gordon R. Dickson - Smoczy rycerz T2.pdf
(1663 KB)
LOKOMOTYWA TOWAROWA EMD JT42CWRM(Class66).pdf
(1662 KB)
Greer Luanshya - Kto sieje wiatr 02 - Po burzy spokój.pdf
(1660 KB)
Inne foldery tego chomika:
- - 2025--FULL---
- - 2024 FILMY NOWE
- WIN DROID IOS - HASŁO ARHIWÓW I FOLD - 1111
█ DUŻY MIX █
12.000 FILMÓW
Zgłoś jeśli
naruszono regulamin