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

[winavr][atmega8][C] DS18b20 Cały czas wyświetla -16.1 st. R

iksmodiw1 19 Lut 2010 00:07 3402 15
  • #1 7716597
    iksmodiw1
    Poziom 11  
    Funkcje do obsługi DS'a

    
    #include <avr/interrupt.h>
    
    #define DQ 		0						// pin danych in/out interfejsu 1-WIRE
    #define SET_DQ 	DDRD &= ~_BV(DQ)
    #define CLR_DQ 	DDRD |= _BV(DQ)
    #define IN_DQ 	PIND & _BV(DQ)
    
    
    
    
    
    //funkcja delay
    void owire_delay(unsigned int __count)
    {
    	__asm__ volatile (
    		"1: sbiw %0,1" "\n\t"
    		"brne 1b"
    		: "=w" (__count)
    		: "0" (__count)
    	);
    }
    
    // funkcja inicjalizująca(zerowanie magistrali)
    void owire_reset()
    {
    	CLR_DQ; 	
    	owire_delay(1920); 	// opóźnienie ok 480us
    	SET_DQ;			
    	owire_delay(1920); 	// opóźnienie ok 480us
    }
    
    // funkcja zapisu bitu na magistralę 1-wire
    void owire_write_bit(char wire_bit)
    {
    	cli(); 				// zablokowanie przerwań
    	CLR_DQ; 		
    	owire_delay(40); 	// opóźnienie 10us
    	if(wire_bit) 
    		SET_DQ; 
    	owire_delay(400);	// opóźnienie 100us
    	SET_DQ; 		
    	sei(); 				// odblokowanie przrerwań
    }
    
    // funkcja odczytu bitu z magistrali 1-wire
    char owire_read_bit(void)
    {
    	cli();				// zablokowanie przerwań
    	CLR_DQ;
    	owire_delay(4);		// opóźnienie 1us	
    	SET_DQ;
    	owire_delay(40); 	// opóźnienie 10us
    	sei();				// odblokowanie pzrerwań
    	if(IN_DQ) 
    		return 1; 
    	else 
    		return 0;
    }
    
    // funkcja odczytu bajtu z magistrali 1-wire
    unsigned char owire_read_byte(void)
    {
    	unsigned char licznik98;
    	unsigned char temp98 = 0;
    	for (licznik98=0;licznik98<8;licznik98++)
    	{
    		if(owire_read_bit()) 
    			temp98|=0x01<<licznik98;
    		owire_delay(200);// opóźnienie 50us
    	}
    	return temp98;
    }
    
    // funkcja zapisu bajtu na magistralę 1-wire
    void owire_write_byte(char wire_wartosc)
    {
    	unsigned char licznik98;
    	unsigned char temp98;
    	for (licznik98=0; licznik98<8; licznik98++)
    	{
    		temp98 = wire_wartosc >> licznik98;
    		temp98 &= 0x01;
    		owire_write_bit(temp98);
    	}
    	owire_delay(20);	// opóźnienie 5us
    }
    
    
    


    A to mam w main:

    
     for(;;) { 
          
    		 owire_reset; 
             owire_write_byte(0xCC); 
             owire_write_byte(0x44); 
             //_delay_ms(750); 
    
             owire_reset; 
             owire_write_byte(0xCC); 
             owire_write_byte(0x44); 
             temp1=owire_read_byte(); 
             temp2=owire_read_byte(); 
    
             owire_reset; 
             float temp=0; 
             temp=(float)(temp1+(temp2*256))/16; 
             dtostrf(temp,1,1,buf);
    		//itoa(temp,buf,10)
             LCDPutStr(buf, 100, 50, LARGE, RED, WHITE);  
             _delay_ms(1000); 
       }


    Problem jest taki, że cały czas wyświetla -16.1 stopnia. Podłączyłem innego DA'a i to samo. Dodam jeszcze że kod pochodzi od jednego użytkownika z forum. U niego działa z kwarcem 16MHz i z odpowiednimi opoźnieniami. U mnie uC jest z zewnętrznym kwarcem 16MHz.
  • #2 7716686
    Kabuto15
    Poziom 19  
    Czy jesteś pewien, że funkcja owire_reset powinna tak wyglądać jak w Twoim kodzie ? Gdzie masz wykrywanie impulsu tzw. Presence Impulse ? Co to za dziwne nazwy zmiennych w stylu: licznik98 ? I to blokowanie przerwań. Poszukaj lepszego kodu/wsadu.
  • #3 7717267
    tmf
    VIP Zasłużony dla elektroda
    Zmien owire_delay na funkcje inline - inaczej generowane krotkie opoznienia rzedu 1us sa super niedokladne (wez pod uwage, ze musisz wykonac mnowstwo instrukcji wywolujacych funkcje). Po rozpoczeciu konwersji musisz miec opoznienie (to co jest zakomentowane), inaczej uklad nie zdazy podac wynikow. Podaje wtedy stala wartosc (do poolingu), stad moze masz ciagle ta sama temp.
  • #4 7719506
    iksmodiw1
    Poziom 11  
    Teraz tak wykombinowałem. I dalej -16.1 stopnia.

    #include <avr/io.h>
    #include <stdio.h>
    
    #define PIN_1WIRE 				0
    #define PORT_1WIRE 				PIND
    #define OUT_1WIRE_LOW   		PORT_1WIRE &=~(1<<PIN_1WIRE);
    #define OUT_1WIRE_HIGHT			PORT_1WIRE |=1<< PIN_1WIRE;
    #define DIR_1WIRE_IN			DDRD &=~(1<<PIN_1WIRE);
    #define DIR_1WIRE_OUT			DDRD |= 1<<PIN_1WIRE;
    
    char cStringBuffer[8];
    
    unsigned char uc1Wire_ResetPulse()
    {
    unsigned char ucPresenceImpulse;
    
    OUT_1WIRE_LOW;				//ustaw port na stan niski
    DIR_1WIRE_OUT;				//kierunek pinu na: wyjście
    _delay_us(500);				//oczekiwanie 500us		
    DIR_1WIRE_IN;				//kierunek pinu na: wejście
    _delay_us(30);				//oczekiweanie 30us
    
    if (bit_is_clear(PORT_1WIRE, PIN_1WIRE))		//sprawdzamy poziom lini
    	ucPresenceImpulse = 1;						//1-obebrano bit PRESENCE
    else
    	ucPresenceImpulse = 0;						//stan nieaktywności
    	
    _delay_us(470);									//oczekiwanie na mastera 470
    
    if (bit_is_set(PORT_1WIRE, PIN_1WIRE))
    	ucPresenceImpulse = 1;
    else
    	ucPresenceImpulse = 0;
    	
    return ucPresenceImpulse;
    }
    
    //Funkcja wysyłająca na magistralę pojedyńczy bit
    void uc1Wire_SendBit(char cBit)
    {
    DIR_1WIRE_OUT;
    _delay_us(5);			
    
    if (cBit == 1)
    	DIR_1WIRE_IN;
    	
    	_delay_us(80);			
    	DIR_1WIRE_IN;
    }
    
    
    //Funkcja odbiera bit z magistrali
    unsigned char uc1Wire_ReadBit()
    {
    unsigned char ucBit;
    
    DIR_1WIRE_OUT;
    _delay_us(2);						
    DIR_1WIRE_IN;
    _delay_us(15);						
    
    if (bit_is_set(PORT_1WIRE, PIN_1WIRE))
    	ucBit = 1;
    else
    	ucBit = 0;
    
    return ucBit;
    }
    
    //Funkcja wysyła bajt na magistralę
    void uc1Wire_SendByte(char ucByteValue)
    {
    unsigned char ucCounter;
    unsigned char ucValueToSend;
    
    for (ucCounter=0; ucCounter<8; ucCounter++)
    	{
    	ucValueToSend = ucByteValue >> ucCounter;
    	ucValueToSend &= 0x01;
    	uc1Wire_SendBit(ucValueToSend);
    	}
    _delay_us(100);								
    }
    
    //Funkcja odbiera bajt z magistrali
    unsigned char uc1Wire_ReadByte()
    {
    unsigned char ucCounter;
    unsigned char ucReadByte = 0;
    
    for (ucCounter=0; ucCounter<8; ucCounter++)
    	{
    	if (uc1Wire_ReadBit())
    		ucReadByte|=0x01 << ucCounter;
    		_delay_us(15);						
    	}
    return ucReadByte;
    }
    


    W main:

    	unsigned char ucReset;
    	float temp=0;
        char temp1=0, temp2=0; 
          
       for(;;) { 
       
          ucReset = uc1Wire_ResetPulse();
    	  if (ucReset == 1)
    		{
    		 uc1Wire_SendByte(0XCC); 
             uc1Wire_SendByte(0X44);
     
             _delay_ms(750); 
    		 
             ucReset = uc1Wire_ResetPulse();
    		 
             uc1Wire_SendByte(0XCC); 
             uc1Wire_SendByte(0XBE); 
    		 
             temp1=uc1Wire_ReadByte(); 
             temp2=uc1Wire_ReadByte();
     
             ucReset = uc1Wire_ResetPulse(); 
    		 
             temp=(float)(temp1+(temp2 << 8))/16;
      
             dtostrf(temp,1,1,cStringBuffer);
    		//itoa(temp,cStringBuffer,10);
             LCDPutStr(cStringBuffer, 100, 50, LARGE, RED, WHITE);  
             _delay_ms(200);
    		}
    		else
    		{
    		LCDPutStr("Cisza", 100, 50, LARGE, RED, WHITE); 
    		}
       }
  • #5 7719859
    morson
    Poziom 14  
    Zerknij na komentarze /*..*/

    #include <avr/io.h>
    #include <stdio.h>
    
    #define PIN_1WIRE 				0
    #define PORT_1WIRE 				PIND
    #define OUT_1WIRE_LOW   		PORT_1WIRE &=~(1<<PIN_1WIRE); /* Bez sensu, po co zapisywać do PIND */
    #define OUT_1WIRE_HIGHT			PORT_1WIRE |=1<< PIN_1WIRE; /* jak wyżej */
    #define DIR_1WIRE_IN			DDRD &=~(1<<PIN_1WIRE);
    #define DIR_1WIRE_OUT			DDRD |= 1<<PIN_1WIRE;
    
    char cStringBuffer[8];
    
    unsigned char uc1Wire_ResetPulse()
    {
    unsigned char ucPresenceImpulse;
    
    OUT_1WIRE_LOW;				//ustaw port na stan niski /* linijka bez sensu */
    /* wyłącz przerwania, bo inaczej Ci się czasy rozjadą
     uint8_t sreg = SREG;
     cli();
    */
    DIR_1WIRE_OUT;				//kierunek pinu na: wyjście
    _delay_us(500);				//oczekiwanie 500us		
    DIR_1WIRE_IN;				//kierunek pinu na: wejście
    _delay_us(30);				//oczekiweanie 30us /* odczekaj 70 */
    
    if (bit_is_clear(PORT_1WIRE, PIN_1WIRE))		//sprawdzamy poziom lini
    	ucPresenceImpulse = 1;						//1-obebrano bit PRESENCE
    else
    	ucPresenceImpulse = 0;						//stan nieaktywności
    	
    _delay_us(470);									//oczekiwanie na mastera 470
    
    /* niema sensu sprawdzać 2 raz
    if (bit_is_set(PORT_1WIRE, PIN_1WIRE))
    	ucPresenceImpulse = 1;
    else
    	ucPresenceImpulse = 0;
    */
    /* włączanie przerwań
     SREG = sreg;
    */
    return ucPresenceImpulse;
    }
    
    //Funkcja wysyłająca na magistralę pojedyńczy bit
    void uc1Wire_SendBit(char cBit)
    {
    /* 
    uint8_t sreg = SREG;
    cli();
    */
    DIR_1WIRE_OUT;
    _delay_us(5);			
    
    if (cBit == 1)
    	DIR_1WIRE_IN;
    	
    	_delay_us(80);	
    	DIR_1WIRE_IN;
    /* odczekanie po bicie
    _delay_us(30);
    SREG = sreg;
    */
    }
    
    
    //Funkcja odbiera bit z magistrali
    unsigned char uc1Wire_ReadBit()
    {
    /* przerwania
    uint8_t sreg = SREG;
    cli();
    */
    unsigned char ucBit;
    
    DIR_1WIRE_OUT;
    _delay_us(2);						
    DIR_1WIRE_IN;
    _delay_us(15);						
    
    if (bit_is_set(PORT_1WIRE, PIN_1WIRE))
    	ucBit = 1;
    else
    	ucBit = 0;
    
    /* brakuje tu oczekiwania na zakończenie cyklu
    _delay_us(75);
    SREG = sreg;
    */
    
    return ucBit;
    }
    
    //Funkcja wysyła bajt na magistralę
    void uc1Wire_SendByte(char ucByteValue)
    {
    unsigned char ucCounter;
    unsigned char ucValueToSend;
    
    for (ucCounter=0; ucCounter<8; ucCounter++)
    	{
    	ucValueToSend = ucByteValue >> ucCounter;
    	ucValueToSend &= 0x01;
    	uc1Wire_SendBit(ucValueToSend);
    	}
    _delay_us(100);								
    }
    
    //Funkcja odbiera bajt z magistrali
    unsigned char uc1Wire_ReadByte()
    {
    unsigned char ucCounter;
    unsigned char ucReadByte = 0;
    
    for (ucCounter=0; ucCounter<8; ucCounter++)
    	{
    	if (uc1Wire_ReadBit())
    		ucReadByte|=0x01 << ucCounter;
    		_delay_us(15);						
    	}
    return ucReadByte;
    }
    


    W main:

    	unsigned char ucReset;
    	float temp=0;
        char temp1=0, temp2=0; 
          
       for(;;) { 
       
          ucReset = uc1Wire_ResetPulse();
    	  if (ucReset == 1)
    		{
    		 uc1Wire_SendByte(0XCC); 
             uc1Wire_SendByte(0X44);
     
             _delay_ms(750); 
    		 
             ucReset = uc1Wire_ResetPulse();
    		 
             uc1Wire_SendByte(0XCC); 
             uc1Wire_SendByte(0XBE); 
    		 
             temp1=uc1Wire_ReadByte(); 
             temp2=uc1Wire_ReadByte();
     
             ucReset = uc1Wire_ResetPulse(); 
    		 
             temp=(float)(temp1+(temp2 << 8))/16;
      
             dtostrf(temp,1,1,cStringBuffer);
    		//itoa(temp,cStringBuffer,10);
             LCDPutStr(cStringBuffer, 100, 50, LARGE, RED, WHITE);  
             _delay_ms(200);
    		}
    		else
    		{
    		LCDPutStr("Cisza", 100, 50, LARGE, RED, WHITE); 
    		}
       }


    Powinno chodzić po poprawkach
  • #6 7719952
    tmf
    VIP Zasłużony dla elektroda
    iksmodiw1: Juz chyba po raz 3 w ostatnim czasie widze ten kod prezentowany przez roznych uzytkownikow, ktorych laczy wspolny problem - to nie dziala :) Przejrzyj w ktoryms z watkow, tam byly wyszczegolnione wszystkie nonsensy w tym kodzie.
  • #7 7721708
    iksmodiw1
    Poziom 11  
    Przejrzałem troche stron i nic konkretnego nie znalazłem oprócz tego
    
    #define ONEWIRE_PIN PB2 
    #define ONEWIRE_PORT PINB 
    #define ONEWIRE_DDR DDRB 
    
    static uint8_t onewire_reset() 
    { 
     ONEWIRE_DDR |= (1<<ONEWIRE_PIN); 
     _delay_us(480); 
     ONEWIRE_DDR &= ~(1<<ONEWIRE_PIN); 
     _delay_us(70); 
     uint8_t ret = ~(ONEWIRE_PORT & (1<<ONEWIRE_PIN)); 
     _delay_us(410); 
     return ret; 
    } 
    
    static void _onewire_write_bit(uint8_t value) 
    { 
     uint8_t sreg = SREG; 
     cli(); 
     ONEWIRE_DDR |= (1<<ONEWIRE_PIN); 
     _delay_us(1); 
     if(value) 
     { 
      ONEWIRE_DDR &= ~(1<<ONEWIRE_PIN); 
      _delay_us(59); 
     } 
     else 
     { 
      _delay_us(59); 
      ONEWIRE_DDR &= ~(1<<ONEWIRE_PIN); 
     } 
     SREG = sreg; 
     _delay_us(30); 
    } 
    
    static uint8_t _onewire_read_bit() 
    { 
     uint8_t sreg = SREG; 
     cli(); 
     ONEWIRE_DDR |= (1<<ONEWIRE_PIN); 
     _delay_us(1); 
     ONEWIRE_DDR &= ~(1<<ONEWIRE_PIN); 
     _delay_us(15); 
     uint8_t ret = ONEWIRE_PORT & (1<<ONEWIRE_PIN); 
     SREG = sreg; 
     _delay_us(75); 
     return ret; 
    } 
    
    static void onewire_write_byte(uint8_t value) 
    { 
     for(uint8_t i = 0; i < 8; i++) 
     { 
      _onewire_write_bit(value & 0x01); 
      value = value >> 1; 
     } 
    } 
    
    static uint8_t onewire_read_byte() 
    { 
     uint8_t ret = 0; 
     for(uint8_t i = 0; i < 8; i++) 
     { 
      ret = ret >> 1; 
      if(_onewire_read_bit()) ret |= 0x80; 
     } 
     return ret; 
    }
    

    Na tym kodzie oczywiście po zmianie portów nie znajduje DS'a. A co do poprzedniego zastosowałem sie co do poprawek + zmieniłem w uc1Wire_ReadByte
    linijkę na taką:
    ucReadByte|=0x01 >> ucCounter;

    I teraz pokazuje temperaturę 16 stopni.
  • #8 7722147
    morson
    Poziom 14  
    Zastanawia mnie czy masz wyprowadzenie 1wire podwieszone rezystorem np 4,7k do +.
    Spróbuj ustawić oscylator na wewnętrzny 8MHz i ustawić odpowiednio F_CPU.
    Powyższy kod chodził mi (i nie tylko) w niejednym urządzeniu, więc wg mnie masz coś skopane w urządzeniu.

    I spróbuj kod
    
    if(onewire_reset()) // niekoniecznie onewire_reset() == 1, ale zawsze jeśli znajdzie jest > 0
    {
     onewire_write_byte(0xCC);
     onewire_write_byte(0x44);
     _delay_ms(750);
     onewire_reset();
     onewire_write_byte(0xCC);
     onewire_write_byte(0xBE);
     temp1 = onewire_read_byte();
     temp2 = onewire_read_byte();
     ... // ciąg dalszy
    
  • #9 7722650
    iksmodiw1
    Poziom 11  
    Termometr mam dobrze podłączony z rezystorem 4,7k. Zmieniłem ten warunek i termometr pokazuje nieszczęsne -16.1 stopnia. Zauważyłem że nawet gdy nie jest podłączony DS to też pokazuje -16.1. Częstotliwości też zmieniałem na 8MHz i to nic nie dało.A napewno się zmieniała bo było widaś np. po rysującum się tle.
  • #10 7731487
    iksmodiw1
    Poziom 11  
    Problemu dalej nie rozwiązałem. Poniżej zamieszczam kod. Przy ustawieniu atmegi na 8MHz (fusy jak i w kodzie) temperatura wynosi 0, a gdy atmega pracuje z zegarem 1 MHz (default) temperatura jest pokazywana 85 stopni.Po odłączeniu DS'a pokazuje 0 stopni, czyli coś z niego szczytuje. Ale zmiana czasów nic nie daje, cały czas takie same wyniki. Wszystko kilka razy sprawdzałem, przepinałem na różne porty, podłączałem kilka termometrów. Napięcie na na nóżkach termometru wynosi około 4,9 V oczywiście jest podwieszony 4,7K rezystorem do Vcc +5V. Układ pasożytniczy.Oczywiście na razie 1 termometr więc całość kodu sie nie wykonuje.

    W main:
    char temp[10];
    int16_t temperatura; 
    for(;;){
    onewire_reset();
    DS18B20_start_conv(0); 
    _delay_ms(750);
    onewire_reset(); 
    DS18B20_read_scratchpad(0, (uint8_t *)&temperatura, 2); 
    dtostrf(temperatura,1,1,temp);
    LCDPutStr(temp, 100, 30, LARGE, RED, WHITE);
    LCDPutStr("*C", 100, 65, LARGE, RED, WHITE);
    }


    A tu funkcje:
    
    #ifndef _AVR_DS18B20_
    #define _AVR_DS18B20_
    
    #include "1wire.c"
    
    static void DS18B20_start_conv(uint8_t *id)
    {
     onewire_write_command(id);
     //onewire_write_byte(0xCC);
     onewire_write_byte(0x44);
    }
    
    static void DS18B20_read_scratchpad(uint8_t *id, uint8_t *data, uint8_t count)
    {
     onewire_write_command(id);
     
     onewire_write_byte(0xBE);
     while(count--)
      *data++ = onewire_read_byte();
    }
    
    static void DS18B20_write_scratchpad(uint8_t *id, uint8_t *data, uint8_t count)
    {
     onewire_write_command(id);
     onewire_write_byte(0x4E);
     while(count--)
      onewire_write_byte(*data++);
    }
    
    #endif
    


    
    #ifndef _AVR_ONEWIRE_
    #define _AVR_ONEWIRE_
    
    #include <avr/interrupt.h>
    
    #ifdef ONEWIRE_CRC
    #include <avr/pgmspace.h>
    #endif
    #include <util/delay.h>
    
    #define ONEWIRE_SEARCH_ROM 0xF0
    #define ONEWIRE_NO_DEVICES 0xFF
    #define ONEWIRE_DATA_ERROR 0xFE
    #define ONEWIRE_CRC_ERROR 0xFD
    #define ONEWIRE_OK 0x00
    
    //  to odpowiednio do wybranego wyprowadzenia (musi być podwieszone rezystorem do +) 
    #define ONEWIRE_PORT PINB 
    #define ONEWIRE_DDR DDRB 
    #define ONEWIRE_PIN PB0
    
    uint8_t _onewire_LastDevice;
    uint8_t _onewire_LastDiscrepency;
    uint8_t _onewire_LastFamilyDiscrepency;
    uint8_t *_onewire_last_buffer;
    
    static uint8_t onewire_reset()
    {
     ONEWIRE_DDR |= (1<<ONEWIRE_PIN);
     _delay_us(480);	//480
     ONEWIRE_DDR &= ~(1<<ONEWIRE_PIN);
     _delay_us(70);		//70
     uint8_t ret = ~(ONEWIRE_PORT & (1<<ONEWIRE_PIN));
     _delay_us(410);	//410
     return ret;
    }
    
    static void _onewire_write_bit(uint8_t value)
    {
     uint8_t sreg = SREG;
     cli();
     ONEWIRE_DDR |= (1<<ONEWIRE_PIN);
     _delay_us(1);		//1
     if(value)
     {
      ONEWIRE_DDR &= ~(1<<ONEWIRE_PIN);
      _delay_us(59);		//59
     }
     else
     {
      _delay_us(59);		//59
      ONEWIRE_DDR &= ~(1<<ONEWIRE_PIN);
     }
     SREG = sreg;
     _delay_us(30);
    }
    
    static uint8_t _onewire_read_bit()
    {
     uint8_t sreg = SREG;
     cli();
     ONEWIRE_DDR |= (1<<ONEWIRE_PIN);
     _delay_us(1);
     ONEWIRE_DDR &= ~(1<<ONEWIRE_PIN);
     _delay_us(15);
     uint8_t ret = ONEWIRE_PORT & (1<<ONEWIRE_PIN);
     SREG = sreg;
     _delay_us(75);
     return ret;
    }
    
    static void onewire_write_byte(uint8_t value)
    {
    uint8_t i;
     for(i = 0; i < 8; i++)
     {
      _onewire_write_bit(value & 0x01);
      value = value >> 1;
     }
    
    }
    
    static uint8_t onewire_read_byte()
    {
    uint8_t i;
     uint8_t ret = 0;
     for(i = 0; i < 8; i++)
     {
      ret = ret >> 1;
      if(_onewire_read_bit()) ret |= 0x80;
    
     }
     return ret;
    }
    
    static void onewire_write_command(uint8_t *id)
    {
     onewire_reset();
     if(id)
     {
     uint8_t i;
      onewire_write_byte(0x55);
      for(i = 0; i < 8; i++)
       onewire_write_byte(*id++);
     }
     else
     {
      onewire_write_byte(0xCC);
     }
    }
    
    #ifdef ONEWIRE_CRC
    
    uint8_t PROGMEM _onewire_crc_table[] = {
            0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
          157,195, 33,127,252,162, 64, 30, 95,  1,227,189, 62, 96,130,220,
           35,125,159,193, 66, 28,254,160,225,191, 93,  3,128,222, 60, 98,
          190,224,  2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
           70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89,  7,
          219,133,103, 57,186,228,  6, 88, 25, 71,165,251,120, 38,196,154,
          101, 59,217,135,  4, 90,184,230,167,249, 27, 69,198,152,122, 36,
          248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91,  5,231,185,
          140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
           17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
          175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
           50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
          202,148,118, 40,171,245, 23, 73,  8, 86,180,234,105, 55,213,139,
           87,  9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
          233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
          116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
    
    static void _onewire_crc8(uint8_t *crc, uint8_t value)
    {
     *crc = pgm_read_byte(&_onewire_crc_table[*crc ^ value]);
    }
    
    #endif
    
    static void onewire_findinit()
    {
     _onewire_LastDevice = 0;
     _onewire_LastDiscrepency = 0;
     _onewire_LastFamilyDiscrepency = 0;
     _onewire_last_buffer = 0;
    }
    
    static uint8_t _onewire_search_rom(uint8_t *buffer)
    {
     uint8_t id_bit_number = 1;
     uint8_t last_zero = 0;
     uint8_t rom_byte_number = 0;
     uint8_t search_result = ONEWIRE_NO_DEVICES;
     uint8_t id_bit, cmp_id_bit;
     uint8_t rom_byte_mask = 1;
     uint8_t search_direction;
    #ifdef ONEWIRE_CRC
     uint8_t crc8 = 0;
    #endif
     if(!_onewire_LastDevice)
     {
      if(!onewire_reset())
      {
       onewire_findinit();
       return ONEWIRE_NO_DEVICES;
      }
      onewire_write_byte(ONEWIRE_SEARCH_ROM);
      do
      {
       id_bit = _onewire_read_bit();
       cmp_id_bit = _onewire_read_bit();
       if(id_bit && cmp_id_bit)
        return ONEWIRE_DATA_ERROR;
       else
       {
        if(id_bit | cmp_id_bit)
         search_direction = id_bit;
        else
    	{
    	 if(id_bit_number < _onewire_LastDiscrepency)
    	 {
    	  if(_onewire_last_buffer)
    	   search_direction = (_onewire_last_buffer[rom_byte_number] & rom_byte_mask);
          else
    	   search_direction = (buffer[rom_byte_number] & rom_byte_mask);
         }
         else
    	  search_direction = id_bit_number == _onewire_LastDiscrepency;
         if(search_direction == 0)
    	 {
    	  last_zero = id_bit_number;
    	  if(last_zero < 9)
    	   _onewire_LastFamilyDiscrepency = last_zero;
         }
        }
    	if(search_direction)
    	 buffer[rom_byte_number] |= rom_byte_mask;
        else
    	 buffer[rom_byte_number] &= ~rom_byte_mask;
        _onewire_write_bit(search_direction);
        id_bit_number++;
    	rom_byte_mask <<= 1;
    	if(rom_byte_mask == 0)
    	{
    	 rom_byte_mask = 1;
    #ifdef ONEWIRE_CRC
         _onewire_crc8(&crc8, buffer[rom_byte_number]);
    #endif
    	 rom_byte_number++;
        }
       }
      }
      while(rom_byte_number < 8);
      if(id_bit_number > 64)
      {
       _onewire_LastDiscrepency = last_zero;
       if(_onewire_LastDiscrepency == 0)
       {
        _onewire_LastDevice = 1;
       }
       search_result = ONEWIRE_OK;
      }
      if(search_result != ONEWIRE_OK || !buffer[0])
      {
       onewire_findinit();
       search_result = ONEWIRE_DATA_ERROR;
      }
    #ifdef ONEWIRE_CRC
      if(crc8 != 0)
      {
       onewire_findinit();
       search_result = ONEWIRE_CRC_ERROR;
      }
    #endif
     }
     _onewire_last_buffer = buffer;
     return search_result;
    }
    
    static inline uint8_t onewire_find(uint8_t *buffer)
    {
     return _onewire_search_rom(buffer);
    }
    
    #endif
    
  • #12 7731861
    morson
    Poziom 14  
    Piszą także
    
    When the user request delay which exceed the maximum possible one, _delay_ms() provides a decreased resolution functionality. In this mode _delay_ms() will work with a resolution of 1/10 ms, providing delays up to 6.5535 seconds (independent from CPU frequency). The user will not be informed about decreased resolution.
    
  • #14 7731906
    Konto nie istnieje
    Poziom 1  
  • #15 7731910
    michalko12
    Specjalista - Mikrokontrolery
    A najlepsze z tego wszystkiego jest to:

    
    char temp[10]; 
    int16_t temperatura;
    ...
    DS18B20_read_scratchpad(0, (uint8_t *)&temperatura, 2); 
    dtostrf(temperatura,1,1,temp);
  • #16 7733960
    iksmodiw1
    Poziom 11  
    atom1477 napisał:
    Ale już miałeś 85*C. Co zmieniłeś że masz 0,0*C? Bo napisałeś "I dalej to samo 0,0 stopnia" czyli rozumiem że przed zmianą opóźnienia też miałeś 0,0. A powinieneś testować to na kodzie który dawał wynik 85*C.
    Czyli ostatecznie: wróć do kodu który dawał wynik 85*C i to w nim zmień opóźnienie na to opóźnienie w pętli.


    85 stopni pokazuje gdy uC jest taktowany 1MHz, a 0 stopni gdy 8MHz.

    Zmieniałem opóźnienie w petli dla tych 85 stopni i dalej to samo.

    Dodano po 5 [godziny] 7 [minuty]:

    :D:D:D Wszystko działa.

    To w main
     // odczytanie temperatury na czujniku 
       unsigned char lsb = 0;         // młodsze bity odczytane z czujnika temperatury       
       unsigned char msb = 0;         // starsze bity odczytane z czujnika temperatury 
       float temp;
       int k;
       char cStringBuffer[8];
    for(;;){
       owire_reset();               // sekwencja inicjalizująca 
       owire_write_byte(0xCC);         // rozkaz pomiń ROM 
       owire_write_byte(0x44);         // rozkaz konwertuj temperaturę 
       _delay_ms(750);
       owire_reset(); 
       owire_write_byte(0xCC);         // rozkaz pomiń ROM 
       owire_write_byte(0xBE);         // rozkaz umożliwiający odczytanie temperatury 
       lsb = owire_read_byte();      // odczytanie młodszych bitów temperatury 
       msb = owire_read_byte();      // odczytanie starszych bitów temperatury 
        
       
    	temp=(float)(lsb+(msb<<8))/16; 
      
        dtostrf(temp,1,1,cStringBuffer);
    	LCDPutStr(cStringBuffer, 100, 30, LARGE, RED, WHITE);
    	LCDPutStr("*C", 100, 70, LARGE, RED, WHITE); 
     }


    A w załączniku funkcje.

    Można zmienić funkcje konwertującą temp. na inną bo ta jest pamięciożerna.
    Czasy ustawione dla uC 16MHz, ale bardzo łatwo można zmienić.

    A problemem okazało się że w podłączeniu pasożytniczym odczytywało 85 stopni po czym zmierzyłem napięcie na ds'ie i się okazało 1,8 V:?:.Podłączyłem 3 przewodami i hula.
REKLAMA