Meranie teploty pomocou teplomera DS18S20: Rozdiel medzi revíziami

Z Kiwiki
Skočit na navigaci Skočit na vyhledávání
d
 
(15 medziľahlých úprav od 2 ďalších používateľov nie je zobrazených)
Riadok 1: Riadok 1:
== Reálne meranie teploty s DS18S20 ==
+
[[Kategória:Konfigurovateľné mikroprocesorové systémy]]
 +
[[Kategória:Sériové komunikačné zbernice]]
 +
{{sablona_mikroprocoserove_systemy|Sériové komunikačné zbernice|Synchrónna komunikácia I2C|Meranie teploty pomocou LM92|Hodiny reálneho času|Synchrónna komunikácia SPI|Distribuovaný systém zber dát 1-Wire|Protokol 1-Wire|Meranie teploty pomocou teplomera DS18S20}}
 +
== Základný popis úlohy ==
  
 
Tento systém bude obsahovať dva teplomery DS18S20 a teplota sa bude vypisovať na display. Prepínať medzi jednotlivými teplomermi budeme pomocou tlačítka. Teplota bude na LCD zobrazená v desiatkovej sústave s presnosťou na desatiny stupňa celsia.
 
Tento systém bude obsahovať dva teplomery DS18S20 a teplota sa bude vypisovať na display. Prepínať medzi jednotlivými teplomermi budeme pomocou tlačítka. Teplota bude na LCD zobrazená v desiatkovej sústave s presnosťou na desatiny stupňa celsia.
  
V článku o 1-wire <ref>http://kiwiki.fmtnuni.sk/mediawiki/index.php/Protokol_1-Wire#DS18S20</ref> rozhraní sú uvedené aj základné vlastnosti tohto teplomera, takže sa k tomu už nebudem vyjadrovať, snáď len uvediem zapojenie jednotlivých teplomerov.
+
== Zapojenie teplomerov ==
 +
 
 +
V článku o 1-wire <ref>http://kiwiki.fmtnuni.sk/mediawiki/index.php/Protokol_1-Wire#DS18S20</ref> rozhraní sú uvedené aj základné vlastnosti tohto teplomera, takže sa k tomu už nebudem vyjadrovať, snáď len uvediem zapojenie jednotlivých teplomerov, ktoré možno vidieť na obr. 1. Pull-up rezistor je nutný, nakoľko bez neho to nefunguje ako má.
 +
 
 +
[[Súbor:Zapojenie teplomerov DS18S20.png|center|thumb|400px|Obr. 1. Zapojenie teplomerov]]
 +
 
 +
Na komunikáciu s viacerými teplomermi na zbernici 1-wire potrebujeme poznať adresu každého teplomera. Jednotlivé adresy sú uvedené v tabuľke 1.
 +
 
 +
 
 +
{|border="2" cellspacing="0" cellpadding="4" width="600" align="center"
 +
 
 +
|-
 +
|align = "center"|Názov teplomera
 +
|align = "center"|Adresa teplomera
 +
 
 +
|-
 +
|align = "center"|Vonkajší teplomer
 +
|align = "center"|105FD4CD010800C9
 +
 
 +
|-
 +
|align = "center"|Vnútorný teplomer
 +
|align = "center"|1059F7CD010800CD
 +
 
 +
|+align="bottom" |Tab. 1 Názov a adresa teplomerov
 +
|}
 +
 
 +
 
 +
== Rozhranie 1-wire v PSoC ==
 +
 
 +
V samotnom dizajneri sa nachádza hardvérový blok pre podporu tejto zbernice. My však budeme používať softvérový blok, ktorý sa dá stiahnuť na nasledovnej adrese:
 +
 
 +
http://www.psocdeveloper.com/tools/misc-dev-tools.html
 +
 
 +
Potom ho doinštalujeme podľa návodu, ktorý sa nachádza tu:
 +
 
 +
http://www.psocdeveloper.com/forums/viewtopic.php?p=29&sid=2d053ae959fd795eaf997f498bfe3de5&view=next
 +
 
 +
Po umiestnení tohto bloku do projektu musíme vykonať zopár nastavení. Názorne sú ukázané na obr. 2.
 +
 
 +
[[Súbor:Nastavenia_1-wireSW.jpg|center|thumb|400px|Obr. 2. Nastavenia 1-wireSW]]
 +
 
 +
 
 +
'''LCD blok'''
 +
 
 +
Pre komunikáciu s LCD musíme použiť blok LCD. Jeho nastavenie je jednoduché, nastavíme len, ktorý port sa na komunikáciu bude používať a či chceme povoliť alebo zakázať bar grafy.
 +
 
 +
 
 +
== Samotný program teplomera ==
 +
 
 +
Program je napísaný v jazyku C, chcel by som pridať aj kód v assembleri, ale zatiaľ aspoň takto.
 +
 
 +
<source lang="C">
 +
#include <m8c.h>     
 +
#include "PSoCAPI.h"
 +
 
 +
// funkcia PREVOD služi na výpis teploty v desiatkovej sústave na LCD
 +
// a zároveň počíta vyššiu presnosť nameranej teploty
 +
 
 +
