REKLAMA

kod.c

[Attiny2313][C] Prośba o sprawdzenie programu - ds18b20

Witam Bazując na którymś z kodów dostępnych na forum, opracowałem obsługę czujnika temperatury ds18b20. Kod działa, proszę jednak o wskazówki co do możliwej optymalizacji oraz o sprawdzenie czy poprawnie jest zrealizowany odczyt temperatury ujemnej.. Kod w załączniku, natomiast poniżej najbardziej interesujący mnie fragment : unsigned char lsb = ow_byte_rd(); // onewire - odczytaj bajt unsigned char msb = ow_byte_rd(); // onewire - odczytaj bajt char buffer[5]; int calk = ((lsb & 0b11110000)>>4) | ((msb & 0b00000111)<<4); //składamy liczbe calkowita temperatury if (msb & 0b10000000) { if (calk==127) //aby dla -0.1 byl "-" { LCD_WriteText("-"); } calk= calk-127; } LCD_Clear(); itoa(calk, buffer, 10); LCD_WriteText(buffer); int ulamek = ((lsb & 0b00001111)*625)/1000; if (msb & 0b10000000) { if (ulamek >0) //po to aby dla ujemnych temp. ulamek nie odliczal w dol tzn. -1.9, -1,8 itd.. { ulamek = 9-ulamek; } } LCD_WriteText("."); itoa(ulamek, buffer, 10); LCD_WriteText(buffer); LCD_WriteText("'C");


Pobierz plik - link do postu

#include &amp; lt; avr/io.h &amp; gt;
#include &amp; lt; avr/interrupt.h &amp; gt;
#include &amp; lt; util/delay.h &amp; gt;
#include &amp; lt; hd44780.c &amp; gt;
#include &quot; onewire.h &quot;

#ifdef OW_ONE_BUS

#define OW_GET_IN() ( OW_IN &amp; (1 &amp; lt; &amp; lt; OW_PIN))
#define OW_OUT_LOW() ( OW_OUT &amp; = (~(1 &amp; lt; &amp; lt; OW_PIN)) )
#define OW_OUT_HIGH() ( OW_OUT |= (1 &amp; lt; &amp; lt; OW_PIN) )
#define OW_DIR_IN() ( OW_DDR &amp; = (~(1 &amp; lt; &amp; lt; OW_PIN )) )
#define OW_DIR_OUT() ( OW_DDR |= (1 &amp; lt; &amp; lt; OW_PIN) )

#else

/* set bus-config with ow_set_bus() */
uint8_t OW_PIN_MASK;
volatile uint8_t* OW_IN;
volatile uint8_t* OW_OUT;
volatile uint8_t* OW_DDR;

#define OW_GET_IN() ( *OW_IN &amp; OW_PIN_MASK )
#define OW_OUT_LOW() ( *OW_OUT &amp; = (uint8_t) ~OW_PIN_MASK )
#define OW_OUT_HIGH() ( *OW_OUT |= (uint8_t) OW_PIN_MASK )
#define OW_DIR_IN() ( *OW_DDR &amp; = (uint8_t) ~OW_PIN_MASK )
#define OW_DIR_OUT() ( *OW_DDR |= (uint8_t) OW_PIN_MASK )
//#define OW_PIN2 PD6
//#define OW_DIR_IN2() ( *OW_DDR &amp; = ~(1 &amp; lt; &amp; lt; OW_PIN2 ) )

void ow_set_bus(volatile uint8_t* in,
volatile uint8_t* out,
volatile uint8_t* ddr,
uint8_t pin)
{
OW_DDR=ddr;
OW_OUT=out;
OW_IN=in;
OW_PIN_MASK=(1 &amp; lt; &amp; lt; pin);
ow_reset();
}

#endif

uint8_t ow_input_pin_state()
{
return OW_GET_IN();
}

void ow_parasite_enable(void)
{
OW_OUT_HIGH();
OW_DIR_OUT();
}

void ow_parasite_disable(void)
{
OW_OUT_LOW();
OW_DIR_IN();
}

uint8_t ow_reset(void)
{
uint8_t err;
uint8_t sreg;

OW_OUT_LOW(); // disable internal pull-up (maybe on from parasite)
OW_DIR_OUT(); // pull OW-Pin low for 480us

_delay_us(480);

sreg=SREG;
cli();

// set Pin as input - wait for clients to pull low
OW_DIR_IN(); // input

_delay_us(66);
err = OW_GET_IN(); // no presence detect
// nobody pulled to low, still high

SREG=sreg; // sei()

// after a delay the clients should release the line
// and input-pin gets back to high due to pull-up-resistor
_delay_us(480-66);
if( OW_GET_IN() == 0 ) // short circuit
err = 1;

return err;
}

