logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[PIC] PIC C: Nie działa komunikacja 1-Wire z DS1820 – reset nie wykrywa obecności

tgm 30 Kwi 2005 21:33 6065 17
REKLAMA
  • #1 1451346
    tgm
    Poziom 11  
    Posty: 6
    Czesc,
    Mam problem z urochomieniem mego DS1820
    Oto moj Cod:

    #include <16f870.h>
    #use delay(clock=4000000)
    #fuses XT,NOWDT,NOLVP
    
    #define SKIP_ROM 0xCC
    #define CONVERT_T 0x44
    #define READ_SCRATCHPAD 0xBE
    
    #define DQ PIN_C4
    //#define Tx_DS1820 PIN_C5
    
    #use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
    
    
    //////////////////////////////////////////////////////////////////////////////
    // OW_RESET - performs a reset on the one-wire bus and
    // returns the presence detect. Reset is 480us, so delay
    // value is (480-24)/16 = 28.5 - we use 29. Presence checked
    // another 70us later, so delay is (70-24)/16 = 2.875 - we use 3.
    //
    unsigned char ow_reset(void)
       {
          unsigned char presence;
          output_low(DQ); //pull DQ line low
          delay_us(480); // leave it low for 480us
          input(DQ); // allow line to return high
          delay_us(70); // wait for presence
          presence = DQ; // get presence signal
          delay_us(424); // 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;
             output_low(DQ); // pull DQ low to start timeslot
             input(DQ);// then return high
             for (i=0; i<3; i++); // delay 15us 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)
    {
          output_low(DQ); // pull DQ low to start timeslot
          if(bitval==1) input(DQ); // return DQ high if write 1
          delay_us(104); // hold value for remainder of timeslot
          input(DQ);
    }// Delay provides 16us per loop, plus 24us. Therefore delay(5) = 104us
    
    
    //////////////////////////////////////////////////////////////////////////////
    // READ_BYTE - reads a byte from the one-wire bus.
    //
    unsigned char read_byte(void)
    {
          unsigned char i;
          unsigned char value = 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_us(120); // wait for rest of timeslot
    }
          return(value);
    }
    
    
    
    //////////////////////////////////////////////////////////////////////////////
    // WRITE_BYTE - writes a byte to the one-wire bus.
    //
    void write_byte(char val)
    {
          unsigned char i;
          unsigned char temp;
          for (i=0; i<8; i++) // writes byte, one bit at a time
          {
          temp = val>>i; // shifts val right 'i' spaces
          temp &= 0x01; // copy that bit to temp
          write_bit(temp); // write bit in temp into
    }
          delay_us(104);
    }
    
    void main()
    {
             char get[10];
             int k;
             char temp_f,temp_c;
    
       while(1)
          {
    
                ow_reset();
                write_byte(0xCC); //Skip ROM
                write_byte(0x44); // Start Conversion
                delay_us(104);
                ow_reset();
                write_byte(0xCC); // Skip ROM
                write_byte(0xBE); // Read Scratch Pad
                for (k=0;k<9;k++)
                   {  get[k]=read_byte();
                   }
    
                printf("\n ScratchPAD DATA = %X%X%X%X%X\n",get[8],get[7],get[6],get[5],get[4],get[3],get[2],get[1],get[0]);
    
    
          }
    }



    wychodzi tylko FFFFFFFF
    -kto moze mi powiedziec gdzie jest blad?

    Thx , potzrebuje jak najszybciej !!, bo projekt szkolny!!
  • REKLAMA
  • REKLAMA
  • #3 1451471
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    A jak myślisz,po kiego grzyba funkcja "ow_reset()" zwraca "presence" :?:
    Żeby to sprawdzić w programie , a nie dla widzimisię.
    
    If(ow_reset())
      {
      //cisza na 1wire ;)
    else
      //jeeeeest coś :)
      ...
    


    Ile razy można to wałkować :(

    Pozdrawiam
    Piotrek
  • #4 1451650
    tgm
    Poziom 11  
    Posty: 6
    Cytat:

    A jak myślisz,po kiego grzyba funkcja "ow_reset()" zwraca "presence"
    Żeby to sprawdzić w programie , a nie dla widzimisię.



    chyba nie rozumie o co ci chodzi, moglbys doklandniej sformuowac?
    -Presence jest 0
    a wiec widzi mego Sensora
    ale chyba ci o cos innego chodzi..

    Sensor: DS18S20
    Supply: Vcc 5V
    DQ na PIC i na 5Vcc prez 4,7kO
    G na Ground

    ..prosze o dalsza pomoc
    dzienki
  • #5 1451682
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    Dlaczego bufor danych się nazywa "get[]" ? nie było ładniejszej nazwy ? ;) Ta nazwa nie jest przypadkiem zastrzeżona dla jakiegoś słowa kluczowego ?
  • #6 1452100
    jacur
    Poziom 32  
    Posty: 1748
    Pomógł: 166
    Ocena: 295
    A czas konwersji temperatury jest w ms-milisekundach czy w us-mikrosekundach ?
  • #7 1452669
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    tgm napisał:
    -Presence jest 0
    a wiec widzi mego Sensora

    W którym miejscu programu , jest to sprawdzane :?:
    jacur ma rację - dajesz za mało czasu na konwersję temperatury.
    Na początek , spróbuj odczytać seriala.
    
    void main()
    {
             char get[10];
             int k;
             char temp_f,temp_c;
    
       while(1)
          {
    
                if!(ow_reset())
                  {
                   write_byte(0x33); //Read ROM
                   for (k=0;k<8;k++)
                      { get[k]=read_byte(); }
                   printf("\n ROM Code = %X%X%X%X\n",get[7],get[6],get[5],get[4],get[3],get[2],get[1],get[0]);
                  }
                else
                  {printf("\n NO presence !!! \n");}
          }
    }
    

    Jeśli to zadziała , to masz pewność , że zapis i odczyt na 1wire działa :)

    Piotrek
  • #8 1453287
    tgm
    Poziom 11  
    Posty: 6
    Czesc,

    sprobowale to co proponowaliscie



    #include <16f870.h>
    #use delay(clock=4000000)
    #fuses XT,NOWDT,NOLVP
    
    #define SKIP_ROM 0xCC
    #define CONVERT_T 0x44
    #define READ_SCRATCHPAD 0xBE
    
    #define DQ PIN_C4
    //#define Tx_DS1820 PIN_C5
    
    #use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
    
    //char presence;
    //////////////////////////////////////////////////////////////////////////////
    // OW_RESET - performs a reset on the one-wire bus and
    // returns the presence detect. Reset is 480us, so delay
    // value is (480-24)/16 = 28.5 - we use 29. Presence checked
    // another 70us later, so delay is (70-24)/16 = 2.875 - we use 3.
    //
    unsigned char ow_reset(void)
       {
          unsigned char presence;
          output_low(DQ); //pull DQ line low
          delay_us(480); // leave it low for 480us
          input(DQ); // allow line to return high
          delay_us(60); // wait for presence
          presence = DQ; // get presence signal
          delay_us(424);// 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;
             output_low(DQ); // pull DQ low to start timeslot
             input(DQ);// then return high
             delay_us(15);
             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)
    {
          output_low(DQ); // pull DQ low to start timeslot
          if(bitval==1) input(DQ); // return DQ high if write 1
          delay_us(104); // hold value for remainder of timeslot
          input(DQ);
    }// Delay provides 16us per loop, plus 24us. Therefore delay(5) = 104us
    
    
    //////////////////////////////////////////////////////////////////////////////
    // READ_BYTE - reads a byte from the one-wire bus.
    //
    unsigned char read_byte(void)
    {
          unsigned char i;
          unsigned char value = 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_us(120); // wait for rest of timeslot
    }
          return(value);
    }
    
    
    
    //////////////////////////////////////////////////////////////////////////////
    // WRITE_BYTE - writes a byte to the one-wire bus.
    //
    void write_byte(char val)
    {
          unsigned char i;
          unsigned char temp;
          for (i=0; i<8; i++) // writes byte, one bit at a time
          {
          temp = val>>i; // shifts val right 'i' spaces
          temp &= 0x01; // copy that bit to temp
          write_bit(temp); // write bit in temp into
    }
          delay_us(104);
    }
    
    void main()
    {
             char get[10];
             int k;
             char temp_f,temp_c;
    
       while(1)
          {
                if(ow_reset()=0)
                {
                   write_byte(0x33); //Read ROM
                   for (k=0;k<8;k++)
                      { get[k]=read_byte(); }
                   printf("\n ROM Code = %X%X%X%X\n",get[7],get[6],get[5],get[4],get[3],get[2],get[1],get[0]);
    
                }
          else
    
          printf("no part");
    
    
          }
    
    }




    ...no i niewchodizi do 'if'a
    zo zrobic?
    Thx,Michal

    Dodano po 59 [minuty]:

    jescze cos
    moj PIC nie daje dokladnej delay_us
    potrzebowalbym funkcje ktora dokladniej segmentuje 10^-6 (us)sek

    Czy ktos to ma ?
    Czy ktos moze mi pomoc ?
    Dziekuje
  • REKLAMA
  • #9 1453470
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    A to czytałeś :?:
    
    // OW_RESET - performs a reset on the one-wire bus and
    // returns the presence detect. Reset is 480us, so delay
    // value is (480-24)/16 = 28.5 - we use 29. Presence checked
    // another 70us later, so delay is (70-24)/16 = 2.875 - we use 3.
    // 
    

    Zaskoczony brakiem presence , przeczytałem komentarze.
    Spróbuj podstawić wartości z komentarza.

    Piotrek
  • REKLAMA
  • #10 1453482
    juntom
    Poziom 19  
    Posty: 216
    Pomógł: 35
    Ocena: 27
    w main ,zle sprawdzasz warunek if (ow_reset()=0) , w winavr pojawilo by sie ostrzezenie, ale byc moze w twoj kompilator sam to zooptymalizuje


    void main()
    {
    char get[10];
    int k;
    char temp_f,temp_c;

    while(1)
    {
    if(ow_reset()==0) // tak powinno to wygladac ....lub tak
    // if (!ow_reset()) ...
    {
    write_byte(0x33); //Read ROM
    for (k=0;k<8;k++)
    { get[k]=read_byte(); }
    printf("\n ROM Code = %X%X%X%X\n",get[7],get[6],get[5],get[4],get[3],get[2],get[1],get[0]);

    }
    else

    printf("no part");


    }

    }

    pozdr.
  • #11 1453760
    tgm
    Poziom 11  
    Posty: 6
    ups..
    oczywiscie 10^-7! Sekund

    dzeinki za porade, zaraz zprobuje

    Dodano po 1 [godziny] 27 [minuty]:

    // OW_RESET - performs a reset on the one-wire bus and 
    // returns the presence detect. Reset is 480us, so delay 
    // value is (480-24)/16 = 28.5 - we use 29. Presence checked 
    // another 70us later, so delay is (70-24)/16 = 2.875 - we use 3. 
    // 


    ten Code lub Formuly sa dla 11Mhz

    ja mam 4 Mhz..

    co zrobic?
  • #12 1455639
    tgm
    Poziom 11  
    Posty: 6
    Czesc,

    Potrzebuje do jutra funktionujacy protokol lub program od DS18S20( poniewaz moj nie funktconuje.)mam jutro prezentacje projektu w szkole.
    -moze byc w CCS C , ASM, etc...

    uzywam
    PIC16F870
    RS232
    4Mhz

    dokladniejsza konfiguracja jest pod 1WIRE DS1820 IMPORTANT

    jesli ktos by mial to byl bym bardzo wdzieczny
    Dziekuje Michal
  • #13 2339897
    Krzychoo.s
    Poziom 11  
    Posty: 9
    Witam! Od jakiegoś miesiąca męczę się nad uruchomieniem mojego termometru. Jestem bardzo początkujący w tej tematyce, więc proszę o wyrozumiałość, to jest mój pierwszy taki projekt ;). Termometr zbudowany jest o procesor AT89C2051, czujnik DS18B20 i dwa pojedyńcze wyświetlacze LED. Kwarc to 24 MHz. Zasilanie 5V.
    Problem polega na tym, że czujnik nie reaguje! Na wyświetlaczu pokazuje się liczba 25 lub 00, niezależnie czy jest podłączony czujnik czy nie.
    Poniżej zamieszczam mój program. Może któś powiedzieć, czy ma on szansę zadziałać i co jest ewentualnie źle??


    Proszę o pomoc :)

    ----------------------------------------------------------------------------------------
    #include <reg51.h>
    #include "1-Wire.h"
    #include <stdio.h>
    //dołączenie definicji rejestrów mikrokontrolera


    // definicje
    #define CONVERT_T 0x44 // DS1820 commands
    #define SKIP_ROM 0xCC
    #define READ1W 0xBE

    //deklaracje zmiennych
    unsigned char t10,t01;
    unsigned char Bd[9]; // tabela pamięci
    bit minus;
    char Tb;

    #define PortLED P1
    #define PortSW P3

    #define _A 247 //gut
    #define _B 239 //gut
    #define _C 254 //gut
    #define _D 253 //gut
    #define _E 251 //gut
    #define _F 191 //gut
    #define _G 223 //gut

    sbit Dioda = P1^7;

    #define LED_1 0xEF //239
    #define LED_2 0xDF //223
    #define LED_off 0xFF //255


    //definicje wyglądu cyfr od 0 do 9
    char code Digits[10] = { _A & _B & _C & _D & _E & _F, //0
    _B & _C, //1
    _A & _B & _D & _E & _G, //2
    _A & _B & _C & _D & _G, //3
    _B & _C & _F & _G, //4
    _A & _C & _D & _F & _G, //5
    _A & _C & _D & _E & _F & _G, //6
    _A & _B & _C, //7
    _A & _B & _C & _D & _E & _F & _G, //8
    _A & _B & _C & _D & _F & _G }; //9


    char code Awaria[1] = {_G};


    //opóźnienie około 1 sekundy dla kwarcu 8MHz
    void Delay(unsigned int time)
    {
    unsigned int j;

    while (time-- >= 1) for (j=0; j<30; j++); //pętla FOR jest powtarzana TIME razy
    }


    void Delay1ms (unsigned int k)
    {
    unsigned int i,j;
    for (j = 0; j < k; j++)
    for (i = 0; i <= 482; i++);
    }




    //funkcja zwraca cyfrę będącą na pozycji POSITION
    char Subnumber(unsigned int number, char position)
    {
    switch (position)
    {
    case 1:
    return(number / 100); //cyfra 1 - zwróć część całkowitą z dzielenia przez 100
    case 2:
    number %= 100; //cyfra 2 - dzielenie całkowite przez 10 reszty z
    return(number / 10); //dzielenia przez 100
    case 3:
    return(number % 10); //cyfra 3 - reszta z dzielenia przez 10
    default:
    return(0); //przypadek zabroniony
    break;
    }
    }


    //początek programu głównego
    void main(void)
    {
    unsigned char tp,tpd,n;

    while (1) //pętla nieskończona
    {

    if (!one_wire_reset()) //sprawdzany jest stan urzadzenia 1-Wire, reset
    {

    one_wire_reset();
    one_wire_byte_write(SKIP_ROM); // pominięcie sprawdzenia nr identyfikacji
    one_wire_byte_write(CONVERT_T); // inicjalizacja pomiaru temperatury
    Delay1ms(700); // opóźnienie 255ms
    one_wire_reset();
    one_wire_byte_write(SKIP_ROM); // pominięcie sprawdzenia nr identyfikacji
    one_wire_byte_write(READ1W);

    for (n = 1;n < 10;n++)
    {
    Bd[n] = one_wire_byte_read();
    }

    if (Bd[2] > 0)
    {
    Bd[1] =~ Bd[1];
    minus = 1;
    }
    Bd[1] = Bd[1] >> 1; // pominięcie bitu b0
    t10 = 0;

    while(Bd[1] > 0x09){Bd[1] = Bd[1] - 0x0A;t10++;}// rozdzielenie dziesiątek
    // i jednostek temp
    t01 = (Bd[8] * 10 - Bd[7] * 10) / Bd[8];


    PortLED = Digits[Subnumber(t01,1)]; //zapis kodu cyfry numer 2 do portu
    PortSW = LED_1; //załączenie wyświetlania cyfry 2
    Delay(2000);
    PortSW = LED_off; //opóźnienie około 20ms


    PortLED = Digits[Subnumber(t01,2)]; //zapis kodu najstarszej cyfry do portu
    PortSW = LED_2; //załącznie cyfry numer 1
    Delay(2000); //opóźnienie około 20ms
    PortSW = LED_off;

    }
    else
    {

    /*Tu jest kod awaryjny, gdy urzadzenie zostanie odlaczone lub
    uszkodzone*/
    PortLED = Digits[1];
    PortSW = LED_1;
    Delay(1000);

    PortLED = Digits[5];
    PortSW = LED_2;
    Delay(1000);

    Dioda = 0;
    Delay(5000);
    Dioda = 1;

    }
    }

    }
  • #14 2340501
    Jacu$
    Poziom 27  
    Posty: 730
    Pomógł: 119
    Ocena: 26
    Jak należy rozumieć tą linię?
     Delay1ms(700); // opóźnienie 255ms

    Ile dokładnie wyniesie opóźnienie? Jeśli 255ms to układ nie wyrobi się z konwersją.

    A dalej taki "kwiatek":
    //opóźnienie około 1 sekundy dla kwarcu 8MHz
    void Delay(unsigned int time)
    

    Jeśli wszystko jest obliczone dla zegara 8 MHz a Ty podłączasz 24 MHz to na 100% nie będzie działać. Protokół magistrali 1-wire jest ściśle związany z dokładnym odmierzaniem czasu (z dokładnością do pojedynczych mikrosekund).

    Sam wymyśliłeś ten program, czy przepisałeś?
  • #15 2341862
    Krzychoo.s
    Poziom 11  
    Posty: 9
    Co do linii to chodziło mi o 700 ms, komentarz z boku jest błędny. Natomiast programu niestety nie wymyśliłem. Dopiero się uczę tego wszystkiego i część programu oparta jest o wiedzę z książki "Programowanie mikrokontrolerów 8051 w C" a część ze strony http://www.republika.pl/rejestr/

    W takim razie mam jeszcze jedno pytanie. W plikach np 1Wire.c najczęściej znajduje się linia
    #define XTAL	11059200
    Skoro ja mam kwarc 24MHz to czy nie powienienem zmienić tej wartości ? Przy okazji dodam że mój plik 1Wire.C jest identyczny z plikiem na stronie http://www.republika.pl/rejestr/ Proszę o podpowiedź :)
  • #16 2343907
    Jacu$
    Poziom 27  
    Posty: 730
    Pomógł: 119
    Ocena: 26
    Oczywiście, że musisz wpisać właściwą częstotliwość kwarcu, dla jakiej kompilator ma wyliczyć zależności czasowe. Bez tego 1-wire działać nie będzie. Powtórzę jeszcze raz: w 1-wire czas ma pierwszorzędne znaczenie.
  • #17 4609528
    krzykoz
    Poziom 12  
    Posty: 61
    Ocena: 7
    Witam! Odgrzebałem trochę temat, ale termometry z Dallasa chyba są i będą jeszcze długo na topie.
    Znalazłem błąd i wiem skąd Tgm-owi pojawiały się same F-y. Otóż błąd tkwił w timingach a szczególnie w procedurze read_bit. Nie wiem, jakiego PIC-a używałeś ale pomiędzy:
    Cytat:
    output_low(DQ); // pull DQ low to start timeslot

    a
    Cytat:
    input(DQ);// then return high

    musi występować conajmniej 1us przerwy.
    W moim przypadku (PIC18F252) cykl zegara wynosi 0.1us (40MHz / 4) więc wprowadziłem delay 18*TCY (bo akurat takie opóźnienie potrzebowałem do LCD).
    Poniżej przedstawiam mój kod:
    
    //////////////////////////////////////////////////////////////////////////////
    // SensorReset - performs a reset on the one-wire bus and
    // returns the presence detect.
    //
    unsigned char SensorReset(void)
       {
    	unsigned char Presence;
    	DQTris = 0;
    	DQ = 0;						//pull DQ line low
    	DelayUs(500);				// leave it low for 480us
    	DQTris = 1;					// allow line to return high
    	DelayUs(70);				// wait for presence
    	Presence = DQ;				// get presence signal
    	DelayUs(300);				// wait for end of timeslot
    	return(Presence);			// presence signal returned
    }                       		// 0=presence, 1 = no part
    
    //////////////////////////////////////////////////////////////////////////////
    // ReadBitFromSensor - reads a bit from the one-wire bus. The delay
    // required more then 1us after timeslot begin, then make the port as Input,
    // wait max 40us and return state od DQ port
    //
    unsigned char ReadBitFromSensor(void)
    {
    	unsigned char i;
    	 DQTris = OUT;				//
    	 DQ = 0;					// pull DQ low to start timeslot
    	 DelayFor18TCY();			// wait 1.8us
    	 DQTris = IN;				// then return high
    	 for (i = 0; i<40; i++);	// delay 20us from start of timeslot
    	 return(DQ);			// return value of DQ line
    } 
    
    //////////////////////////////////////////////////////////////////////////////
    // WriteBitToSensor - writes a bit to the one-wire bus, passed in BitValue.
    // Make the DQ potr Output and reset (0), delay min 1us, then if "1" has to sended make the
    // port as Input and wait 100us, or if "0" has to be sended after min 1us delay
    // keep the reseted output port for 100us, then change direction to IN
    //
    void WriteBitToSensor(unsigned char BitValue)
    {
    	unsigned char i;
    	DQTris = OUT;			//
    	DQ = 0;					// pull DQ low to start timeslot
    	DelayFor18TCY();		// wait 1.8us
    	if(BitValue == 1)
    	{
    		DQTris = IN;			// return DQ high if write 1
    	}
    	DelayUs(100);			// hold value for remainder of timeslot
    	DQTris = IN;
    }
    
    //////////////////////////////////////////////////////////////////////////////
    // ReadByteFromSensor - reads a byte from the one-wire bus.
    //
    unsigned char ReadByteFromSensor(void)
    {
    	unsigned char i;
    	unsigned char Value = 0;
    	for (i=0;i<8;i++)
    	{
    		if(ReadBitFromSensor() == 1)
    		{
    			Value|=0x01<<i;		// reads byte in, one byte at a time and then shifts it left
    		}
    		DelayUs(150);			// wait for rest of timeslot
    	}
    	return(Value);
    	} 
    	
    	//////////////////////////////////////////////////////////////////////////////
    // WriteByteToSensor - writes a byte to the one-wire bus.
    //
    void WriteByteToSensor(unsigned char Value)
    {
    	unsigned char i;
    	unsigned char Temp;
    	for (i=0; i<8; i++) 		// writes byte, one bit at a time
    	{
    		Temp = Value>>i; 		// shifts val right 'i' spaces
    		Temp &= 0x01; 			// copy that bit to temp
    		WriteBitToSensor(Temp); // write bit in temp into
    	}
    	DelayUs(150);
    }
    



    Wszystko działa jak należy...
    Wniosek:
    Zależności czasowe w magistrali 1-wire są bardzo ważne, a kod najlepiej pisać patrząc na wykresy w nocie katalogowej...

    Pozdrawiam!
  • #18 6952217
    mojsamspam
    Poziom 11  
    Posty: 39
    Ocena: 1
    Cytat:

    Zależności czasowe w magistrali 1-wire są bardzo ważne, a kod najlepiej pisać patrząc na wykresy w nocie katalogowej...

    Oj prawda, prawda :). Ja się bujałem z tym kilka dni, aby termometr działał jak należy. Mój kod zczytywał temperaturę w pętli nieskończonej i raz na jakiś czas wynik był niepoprawny (41.2,80.5,125.4,-1023.x,itp. - przy temperaturze pokojowej). Dzisiaj po całym dniu spędzonym przy uC, w końcu udało mi się znaleźć dobrą konfigurację (wszystkie biblioteki od 1wire.c, które znalazłem w sieci nie chciały u mnie działać poprawnie - każda miała inne timingi).

    Mam nadzieję, że się komuś przyda i oszczędzi nerwów.

    
    
    #define WE 4
    #define PORT_1Wire PIND
    #define SET_1Wire DDRD&=~_BV(WE)
    #define CLEAR_1Wire DDRD|=_BV(WE)
    
    unsigned char RESET_PULSE(void)
    {
    	unsigned char PRESENCE=0;
    	int i;
    	CLEAR_1Wire;
    	_delay_us(480);
    	SET_1Wire;
    	_delay_us(15);
    	for(i=0;i<55;i++)
    	{
    		if(bit_is_clear(PORT_1Wire,WE)) PRESENCE=1;
    		_delay_us(1);
    	}
    	_delay_us(200);
    	return PRESENCE;
    }
    
    float getTemp(void)
    {
    unsigned char PRESENCE;
    char temp1=0, temp2=0;
    PRESENCE=RESET_PULSE();
     if(PRESENCE==1)
     {
      send_byte(0xCC);
      send_byte(0x44);
      PRESENCE=RESET_PULSE();
      send_byte(0xCC);
      send_byte(0xBE);
      temp1=read_byte();
      temp2=read_byte();
      PRESENCE=RESET_PULSE();
      float temp=0;
      temp=(float)(temp1+(temp2*256))/16*(-1);
      return temp;
     }
     else
     {
      return 0;
     }
    }
    
    void send(char bit)
    {
    	CLEAR_1Wire;
    	_delay_us(2);
    	if(bit==1) SET_1Wire;
    	_delay_us(100);
    	SET_1Wire;
    
    }
    
    unsigned char read(void)
    {
    	unsigned char i, PRESENCE=0;
    	CLEAR_1Wire;
    	_delay_us(6);
    	SET_1Wire;
    	_delay_us(7);
    	for(i=0;i<50;i++)
    	{
    		if(bit_is_clear(PORT_1Wire,WE)) PRESENCE=1;
    		_delay_us(1);
    	}
    	_delay_us(50);
    	return(PRESENCE);
    }
    
    void send_byte(char wartosc)
    {
    	int i;
    	unsigned char pom;
    	for(i=0;i<8;i++)
    	{
    		pom=wartosc>>i;
    		pom&=0x01;
    		send(pom);
    	}
    }
    
    unsigned char read_byte(void)
    {
    	uint8_t i;
    	unsigned char wartosc=0;
    	for(i=0;i<8;i++)
    	{
    		if(read()) wartosc|=0x01<<i;
    	}
    	return(wartosc);
    }
    


    Poniżej screen z Excela - pomiar od momentu włożenia termometru do zamrażalnika (delikatne wahania spowodowane są (chyba) ?niedokładnością? - poprawcie mnie, jeśli się mylę). W pomiarze wykonano 2246 prób.

    [PIC] PIC C: Nie działa komunikacja 1-Wire z DS1820 – reset nie wykrywa obecności

    Pozdrawiam :)