void PREVOD(BYTE vstup, BYTE znamienko, BYTE count_remain) 
 +
{
 +
long a, b=0, c, i, d;
 +
char vystup[]="00.0", cisla[]="0123456789";
 +
float teplota, remain, presnost;
 +
remain=count_remain;
 +
teplota=vstup;
 +
teplota=(teplota/2.0)-0.25;
 +
presnost=(16.0-remain)/16.0;
 +
teplota=teplota+presnost;
 +
if(znamienko==0xFF)
 +
{
 +
teplota=256-vstup;
 +
teplota=(teplota/2.0)-0.25;
 +
teplota=teplota+presnost;
 +
}
 +
teplota=teplota*10.0;
 +
for(i=100;i>=1;i=i/10)
 +
 +
a=teplota/i;
 +
c=a-b*10;
 +
b=a;
 +
if(i==100) d=0;
 +
if(i==10) d=1;
 +
if(i==1) d=3;
 +
 +
 +
if(c==0)vystup[d]=cisla[0];
 +
if(c==1)vystup[d]=cisla[1];
 +
if(c==2)vystup[d]=cisla[2];
 +
if(c==3)vystup[d]=cisla[3];
 +
if(c==4)vystup[d]=cisla[4];
 +
if(c==5)vystup[d]=cisla[5];
 +
if(c==6)vystup[d]=cisla[6];
 +
if(c==7)vystup[d]=cisla[7];
 +
if(c==8)vystup[d]=cisla[8];
 +
if(c==9)vystup[d]=cisla[9];
 +
}
 +
 
 +
  LCD_Position(1,3);
 +
  LCD_PrString(vystup);
 +
 
 +
}
 +
// začiatok hlavnej funkcie
 +
 
 +
void main(void)
 +
{
 +
BYTE vystup, znamienko,count_remain,byte;
 +
int p=1;
 +
char eteplota[]="Teplota vonku:", plus[]="+", minus[]="-";
 +
char prazdny[]="                ", iteplota[]="Teplota vnutri";
 +
M8C_EnableGInt ;
 +
OW_Start();
 +
LCD_Start();
 +
LCD_Init();
 +
while(1)
 +
{                       //na pin P1.0 privedieme cez tlačitko 5V
 +
PRT1DR=0;            //na port 1 sa zapíše 0
 +
if(PRT1DR==1) p++;    //ak sa na porte 1 objaví 1, inkrementuje sa p
 +
if (p>2) p=1;        //pre správnu funkčnosť musí byť pin P1.0 nastavený na režim Hi_Z digital
 +
OW_Reset();
 +
if(p==1)              //ak bude p=1, komunikácia bude prebiehať s vonkajším teplomerom
 +
{
 +
OW_WriteByte(0x55);  //príkaz Match ROM
 +
OW_WriteByte(0x10);  //zadanie adresy teplomera
 +
OW_WriteByte(0x5F);
 +
OW_WriteByte(0xD4);
 +
OW_WriteByte(0xCD);
 +
OW_WriteByte(0x01);
 +
OW_WriteByte(0x08);
 +
OW_WriteByte(0x00);
 +
OW_WriteByte(0xC9);
 +
OW_WriteByte(0x44);  //príkaz pre konverziu teploty
 +
OW_Delay10mTimes(75); //čakanie 750us
 +
OW_Reset();          //reset rozhrania
 +
OW_WriteByte(0x55);  //Match ROM
 +
OW_WriteByte(0x10);  //zaddanie adresy teplomera
 +
OW_WriteByte(0x5F);
 +
OW_WriteByte(0xD4);
 +
OW_WriteByte(0xCD);
 +
OW_WriteByte(0x01);
 +
OW_WriteByte(0x08);
 +
OW_WriteByte(0x00);
 +
OW_WriteByte(0xC9);
 +
OW_WriteByte(0xBE);  //príkaz pre čítanie Scratch Pad
 +
vystup = OW_ReadByte(); // čítanie jednotlivých bytov (teplota)
 +
znamienko = OW_ReadByte(); //(znamienko)
 +
byte = OW_ReadByte();
 +
byte = OW_ReadByte();
 +
byte = OW_ReadByte();
 +
byte = OW_ReadByte();
 +
count_remain = OW_ReadByte(); //(byte pre zvýšenie presnosti teplomera)
 +
LCD_Position(0,0);    //nastavenie kurzora na LCD na pozíciu 0,0
 +
LCD_PrString(prazdny); //vytlacenie prázdneho reťazca na LCD
 +
LCD_Position(0,0);    //nastavenie kurzora na LCD na pozíciu 0,0
 +
LCD_PrString(eteplota);//vytlacenie retazca eteplota na LCD
 +
LCD_Position(1,1);    //nastavenie kurzora na LCD na pozíciu 1,1
 +
if(znamienko==0x00)    //ak bude znamienko=0, vytlaci sa na LCD +
 +
LCD_PrString(plus);
 +
else
 +
LCD_PrString(minus);  //inak sa vytlaci na LCD -
 +
PREVOD(vystup, znamienko, count_remain); //nacitane 3 byty sa odovzdajú funkcií PREVOD, ktorá vyslednú teplotu vypíše na LCD
 +
}
 +
if(p==2)              //ak p=2, komunikácia bude prebiehať s vnútorným teplomerom
 +
{                      //postup je presne taký ako aj pri predchádzajúcom teplomery
 +
OW_WriteByte(0x55);
 +
OW_WriteByte(0x10);    //zadanie adresy teplomera
 +
OW_WriteByte(0x59);
 +
OW_WriteByte(0xF7);
 +
OW_WriteByte(0xCD);
 +
OW_WriteByte(0x01);
 +
OW_WriteByte(0x08);
 +
OW_WriteByte(0x00);
 +
OW_WriteByte(0xCD);
 +
OW_WriteByte(0x44);    // Start Conversion
 +
OW_Delay10mTimes(75);
 +
OW_Reset();
 +
OW_WriteByte(0x55);
 +
OW_WriteByte(0x10);
 +
OW_WriteByte(0x59);
 +
OW_WriteByte(0xF7);
 +
OW_WriteByte(0xCD);
 +
OW_WriteByte(0x01);
 +
OW_WriteByte(0x08);
 +
OW_WriteByte(0x00);
 +
OW_WriteByte(0xCD);
 +
OW_WriteByte(0xBE);    // Read Scratch Pad
 +
vystup = OW_ReadByte();
 +
znamienko = OW_ReadByte();
 +
byte = OW_ReadByte();
 +
byte = OW_ReadByte();
 +
byte = OW_ReadByte();
 +
byte = OW_ReadByte();
 +
count_remain = OW_ReadByte();
 +
LCD_Position(0,0);
 +
LCD_PrString(iteplota);
 +
LCD_Position(1,1);
 +
if(znamienko==0x00)
 +
LCD_PrString(plus);
 +
else
 +
LCD_PrString(minus);
 +
PREVOD(vystup, znamienko, count_remain);
 +
}
 +
 
 +
}
 +
}
 +
 
 +