/* Timing issue when using runtime-bus-selection (!OW_ONE_BUS):
The master should sample at the end of the 15-slot after initiating
the read-time-slot. The variable bus-settings need more
cycles than the constant ones so the delays had to be shortened
to achive a 15uS overall delay
Setting/clearing a bit in I/O Register needs 1 cyle in OW_ONE_BUS
but around 14 cyles in configureable bus (us-Delay is 4 cyles per uS) */
uint8_t ow_bit_io( uint8_t b )
{
uint8_t sreg;

sreg=SREG;
cli();

OW_DIR_OUT(); // drive bus low

_delay_us(1); // Recovery-Time wuffwuff was 1
if ( b ) OW_DIR_IN(); // if bit is 1 set bus high (by ext. pull-up)

// wuffwuff delay was 15uS-1 see comment above
_delay_us(15-1-OW_CONF_DELAYOFFSET);

if( OW_GET_IN() == 0 ) b = 0; // sample at end of read-timeslot

_delay_us(60-15);
OW_DIR_IN();

SREG=sreg; // sei();
_delay_us(30); // added 20091001, b/o remarks from Karol Zdunki and Andreas Kaiser

return b;
}


uint8_t ow_byte_wr( uint8_t b )
{
uint8_t i = 8, j;

do {
j = ow_bit_io( b &amp; 1 );
b &amp; gt; &amp; gt; = 1;
if( j ) b |= 0x80;
} while( --i );

return b;
}


uint8_t ow_byte_rd( void )
{
// read by sending 0xff (a dontcare?)
return ow_byte_wr( 0xFF );
}


uint8_t ow_rom_search( uint8_t diff, uint8_t *id )
{
uint8_t i, j, next_diff;
uint8_t b;

if( ow_reset() ) return OW_PRESENCE_ERR; // error, no device found

ow_byte_wr( OW_SEARCH_ROM ); // ROM search command
next_diff = OW_LAST_DEVICE; // unchanged on last device

i = OW_ROMCODE_SIZE * 8; // 8 bytes

do {
j = 8; // 8 bits
do {
b = ow_bit_io( 1 ); // read bit
if( ow_bit_io( 1 ) ) { // read complement bit
if( b ) // 11
return OW_DATA_ERR; // data error
}
else {
if( !b ) { // 00 = 2 devices
if( diff &amp; gt; i || ((*id &amp; 1) &amp; &amp; diff != i) ) {
b = 1; // now 1
next_diff = i; // next pass 0
}
}
}
ow_bit_io( b ); // write bit
*id &amp; gt; &amp; gt; = 1;
if( b ) *id |= 0x80; // store bit

i--;

} while( --j );

id++; // next byte

} while( i );

return next_diff; // to continue search
}


void ow_command( uint8_t command, uint8_t *id )
{
uint8_t i;

ow_reset();

if( id ) {
ow_byte_wr( OW_MATCH_ROM ); // to a single device
i = OW_ROMCODE_SIZE;
do {
ow_byte_wr( *id );
id++;
} while( --i );
}
else {
ow_byte_wr( OW_SKIP_ROM ); // to all devices
}

ow_byte_wr( command );
}

int main(void)
{

LCD_Initalize();
LCD_Clear();

LCD_WriteText( &quot; Termomet &quot; );
LCD_GoTo(0,1);
LCD_WriteText( &quot; r =^^= &quot; );

while(1)
{
ow_reset(); // onewire reset
ow_command(0xCC, 0); // onewire - wyœlij bajt
ow_command(0x44, 0); // onewire - wyœlij bajt (convert t)

_delay_ms(250); // poczekaj 750ms na przetworzenie temperatury
_delay_ms(250);
_delay_ms(250);

ow_reset();
ow_command(0xCC, 0); // onewire - wyœlij bajt
ow_command(0xBE, 0); // onewire - wyœlij bajt (Read Scratchpad)

unsigned char lsb = ow_byte_rd(); // onewire - odczytaj bajt
unsigned char msb = ow_byte_rd(); // onewire - odczytaj bajt


char buffer[5];

int calk = ((lsb &amp; 0b11110000) &amp; gt; &amp; gt; 4) | ((msb &amp; 0b00000111) &amp; lt; &amp; lt; 4); //sk³adamy liczbe calkowita temperatury
if (msb &amp; 0b10000000)
{
if (calk==127) //aby dla -0.1 byl &quot; - &quot;
{
LCD_WriteText( &quot; - &quot; );
}
calk= calk-127;
}

LCD_Clear();

itoa(calk, buffer, 10);
LCD_WriteText(buffer);

int ulamek = ((lsb &amp; 0b00001111)*625)/1000;
if (msb &amp; 0b10000000)
{
if (ulamek &amp; gt; 0) //po to aby dla ujemnych temp. ulamek nie odliczal w dol tzn. -1.9, -1,8 itd..
{
ulamek = 9-ulamek;
}
}

LCD_WriteText( &quot; . &quot; );

itoa(ulamek, buffer, 10);
LCD_WriteText(buffer);
LCD_WriteText( &quot; 'C &quot; );
}
}