Piszę obecnie program obsługujący termometr ds18b20. Nie mogę wykorzystać gotowych bibliotek dostarczonych razem z kompilatorem (CodeVision), więc obsługę 1 wire napisałem sam na podstawie specyfikacji. Jednak poza wysłaniem resetu komunikacja nie przebiega poprawnie. Oto mój kod:
Czytając pamięć czujnika dostaję stabilne, powtarzalne dane jednak różnią sie one od zakładanych.
Mapa pamięci czujnika z odebranych danych jest następująca:
Tak więc sądząc po rejestrach 6-8 coś tu nie działa tak jak powinno. Ponowna analiza kodu nic nie dała. Problem ciągle sie powtarza. Program sprawdziłem na 2 sztukach czujnika w tym jeden był całkowicie nowy.
Czy któryś z Kolegów byłby w stanie mi pomóc? Będę bardzo wdzięczny.
Pozdrawiam
PS
Proszę nie zwracać uwagi na "wykwintność" treści komentarzy
/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.4 Standard
Automatic Program Generator
© Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 2009-07-10
Author :
Company :
Comments:
Chip type : ATmega8
Program type : Application
Clock frequency : 8,000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
*****************************************************/
#include <mega8.h>
#include <delay.h>
//PC.3 -> 1wire
#define CATCH1WIRE DDRC.3=1
#define RELEACE1WIRE DDRC.3=0
#define SET1WIRE PORTC.3=1
#define CLEAR1WIRE PORTC.3=0
#define PIN1WIRE PINC.3
//*** FUNKCJA RESETUJACA MAGISTRALE 1WIRE ***//
unsigned char reset_1wire(void)
{
unsigned char prescence=0;
CATCH1WIRE; //przejmij magistrale
CLEAR1WIRE; //wyslij reset na magistrale
delay_us(500); //odczekaj 500us
RELEACE1WIRE; //zwolnienie magstral - przejsce w stan wysokiej -impedancj
delay_us(30); //odczekaj 30us
if(PIN1WIRE==0) //jesli slave ustawil linie w stan niski
{
prescence=1; //znaczy ze wyslal sygnal zgloszenia
}
else
{
delay_us(470);
SET1WIRE; //wlaczenie rezystora podciagajacego - wymuszenie 1
CATCH1WIRE;
return(0); //jesli nie, to uklad niekatywny
}
delay_us(470); //odczekaj 470us i sprawdz czy slave podciagnal stan magistrali - czy ja zwolnil
if(PIN1WIRE==1)
{
prescence=1; //zwolnil
}
else
{
prescence=0; //nie zwolnil
}
SET1WIRE; //wlaczenie rezystora podciagajacego - wymuszenie 1
CATCH1WIRE; //zmiana kierunku pina - wyjscie w stanie wysokim
return(prescence);
}
//*** FUNCJA WYSYLAJACA 1 BIT NA MAGISTRALE 1WIRE ***//
void send1bit_1wire(char mark)
{
CATCH1WIRE; //przejmin magistrale
CLEAR1WIRE; //wyslij reset na magistrale
delay_us(5); //odczekaj 5us
if(mark==1)
{
SET1WIRE; //jesli zadanie wyslania 1 to ustaw magistrale
}
delay_us(80); //poczekaj az save zakoczy probkowanie stanu lini
SET1WIRE; //ustaw magistrale w stan spoczynku
}
//*** FUNKCJA ODBIERAJACA 1 BIT Z MAGISTRALI 1WIRE ***//
unsigned char recive1bit_1wire(void)
{
unsigned char rebit=0;
CATCH1WIRE; //przejmij magistrale
CLEAR1WIRE; //resetuj magistrale
delay_us(3); //czekaj 3us
RELEACE1WIRE; //zwolnij magistrale - pin jako wejscie
delay_us(15); //odczekaj 15us i probkuj stan magistrali - czast trwania bitu na magistrali to 15us
if(PIN1WIRE==1) //jesli stan magistrali to 1
{
rebit=1; //odebrano jedynke
}
else
{
rebit=0;
}
delay_us(60);
SET1WIRE; //wlaczenie rezystora podciagajacego - wymuszenie 1
CATCH1WIRE; //zmiana kierunku pina - wyjscie w stanie wysokim
return(rebit); //zwroc wartosc odebranego bitu
}
//*** FUNKCA WYSYLAJACA 1 BAJT NA MAGISTALE 1WIRE ***//
void send1byte_1wire(unsigned char data)
{
unsigned char i=0; //zmienna pomocnicza
unsigned char bufor=0;
for(i=0; i<8; i++)
{
bufor=data>>i; //przesun dana o jedna pozycje w prawo
send1bit_1wire(bufor &=0x01); //wyslij najmlodszy bit zmiennej data
}
delay_us(100); //odczekaj 100us po zakonczeniu transmisji
}
//*** FUNKCJA ODBIERAJACA 1 BAJT Z MAGISTRALI 1 WIRE ***//
unsigned char recive1byte_1wire(void)
{
unsigned char i=0;
unsigned char data=0;
for(i=0; i<8; i++)
{
if(recive1bit_1wire())
{
data|=0x01<<i;
delay_us(15);
}
}
return(data);
}
//===================================================
void main(void)
{
unsigned char temp_high=0;
unsigned char temp_low=0;
PORTB=0x00;
DDRB=0xFF;
PORTC=0x0E;
DDRC=0x7E;
PORTD=0x00;
DDRD=0xFF;
TCCR0=0x00;
TCNT0=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
MCUCR=0x00;
TIMSK=0x00;
ACSR=0x80;
SFIOR=0x00;
while (1)
{
delay_ms(500);
PORTB.0=0; //KONTROLA
/*if(reset_1wire())
{
send1byte_1wire(0x33); //wybierz jeden uklad
send1byte_1wire(0x4E); //zapisz pamiec slave
send1byte_1wire(0x00); //zapisz Th
send1byte_1wire(0x00); //zapisz Tl
send1byte_1wire(0x1F); //zapisz R0=0 R1=0 - rozdzielczosc 9 bitowa
reset_1wire();
send1byte_1wire(0x33); //wybierz jeden uklad
send1byte_1wire(0x48); //zapisz pamiec eeprom slave
reset_1wire();
}*/
if(reset_1wire())
{
//send1byte_1wire(0x33); //wybierz jeden uklad
//send1byte_1wire(0xB8); //recall ee
//reset_1wire();
send1byte_1wire(0x33); //wybierz jeden uklad
send1byte_1wire(0xBE); //odczytaj pamiec slave
temp_low=recive1byte_1wire(); //odczytaj mlodsza czesc temp
reset_1wire();
PORTD=temp_low;
PORTB.0=1; //KONTROLA
delay_ms(1000);
}
/*
if(reset_1wire()) //jesli uklad jest
{
send1byte_1wire(0x33); //odczytaj jego pamiec
delay_us(10);
send1byte_1wire(0x44); //rozpocznij konwersje temperatury
//strong pull-up
delay_ms(800); //poczekaj na koniec pomiaru
if(reset_1wire()) //wyslij reset
{
send1byte_1wire(0x33); //wybierz jeden uklad
send1byte_1wire(0xBE); //odczytaj pamiec slave
temp_low=recive1byte_1wire(); //odczytaj mlodsza czesc temp
temp_high=recive1byte_1wire(); //odczytaj starsza czesc
reset_1wire();
}
}
if(temp_low!=0)
{
PORTD=temp_high;
//PORTD=temp_low;
}
*/
};
}
Czytając pamięć czujnika dostaję stabilne, powtarzalne dane jednak różnią sie one od zakładanych.
Mapa pamięci czujnika z odebranych danych jest następująca:
0x00 - 10001010
0x01 - 11000101
0x02 - 11001011
tych wartości zapomniałem zapisać
0x05 - 00000000 - według specyfikacji powinno być FFh
0x06 - 11001101 - według specyfikacji powinno być 0Ch
0x07 - 11111111 - według specyfikacji powinno być 10h
0x08 - 11111111
Tak więc sądząc po rejestrach 6-8 coś tu nie działa tak jak powinno. Ponowna analiza kodu nic nie dała. Problem ciągle sie powtarza. Program sprawdziłem na 2 sztukach czujnika w tym jeden był całkowicie nowy.
Czy któryś z Kolegów byłby w stanie mi pomóc? Będę bardzo wdzięczny.
Pozdrawiam
PS
Proszę nie zwracać uwagi na "wykwintność" treści komentarzy