</source>
 +
 
 +
Teraz uvediem kód v assembleri. Tento program je podstatne dlhší a nefunguje rovnako ako vyššie uvedený program v jazyku C. Z jednotlivých teplomerov sú len vyčítané byty, ktoré sa vypíšu na LCD a aj na rozhranie RS232. Medzi jednotlivými teplomermi prepíname pomocou sériového rozhrania. Ak stlačíme i, zobrazia sa údaje z vnútorného teplomera, ak stlačíme o, zobrazia sa údaje z vonkajšieho teplomera.
 +
Na sériovom rozhrané sú údaje vypísané v napríklad nasledovnom tvare:
 +
 
 +
00      (znamienko)
 +
 
 +
3A      (teplota)
 +
 
 +
0D      (byte count_remain pre zvýšenie presnosti nameranej teploty)
 +
 
 +
Na LCD to vyzerá nasledovne:
 +
 
 +
Teplota vonku:
 +
 
 +
+  3A  0D
 +
 
 +
Samozrejme, údaje sú vypisované v hexadecimálnom tvare.
 +
 
 +
<source lang="asm">
 +
include "m8c.inc"      ; part specific constants and macros
 +
include "memory.inc"    ; Constants & macros for SMM/LMM and Compiler
 +
include "PSoCAPI.inc"  ; PSoC API definitions for all User Modules
 +
 
 +
export _main
 +
 
 +
area bss(ram) ;premenne
 +
teplota: blk 1
 +
znamienko: blk 1
 +
presnost: blk 1
 +
 
 +
area lit ;definovanie retazcov
 +
out: DS "Teplota vonku"
 +
DB 0x00
 +
in:  DS "Teplota vnutri"
 +
DB 0x00
 +
plus: DS "+"
 +
DB 0x00
 +
minus: DS "-"
 +
DB 0x00
 +
text: DS "Komunikacia OK"
 +
DB 0x00
 +
 +
area text
 +
 
 +
;--------------------------------zaciatok hlavnej funkcie--------------------------------------------
 +
_main:
 +
M8C_EnableGInt
 +
call LCD_Start
 +
mov  A, UART_PARITY_NONE 
 +
lcall  UART_Start
 +
WaitForData:         ; cakanie na povel
 +
    lcall  UART_bReadRxStatus   
 +
    and  A, UART_RX_COMPLETE   
 +
    jz    WaitForData
 +
 +
    lcall  UART_bReadRxData                    ; citanie dat   
 +
    lcall  UART_SendData 
 +
 +
cmp A,'q' ; kontrola komunikacie
 +
jz state_q
 +
 +
cmp A,'o' ; vycitanie bytov z DS18S20(vonkajsi teplomer)
 +
jz state_w
 +
 +
cmp A,'i' ; vycitanie bytov z DS18S20(vnutorny teplomer)
 +
jz state_s
 +
 
 +
;--------------------------------------------------------------------------------------------
 +
state_w:
 +
lcall OW_Start
 +
lcall OW_Reset
 +
mov  A,55h                            ;skip ROM 
 +
lcall  OW_WriteByte
 +
 
 +
mov  A,10h        ;zadanie adresy teplomera   
 +
lcall  OW_WriteByte
 +
mov  A,5Fh           
 +
lcall  OW_WriteByte
 +
