Teploměr pro rozhraní RS232C
Vypracoval: Martin Zeman
6.1. 2000
Základní popis: změřená teplota je vysílána po rozhraní RS232C v textovém formátu ASCII a ukončena znakem CR (#13).
Technické parametry:
Popis zapojení: teplota je měřena čidlem Th0 - SMT160-30, což je převodník teplota-střída s převodním vzorcem DC=0.32+0.0047*t, kde DC je střída v rozsahu hodnot 0-1 (0-100%) a t je teplota ve stupních Celsia. Střídu změřím jednočipovým mikropočítačem IO1 – 89C2051, změřenou střídu převedu na stupně Celsia a v textovém formátu ASCII odešlu sériovým výstupem přes převodník-budič IO2 – MAX232, který převede logické úrovně TTL na logické úrovně rozhraní RS232C +/-12V.
Schéma:
Seznam součástek:
IO1 AT89C2051
IO2 MAX232 (ICL232), ta nejobyčejnější verze
X1 krystal 11.059MHz
Cx1-2 22pF keramika, 2ks
C0-C4 1uF/25V elektrolyt, 5ks
C5-7 100nF keramika, 2ks
C6 50uF/25V elektrolyt
D1 KY132, libovolná dioda 0.5-1A
F1 tavná přístrojová pojistka 50-100mA (<5R),
a držák pojistek (spotřeba je do 20mA)
Th0 SMT160-30 TO92 a třížilový kabel do 20m
konektor Cannon9F nebo Cannon25F a propojovací dvojlinka do 15 m
konektor DIN5M a DIN5F a propojovací 6 žilový kabel
patice DIL20 a DIL16
krabička např.: KM26N
plošný spoj viz příloha v OrCADu
Mechanické provedení:
Je koncipováno pro připojení k PC. Napájení je realizováno průchozím konektorem, který se připojí sériově před klávesnici. Výstup může být na konektor Cannon9 nebo Cannon25. Měřící čidlo může připojeno až 20 metrů dlouhým třížilovým kabelem, který se přímo zaletuje do plošného spoje nebo přes pinový konektor.
Realizovaný teploměr ukazují následující obrázky:
Teplotní čidlo SMT160-30 (viz [1]) měří teplotu v rozsahu –45°C až +130°C s absolutní přesností +/-0.7°C. Napájení je 5V a výstup je slučitelný s logikou TTL. Výstupní obdélníkový signál lze měřit analogově, kdy střední hodnota napětí výstupu je střída*5V, nebo čislicově kdy změříme střídu výstupního signálu. Výstupní signál je v rozsahu 1-4kHz a střída se rovná:
T1~stavu log. 1, T2~ stavu log. 0
Ale měříme střídu a potřebuje
me zjistit teplotu.tímto převodním vzorcem již získáme teplotu, ale výpočet budeme provádět na 8bitovém jednočipu a je tedy vhodné počítat v pevné řádové čárce. Provedeme úpravy na odstranění desetinných čísel a rozšíříme zlomek číslem 1/0.0047 . Přesnost čidla je +/-0.7°C a odpovídající měřené rozlišení bude vhodné na desetiny, proto zlomek vynásobíme 10krát a výsledek v pevné desetinné čárce bude v decistupních Celsia.
Popis programu
Program se skládá z cyklu následujících úkonů:
1. Změření střídy signálu čidla
Vlastní měření se provede dvěma 16bitovými časovači jednočipu. Měříme časy stavů log. 1 a 0 pro několik period signálu (viz [1] str.9). Při krystalu 11.059Mhz trvá instrukce a 1 takt časovače cca 1us a nejdelší perioda by měla být 1000us (signál 1kHz), při použití 16bitových časovačů bez přetečení je vhodné měřit střídu 64 period signálu.
nastavíme režim časovačů a vynulujeme je
; meření střídy, log 1 - počet taktů v C/T0, log 0 - počet taktů v C/T1
; nasta
vení C/T0 a C/T1 na mod1, časovačMOV TMOD, #00010001B;
ANL TCON, #0Fh ; vynulovat přetečení a stopnout je
MOV TL0, #0 ;
MOV TH0, #0 ; nulovaní C/T0
MOV TL1, #0 ;
MOV TH1, #0 ; nulovaní C/T1
měření spustíme od náběžné hrany signálu
; nalezení synchronu
MOV R2, #64 ; 64 meření
JB T0, $ ;
JNB T0, $ ;
podle log. hodnoty signálu zastavujeme a spouštíme jednotlivé časovače 64 krát ve smyčce
; vlastní měřící smyčka
loopme: setb TR0 ;
jb T0, $ ;
clr TR0 ; signal v "1"
setb TR1 ;
jnb T0, $ ;
clr TR1 ; signal v "0"
DJNZ R2, loopme ;
ke stavu časovačů přičteme korekční hodnoty, které potřebovali instrukce k jejich zastavení a spuštění a časovače v ten okamžik nečítali a uložíme do proměnných var1 a var2
; uložení "1" stavu do var1
MOV A, TL0 ;
ADD A, #189 ; korekce za (5-2) instrukce*64-3
MOV var1, A ;
MOV A, TH0 ;
ADDC A, #0 ; pričtení přetečení řádu od TL0
MOV var1+1, A ;
; uložení "0" stavu do var2
MOV A, TL1 ;
ADD A, #64 ; korekce za (3-2) instrukci*64
MOV var2, A ;
MOV A, TH1 ;
ADDC A, #0 ; pričtení přetečení řádu radu od TL1
MOV var2+1, A ;
2.) výpočet převodu střída->teplota v °dC v binárním soustavě
Jedná se o realizaci výpočtu vzorce:
Rozsahy čísel z časovačů jsou 16 bitů a konstanty 1446 a 681 nevystačí s 8 bity a budou 16 bitové. Operací násobení vznikne číslo o 32 bitech, je třeba používat 16-32 bitovou aritmetiku. Tyto výpočty jsem realizoval makry v souboru MATH.ASM .
nastavíme konstanty 1446 a 681
; konstanty do var3 a var4
MOV var3, #0A6h ;
MOV var3+1, #05h ; 1446 = 05A6h
MOV var4, #0A9h ;
MOV var4+1, #02h ; 681 = 02A9h
provedeme součiny čitatele 1446*T1 a 681*T2, a součet jmenovatele T1+T2
; výpočet teploty
SOUCIN var1, var3, var5, var6 ; výsledek do var5
SOUCIN var2, var4, var7, var8 ; výsledek do var7
PLUS var1, var2 ; jmenovatel do var1
teplota může být i záporná, to zjistíme porovnáním součinů čitatele
; zjisteni znamenka
mov R0, #var5 ;
mov R1, #var7 ;
call cmp ;
JC kladne ;
je-li teplota záporná nastavíme příznak mínus do R7, vypočteme var7:=var7-var5 a výsledek přemístíme do var5
MINUS var7, var5 ; záporný čitatel do var7
mov A, var7 ; přemístění do var5
mov var5, A ;
mov A, var7+1 ;
mov var5+1,A ;
mov A, var7+2 ;
mov var5+2, A ;
mov A, var7+3 ;
mov var5+3, A ;
mov R7, #255 ; znaménko -
JMP hps ;
je-li teplota kladná vypočteme var5:=var5-var7
kladne: MINUS var5, var7 ; kladný čitatel do var5
mov R7, #0 ; znaménko +
výpočteme podíl čitatele var
5 a jmenovatele var1hps: PODIL var5, var1, var9, var10 ; var9 výsledek
pro zpřesnění vypočtu průměr z 256 hodnot, dělení 256 se provede adresací výsledku o 1 byte výše
; průměr z 256 hodnot
PLUS prumer, var9 ;
INC R6 ;
mov A, R6 ;
JZ nenuly ;
jmp nuly ;
nenuly: NOP ;
3.) převod z binárního soustavy do kódu BCD
; převod do BCD
BINBCD prumer+1, var11 ;
; nulování proměnné prumer
mov prumer, #0 ;
mov prumer+1, #0 ;
mov prumer+2, #0 ;
mov prumer+3, #0 ;
mov prumer+4, #0 ;
4.) vyslání sériovým portem v kódu ASCII včetně desetinné tečky
Nastavíme časovač 1 jako generátor hodin pro sériový port. K jednotlivým BCD číslovkám přičteme číslo 48 (v ASCII ‘0’~48) a vyšleme sériovým kanálem. nejprve vyšleme případné znaménko mínus. Mezi jednotkami a desetinami vyšleme znak desetinné tečky a na závěr znak Enter (#13).
; nastavení sériového portu na 9600b/s, 8 bitů bez parity
ANL TMOD, #0Fh ;
ORL TMOD, #00100000B;
MOV TH1, #0FDh ;
ANL PCON, #7Fh ;
MOV SCON, #01000000B;
SETB TR1 ;
CLR RI ;
CLR TI ;
; znaménko mínus nebo mezera
MOV A, R7 ;
JZ kld ;
mov A, #45 ;
jmp nkld ;
kld: mov A, #32
nkld: MOV SBUF, A ;
JNB TI, $ ;
CLR TI ;
; stovky
MOV A, var11+1 ;
ANL A, #0F0h ;
SWAP A ;
ADD A, #48 ;
MOV SBUF, A ;
JNB TI, $ ;
CLR TI ;
; desítky
MOV A, var11+1 ;
ANL A, #0Fh ;
ADD A, #48 ;
MOV SBUF, A ;
JNB TI, $ ;
CLR TI ;
;jednotky
MOV A, var11 ;
ANL A, #0F0h ;
SWAP A ;
ADD A, #48 ;
MOV SBUF, A ;
JNB TI, $ ;
CLR TI ;
; desetinná tečka
MOV A, #46 ;
MOV SBUF, A ;
JNB TI, $ ;
CLR TI ;
; desetiny
MOV A, var11 ;
ANL A, #0Fh ;
ADD A, #48 ;
MOV SBUF, A ;
JNB TI, $ ;
CLR TI ;
; Enter
MOV A, #13 ;
MOV SBUF, A ;
JNB TI, $ ;
CLR TI ;
na závěr vynuluji pamět a skočím na začá
tek programu;nulování paměti
nuly: MOV R0, #30h ;
MOV R2, #60 ;
nuluj: MOV @R0, #0 ;
INC R0 ;
DJNZ R2, nuluj ;
Pro výpočty jsem napsal makra na součet, rozdíl, součin a podíl. Dále pomocné fce na porovnání dvou čísel a převod z
binárního kódu do kódu BCD. (viz MATH.ASM)Makra SOUCET a ROZDIL jsou posloupností součtu/rozdílu pro čtyři 8 bitová čísla s přenosem do vyššího řádu.
Makro SOUCIN se skládá z posloupnosti součtů součinů jednotlivých řádů činitelů.
Makro PODIL je založeno na binárním postupném dělení, kde se využívá efektu binární soustavy: dělení dvěma je totéž jako odečtení. Toto makro jako jediné může být v programu použito jen jednou, neboť používá smyčky. Pro vícenásobné použití je třeba udělat kopii jiného názvu s j
inými názvy návěští skoků.Fce CMP porovnává dvě čísla postupně od nějvětšího řádu na shodu, a při neshodě nastaví příznak CY pro první větší číslo.
Fce BINBCD využíná postupného přepočtu binární soustavy řád po řádu (bit po bitu), ale v soustavě BCD. Postupně od nejvyšší bitu vynásobíme BCD číslo dvěma a pokud je následující bit roven '1' přičteme ješte jedničku.
Závěr:
Přesnost měření jsem ověřil pomocí ustálené směsi vody a ledu pro 0°C, a porovnáním chladnoucí vody v rozsahu 30-80°C. Měření byla bezpečně v toleranci +/-1°C.
Rychlost měření můžeme zrychlit odstraněním průměrování z 256 hodnot. Počet čidel lze přímo rozšířit až na čtyři, připojením na piny T0, T1, INT0 a INT1. Stav těchto vstupů lze testovat instrukcemi s délkou 1 takt. Více čidel lze připojit pomocí multiplexeru. Stavající program však počítá s jedním čidlem, pro více čidel stačí udělat nastavení příznaku-čísla měřeného čidla a zasílaný text rozšířit o číslo čidla.
Přílohy:
Kompletní výpis programu pro jednočip TEP_OK.ASM :
; program teplomer s ASCII vystupem na seriovy port RS232C
$MOD51
var1 DATA 030H ;
var2 DATA 030H+4 ;
var3 DATA 030H+8 ;
var4 DATA 030H+8+4 ;
var5 DATA 030H+16+4 ;
var6 DATA 030H+16+8 ;
var7 DATA 030H+16+8+4 ;
var8 DATA 030H+32 ;
var9 DATA 030H+32+4 ;
var10 DATA 030H+32+8 ;
var11 DATA 030H+32+8+4 ;
var12 DATA 030H+32+8+8 ;
prumer DATA 120 ;
ORG 0H ;
JMP tepl ;
$include(MATH.ASM)
tepl: NOP ;
; mereni stridy, log 1 - pocet taktu v C/T0, log 0 - pocet taktu v C/T1
; nastaveni C/T0 a C/T1 na mod1, casovac
MOV TMOD, #00010001B;
ANL TCON, #0Fh ; vynulovat preteceni a stopnout je
MOV TL0, #0 ;
MOV TH0, #0 ; nulovani C/T0
MOV TL1, #0 ;
MOV TH1, #0 ; nulovani C/T1
; nalezeni synchronu
MOV R2, #64 ; 64 mereni
JB T0, $ ;
JNB T0, $ ;
; vlastni merici smycka
loopme: setb TR0 ;
jb T0, $ ;
clr TR0 ; signal v "1"
setb TR1 ;
jnb T0, $ ;
clr TR1 ; signal v "0"
DJNZ R2, loopme ;
; ulozeni "1" stavu do var1
MOV A, TL0 ;
ADD A, #189 ; korekce za (5-2) instrukce*64-3
MOV var1, A ;
MOV A, TH0 ;
ADDC A, #0 ; pricteni preteceni radu od TL0
MOV var1+1, A ;
; ulozeni "0" stavu do var2
MOV A, TL1 ;
ADD A, #64 ; korekce za (3-2) instrukci*64
MOV var2, A ;
MOV A, TH1 ;
ADDC A, #0 ; pricteni preteceni radu od TL1
MOV var2+1, A ;
; konstanty do var3 a var4
MOV var3, #0A6h ;
MOV var3+1, #05h ; 1446 = 05A6h
MOV var4, #0A9h ;
MOV var4+1, #02h ; 681 = 02A9h
; vypocet teploty
SOUCIN var1, var3, var5, var6 ; vysledek do var5
SOUCIN var2, var4, var7, var8 ; vysledek do var7
PLUS var1, var2 ; jmenovatel do var1
; zjisteni znamenka
mov R0, #var5 ;
mov R1, #var7 ;
call cmp ;
JC kladne ;
;
MINUS var7, var5 ; zaporny citatel do var7
mov A, var7 ; premisteni do var5
mov var5, A ;
mov A, var7+1 ;
mov var5+1,A ;
mov A, var7+2 ;
mov var5+2, A ;
mov A, var7+3 ;
mov var5+3, A ;
mov R7, #255 ; znamenko -
JMP hps ;
;
kladne: MINUS var5, var7 ; kladny citatel do var5
mov R7, #0 ; znamenko +
hps: PODIL var5, var1, var9, var10 ; var9 vysledek
;
; prumer z 256 hodnot
PLUS prumer, var9 ;
INC R6 ;
mov A, R6 ;
JZ nenuly ;
jmp nuly ;
nenuly: NOP ;
; prevod do BCD
BINBCD prumer+1, var11 ;
; nulovani prumer
mov prumer, #0 ;
mov prumer+1, #0 ;
mov prumer+2, #0 ;
mov prumer+3, #0 ;
mov prumer+4, #0 ;
; castecny opis na P1
MOV A, var11 ;
MOV P1, A ;
; nastaveni serioveho portu na 9600b/s
ANL TMOD, #0Fh ;
ORL TMOD, #00100000B;
MOV TH1, #0FDh ;
ANL PCON, #7Fh ;
MOV SCON, #01000000B;
SETB TR1 ;
CLR RI ;
CLR TI ;
; znamenko
MOV A, R7 ;
JZ kld
mov A, #45
jmp nkld ;
kld: mov A, #32
nkld: MOV SBUF, A ;
JNB TI, $ ;
CLR TI ;
; stovky
MOV A, var11+1 ;
ANL A, #0F0h ;
SWAP A ;
ADD A, #48 ;
MOV SBUF, A ;
JNB TI, $ ;
CLR TI ;
; desitky
MOV A, var11+1 ;
ANL A, #0Fh ;
ADD A, #48 ;
MOV SBUF, A ;
JNB TI, $ ;
CLR TI ;
;jednotky
MOV A, var11 ;
ANL A, #0F0h ;
SWAP A ;
ADD A, #48 ;
MOV SBUF, A ;
JNB TI, $ ;
CLR TI ;
; desetinna tecka
MOV A, #46 ;
MOV SBUF, A ;
JNB TI, $ ;
CLR TI ;
; desetiny
MOV A, var11 ;
ANL A, #0Fh ;
ADD A, #48 ;
MOV SBUF, A ;
JNB TI, $ ;
CLR TI ;
; Enter
MOV A, #13 ;
MOV SBUF, A ;
JNB TI, $ ;
CLR TI ;
;nulovani pameti
nuly: MOV R0, #30h ;
MOV R2, #60 ;
nuluj: MOV @R0, #0 ;
INC R0 ;
DJNZ R2, nuluj ;
JMP 0 ;
END ;
Kompletní výpis maker a fci pouzitých v TEP_OK.ASM MATH.ASM:
; podpogram na porovnani dvou 32bit cisel, adresy v @R0, @R1
; @R0 => @R1 CY=1
; @R0 < @R1 CY=0
; @R0 = @R1 CY=1 & ACC=0
cmp: INC R0 ;
INC R0 ;
INC R0 ;
INC R1 ;
INC R1 ;
INC R1 ; zacneme od vyssich cislic
MOV A, @R1 ;
CPL A ; dvojkovy doplnek
ADD A, @R0 ; porovnani cislic 3 radu
CPL A ;
JZ mm1 ; ACC=0, rovnost
RET ;
mm1: DEC R0 ;
DEC R1 ;
MOV A, @R1 ;
CPL A ; dvojkovy doplnek
ADD A, @R0 ; porovnani cislic 2 radu
CPL A ;
JZ mm2 ; ACC=0, rovnost
RET ;
mm2: DEC R0 ;
DEC R1 ;
MOV A, @R1 ;
CPL A ; dvojkovy doplnek
ADD A, @R0 ; porovnani cislic 1 radu
CPL A ;
JZ mm3 ; ACC=0, rovnost
RET ;
mm3: DEC R0 ;
DEC R1 ;
MOV A, @R1 ;
CPL A ; dvojkovy doplnek
ADD A, @R0 ; porovnani cislic 0 radu
CPL A ;
JZ nastavC ;
RET ;
nastavC:CLR C ;
CPL C ;
RET ;
; podpogram na posun doleva od CY, pres CY 32bit cisla
; adresa v @R0
rotuj: MOV A, @R0 ;
RLC A ;
MOV @R0, A ;
INC R0 ; 0 rad
MOV A, @R0 ;
RLC A ;
MOV @R0, A ;
INC R0 ; 1 rad
MOV A, @R0 ;
RLC A ;
MOV @R0, A ;
INC R0 ; 2 rad
MOV A, @R0 ;
RLC A ;
MOV @R0, A ; 3 rad
RET ;
; makro na SOUCET dvou 32bit cisel [adresa1]:=[adresa1]+[adresa2]
PLUS MACRO adresa1, adresa2;
NOP
CLR C ;
MOV A, adresa1 ;
ADDC A, adresa2 ;
MOV adresa1, A ; 1 byte
MOV A, adresa1+1 ;
ADDC A, adresa2+1 ;
MOV adresa1+1, A ; 2 byte
MOV A, adresa1+2 ;
ADDC A, adresa2+2 ;
MOV adresa1+2, A ; 3 byte
MOV A, adresa1+3 ;
ADDC A, adresa2+3 ;
MOV adresa1+3, A ; 4 byte
NOP
ENDM ;
; makro na ROZDIL dvou 32bit cisel [adresa1]:=[adresa1]-[adresa2]
MINUS MACRO adresa1, adresa2;
NOP ;
CLR C ;
MOV A, adresa1 ;
SUBB A, adresa2 ;
MOV adresa1, A ; 1 byte
MOV A, adresa1+1 ;
SUBB A, adresa2+1 ;
MOV adresa1+1, A ; 2 byte
MOV A, adresa1+2 ;
SUBB A, adresa2+2 ;
MOV adresa1+2, A ; 3 byte
MOV A, adresa1+3 ;
SUBB A, adresa2+3 ;
MOV adresa1+3, A ; 4 byte
NOP ;
ENDM ;
; makro na SOUCIN 16bit*16bit cisel [adresa3]:=[adresa1]*[adresa2]
; pomocna [adresa4]
SOUCIN MACRO adresa1, adresa2, adresa3, adresa4;
NOP ;
; 1-1
MOV A, adresa1 ;
MOV B, adresa2 ;
MUL AB ;
MOV adresa3, A ;
MOV adresa3+1, B ;
MOV adresa3+2, #0 ;
MOV adresa3+3, #0 ;
; 2-1
MOV A, adresa1+1 ;
MOV B, adresa2 ;
MUL AB ;
MOV adresa4, #0 ;
MOV adresa4+1, A ;
MOV adresa4+2, B ;
MOV adresa4+3, #0 ;
PLUS adresa3, adresa4;
; 1-2
MOV A, adresa1 ;
MOV B, adresa2+1 ;
MUL AB ;
MOV adresa4, #0 ;
MOV adresa4+1, A ;
MOV adresa4+2, B ;
MOV adresa4+3, #0 ;
PLUS adresa3, adresa4;
; 2-2
MOV A, adresa1+1 ;
MOV B, adresa2+1 ;
MUL AB ;
MOV adresa4, #0 ;
MOV adresa4+1, #0 ;
MOV adresa4+2, A ;
MOV adresa4+3, B ;
PLUS adresa3, adresa4;
NOP ;
ENDM ;
; makro na PODIL 32bit a 32bit cisla [adresa3]:=[adresa1] div [adresa2]
; pomocna [adresa4] , pocitadlo v R2
PODIL MACRO adresa1, adresa2, adresa3, adresa4;
NOP ;
MOV R2, #32 ; prednastaveni 32 krat
deldal: MOV R0, #adresa1 ;
CALL rotuj ; ziskani nejvyssiho bitu delence do CY
MOV R0, #adresa4 ;
CALL rotuj ; bit co je vyse v CY do pomocneho delence
MOV R0, #adresa4 ; adresa pomocneho delence
MOV R1, #adresa2 ; adresa delitele
NOP
CALL cmp ; porovnani
NOP
JNC neodcit ; pokud delenec<delitel skok
MOV R0, #adresa3 ; pokud delenec>=delitel,
CALL rotuj ; subpodil CY=1 do vysledku
MINUS adresa4, adresa2; jinak odecist, delenec=delenec-delitel
JMP neodci1
neodcit:MOV R0, #adresa3 ;
CALL rotuj ; subpodil CY=0 do vysledku
neodci1:DJNZ R2, deldal ;
ENDM ;
; makro na prevod bin->BCD adresa1-binvstup adresa2-BCDvystup
;
BINBCD MACRO adresa1, adresa2;
MOV R2, #32 ; pocitadlo
; adresa2=adresa2+adresa2 , nasobeni dvakrat
znobi: MOV A, adresa2 ;
ADD A, adresa2 ;
DA A ; spodni 2 cislice
MOV adresa2, A ;
MOV A, adresa2+1 ;
ADDC A, adresa2+1 ;
DA A ; dalsi 2 cislice
MOV adresa2+1, A ;
MOV A, adresa2+2 ;
ADDC A, adresa2+2 ;
DA A ; dalsi 2 cislice
MOV adresa2+2, A ;
MOV A, adresa2+3 ;
ADDC A, adresa2+3 ;
DA A ; dalsi 2 cislice
MOV adresa2+3, A ;
; ziskani horniho bitu z adresa1
MOV R0, #adresa1 ;
CALL rotuj ;
JNC dabin ; je-li CY=1 prictem 1
MOV A, adresa2 ;
ADD A, #1 ;
DA A ; spodni 2 cislice
MOV adresa2, A ;
MOV A, adresa2+1 ;
ADDC A, #0 ;
DA A ; dalsi 2 cislice
MOV adresa2+1, A ;
MOV A, adresa2+2 ;
ADDC A, #0 ;
DA A ; dalsi 2 cislice
MOV adresa2+2, A ;
MOV A, adresa2+3 ;
ADDC A, #0 ;
DA A ; dalsi 2 cislice
MOV adresa2+3, A ;
dabin: DJNZ R2, znobi ;
ENDM ;
.