problem z 1wire (ds18b20, gcc@avr), dlugie

Witam,

Mam maly problem z moim kodem obslugujacym magistrale 1Wire. Jak dotad napisalem takie cos:

<src_code_mode="on">

#include "1wire.h"

unsigned char onewire_reset(void) { unsigned char i = 200; sbi(DDRD, 4); cbi(PORTD, 4); delay_us(500); cbi(DDRD, 4); sbi(PORTD, 4); delay_us(50);

while(i--) { if (bit_is_clear(PIND, 4)) { delay_us(500); return ONEWIRE_OK; } delay_1us(); }

return ONEWIRE_BUS_ERROR; }

void onewire_write(unsigned char byte) { unsigned char i = 0;

for(i = 0; i < 8; i++) { sbi(DDRD, 4); cbi(PORTD, 4); delay_us(5); if ((byte & 0x01) == 1) { cbi(DDRD, 4); sbi(PORTD, 4); } delay_us(60); cbi(DDRD, 4); sbi(PORTD, 4); delay_2us(); byte >>= 1; }

cbi(DDRD, 4); cbi(PORTD, 4); }

unsigned char onewire_read(void) { unsigned char byte = 0; unsigned char i = 0;

for(i = 0; i < 8; i++) { sbi(DDRD, 4); cbi(PORTD, 4); delay_1us(); cbi(DDRD, 4); sbi(PORTD, 4); delay_us(18); byte |= (bit_is_set(PIND, 4) ? 1 : 0) << i; delay_us(45); }

return byte; }

<src_code_mode="off">

Program jest pisany pod at90s2313, kompiluje w avr-gcc 3.3. Zegar 4MHz. Rezystorek podciagajacy 4,7k, DS18b20 jest podlaczony 3 krotkimi przewodami (+, -, data). Opoznienia sa realizowane w makrach: dla 1 i

2us sa to nop'y, a dla wiekszych petla (zazwyczaj opoznienie jest +2us wieksze od zadeklarowanego). Narazie nie uzywam przerwan ani timer'kow. Tylko reset dziala - ds18b20 zglasza sie prawidlowo, reszta juz nie (tzn. wysylam mu 0xcc, 0x44, czekam >100ms, wysylam 0xcc, 0xbe, odbieram co nadaje - dostaje same jedynki, ds18b20 chyba nie zinterpretowal albo nie przyjal rozkazu). Napisalem program wyswietlajacy temperature w Bascom'ie, dziala wysmienicie - znaczy sie ze sprzet jest zmontowany dobrze. Czemu nie zrobie tego w Bascomie? Jak do niczego nie dojde, to dopiero wtedy, ale wole to napisac w bardziej czytelnym c.

Podejrzewam ze problem tkwi w opoznieniach w slotach read & write. W dokumentacji przeczytalem takie cos (poprawcie mnie jesli sie myle):

a) slot write

- dla 0: pin (w avr) do masy przez ~60us, potem uaktywnienie pull-up'a

- dla 1: pin do masy przez 1us, potem przez ~60us uaktywnienie pull-up'a, czyli jedynka na pin'ie

b) slot read: pin do masy przez 1us, zmiana stanu na odbior, poczekanie >15us, odczytanie stanu linii, poczekanie ~45us na koniec slot'u

A teraz co robie zle ze nie dziala?? Mecze sie z tym juz kolejny tydzien. Szukalem rozwiazania na sieci - usenet, avrfreaks, google. Znalazlem rozne przyklady, ale nie dzialaly. W dodatku w kazdym byly inne timmingi :/ W swoim kodzie tez zmienialem czasy, ale nie pomoglo.

Bede wdzieczny za wszelkie konstruktywne porady.

Pozdrawiam, Krzysiek

Reply to
Krzysztof Dziuba
Loading thread data ...

W artykule <bt9t3b$7ii$ snipped-for-privacy@inews.gazeta.pl> Krzysztof Dziuba napisal(a):

A na końcu tej procedury nie powinieneś linii ustawić w stan wysoki? sbi(PORTD, 4); sbi(DDRD, 4)? IDLE dla 1Wire to 1... Taki strzał, bo właśnie sam od dwóch dni przerabiam stare procedurki do obsługi

