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

[ATmega8][C][DS18B20] Funkcja czytajaca zle działa!

rozumek 25 Lut 2009 13:08 1382 6
REKLAMA
  • #1 6202080
    rozumek
    Poziom 10  
    Pomocy pisze obsługe DS18B20 na ATmega8... i funkcja czytajaca mi nie działa, dobrze, nie zczytuje mi temperatury jak nalezy, własciwie to odbieram jakieś misie;/

    Oto kod mojej funkcji:

    unsigned char read_data_DS18B20(void)
    {
       volatile unsigned char data = 0x00;
       
       for(unsigned char i = 0; i < 8; i++)
       {
        _1_WIRE_DIR |= _BV(_1_WIRE);
        _1_WIRE_OUT &=~ _BV(_1_WIRE);
        _delay_us(5);
        _1_WIRE_DIR &=~ _BV(_1_WIRE);
        _delay_us(15);
        
        if((_1_WIRE_IN & _BV(_1_WIRE)))
        {
         data+=0x80;
        }
        
        data>>=1;
        _delay_us(15);
       }
       
       return data;
    }


    gdzie 1_WIRE_DIR oznacza DDRC, 1_WIRE oznacza 0, 1_WIRE_OUT oznacza PORTC, a 1_WIRE_IN oznacza PINC.

    Prosze pomóżcie, przeleciałęm mase podobnych tematów i starałem sie implementowac tamte rozwiazania i nie bardzo pomogło...
  • REKLAMA
  • #2 6202182
    korneliuszo
    Poziom 17  
    Uważam że błąd jest w timingu

        _1_WIRE_DIR |= _BV(_1_WIRE);
        _1_WIRE_OUT &=~ _BV(_1_WIRE);
        _delay_us(5);
        _1_WIRE_DIR &=~ _BV(_1_WIRE);
        _delay_us(15);
       
        if((_1_WIRE_IN & _BV(_1_WIRE)))
        {
         data+=0x80;
        }
       
        data>>=1;
        _delay_us(15);  


    zamienić na
        _1_WIRE_DIR |= _BV(_1_WIRE);
        _1_WIRE_OUT &=~ _BV(_1_WIRE);
        _delay_us(3);
        _1_WIRE_DIR &=~ _BV(_1_WIRE);
        _delay_us(10);
       
        if((_1_WIRE_IN & _BV(_1_WIRE)))
        {
         data+=0x80;
        }
       
        data>>=1;
        _delay_us(50); 
  • REKLAMA
  • #3 6207712
    rozumek
    Poziom 10  
    dalej nie idzie...
    moze problem tkwi jednak w funki wpisujacej?

    void write_data_DS18B20(unsigned char data)
    {
     volatile unsigned char bit = 0x00;
     
     for(unsigned char i = 0; i < 8; i++)
     {
      bit = 0x01 & data;
    					    
      _1_WIRE_DIR |= _BV(_1_WIRE);
      _1_WIRE_OUT &=~ _BV(_1_WIRE);
      
      if(bit == 0)                         
      {
         _delay_us(80);                  
         _1_WIRE_DIR &=~ _BV(_1_WIRE);
         _delay_us(5);                    
      }
      else                           
      {
         _delay_us(5);                    
         _1_WIRE_DIR &=~ _BV(_1_WIRE);
         _delay_us(80);                   
      }
      data>>=1;
      
     }
    }
  • REKLAMA
  • #4 6208616
    korneliuszo
    Poziom 17  
    Osobiście używam biblioteki RKLibAVR i ona ma już w sobie funkcje do ds'a (używa jednej procedury do wysyłania i odbioru danych) i bez problemu działa.

    W twoich procedurach nie wiem co jest źle (może to wina zasilania ds'a??)
  • REKLAMA
  • #5 6209064
    rozumek
    Poziom 10  
    juz sam nie wiem... mam zasilanie podłaczone normalnie do +5V, wiec teorretycznie nei powinno byc problemu.

    Dodano po 2 [minuty]:

    korneliuszo napisał:
    Osobiście używam biblioteki RKLibAVR i ona ma już w sobie funkcje do ds'a (używa jednej procedury do wysyłania i odbioru danych) i bez problemu działa.

    W twoich procedurach nie wiem co jest źle (może to wina zasilania ds'a??)


    A mógłbyś mi ta biblioteke podrzucic?
  • #7 6227061
    rozumek
    Poziom 10  
    Wiem juz w czym tkwi problem... przy odczycie, zjada mi najmniej znaczący bit

    Dodano po 1 [godziny] 7 [minuty]:

    No jak to mówią... krok po kroczku... i problem sie sam rozwiązał... jak sie okazało problem tkwił w złym umieszczeniu instrukcji



    Tak więc po zrobieniu funkcji czytającej w ten sposób:

    unsigned char read_data_DS18B20(void) 
    { 
       volatile unsigned char data = 0x00; 
        
       for(unsigned char i = 0; i < 8; i++) 
       { 
        data>>=1; 
        _1_WIRE_DIR |= _BV(_1_WIRE); 
        _1_WIRE_OUT &=~ _BV(_1_WIRE); 
        _delay_us(1); 
        _1_WIRE_DIR &=~ _BV(_1_WIRE); 
        _delay_us(10); 
        
        if((_1_WIRE_IN & _BV(_1_WIRE))) 
        { 
         data+=0x80; 
        } 
        
        
        _delay_us(50); 
       } 
        
       return data; 
    }


    Wszystko działa jak nalezy... wystarczyło pomyslec i problem sie sam rozwiązał...

    Także temat można zamknąc... a dla potomnych.... jak ktos bedzie chciał działający kod na DS18B20 to piszcie do mnie!!
REKLAMA