mov  A,D4h           
 +
lcall  OW_WriteByte
 +
mov  A,CDh           
 +
lcall  OW_WriteByte
 +
mov  A,01h           
 +
lcall  OW_WriteByte
 +
mov  A,08h           
 +
lcall  OW_WriteByte
 +
mov  A,00h           
 +
lcall  OW_WriteByte
 +
mov  A,C9h           
 +
lcall  OW_WriteByte
 +
mov  A,44h                ;start konverzie teploty 
 +
 
 +
lcall  OW_WriteByte
 +
mov  A,4Bh                  ;oneskorenie 750ms
 +
 
 +
lcall  OW_Delay10mTimes           
 +
 
 +
lcall OW_Reset
 +
 
 +
mov  A,55h           
 +
lcall  OW_WriteByte
 +
 
 +
mov  A,10h        ;zadanie adresy teplomera   
 +
lcall  OW_WriteByte
 +
mov  A,5Fh           
 +
lcall  OW_WriteByte
 +
mov  A,D4h           
 +
lcall  OW_WriteByte
 +
mov  A,CDh           
 +
lcall  OW_WriteByte
 +
mov  A,01h           
 +
lcall  OW_WriteByte
 +
mov  A,08h           
 +
lcall  OW_WriteByte
 +
mov  A,00h           
 +
lcall  OW_WriteByte
 +
mov  A,C9h           
 +
lcall  OW_WriteByte
 +
 
 +
mov  A,BEh                ;start konverzie teploty 
 +
lcall  OW_WriteByte
 +
 
 +
lcall  OW_ReadByte
 +
mov [teplota], A
 +
lcall  OW_ReadByte
 +
mov [znamienko], A
 +
lcall  OW_ReadByte
 +
lcall  OW_ReadByte
 +
lcall  OW_ReadByte
 +
lcall  OW_ReadByte
 +
lcall  OW_ReadByte
 +
mov [presnost], A
 +
lcall UART_PutCRLF
 +
mov A,[znamienko]
 +
lcall UART_PutSHexByte
 +
lcall UART_PutCRLF
 +
mov A,[teplota]
 +
lcall UART_PutSHexByte
 +
lcall UART_PutCRLF
 +
mov A,[presnost]
 +
lcall UART_PutSHexByte
 +
 
 +
mov A,00h ; riadok
 +
mov X,00h ; bunka
 +
lcall LCD_Position
 +
mov A, >out
 +
mov X, <out
 +
call LCD_PrCString
 +
cmp [znamienko], 00h
 +
jz tlac_plus
 +
jnz tlac_minus
 +
tlac_plus:
 +
mov A,01h ; riadok
 +
mov X,00h ; bunka
 +
lcall LCD_Position
 +
mov A, >plus
 +
mov X, <plus
 +
call LCD_PrCString
 +
jmp Pokracuj
 +
tlac_minus:
 +
mov A,01h ; riadok
 +
mov X,00h ; bunka
 +
lcall LCD_Position
 +
mov A, >minus
 +
mov X, <minus
 +
call LCD_PrCString
 +
jmp Pokracuj
 +
Pokracuj:
 +
mov A,01h ; riadok
 +
mov X,03h ; bunka
 +
lcall LCD_Position
 +
mov A, [teplota] ; nacita byt pre tlac
 +
lcall LCD_PrHexByte
 +
mov A,01h ; riadok
 +
mov X,07h ; bunka
 +
lcall LCD_Position
 +
mov A, [presnost] ; nacita byt pre tlac
 +
lcall LCD_PrHexByte
 +
jmp WaitForData
 +
;------------------------------------------------------------------------------------
 +
state_s:
 +
lcall OW_Start
 +
lcall OW_Reset
 +
mov  A,55h           
 +
lcall  OW_WriteByte
 +
 
 +
mov  A,10h        ;zadanie adresy teplomera   
 +
lcall  OW_WriteByte
 +
mov  A,59h           
 +
lcall  OW_WriteByte
 +
mov  A,F7h           
 +
lcall  OW_WriteByte
 +
mov  A,CDh           
 +
lcall  OW_WriteByte
 +
mov  A,01h           
 +
lcall  OW_WriteByte
 +
mov  A,08h           
 +
lcall  OW_WriteByte
 +
mov  A,00h           
 +
lcall  OW_WriteByte
 +
mov  A,CDh           
 +
lcall  OW_WriteByte
 +
mov  A,44h          ;start konverzie teploty 
 +
 
 +
lcall  OW_WriteByte
 +
mov  A,4Bh            ; Load delay time (example 3 would be 30mSec).
 +
 
 +
lcall  OW_Delay10mTimes      ; Call function
 +
 
 +
lcall OW_Reset
 +
 
 +
mov  A,55h           
 +
lcall  OW_WriteByte
 +
 
 +
mov  A,10h        ;zadanie adresy teplomera   
 +
lcall  OW_WriteByte
 +
mov  A,59h           
 +
lcall  OW_WriteByte
 +
mov  A,F7h           
 +
lcall  OW_WriteByte
 +
mov  A,CDh           
 +
lcall  OW_WriteByte
 +
mov  A,01h           
 +