Podsumowanie tematu

✨ Dyskusja dotyczy problemów z komunikacją magistrali 1-Wire pomiędzy mikrokontrolerem PIC16F870 a czujnikiem temperatury DS1820/DS18S20. Głównym problemem jest brak wykrycia sygnału obecności (presence) po wykonaniu resetu magistrali, co uniemożliwia poprawną komunikację z czujnikiem. Wskazano, że kluczowe jest prawidłowe odmierzanie czasów w procedurze resetu i odczytu bitów, które muszą być dostosowane do częstotliwości taktowania mikrokontrolera (w tym przypadku 4 MHz). Podkreślono, że opóźnienia w mikrosekundach są krytyczne dla protokołu 1-Wire i błędne timingi powodują brak odpowiedzi czujnika. Zaproponowano poprawki w funkcji ow_reset(), m.in. dostosowanie wartości delay_us do zegara 4 MHz oraz poprawne sprawdzanie warunku if (ow_reset()==0). Zwrócono uwagę na konieczność stosowania rezystora podciągającego 4,7 kΩ na linii DQ oraz zasilania czujnika napięciem 5 V. W dyskusji pojawiły się także przykłady kodów i sugestie dotyczące testowania komunikacji poprzez odczyt ROM czujnika. W dalszej części omówiono podobne problemy z timingiem w innych mikrokontrolerach (np. AT89C2051, PIC18F252) oraz konieczność dostosowania definicji częstotliwości kwarcu w plikach źródłowych, aby zapewnić prawidłowe odmierzanie czasu. Podsumowując, prawidłowa implementacja protokołu 1-Wire wymaga precyzyjnego dostosowania opóźnień do częstotliwości taktowania, poprawnego sprawdzania sygnału presence oraz odpowiedniego sprzętowego podłączenia czujnika DS1820/DS18S20.
Wygenerowane przez model językowy.
REKLAMA