Błędy w komunikacji 1-Wire z czujnikiem DS18B20 na AT90S2313 ? kod do analizy
problem z 1wire (ds18b20, gcc_at_nospam_avr), dlugie
From: Krzysztof Dziuba <yeti_NOSPAM__at_nospam_zeus.polsl.gliwice.pl>
Subject: problem z 1wire (ds18b20, gcc_at_nospam_avr), dlugie
Date: Sun, 04 Jan 2004 21:25:26 +0100
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
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!not-for-mai
From: Marcin Stanisz <mstanisz_at_nospam_poczta.bzdury.onet.pl>
Subject: Re: problem z 1wire (ds18b20, gcc_at_nospam_avr), dlugie
Date: 4 Jan 2004 21:10:29 GMT
W artykule <bt9t3b$7ii$1_at_nospam_inews.gazeta.pl> Krzysztof Dziuba napisal(a):
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);
}
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
--
"A lie will go round the world before the truth has got its boots on"
Terry Pratchett, "Truth"
========
Path: news-archive.icm.edu.pl!news.rmf.pl!news.ipartners.pl!newsfeed.gazeta.pl!news.onet.pl!not-for-mai
From: Marcin Stanisz <mstanisz_at_nospam_poczta.bzdury.onet.pl>
Subject: Re: problem z 1wire (ds18b20, gcc_at_nospam_avr), dlugie
Date: 4 Jan 2004 23:26:30 GMT
W artykule <bt9t3b$7ii$1_at_nospam_inews.gazeta.pl> Krzysztof Dziuba napisal(a):
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);
^^^^^^^^^^^^^
To bym wyrzucił - ustawiasz port jako wejście?
sbi(PORTD, 4);
}
delay_us(60);
cbi(DDRD, 4);
sbi(PORTD, 4);
delay_2us();
byte >>= 1;
}
cbi(DDRD, 4);
cbi(PORTD, 4);
}
Więcej nic nie widzę.
Jeśli chcesz, uruchomiłem moje procedury - mogę na priva puścić
(ATmega32, 1MHz zegar).
Marcin Stanisz
--
"A lie will go round the world before the truth has got its boots on"
Terry Pratchett, "Truth"
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!newsfeed.gazeta.pl!news.gazeta.pl!not-for-mai
From: Krzysztof Dziuba <yeti_NOSPAM__at_nospam_zeus.polsl.gliwice.pl>
Subject: Re: problem z 1wire (ds18b20, gcc_at_nospam_avr), dlugie
Date: Mon, 05 Jan 2004 15:45:57 +0100
Witam,
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);
^^^^^^^^^^^^^
To bym wyrzucił - ustawiasz port jako wejście?
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.
Więcej nic nie widzę.
Jeśli chcesz, uruchomiłem moje procedury - mogę na priva puścić
(ATmega32, 1MHz zegar).
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
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!not-for-mai
From: Marcin Stanisz <mstanisz_at_nospam_poczta.bzdury.onet.pl>
Subject: Re: problem z 1wire (ds18b20, gcc_at_nospam_avr), dlugie
Date: 5 Jan 2004 18:11:00 GMT
W artykule <btbtin$kmv$1_at_nospam_inews.gazeta.pl> Krzysztof Dziuba napisal(a):
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.
Pojszło na priv.
Marcin Stanisz
--
"A lie will go round the world before the truth has got its boots on"
Terry Pratchett, "Truth"
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!newsfeed.gazeta.pl!news.gazeta.pl!not-for-mai
From: Krzysztof Dziuba <yeti_NOSPAM__at_nospam_zeus.polsl.gliwice.pl>
Subject: Re: problem z 1wire (ds18b20, gcc_at_nospam_avr), dlugie
Date: Mon, 05 Jan 2004 20:50:23 +0100
Witam,
Użytkownik Marcin Stanisz napisał:
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.
Pojszło na priv.
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
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!newsfeed.silweb.pl!newsfeed.tpinternet.pl!opal.futuro.pl!newsfeed.gazeta.pl!news.gazeta.pl!not-for-mai
From: Krzysztof Dziuba <yeti_NOSPAM__at_nospam_zeus.polsl.gliwice.pl>
Subject: Re: problem z 1wire (ds18b20, gcc_at_nospam_avr), dlugie
Date: Mon, 05 Jan 2004 23:01:34 +0100
aa Krzysztof Dziuba napisał:
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.
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_at_nospam_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 hendrix_at_nospam_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
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!not-for-mai
From: Marcin Stanisz <mstanisz_at_nospam_poczta.bzdury.onet.pl>
Subject: Re: problem z 1wire (ds18b20, gcc_at_nospam_avr), dlugie
Date: 5 Jan 2004 22:37:39 GMT
W artykule <btcn4c$acm$1_at_nospam_inews.gazeta.pl> Krzysztof Dziuba napisal(a):
Te dwa czujniki padly - nie dziala konwersja temperatury :/ Trzeci
-(
czujnik dziala wysmienicie. Dzieki pomocy Pana Marcina udalo mi sie
Już ci więcej nie pomogę. Za tego pana, jeszcze z wielkiej litery ;-)
Pozdrawiam
Marcin Stanisz
--
"A lie will go round the world before the truth has got its boots on"
Terry Pratchett, "Truth"
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!not-for-mai
From: Marcin Stanisz <mstanisz_at_nospam_poczta.bzdury.onet.pl>
Subject: Re: problem z 1wire (ds18b20, gcc_at_nospam_avr), dlugie
Date: 5 Jan 2004 22:22:39 GMT
W artykule <btcfe5$6r5$1_at_nospam_inews.gazeta.pl> Krzysztof Dziuba napisal(a):
Witam,
Użytkownik Marcin Stanisz napisał:
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.
Pojszło na priv.
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);
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.
byte |= ((bit_is_set(PIND, 4) ? 1 : 0) << i);
Nie lubię konstrukcji ?: - sprawdź w pliku .LSS albo .LST
co ci GCC z tego robi. I zmień na if else ;-)
Powodzenia
Marcin Stanisz
--
"A lie will go round the world before the truth has got its boots on"
Terry Pratchett, "Truth"
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news2.icm.edu.pl!newsfeed.tpinternet.pl!atlantis.news.tpi.pl!news.tpi.pl!not-for-mai