lcall  OW_WriteByte
 +
mov  A,08h           
 +
lcall  OW_WriteByte
 +
mov  A,00h           
 +
lcall  OW_WriteByte
 +
mov  A,CDh           
 +
lcall  OW_WriteByte
 +
 
 +
mov  A,BEh          ;start konverzie teploty 
 +
lcall  OW_WriteByte
 +
 
 +
lcall  OW_ReadByte
 +
mov [teplota], A
 +
lcall  OW_ReadByte
 +
mov [znamienko], A
 +
lcall  OW_ReadByte
 +
lcall  OW_ReadByte
 +
lcall  OW_ReadByte
 +
lcall  OW_ReadByte
 +
lcall  OW_ReadByte
 +
mov [presnost], A
 +
lcall UART_PutCRLF
 +
mov A,[znamienko]
 +
lcall UART_PutSHexByte
 +
lcall UART_PutCRLF
 +
mov A,[teplota]
 +
lcall UART_PutSHexByte
 +
lcall UART_PutCRLF
 +
mov A,[presnost]
 +
lcall UART_PutSHexByte
 +
 
 +
mov A,00h ; riadok
 +
mov X,00h ; bunka
 +
lcall LCD_Position
 +
mov A, >in
 +
mov X, <in
 +
call LCD_PrCString
 +
cmp [znamienko], 00h
 +
jz tlac_plus2
 +
jnz tlac_minus2
 +
tlac_plus2:
 +
mov A,01h ; riadok
 +
mov X,00h ; bunka
 +
lcall LCD_Position
 +
mov A, >plus
 +
mov X, <plus
 +
call LCD_PrCString
 +
jmp Pokracuj2
 +
tlac_minus2:
 +
mov A,01h ; riadok
 +
mov X,00h ; bunka
 +
lcall LCD_Position
 +
mov A, >minus
 +
mov X, <minus
 +
call LCD_PrCString
 +
jmp Pokracuj2
 +
Pokracuj2:
 +
mov A,01h ; riadok
 +
mov X,03h ; bunka
 +
lcall LCD_Position
 +
mov A, [teplota] ; nacita byt pre tlac
 +
lcall LCD_PrHexByte
 +
mov A,01h ; riadok
 +
mov X,07h ; bunka
 +
lcall LCD_Position
 +
mov A, [presnost] ; nacita byt pre tlac
 +
lcall LCD_PrHexByte
 +
jmp WaitForData
 +
;------------------------------------------------------------------------------------
 +
state_q:
 +
lcall UART_PutCRLF
 +
mov A, >text
 +
mov X, <text
 +
lcall UART_CPutString
 +
lcall UART_PutCRLF
 +
jmp  WaitForData
 +
 
 +
</source>
  
 
== Odkazy a referencie ==
 
== Odkazy a referencie ==
 
<references/>
 
<references/>

Aktuálna revízia z 10:02, 21. marec 2013

Predmet

Konfigurovateľné mikroprocesorové systémy
Tématická časť:
Sériové komunikačné zbernice

Základný popis úlohy

Tento systém bude obsahovať dva teplomery DS18S20 a teplota sa bude vypisovať na display. Prepínať medzi jednotlivými teplomermi budeme pomocou tlačítka. Teplota bude na LCD zobrazená v desiatkovej sústave s presnosťou na desatiny stupňa celsia.

Zapojenie teplomerov

V článku o 1-wire [1] rozhraní sú uvedené aj základné vlastnosti tohto teplomera, takže sa k tomu už nebudem vyjadrovať, snáď len uvediem zapojenie jednotlivých teplomerov, ktoré možno vidieť na obr. 1. Pull-up rezistor je nutný, nakoľko bez neho to nefunguje ako má.

Obr. 1. Zapojenie teplomerov

Na komunikáciu s viacerými teplomermi na zbernici 1-wire potrebujeme poznať adresu každého teplomera. Jednotlivé adresy sú uvedené v tabuľke 1.


Názov teplomera Adresa teplomera
Vonkajší teplomer 105FD4CD010800C9
Vnútorný teplomer 1059F7CD010800CD
Tab. 1 Názov a adresa teplomerov


Rozhranie 1-wire v PSoC

V samotnom dizajneri sa nachádza hardvérový blok pre podporu tejto zbernice. My však budeme používať softvérový blok, ktorý sa dá stiahnuť na nasledovnej adrese:

http://www.psocdeveloper.com/tools/misc-dev-tools.html

Potom ho doinštalujeme podľa návodu, ktorý sa nachádza tu:

http://www.psocdeveloper.com/forums/viewtopic.php?p=29&sid=2d053ae959fd795eaf997f498bfe3de5&view=next

Po umiestnení tohto bloku do projektu musíme vykonať zopár nastavení. Názorne sú ukázané na obr. 2.

Obr. 2. Nastavenia 1-wireSW


LCD blok

Pre komunikáciu s LCD musíme použiť blok LCD. Jeho nastavenie je jednoduché, nastavíme len, ktorý port sa na komunikáciu bude používať a či chceme povoliť alebo zakázať bar grafy.


Samotný program teplomera

Program je napísaný v jazyku C, chcel by som pridať aj kód v assembleri, ale zatiaľ aspoň takto.

#include <m8c.h>       
#include "PSoCAPI.h"

// funkcia PREVOD služi na výpis teploty v desiatkovej sústave na LCD 
// a zároveň počíta vyššiu presnosť nameranej teploty

void PREVOD(BYTE vstup, BYTE znamienko, BYTE count_remain)  
{
 long a, b=0, c, i, d;
 char vystup[]="00.0", cisla[]="0123456789"; 
 float teplota, remain, presnost;
 remain=count_remain;
 teplota=vstup;
 teplota=(teplota/2.0)-0.25;
 presnost=(16.0-remain)/16.0;
 teplota=teplota+presnost;
 if(znamienko==0xFF)
 {
 teplota=256-vstup;
 teplota=(teplota/2.0)-0.25;
 teplota=teplota+presnost;
 }
 teplota=teplota*10.0;
 for(i=100;i>=1;i=i/10)
	 {  
	 	a=teplota/i;
		c=a-b*10;
		b=a;
		if(i==100) d=0;
		if(i==10) d=1;
		if(i==1) d=3;
		
		
		if(c==0)vystup[d]=cisla[0];
		if(c==1)vystup[d]=cisla[1];
		if(c==2)vystup[d]=cisla[2];
		if(c==3)vystup[d]=cisla[3];
		if(c==4)vystup[d]=cisla[4];
		if(c==5)vystup[d]=cisla[5];
		if(c==6)vystup[d]=cisla[6];
		if(c==7)vystup[d]=cisla[7];
		if(c==8)vystup[d]=cisla[8];
		if(c==9)vystup[d]=cisla[9];
	 }

   LCD_Position(1,3);
   LCD_PrString(vystup);
  
}
// začiatok hlavnej funkcie

void main(void)
{	
	BYTE vystup, znamienko,count_remain,byte;
	int p=1;
	char eteplota[]="Teplota vonku:", plus[]="+", minus[]="-";
	char prazdny[]="                ", iteplota[]="Teplota vnutri";
	M8C_EnableGInt ;
	OW_Start();
	LCD_Start();
	LCD_Init();
	while(1)
	{	                      //na pin P1.0 privedieme cez tlačitko 5V
		PRT1DR=0;             //na port 1 sa zapíše 0
		if(PRT1DR==1) p++;    //ak sa na porte 1 objaví 1, inkrementuje sa p 
		if (p>2) p=1;         //pre správnu funkčnosť musí byť pin P1.0 nastavený na režim Hi_Z digital
		OW_Reset();
		if(p==1)              //ak bude p=1, komunikácia bude prebiehať s vonkajším teplomerom
		{
		OW_WriteByte(0x55);   //príkaz Match ROM
		OW_WriteByte(0x10);   //zadanie adresy teplomera
		OW_WriteByte(0x5F);
		OW_WriteByte(0xD4);
		OW_WriteByte(0xCD);
		OW_WriteByte(0x01);
		OW_WriteByte(0x08);
		OW_WriteByte(0x00);
		OW_WriteByte(0xC9);
		OW_WriteByte(0x44);   //príkaz pre konverziu teploty
		OW_Delay10mTimes(75); //čakanie 750us
		OW_Reset();           //reset rozhrania
		OW_WriteByte(0x55);   //Match ROM
		OW_WriteByte(0x10);   //zaddanie adresy teplomera
		OW_WriteByte(0x5F);
		OW_WriteByte(0xD4);
		OW_WriteByte(0xCD);
		OW_WriteByte(0x01);
		OW_WriteByte(0x08);
		OW_WriteByte(0x00);
		OW_WriteByte(0xC9);
		OW_WriteByte(0xBE);   //príkaz pre čítanie Scratch Pad
		vystup = OW_ReadByte(); // čítanie jednotlivých bytov (teplota)
		znamienko = OW_ReadByte(); //(znamienko)
		byte = OW_ReadByte();
		byte = OW_ReadByte();
		byte = OW_ReadByte();
		byte = OW_ReadByte();
		count_remain = OW_ReadByte(); //(byte pre zvýšenie presnosti teplomera)
		LCD_Position(0,0);     //nastavenie kurzora na LCD na pozíciu 0,0
		LCD_PrString(prazdny); //vytlacenie prázdneho reťazca na LCD
		LCD_Position(0,0);     //nastavenie kurzora na LCD na pozíciu 0,0
		LCD_PrString(eteplota);//vytlacenie retazca eteplota na LCD
		LCD_Position(1,1);     //nastavenie kurzora na LCD na pozíciu 1,1
		if(znamienko==0x00)    //ak bude znamienko=0, vytlaci sa na LCD +
		LCD_PrString(plus);
		else
		LCD_PrString(minus);   //inak sa vytlaci na LCD -
		PREVOD(vystup, znamienko, count_remain); //nacitane 3 byty sa odovzdajú funkcií PREVOD, ktorá vyslednú teplotu vypíše na LCD
		}
		if(p==2)               //ak p=2, komunikácia bude prebiehať s vnútorným teplomerom
		{                      //postup je presne taký ako aj pri predchádzajúcom teplomery
		OW_WriteByte(0x55);
		OW_WriteByte(0x10);    //zadanie adresy teplomera
		OW_WriteByte(0x59);
		OW_WriteByte(0xF7);
		OW_WriteByte(0xCD);
		OW_WriteByte(0x01);
		OW_WriteByte(0x08);
		OW_WriteByte(0x00);
		OW_WriteByte(0xCD);
		OW_WriteByte(0x44);    // Start Conversion
		OW_Delay10mTimes(75);
		OW_Reset();
		OW_WriteByte(0x55);
		OW_WriteByte(0x10);
		OW_WriteByte(0x59);
		OW_WriteByte(0xF7);
		OW_WriteByte(0xCD);
		OW_WriteByte(0x01);
		OW_WriteByte(0x08);
		OW_WriteByte(0x00);
		OW_WriteByte(0xCD);
		OW_WriteByte(0xBE);    // Read Scratch Pad
		vystup = OW_ReadByte();
		znamienko = OW_ReadByte();
		byte = OW_ReadByte();
		byte = OW_ReadByte();
		byte = OW_ReadByte();
		byte = OW_ReadByte();
		count_remain = OW_ReadByte();
		LCD_Position(0,0);
		LCD_PrString(iteplota);
		LCD_Position(1,1);
		if(znamienko==0x00)
		LCD_PrString(plus);
		else 
		LCD_PrString(minus);
		PREVOD(vystup, znamienko, count_remain);
		}

	} 
}

Teraz uvediem kód v assembleri. Tento program je podstatne dlhší a nefunguje rovnako ako vyššie uvedený program v jazyku C. Z jednotlivých teplomerov sú len vyčítané byty, ktoré sa vypíšu na LCD a aj na rozhranie RS232. Medzi jednotlivými teplomermi prepíname pomocou sériového rozhrania. Ak stlačíme i, zobrazia sa údaje z vnútorného teplomera, ak stlačíme o, zobrazia sa údaje z vonkajšieho teplomera. Na sériovom rozhrané sú údaje vypísané v napríklad nasledovnom tvare:

00 (znamienko)

3A (teplota)

0D (byte count_remain pre zvýšenie presnosti nameranej teploty)

Na LCD to vyzerá nasledovne:

Teplota vonku:

+ 3A 0D

Samozrejme, údaje sú vypisované v hexadecimálnom tvare.

include "m8c.inc"       	; part specific constants and macros
include "memory.inc"    	; Constants & macros for SMM/LMM and Compiler
include "PSoCAPI.inc"   	; PSoC API definitions for all User Modules

export _main

area bss(ram)				;premenne
	teplota:	blk 1
	znamienko:	blk 1
	presnost:	blk 1

area lit					;definovanie retazcov
	out: 		DS "Teplota vonku"
				DB 0x00
	in:  		DS "Teplota vnutri"
				DB 0x00
	plus:		DS "+"
				DB 0x00
	minus:		DS "-"
				DB 0x00
	text:		DS "Komunikacia OK"
				DB 0x00
	
area text

;--------------------------------zaciatok hlavnej funkcie--------------------------------------------
_main:
M8C_EnableGInt
call LCD_Start
mov   A, UART_PARITY_NONE  
lcall  UART_Start
WaitForData: 				        ; cakanie na povel 
    lcall  UART_bReadRxStatus    
    and   A, UART_RX_COMPLETE    
    jz    WaitForData
	
    lcall  UART_bReadRxData                     ; citanie dat    
    lcall  UART_SendData  
		
	cmp A,'q'				; kontrola komunikacie
 	jz state_q
	
	cmp A,'o'				; vycitanie bytov z DS18S20(vonkajsi teplomer)
 	jz state_w
	
	cmp A,'i'				; vycitanie bytov z DS18S20(vnutorny teplomer)
 	jz state_s

;--------------------------------------------------------------------------------------------	
state_w:
lcall OW_Start 
lcall OW_Reset 
mov   A,55h                             ;skip ROM  
lcall  OW_WriteByte

mov   A,10h        			;zadanie adresy teplomera     
lcall  OW_WriteByte
mov   A,5Fh             
lcall  OW_WriteByte
mov   A,D4h             
lcall  OW_WriteByte
mov   A,CDh             
lcall  OW_WriteByte
mov   A,01h             
lcall  OW_WriteByte
mov   A,08h             
lcall  OW_WriteByte
mov   A,00h             
lcall  OW_WriteByte
mov   A,C9h             
lcall  OW_WriteByte
mov   A,44h           		       ;start konverzie teploty  

lcall  OW_WriteByte
mov   A,4Bh            		       ;oneskorenie 750ms 

lcall  OW_Delay10mTimes            

lcall OW_Reset

mov   A,55h             
lcall  OW_WriteByte

mov   A,10h        			;zadanie adresy teplomera     
lcall  OW_WriteByte
mov   A,5Fh             
lcall  OW_WriteByte
mov   A,D4h             
lcall  OW_WriteByte
mov   A,CDh             
lcall  OW_WriteByte
mov   A,01h             
lcall  OW_WriteByte
mov   A,08h             
lcall  OW_WriteByte
mov   A,00h             
lcall  OW_WriteByte
mov   A,C9h             
lcall  OW_WriteByte

mov   A,BEh           		       ;start konverzie teploty  
lcall  OW_WriteByte

lcall  OW_ReadByte
mov [teplota], A
lcall  OW_ReadByte
mov [znamienko], A
lcall  OW_ReadByte
lcall  OW_ReadByte
lcall  OW_ReadByte
lcall  OW_ReadByte
lcall  OW_ReadByte
mov [presnost], A
lcall UART_PutCRLF
mov A,[znamienko] 
lcall UART_PutSHexByte
lcall UART_PutCRLF
mov A,[teplota] 
lcall UART_PutSHexByte
lcall UART_PutCRLF
mov A,[presnost] 
lcall UART_PutSHexByte

mov A,00h 					; riadok
mov X,00h					; bunka
lcall LCD_Position
mov A, >out
mov X, <out
call LCD_PrCString
cmp [znamienko], 00h
jz tlac_plus
jnz tlac_minus
tlac_plus:
mov A,01h 					; riadok
mov X,00h					; bunka
lcall LCD_Position
mov A, >plus
mov X, <plus
call LCD_PrCString
jmp Pokracuj
tlac_minus:
mov A,01h 					; riadok
mov X,00h					; bunka
lcall LCD_Position
mov A, >minus
mov X, <minus
call LCD_PrCString
jmp Pokracuj
Pokracuj:
mov A,01h 					; riadok
mov X,03h					; bunka
lcall LCD_Position
mov A, [teplota] 			; nacita byt pre tlac
lcall LCD_PrHexByte 
mov A,01h 					; riadok
mov X,07h					; bunka
lcall LCD_Position
mov A, [presnost] 			; nacita byt pre tlac
lcall LCD_PrHexByte 
jmp WaitForData
;------------------------------------------------------------------------------------
state_s:
lcall OW_Start 
lcall OW_Reset 
mov   A,55h             
lcall  OW_WriteByte

mov   A,10h        			;zadanie adresy teplomera     
lcall  OW_WriteByte
mov   A,59h             
lcall  OW_WriteByte
mov   A,F7h             
lcall  OW_WriteByte
mov   A,CDh             
lcall  OW_WriteByte
mov   A,01h             
lcall  OW_WriteByte
mov   A,08h             
lcall  OW_WriteByte
mov   A,00h             
lcall  OW_WriteByte
mov   A,CDh             
lcall  OW_WriteByte
mov   A,44h           		;start konverzie teploty  

lcall  OW_WriteByte
mov   A,4Bh            		; Load delay time (example 3 would be 30mSec).

lcall  OW_Delay10mTimes      ; Call function

lcall OW_Reset

mov   A,55h             
lcall  OW_WriteByte

mov   A,10h        			;zadanie adresy teplomera     
lcall  OW_WriteByte
mov   A,59h             
lcall  OW_WriteByte
mov   A,F7h             
lcall  OW_WriteByte
mov   A,CDh             
lcall  OW_WriteByte
mov   A,01h             
lcall  OW_WriteByte
mov   A,08h             
lcall  OW_WriteByte
mov   A,00h             
lcall  OW_WriteByte
mov   A,CDh             
lcall  OW_WriteByte

mov   A,BEh           		;start konverzie teploty  
lcall  OW_WriteByte

lcall  OW_ReadByte
mov [teplota], A
lcall  OW_ReadByte
mov [znamienko], A
lcall  OW_ReadByte
lcall  OW_ReadByte
lcall  OW_ReadByte
lcall  OW_ReadByte
lcall  OW_ReadByte
mov [presnost], A
lcall UART_PutCRLF
mov A,[znamienko] 
lcall UART_PutSHexByte
lcall UART_PutCRLF
mov A,[teplota] 
lcall UART_PutSHexByte
lcall UART_PutCRLF
mov A,[presnost] 
lcall UART_PutSHexByte

mov A,00h 					; riadok
mov X,00h					; bunka
lcall LCD_Position
mov A, >in
mov X, <in
call LCD_PrCString
cmp [znamienko], 00h
jz tlac_plus2
jnz tlac_minus2
tlac_plus2:
mov A,01h 					; riadok
mov X,00h					; bunka
lcall LCD_Position
mov A, >plus
mov X, <plus
call LCD_PrCString
jmp Pokracuj2
tlac_minus2:
mov A,01h 					; riadok
mov X,00h					; bunka
lcall LCD_Position
mov A, >minus
mov X, <minus
call LCD_PrCString
jmp Pokracuj2
Pokracuj2:
mov A,01h 					; riadok
mov X,03h					; bunka
lcall LCD_Position
mov A, [teplota] 			; nacita byt pre tlac
lcall LCD_PrHexByte 
mov A,01h 					; riadok
mov X,07h					; bunka
lcall LCD_Position
mov A, [presnost] 			; nacita byt pre tlac
lcall LCD_PrHexByte 
jmp WaitForData
;------------------------------------------------------------------------------------
state_q:
lcall UART_PutCRLF
mov A, >text
mov X, <text
lcall UART_CPutString
lcall UART_PutCRLF
jmp   WaitForData

Odkazy a referencie