1Wire z Keila i 51 na avr-gcc i mega32 (taki jest pod ręką). Jak tylko zacznie działać - dam znać ;-)

Marcin Stanisz

Reply to
Marcin Stanisz

W artykule <bt9t3b$7ii$ snipped-for-privacy@inews.gazeta.pl> Krzysztof Dziuba napisal(a):

^^^^^^^^^^^^^ To bym wyrzucił - ustawiasz port jako wejście?

Więcej nic nie widzę.

Jeśli chcesz, uruchomiłem moje procedury - mogę na priva puścić (ATmega32, 1MHz zegar).

Marcin Stanisz

Reply to
Marcin Stanisz

Witam,

Ustawienie portu jako wejscie uaktywnia pull-up (wewnetrzny procka [dla

+sbi(PORTD, 4)] i zewnetrzny), dla ds18b20 znaczy to stan wysoki. Zmienilem to na sbi(DDRD, 4) & sbi(PORTD, 4) ale to tez nic nie daje.

O, bylbym wdzieczny. Moj mail to: yeti[at]zeus[dot]polsl[dot]gliwice[dot]pl Przepraszam za taka postac, ale maile z Korei mnie powoli juz dobijaja.

Pozdrawiam, Krzysiek

Reply to
Krzysztof Dziuba

W artykule <btbtin$kmv$ snipped-for-privacy@inews.gazeta.pl> Krzysztof Dziuba napisal(a):

Pojszło na priv.

Marcin Stanisz

Reply to
Marcin Stanisz

Witam,

Użytkownik Marcin Stanisz napisał:

Dziekuje, doszlo.

Twoj kawalek kodu spowodowal, ze wydluzylem wszystkie opoznienia. Szczegolnie wazne okazalo sie wydluzenie 'recovery time' dla slotu zapisu. Kod wyglada teraz tak:

void onewire_write(unsigned char byte) { unsigned char i = 0;

sbi(DDRD, 4);

for(i = 0; i < 8; i++) { cbi(PORTD, 4); delay_1us(); if (((byte >> i) & 0x01) == 1) sbi(PORTD, 4); delay_us(100); sbi(PORTD, 4); delay_us(15); } }

unsigned char onewire_read(void) { unsigned char byte = 0; unsigned char i = 0;

for(i = 0; i < 8; i++) { sbi(DDRD, 4); sbi(PORTD, 4); delay_1us(); cbi(PORTD, 4); delay_2us(); cbi(DDRD, 4); cbi(PORTD, 4); delay_us(10); byte |= ((bit_is_set(PIND, 4) ? 1 : 0) << i); delay_us(100); }

return byte; }

Teraz pojawia sie inny problem :) Mam trzy czujniki ds18b20. Pod podlaczeniu dwoch (nie dwa na jednej linii, tylko jeden po drugim dla sprawdzenia), na wyswietlaczu pojawia sie 85. Rozumiem, ze to moze wystepowac za pierwszym razem gdy odczytuje temperature, ale u mnie wyswietla to sie caly czas :/ Najciekawszy jest trzeci czujnik. W pierwszej iteracji wyswietla 85, w nastepnych dwoch, trzech normalna temperature (ale troche chyba zawyzona, bo 24 stopnie to u mnie nie ma :| ), pozniej juz wyswietla -1 (0xff w 2's complement to -1), czyli znow mam problem z odebraniem. Reset mikroprocka nic nie zmienia, ciagle wyswietla -1 (nawet 85 sie nie pojawia). Dopiero wylaczenie i wlaczenie zasilania ponownie odblokowuje uklad. Musze jeszcze raz zaladowac wersje bascom'owa i sprawdzic czujniki.

Pozdrawiam, Krzysiek

Reply to
Krzysztof Dziuba

aa Krzysztof Dziuba napisał:

Te dwa czujniki padly - nie dziala konwersja temperatury :/ Trzeci czujnik dziala wysmienicie. Dzieki pomocy Pana Marcina udalo mi sie wygenerowac taki kod do obslugi 1Wire dla gcc@avr:

<1wire.h>

#include <avr/io.h>

#include "delay.h" #ifndef __1WIRE_H #define __1WIRE_H

#define ONEWIRE_OK 0 #define ONEWIRE_BUS_ERROR 1

unsigned char onewire_reset(void); void onewire_write_bit(unsigned char bit); unsigned char onewire_read_bit(void);

void onewire_write(unsigned char byte); unsigned char onewire_read(void);

unsigned char onewire_wait(void);

#endif </1wire.h>

<1wire.c>

#include "1wire.h"

unsigned char onewire_reset(void) { unsigned char i = 200; sbi(DDRD, 4); cbi(PORTD, 4); delay_us(500); cbi(DDRD, 4); sbi(PORTD, 4); delay_us(50);

while(i--) { if (bit_is_clear(PIND, 4)) { delay_us(500); return ONEWIRE_OK; }

delay_1us(); }

return ONEWIRE_BUS_ERROR; }

void onewire_write_bit(unsigned char bit) { sbi(DDRD, 4); cbi(PORTD, 4); delay_1us(); if ((bit & 0x01) == 1) sbi(PORTD, 4); delay_us(100); sbi(PORTD, 4); }

unsigned char onewire_read_bit(void) { unsigned char bit = 0;

sbi(DDRD, 4); sbi(PORTD, 4); delay_1us(); cbi(PORTD, 4); delay_2us(); cbi(DDRD, 4); cbi(PORTD, 4); delay_us(10); bit = (bit_is_set(PIND, 4) ? 1 : 0); return bit; }

void onewire_write(unsigned char byte) { unsigned char i = 0;

for(i = 0; i < 8; i++) { onewire_write_bit(byte >> i); delay_us(10); }

delay_us(100); }

unsigned char onewire_read(void) { unsigned char byte = 0; unsigned char i = 0;

for(i = 0; i < 8; i++) { byte |= (onewire_read_bit() << i); delay_us(100); }

delay_us(100); return byte; } </1wire.c>

<delay.h>

#ifndef __DELAY_H #define __DELAY_H

#define F_CPU 4000000

#define delay_1us() asm("nop\n nop\n nop\n nop\n") #define delay_2us() asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n")

/* Author: Chris efstathiou snipped-for-privacy@otenet.gr */ /* 6 cpu cycles per loop + 3 overhead when a constant is passed. */ #define DELAY_L_ACCURATE(x) ({ unsigned long number_of_loops=(unsigned long)x; \ __asm__ volatile ( "L_%=: \n\t" \ "subi %A0,lo8(-(-1)) \n\t" \ "sbci %B0,hi8(-(-1)) \n\t" \ "sbci %C0,hlo8(-(-1)) \n\t" \ "sbci %D0,hhi8(-(-1)) \n\t" \ "brne L_%= \n\t" \ : /* NO OUTPUT */ \ : "w" (number_of_loops) \ ); \ })

#define TIME_L1_MS ( 1*(F_CPU/6000) ) /* 1 MILLISECOND */ #define TIME_L100_US ( 1*(F_CPU/60000) ) /* 100 MICROSECONDS */ </delay.h>

Mam nadzieje ze w tym temacie to bedzie juz wszystko.

Pozdrawiam, Krzysiek

Reply to
Krzysztof Dziuba

W artykule <btcfe5$6r5$ snipped-for-privacy@inews.gazeta.pl> Krzysztof Dziuba napisal(a):

Może tu za długo czekasz - w DTR-ce 18B20 napisali, że 15us od wystawienia zera gwarantują podciągnięcie 0 przez slave'a.

Nie lubię konstrukcji ?: - sprawdź w pliku .LSS albo .LST co ci GCC z tego robi. I zmień na if else ;-)

Powodzenia

Marcin Stanisz

Reply to
Marcin Stanisz

W artykule <btcn4c$acm$ snipped-for-privacy@inews.gazeta.pl> Krzysztof Dziuba napisal(a):

:-(

Już ci więcej nie pomogę. Za tego pana, jeszcze z wielkiej litery ;-)

Pozdrawiam

Marcin Stanisz

Reply to
Marcin Stanisz

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.