Witam!
Zle odczyty z czujnika DS18B20.
Zastosowalem do pomiaru temperatury czujniki temperatury DS18B20. Stosuje je do dlugotrwalego monitorowania temperatury. Co 5 sek. wykonuje cykl pomiarowy. Cykl pomiaru temperatury zaczynam od rozkazu Start Conversion. Potem odczekujê oko³o 1 sek. (z dokumentacji wynika, ze konwersja sie dokona po 750msek.) i dokonuje odczytu wyniku. Przy pisaniu kodu skorzysta³em z noty aplikacyjnej Application Note 162 "1-Wire Temperature Sensor in Micro-Controller Environment". Sensor ma zasilanie podpiête do VDD, pin DQ do P3.4 w AT89C52 - z podci±gaj±cym 5.1k oraz masa do GND. Zmiany w kodzie z AN162 polagaly na dokladnym dobraniu opoznien sygnalow i wstawieniu blokad przerwan EA=0;, EA=1; (zeby nie byly naruszone rezimy czasowe zapisu i odczytu bitow przez procedury obslugi przerwan).
Co paredziesiat odczytow sensor podaje bledny wynik - co w systemie monitorowania wywoluje alarm. Czy cos zrobilem zle?
Prosze o pomoc i rade
Przemyslaw oto kod:
#pragma CODE #pragma NOAREGS // tworz kod niezalezny od banku rejestrow
#include <at89x52.h>
#include <intrins.h>
#define DQ P3_4
data int temp_int; // tutaj znajdzie siê temperatura bit presence=0;
/*------------------------------------------------------------------ DELAY - with 11.059 MHz Calling the routine takes about 24 us yeach count takes another 16 us.
-------------------------------------- dla 24 MHZ wywo³anie zabiera 7.5 us ka¿dy obieg pêtli zabiera dodatkowo 6 us
------------------------------------------------------------------*/ void delay(unsigned int useconds) { unsigned int s; for(s=0;s<useconds; s++) ; } /*----------------------------------------------------------------- OW_RESET - performs a reset on the one-wire bus and returns the presence detect. Reset is 480 us, so delay value is (480-24)/16=28.5 - we use 29. Presence checked another 70 us later, so delay is (70-24)/16 = 2.875 - we use 3
--------------------------------------------------------------- dla 24MHz (480-7.5)/6=472.5/6=78.75 u¿ywam 79. Sprawdzenie obecno¶ci nastêpne 70 us, dlatego opó¼nienie jest: (70-7.5)/6=62.5/6=10.41(6) - u¿ywam 10 do koñca szczeliny czasowej=410 us (410-7.5)/6=67
------------------------------------------------------------------*/ unsigned char ow_reset(void) { unsigned char presence; EA=0; // !!! DQ=0; // pull DQ line low delay(79); // leave it low for 480us DQ=1; // allow line to return high delay(10); // wait for presence presence=DQ; // get presence signal EA=1; // !!! delay(67); // wait for end of timeslot return(presence); // presence signal returned 0=presence, 1 no part } /*------------------------------------------------------------------ READ_BIT -reads a bit from the one-wire bus. The delay required for a read is 15us so the DELAY routine won't work. We put our own delay function in this routine in the form of a for() loop.
------------------------------------------------------------------*/ unsigned char read_bit(void) { unsigned char i; DQ=0; // pull DQ line low to start timeslot _nop_(); _nop_(); DQ=1; // then return high for(i=0; i<8; i++); // delay 15 us from start of timeslot ; return(DQ); // return value of DQ line } /*------------------------------------------------------------------ WRITE_BIT - writes a bit to the one-wire bus, passed in bitval.
------------------------------------------------------------------*/ void write_bit(char bitval) { DQ=0; // pull DQ line low to start timeslot if(bitval==1) // DQ=1; // return DQ 1 if write 1 delay(15) ; // hold value for remainder of timeslot =(7.5us +
15*6 us)=100us DQ=1; } /*------------------------------------------------------------------ READ_BYTE - reads a byte from the one-wire bus.
------------------------------------------------------------------*/ unsigned char read_byte(void) { unsigned char i; unsigned char value=0; EA=0; for(i=0;i<8;i++) { if(read_bit()) value |= (0x01<<i); // reads byte in, one byte at a time and then shifts it left delay(7); } EA=1; return(value); } /*------------------------------------------------------------------ WRITE_BYTE - writes a byte to to the one-wire bus
------------------------------------------------------------------*/ void write_byte(char val) { unsigned char i; unsigned char temp; EA=0; for(i=0; i<8; i++) // writes byt, one bit a time { temp=(val>>i); // shifts val right 'i' spaces temp &= 0x01; // copy that bit to temp write_bit(temp); // write bit in tmp into } delay(15); // 100 us 92/6 EA=1; } /*------------------------------------------------------------------
------------------------------------------------------------------*/ void Read_Temperature_step1(void) { presence=ow_reset(); if(presence==1) return; write_byte(0xCC); // Skip ROM write_byte(0x44); // Start Conversion delay(15); // 100 us
return; } /*------------------------------------------------------------------
------------------------------------------------------------------*/ void Read_Temperature_step2(void) { char get[10]; unsigned char k;
ow_reset(); write_byte(0xCC); // Skip ROM write_byte(0xBE); // Read Scratch Pad
for(k=0; k<9; k++) { get[k]=read_byte(); } ((char *)(&temp_int))[0]=get[1]; // High dla KEIL'a ((char *)(&temp_int))[1]=get[0]; // Low
return; }