x, ponechá se MSB v log.1, v opačném případě se nastaví MSB do log.0. V dalším kroku je testován bit MSB-1 pomocí jemu odpovídajícho napětí UR/4, které se přičte k napětí na výstupu D/A převodníku z předchozího kroku. Výsledné napětí UK je opět srovnáno s Ux - je-li UK>Ux, je testovaný bit nastaven na log.0. Stejný postup se opakuje pro zbývající bity D/A převodníku. Počet kroků převodu n je tak roven počtu bitů převodníku.
A/D převodníky s postupnou aproximací se vyrábějí jako 8 až 16-bitové, s odpovídajícím rozlišením 0,4% až 0,0018%. Zopakujeme ještě jednou ostatní vlastnosti, a to velkou rychlost převodu, která bývá zhruba 10µs a schopnost dosáhnout 104 až 105 odběrů(měření) za sekundu. Vyžadují konstantní vstupní napětí během doby převodu, jinak může dojít ke značným chybám, a proto se na jejich vstup umisťuje vzorkovač s pamětí (Sample and Hold). Tyto převodníky jsou citlivé na rušivá napětí, nejsou odolné proti sériovému rušení.
A/D převodník ADC0804
Pro naše účely jsem si vybraly integrovaný A/D převodník ADC0804, vyráběný firmou National Semiconductor. Jedná se o 8-bitový aproximační převodník, jehož funkce vychází z výše uvedeného obecného principu. Maximální celková chyba je ±1 LSB, doba převodu je 100µs. Převodník má třístavové datové výstupy pro připojení na sběrnici, původně byl určen pro připojení k mikroprocesoru i8080 a jeho klonům. Má diferenciální napěťové vstupy, vstupní rozsah je 0 až 5V při napájení z 5V. Nevyžaduje nastavení nuly, všechny log.vstupy a výstupy jsou CMOS/TTL kompatibilní. Pro řízení převodu se používá vnitřní hodinový signál o frekvenci maximálně 1,5 MHz. Převodník nevyžaduje připojení vnějšího referenčního napětí (vnitřně 1/2 Vcc), je možné připojit i externí ref.zdroj (např. LM336). Převodník může pracovat i jako volněběžící, je schopen dosáhnout až 9700 měření/s. Převodník nemá vestavěn vzorkovací obvod typu "Sample and Hold”, takže pokud to daná aplikace vyžaduje, je nutné použít vnější vzorkovací obvod (např. LF398). Bližší popis funkce převodníku a časování signálů lze najít v tomto datasheetu na str. 18 až 24.
Pouzdro obvodu ADC0804
|
|
DB0 – DB7 ---------------- dig. výstup z převodníku
Vref/2 ------------------- referenční napětí
Vin +, Vin - ------------------- difer. napěťové vstupy
Clk in, Clk r ----------------- hodinové vstupy
INTR --------------------- přerušení do procesoru
GND ---------------------- zem
RD ----------------------- příkaz pro čtení
WR ----------------------- příkaz pro zápis
CS ----------------------- povolovací vstup
A GND ----------------------- analogová zem
D GND ----------------------- digitální zem
|
Zapojení obvodu na obrázku č.4 nám dobře posloužil k ověření funkce a vlastností převodníku (testovací obvod dle doporučení výrobce). Bylo třeba zjistit binární hodnotu odpovídající vstupnímu napětí, které se připojuje na piny 6 a 7 (A GND).Pin 6 je vstupní a pin 7 je spojen s analog.zemí(pin 8). Protože jsme měli za úkol sestrojit voltmetr měřící napětí 0 až 10 voltů, museli jsme na vstupu převodníku použít dělič, který je vidět na obrázku č.5. Převodník má v tomto zapojení vstupní rozsah napětí pouze 0 až 5V, z čehož plyne, že jsme použili dělič 1:2. Detailnější rozbor převodníku a způsob zjištění binární hodnoty, která odpovídá vstupnímu napětí, je vysvětlen v části popisující funkci programu.
Dále bylo nutné ošetřit vstup voltmetru před napětím vyšším než 10V. Nejdříve jsme chtěli použít omezovací obvod sestavený přesně pro naše účely, ale jeho cena by nebyla nejnižší a vzhledem ke snadnější realizaci ochrany vstupu pomocí Zenerovy diody jsme využili právě tuto možnost. Bylo potřeba zjistit předřadný odpor k Zenerově diodě, který jsme nejprve zvolili 300W. Po krátkém zkoušení se nám jako nejlepší hodnota předřadného odporu jevila hodnota 34W, která je nastavována pomocí trimru TR1 (viz schéma zapojení).
Trimr TR2 slouží k přesnému doladění vstupního děliče A/D převodníku. Mohli jsme sice použít pevný rezistor, ale z důvodu teplotní nestálosti součástek jsme pro dosažení přesného měření použili právě trimr (vst.rozsah tak lze před měřením zkalibrovat).
Obr.4 Obvod pro ověření funkce převodníku |
|
Obr.5 Odporový dělič na vstupu převodníku |
POZN: Při návrhu voltmetru s A/D převodníkem je známo, že je nutné rozlišovat tzv. "analogovou" a "číslicovou zem". Během našeho zkoušení jsme došli k názoru, že vzájemné propojení těchto zemí není kritické a voltmetr fungoval i tak naprosto správně a přesně. Dále bylo nutné dodržet aplikační podmínky obvodu ADC0804 ohledně blokování napájecího napětí a minimalizace délky vodičů pro připojení měřeného napětí.
|
Připojení displeje
Displej HDSP 5621
Jde o 2-místný sedmisegmentový LED zobrazovač, barva znaků zelená, výška znaků 14 mm, společná anoda, úhel viditelnosti ± 50°, vynikající kontrast, dobrá viditelnost až do vzdálenosti 7m.
|
|
Podrobné informace o HDSP 5621 najdete zde. Informace o dalších typech sedmisegmentových displejů najdete zde. |
Protože displej ovládáme staticky, displej si pro svoji potřebu zabral celé dva v/v porty mikroprocesoru (viz schéma zapojení). Pokud bychom si nemohli takový "přepych" dovolit, může se pro připojení použít nějaký dekoder BCD/7-segment (např. 74247) nebo použít dynamické řízení (přes spínací tranzistory),čímž se značná část vývodů portu ušetří.
Displej je připojen klasicky - na společnou anodu je připojeno napájení +5V, na jednotlivé segmenty jsou připojeny sériové odpory, jejichž hodnotu lze vypočítat z jednoduchého vzorce:
R = (Ucc - UD) / ID = (5 - 1,7) / 0,015 = 220 W
, kde proud diodou (jedním segmentem) ID uvažujeme 15 mA, což je optimální hodnota jak z hlediska dostatečné svítivosti, tak životnosti diody (segmentu).
Popis funkce programu
Program má za úkol zpracovat výstupy A/D převodníku a zobrazit na displeji hodnoty napětí, které této kombinaci odpovídají.
Hlavní část programu je vlastně velice jednoduchá. Obsahuje jen nastavení čítače, určení některých konstant apod. Veškeré výpočty a důležité úkony se provádějí v části obsluhy přerušení.
STOVKY DATA 50H ; určení adres pro pomocné výpočty
DESITKY DATA 51H
JEDNOTKY DATA 52H
ZBYTEK DATA 53H
ORG 0H
JMP START
ORG 0BH ;přerušení čítače/časovače 0
LJMP PRERUS
START: ORG 20H ;vlastní program
MOV R0,#250D ;nastavení počtu cyklů čítače
MOV DPTR,#100H ;pomocná hodnota při výpočtech - displej
MOV TMOD,#00000010B ;nastavení čítače – mód s předvolbou
MOV TH0,#5D ;nastavení předvolby čítače (255 – 250 = 5 µs)
MOV TL0,#5D
SETB ET0 ;povolení přerušení od čítače 0
SETB EA
SETB TR0
KONEC: JMP KONEC ; nekonečná smyčka.
Při běhu nekonečné smyčky je každých 250 µs vyvoláno přerušení. Zpracuje se vstup od A/D převodníku a aktualizuje se údaj na displeji.
Přerušení
Je povoleno jedno přerušení – od čítače/časovače 0. Obsluhu přerušení řídí tyto řádky :
PRERUS: DJNZ R0,CYKLUS
MOV R0,#250D
.
.
CYKLUS: RETI
V registru R0 je konstanta, která určuje, jak často se má měnit údaj na displeji. V našem případě je to hodnota 250. Při každém volání se R0 zmenší o jednčku. Pokud je R0 rovno 0, doplní se na výchozí hodnotu a zpracuje se tělo přerušení. Jelikož se přerušení volá každých 250 µs a v registr R0 je hodnota 250, jsou příkazy v přerušení zpracovávány každých 250 * 250 = 62500 µs = 62,5 ms. Vždy po této době se zpracuje vstup a na výstup displeje se přivede aktualizovaný údaj hodnoty napětí.
Vlastní zpracování vstupů
Převodník je 8-bitový. Jeho výstupem je tedy číslo 0 až 255. Protože pracujeme v rozsahu 0 až 10V, je číslo 255 poněkud nevhodné - číslo 10 děleno 255 dá číslo 0,039215. Toto číslo odpovídá diferenci D – rozdílu jednotlivých stavů výstupu. V osmibitové matematice se s tímto číslem nedá moc dobře počítat.
Pokud ale zmenšíme rozsah na 0 – 250, diference D bude jenom 0,04. Tím se naše počty velice zjednoduší. Vlastní algoritmus je velice jednoduchý. Řekněme, že dekadickou hodnotu výstupu A/D převodníku budeme značit D (D jako Dekadická hodnota výstupu). V tom případě napětí ve voltech získáme ze vzorce
U = D* D* 100 [V]
Pro lepší zřetelnost je celá závislost zakreslena na grafu :
V praxi je to řešeno následovně : data jsou přiváděna z A/D převodníku na bránu P1. Nejdřív se otestuje, jestli hodnota přesahuje 250. Ve vyšších jazycích, jako napři. Pascal nebo C by to šlo napsat třeba „If X > 250 then “ , ale v assembleru porovnávání velikostí není. Můžeme jen využít příkaz CJNE, který otestuje, jestli se daná čísla rovnají. Pokud ne, skočí na zadané návěští:
POZN. (Michal Fuksa): Tady si asi pozorný čtenář všimnul, co je ve výše uvedených řádcích uvedeno za chybu - instrukce CJNE přece umožňuje plnohodnotné porovnávání dvou proměnných. Tady to autoři programu trochu ustřelili (zřejmě hodně spěchali, takže si správné použití CJNE na tomto místě programu neuvědomili), jak je ale vidět dále, kompletní funkce instrukce CJNE jim byla známa.
MOV A,P1
CJNE A,#11111010B,PRVNI ; Otestuje, jestli A =250
LJMP DESET
PRVNI: CJNE A,#11111011B,DRUHY ; Otestuje, jestli A =251
LJMP DESET
DRUHY: CJNE A,#11111100B,TRETI ; Otestuje, jestli A =252
LJMP DESET
TRETI: CJNE A,#11111101B,CTVRTY ; Otestuje, jestli A =253
LJMP EE
CTVRTY: CJNE A,#11111110B,PATY ; Otestuje, jestli A =254
LJMP EE
PATY: CJNE A,#11111111B,NENI_DESET ; Otestuje, jestli A =255
; když ne,skok na NENI_DESET, kde
; pokračují další výpočty a vlastně
; ta nejdůležitější část programu
EE: MOV P0,#10001100B
MOV P2,#00001100B
CYKLUS1: LJMP CYKLUS ;skok na konec cyklu
DESET: MOV P0,#11110011B
MOV P2,#01000000B
LJMP CYKLUS ;skok na konec cyklu
Návěští CYKLUS1 je vlastně meziskok. Některé příkazy, jako CJNE nebo DJNZ, mohou provést skok maximálně o 128 bytů. V našem případě to nestačí a tak je řádek
CYKLUS1: LJMP CYKLUS
jen jakýsi odrazový můstek, který tyto příkazy využívají, aby se dostali na konec programu.
Problém je osmibitová matematika. Vzorec ve formě U = D* D* 100 [V] této formě se nemůže použít. Pokud ale rozdělíme číslo D na stovky, desítky a jednotky, můžeme využít jiný přístup. Nejprve rozdělíme číslo do tří proměnných : STOVKY, DESITKY, JEDNOTKY. Pak každou proměnnou vynásobíme 4. Ve dvouciferném výsledku pak použijeme hodnotu v proměnné STOVKY jako počet desítek, DESITKY jako počet jednotek a jednotky použijeme jako zaokrouhlovací pomocnou proměnnou, aby hodnota výsledku odpovídala. Použijeme definici rozkladu čísel :
Když číslo dělíme číslem 100, získáme počet stovek a zbytek je roven počtu desítek. Dělíme-li počet desítek 10, získáme počet desítek a zbytek je roven počtu jednotek. V praxi to vypadá pro některá náhodně vybraná čísla takto :
V assembleru se dá tento algoritmus zapsat třeba takto: (Návěští se jmenuje NENÍ_DESET, protože před skokem na toto místo došlo k otestování, jestli na vstupu není 10 či více voltů.)
NENI_DESET: MOV B,#100D ;rozdělení čísla na stovky, desítky a jednotky
DIV AB
MOV STOVKY,A ; Stovky
MOV A,#10D
XCH A,B
DIV AB
MOV DESITKY,A ; Desítky
MOV JEDNOTKY,B ; Jednotky
A teprve nyní všechny tři proměnné vynásobíme 4 :
MOV A,STOVKY
MOV B,#4D
MUL AB
MOV STOVKY,A ; STOVKY = STOVKY * 4
MOV A,DESITKY
MOV B,#4D
MUL AB
MOV DESITKY,A ; DESITKY = DESITKY * 4
MOV A,JEDNOTKY
MOV B,#4D
MUL AB
MOV JEDNOTKY,A ; JEDNOTKY = JEDNOTKY * 4
Následuje zaokrouhlení a upřesnění hodnoty výsledku. Obvykle se zaokrouhluje nahoru, když je číslo větší než 5 a dolů, pokud je menší. My místo čísla 5 používáme číslo 7. Je to kompenzace nepřesnosti vstupu. Vstup voltmetru je napěťový dělič z odporů. Bohužel odpory a potenciometry se nedají nastavit s nekonečnou přesností. Ne každý se dá nastavit zcela přesně, je to dáno jak technologií, tak ladícími prvky (šroubovací závity a podobně). Proto v praxi, i když s tím počítáme, není diference D = 4, ale v praxi se o několik setin či tisícin liší. U malých čísel to nevadí, ale odchylka postupně narůstá. Proto jsme zvolili mez zaokrouhlování na hodnotě ne rovné polovině 10, ale spíše jedné třetině, tedy 7.
MOV B,#10D
DIV AB
MOV ZBYTEK,A ;v A jsou (JEDNOTKY * 4 ) /10
MOV A,B ;v B je zbytek po dělení 10
CJNE A,#7D,MENSI_NEZ_7 ;skok při nerovnosti, mění příznak přenosu
;C=1 if A < 7, jinak C=0
LJMP VETSI_NEZ_7
A nyní jak a kam se bude zaokrouhlovat podle výsledku :
MENSI_NEZ_7: JNC VETSI_NEZ_7 ;druhé otestování
MOV A,DESITKY
MOV B,ZBYTEK
ADD A,B ;součet desítek a zbytku po operací s jednotkami
MOV B,#10D
DIV AB ;vydělíme deseti – počet desítek v součtu (v reg. A)
MOV JEDNOTKY,B ;druhé číslo výsledku (zbytek dělení) - výstup
MOV B,STOVKY
ADD A,B ;přičte se výsledek předchozího výpočtu
MOV DESITKY,A ;první číslo výsledku po zaokrouhlení - výstup
LJMP VYSTUP ;výsledek na displej
VETSI_NEZ_7: MOV B,ZBYTEK ;zde je zbytek větší nebo roven 7
MOV A,#1D
ADD A,B
MOV ZBYTEK,A ;zbytek = zbytek + 1
MOV A,DESITKY
MOV B,ZBYTEK
ADD A,B ;součet desítek a zbytku
MOV B,#10D
DIV AB ;A = počet desítek v součtu
MOV JEDNOTKY,B ;druhé číslo výsledku
MOV B,STOVKY
ADD A,B ; + počet stovek
MOV DESITKY,A ;první číslo výsledku
V proměnných DESITKY a JEDNOTKY jsou uloženy čísla, která se dostanou na displej ve tvaru :
Rámečky samozřejmě znamenají jednomístný LED displej a ukazují číslo od 0 do 9.
Zobrazování na displeji
Hardwarová část připojení displeje byla popsána výše. Zbývá ještě probrat softwarovou část. Zobrazování je řešeno staticky. Proto stačí jen přivést na příslušnou bránu patřičnou kombinaci 0 a 1 (tj. segmenty, které budou svítit a které ne). To řeší následující část (umístěno v obsluze přerušení – viz dále) :
MOV A,DESITKY
MOVC A,@A+DPTR
MOV P0,A
MOV A,JEDNOTKY
MOVC A,@A+DPTR
MOV P2,A
V proměnných DESITKY a JEDNOTKY jsou hodnoty v intervalu 0 – 9. Obsah proměnných se postupně dostane do registru A. Následuje řádek
MOVC A,@A+DPTR
který do registru A dosadí hodnotu na A + DPTR. V registru DPTR je hodnota 100h, proto se do registru A dosadí hodnota A + 100h, která odpovídá kombinaci pro rozsvícení jednotlivých segmentů displeje. Pokud je tedy v A hodnota 0, do A se dosadí hodnota z adresy 100h, která odpovídá číslu 0 atd.
číslo |
ABCDEFGH |
0 |
0 0 0 0 0 0 1 1 |
1 |
1 1 0 0 1 1 1 1 |
2 |
0 0 1 0 0 1 0 1 |
3 |
1 0 0 0 0 1 0 1 |
4 |
1 1 0 0 1 0 0 1 |
5 |
1 0 0 1 0 0 0 1 |
6 |
0 0 0 1 0 0 0 1 |
7 |
1 1 0 0 0 1 1 1 |
8 |
0 0 0 0 0 0 0 1 |
9 |
1 0 0 0 0 0 0 1 |
|
|
|
Na konci celého programu jsou do paměti dat umístěny konstanty - kombinace svítících/nesvítících segmentů displeje (první konstanta je pro 0, poslední pro 9). Je jedno, jestli jsou tyto konstanty uvedeny na konci, na začátku nebo uprostřed programu, ale nakonec jsme se rozhodli umístit je na konec. Vyplynulo to při programování – umístili jsme je tam při programování první verze a pak už nebyl důvod to měnit.
ORG 100H
DB 01000000B,01110011B,00100100B,00100001B,00010011B
DB 00001001B,00001000B,01100011B,00000000B,00000001B
END
Schéma zapojení
kliknutím na obrázek získáte schéma zapojení v plné velikosti
Soupiska použitých součástek pro desku plošných spojů:
(značení součástek dle katalogu GM Electronic)
Položka |
Množství |
Referenční označení |
Typ |
1 |
1 |
IO1 |
ADC0804CN |
2 |
1 |
IO2 |
AT89C51 |
3 |
1 |
ST1 |
7805 |
4 |
1 |
ZD1 |
BZX 85V010 (Zenerka 10V/1,3W) |
5 |
1 |
Displej |
HDSP - 5621 |
6 |
1 |
X1 |
krystal 12 MHz |
7 |
3 |
R1,R2,R3 |
10k |
8 |
1 |
R4 |
8k2 |
9 |
15 |
R5 až R19 |
220R |
10 |
1 |
TR1 |
trimr 250R (PT10VE250) |
11 |
1 |
TR2 |
trimr 25k (PT10VK025) |
12 |
1 |
C5 |
10uF/25V |
13 |
1 |
C1 |
150pF |
14 |
3 |
C2,C6,C7 |
100nF |
15 |
1 |
C8 |
470uF/50V |
16 |
2 |
C3,C4 |
33pF |
17 |
2 |
Vstup 0 až 10V, Ucc 24V |
svorkovnice ARK 550/2 |
Další použité komponenty:
1 x patice SOKL20 (20-pin DIP)
1 x patice SOKL40 (40-pin DIP)
1 x patice SIL 10 PZ (jednořadá - pro displej)
Zhodnocení, přednosti a nedostatky: