Meranie teploty pomocou teplomera DS18S20: Rozdiel medzi revíziami
Riadok 54: | Riadok 54: | ||
Program je napísaný v jazyku C, chcel by som pridať aj kód v assembleri, ale zatiaľ aspoň takto. | 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" | ||
+ | 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); | ||
+ | |||
+ | } | ||
+ | |||
+ | 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) | ||
+ | { | ||
+ | PRT1DR=0; | ||
+ | if(PRT1DR==1) p++; | ||
+ | if (p>2) p=1; | ||
+ | OW_Reset(); | ||
+ | if(p==1) | ||
+ | { | ||
+ | OW_WriteByte(0x55); | ||
+ | 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); // Start Conversion | ||
+ | OW_Delay10mTimes(75); | ||
+ | OW_Reset(); | ||
+ | OW_WriteByte(0x55); | ||
+ | OW_WriteByte(0x10); | ||
+ | OW_WriteByte(0x5F); | ||
+ | OW_WriteByte(0xD4); | ||
+ | OW_WriteByte(0xCD); | ||
+ | OW_WriteByte(0x01); | ||
+ | OW_WriteByte(0x08); | ||
+ | OW_WriteByte(0x00); | ||
+ | OW_WriteByte(0xC9); | ||
+ | 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(prazdny); | ||
+ | LCD_Position(0,0); | ||
+ | LCD_PrString(eteplota); | ||
+ | LCD_Position(1,1); | ||
+ | if(znamienko==0x00) | ||
+ | LCD_PrString(plus); | ||
+ | else | ||
+ | LCD_PrString(minus); | ||
+ | PREVOD(vystup, znamienko, count_remain); | ||
+ | } | ||
+ | if(p==2) | ||
+ | { | ||
+ | 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> | ||
== Odkazy a referencie == | == Odkazy a referencie == | ||
<references/> | <references/> |
Verzia zo dňa a času 10:58, 5. júl 2010
Obsah
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á.
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 |
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:
Po umiestnení tohto bloku do projektu musíme vykonať zopár nastavení. Názorne sú ukázané na obr. 2.
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"
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);
}
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)
{
PRT1DR=0;
if(PRT1DR==1) p++;
if (p>2) p=1;
OW_Reset();
if(p==1)
{
OW_WriteByte(0x55);
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); // Start Conversion
OW_Delay10mTimes(75);
OW_Reset();
OW_WriteByte(0x55);
OW_WriteByte(0x10);
OW_WriteByte(0x5F);
OW_WriteByte(0xD4);
OW_WriteByte(0xCD);
OW_WriteByte(0x01);
OW_WriteByte(0x08);
OW_WriteByte(0x00);
OW_WriteByte(0xC9);
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(prazdny);
LCD_Position(0,0);
LCD_PrString(eteplota);
LCD_Position(1,1);
if(znamienko==0x00)
LCD_PrString(plus);
else
LCD_PrString(minus);
PREVOD(vystup, znamienko, count_remain);
}
if(p==2)
{
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);
}
}
}