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

[C][ATMEGA32] brak komunikacji z DS18B20

simoon87 15 Lis 2010 21:59 2433 7
  • #1 8748702
    simoon87
    Poziom 10  
    Witam, napiąłem program do obsługi termometru cyfrowego DS18B0, program kompiluje się bez błędu a po wgraniu na wyświetlaczu wyświetla się tylko -1.0. Proszę o sprawdzenie kodu bo nie wiem już gdzie jest błąd.


    DS18B20.H
    
    #ifndef ds18b20
    #define ds18b20
    
    #define WE	0
    #define PORT_1WIRE	PINC
    #define SET_1WIRE	DDRC &= ~_BV(WE)
    #define CLEAR_1WIRE	DDRC |= _BV(WE)
    
    void delayms(long t);
    void delayus(long t);
    unsigned char RESET_PULSE(void);
    void send(char bit);
    void send_byte(char wartosc);
    unsigned char read(void);
    unsigned char read_byte(void);
    
    #endif
    


    DS18B20.C
    
    #include <avr/io.h>
    #include <util/delay.h>
    #include "ds18b20.h"
    
    /***************************************		Opoznienia		**********************************/
    
    void delayms(long t)
    {
    	while(t)
    	{
    		_delay_ms(10);
    		t--;
    	}
    }
    void delayus(long t)
    {
    	while(t)
    	{
    		_delay_us(1);
    		t--;
    	}
    }
    
    /***************************************	Magistrala 1-wire 	**********************************/
    	
    unsigned char RESET_PULSE(void)		////reset magistrali i oczekiwanie na impuls PRESENCE
    {
    	char PRESENCE;
    	CLEAR_1WIRE;					//magistrala - stan niski
    	delayus(500);
    	SET_1WIRE;						//magastrala - stan wysoki
    	delayus(30);					//oczekiwanie na stan niski od DS
    	
    	if(bit_is_clear(PORT_1WIRE, WE))//sprawdzamy stan linii (LOW)
    	{
    		PRESENCE = 1;				//1 - odebrano bit
    	}
    	else
    	{
    		PRESENCE = 0;				//0 - stan nieaktywny
    	}
    	
    	delayus(470);					//MASTER na stan wysoki od DS
    	
    	if(bit_is_set(PORT_1WIRE, WE))	//sprawdza stan linii (HIGH)
    	{
    		PRESENCE = 1;
    	}
    	else
    	{
    		PRESENCE=0;
    	}
    	return(PRESENCE);				//zwraca wartosc funkcji
    }
    
    void send(char bit)					////wysyłanie pojedynczego bitu do DS
    {
    	CLEAR_1WIRE;
    	delayus(5);
    
    	if(bit == 1)
    	{
    		SET_1WIRE;					//zwolnienie magistrali - wysylanie 1
    		delayus(80);				//przetrzymanie
    		CLEAR_1WIRE;				//wysylanie zera
    	}
    }
    
    void send_byte(char wartosc)		////wysyla caly bajt na magistrale
    {
    	unsigned char i=0;				//zmienna licznikowa
    	unsigned char pom;				//pomocnicza
    
    	for(i=0; i<8; i++)
    	{
    		pom = wartosc>>i;			//przesuniecie bitowe
    		pom = 0x01;					//skopiowanie bitu do zmiennej pomocniczej
    		send(pom);					//wyslanie bitu na magistrale
    	}
    	delayus(100);
    }
    
    unsigned char read(void)			////zczytuje bit z magistralii
    {
    	unsigned char PRESENCE = 0;
    
    	CLEAR_1WIRE;					//ustawienie w stan niski DS
    	delayus(2);						//oczekiwanie
    	SET_1WIRE;						//zwolnienie magistrali
    	delayus(15);					//oczeliwanie
    
    	if(bit_is_set(PORT_1WIRE, WE))	//odbior 1 lub 0
    	{
    		PRESENCE = 1;
    	}
    	else
    	{
    		PRESENCE = 0;
    	}
    	return(PRESENCE);				//zwracanie wartosci funkcjii
    }
    
    unsigned char read_byte(void)		////zczytuje bajt z magistralii
    {
    	unsigned char i = 0;			//zmienna licznikowa
    	unsigned char wartosc = 0;		//pomocnicza
    
    	for(i=0; i<8; i++)
    	{
    		if(read())
    		{
    			wartosc |= 0x01<<i;		//zczystywanie po jednym bicie
    		}
    		delayus(15);
    	}
    	return(wartosc);				//zwrot wartosci funkcjii			
    }
    


    MAIN.C
    
    #define F_CPU 16000000L
    #include <avr/io.h>
    #include <util/delay.h>
    #include <stdlib.h>
    #include "hd44780.h"
    #include "ds18b20.h"
    
    /***************************************	Zmienne i prototypy 	**********************************/
    void sys_init(void);
    
    char buf[8];
    
    /***************************************		Program glowny	 	**********************************/
    void main(void)
    {
    	unsigned char sprawdz;
    	char LSB = 0, MSB = 0;
    
    	sys_init();
    	for(;;)
    	{
    		sprawdz = RESET_PULSE();
    		if(sprawdz)
    		{
    			send_byte(0xCC);		//SKIP ROM
    			send_byte(0x44);		//CONVERT T
    			delayms(75);			//oczekiwanie - czas konwersji
    			
    			sprawdz = RESET_PULSE();//wysylanie sygnalu reset
    			send_byte(0xCC);		//SKIP ROM
    			send_byte(0xBE);		//READ SCRATCHPAD
    
    			LSB = read_byte();		//odczyta czesci mlodszej
    			MSB = read_byte();		//odczyta czesci starszej
    
    			sprawdz = RESET_PULSE();//zwolnienie magistrali
    			
    			float temp = 0;
    			temp = (float)(LSB | (MSB<<8));
    						
    			dtostrf(temp,1,1,buf);	//konswersja FLOAT na STRING
    			LCD_LOCATE(0,0);
    			lcd_puts(buf);
    			delayms(100);
    		}
    	}
    }
    
    /***************************************		Funkcje 		**********************************/
    void sys_init(void)
    {
    	lcd_init();
        LCD_DISPLAY(LCDDISPLAY);
    	LCD_CLEAR;
    	LCD_LOCATE(0,0);
    }
    




    inventco.eu - regulamin p.11.1. Poprawiłem.
  • #2 8748798
    boogdan
    Poziom 15  
    ja na twoim miejscu nie używałbym jakichś dziwnych wrapperów na wbudowane funkcje opóźnień.
    dla ms zwielokrotniasz czas oczekiwania 10 razy, a dla us to ciężko powiedzieć jak sie funkcja _delay_us zachowa przy opóźnieniu 1us.
    lepiej użyj zamiast swoich funkcji te wbudowane _delay_ms i _delay_us
  • #3 8749252
    hotdog
    Poziom 26  
    Powiedz jakie wartości odczytujesz z czujnika (chodzi mi o wartości binarne zmiennych LSB i MSB).

    temp = (float)(LSB | (MSB<<8)); dziwnie mi to wygląda. jak by tu czegoś brakowało...

    Jeżeli na czujniku rzeczywiście by było -1 to byłby uwalony, ale tutaj ewidentnie masz coś w kodzie skopane.

    Podaj jakie LSB i MSB przyjmuje wartości.

    Pozdrawiam
  • #4 8749734
    simoon87
    Poziom 10  
    boogdan napisał:
    ja na twoim miejscu nie używałbym jakichś dziwnych wrapperów na wbudowane funkcje opóźnień.
    dla ms zwielokrotniasz czas oczekiwania 10 razy, a dla us to ciężko powiedzieć jak sie funkcja _delay_us zachowa przy opóźnieniu 1us.
    lepiej użyj zamiast swoich funkcji te wbudowane _delay_ms i _delay_us


    powodem powstania takich funkcji jest to ze _delay_ms i _delay_us maja swoje ograniczenia wg helpa od AVR-GCC (_delay_ms działa poprawinie do ok.200ms itd)

    hotdog napisał:

    Podaj jakie LSB i MSB przyjmuje wartości.


    no niestety nie wiem jak mam to sprawdzic
  • #5 8749865
    hotdog
    Poziom 26  
    simoon87 napisał:

    no niestety nie wiem jak mam to sprawdzic


    To ja nie wiem jak mam Tobie pomóc ;)

    Wyświetl je na wyświetlaczu albo coś...
  • #6 8749946
    tmf
    VIP Zasłużony dla elektroda
    simoon87 napisał:
    boogdan napisał:
    ja na twoim miejscu nie używałbym jakichś dziwnych wrapperów na wbudowane funkcje opóźnień.
    dla ms zwielokrotniasz czas oczekiwania 10 razy, a dla us to ciężko powiedzieć jak sie funkcja _delay_us zachowa przy opóźnieniu 1us.
    lepiej użyj zamiast swoich funkcji te wbudowane _delay_ms i _delay_us


    powodem powstania takich funkcji jest to ze _delay_ms i _delay_us maja swoje ograniczenia wg helpa od AVR-GCC (_delay_ms działa poprawinie do ok.200ms itd)

    hotdog napisał:

    Podaj jakie LSB i MSB przyjmuje wartości.


    no niestety nie wiem jak mam to sprawdzic


    Przeczytaj lepiej tego hepla dokładniej, bo powtarzasz bajki.
    Twoja funkcja realizująca opóźnienia us działa tak sobie - organizacja pętli zajmuje porównywalny czas z realizacja 1us opóźnienia. Poza tym jak Scypio Afrykański dodam, że już po raz 1001 widzę ten sam pokręcony kod 1-wire :) Czy robiąc copy/paste analizowałeś co ten kod robi?
    To, że masz -1 znaczy najpewniej, że obsługa OW nie działa i na tym się skup.
  • Pomocny post
    #7 8750772
    a2d2a2m
    Poziom 15  
    Jeżeli kolega może podłączyć kwarc 16MHz, to po powrocie z pracy mogę załączyć sprawdzony program termometru z atmegą 32, wspomnianym kwarcem i obsługą LCD 2x16.
    Układ DS18b20, jak inne układy 1-wire wymagają bardzo dokładnych czasów, żeby się poprawnie skomunikować. Ja też trochę powalczyłem zanim zobaczyłem prawidłową temperaturę.
    Zgodnie z obietnicą:
    
    #<include <avr/io.h> 
    #include <avr/interrupt.h> 
    #include <avr/eeprom.h> 
    #include <string.h> 
    //#include <avr/signal.h> 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <avr/pgmspace.h> 
    #include <inttypes.h> 
    //#include <util/delay.h>
    #define f_CPU 16000000UL
    
    ////////////////////termometr////////////////////////////////
    #define WE 0 //czujnik podłączony do portu D pin 0
    #define PORT_1WIRE PIND   
    #define CLEAR_1WIRE DDRD |= _BV(WE)
    #define SET_1WIRE DDRD &=  ~_BV(WE)
    char buf[8];
    
    ////////////////////wyswietlacz/////////////////////////
    #define DDR_DB4 DDRA //konfiguracja portów podłączenia wyświetlacza
    #define PORT_DB4 PORTA 
    #define DB4 PA3 
    #define DDR_DB5 DDRA 
    #define PORT_DB5 PORTA 
    #define DB5 PA4 
    #define DDR_DB6 DDRA 
    #define PORT_DB6 PORTA 
    #define DB6 PA5 
    #define DDR_DB7 DDRA 
    #define PORT_DB7 PORTA 
    #define DB7 PA6 
    #define DDR_RS DDRA 
    #define PORT_RS PORTA 
    #define RS PA1 
    #define DDR_E DDRA 
    #define PORT_E PORTA
    #define E PA2  
    #define SET_DB4 PORT_DB4 |= _BV(DB4) 
    #define CLR_DB4 PORT_DB4 &= ~_BV(DB4) 
    #define SET_DB5 PORT_DB5 |= _BV(DB5) 
    #define CLR_DB5 PORT_DB5 &= ~_BV(DB5) 
    #define SET_DB6 PORT_DB6 |= _BV(DB6) 
    #define CLR_DB6 PORT_DB6 &= ~_BV(DB6) 
    #define SET_DB7 PORT_DB7 |= _BV(DB7) 
    #define CLR_DB7 PORT_DB7 &= ~_BV(DB7) 
    #define SET_E PORT_E |= _BV(E) 
    #define CLR_E PORT_E &= ~_BV(E) 
    #define SET_RS PORT_RS |= _BV(RS) 
    #define CLR_RS PORT_RS &= ~_BV(RS) 
    #define tau0 247
    #define LCD_X 16 
    #define LCD_Y 2 
    
    void waitms(char x)
    {
    unsigned char a,b;
    for( ; x>0;--x)
    
    	for (b=53;b>0;--b)
    	for(a=20;a>0;--a)
    
    		__asm("nop");
    		}
    
    void out_nibble(char x) 
    { 
    CLR_DB4; 
    CLR_DB5; 
    CLR_DB6; 
    CLR_DB7; 
    if(x & _BV(0)) SET_DB4; 
    if(x & _BV(1)) SET_DB5; 
    if(x & _BV(2)) SET_DB6; 
    if(x & _BV(3)) SET_DB7; 
    } 
    
    
    void write_to_lcd(char x) 
    { 
    SET_E; 
    out_nibble(x >> 4); 
    CLR_E; 
    SET_E; 
    out_nibble(x); 
    CLR_E; 
    waitms(1); 
    } 
    
    void write_command(char x) 
    { 
    CLR_RS; 
    write_to_lcd(x); 
    } 
    
    void write_char(char x) 
    { 
    SET_RS; 
    write_to_lcd(x); 
    } 
    
    void write_text(char * s) 
    { 
    while(*s) 
    { 
    write_char(*s); 
    s++; 
    } 
    } 
    
    void lcd_init(void) 
    { 
    DDR_DB4 |= _BV(DB4); 
    DDR_DB5 |= _BV(DB5); 
    DDR_DB6 |= _BV(DB6); 
    DDR_DB7 |= _BV(DB7); 
    DDR_E |= _BV(E); 
    DDR_RS |= _BV(RS); 
    //waitms(15);
     waitms(1);
    CLR_E; 
    CLR_RS; 
    char i; 
    for(i = 0; i < 3; i++) 
    { 
    SET_E; 
    out_nibble(0x03); 
    CLR_E; 
     waitms(1);
    } 
    SET_E; 
    out_nibble(0x02); 
    CLR_E; 
    waitms(1); 
    write_command(0x28); // interfejs 4-bity, 2-linie, znak 5x7 
    write_command(0x08); // wy31cz LCD, kursor i miganie 
    write_command(0x01); // czyoa LCD 
    write_command(0x06); // bez przesuwania w prawo 
    write_command(0x0C); // w31cz LCD, bez kursora i mrugania 
    } 
    
    
    void LCD_xy(uint8_t x, uint8_t y) 
    { 
    switch(y) 
    { 
    case 1: y=0x40; break; 
    case 2: y=0x14; break; 
    } 
    write_command(0x80+y+x); 
    } 
    
    void LCD_clr(void) 
    { 
    write_command(0x01); 
    waitms(1); 
    LCD_xy(0,0); 
    } 
    
    ///////////////////////////////////////////////////termometr///////////////////////////////////////
    void owire_delay(unsigned int __count)
    {
    	__asm__ volatile (
    		"1: sbiw %0,1" "\n\t"
    		"brne 1b"
    		: "=w" (__count)
    		: "0" (__count)
    	);
    }
    
    
    
    
    // reset magistrali 
    unsigned char RESET_PULSE(void) 
    { 
    unsigned char PRESENCE; 
    CLEAR_1WIRE; 
    	owire_delay(1920); 	
    SET_1WIRE; 
    
     owire_delay(120); 	
    if (bit_is_clear(PORT_1WIRE, WE)) {PRESENCE=1;} else {PRESENCE=0;} 
    
    owire_delay(1920);
    if (bit_is_set(PORT_1WIRE, WE)) {PRESENCE=1;} else {PRESENCE=0;} 
    
    
    return PRESENCE; 
    } 
    
    void send(char bit) 
    { 
    //cli();
    CLEAR_1WIRE; 
    
    owire_delay(20); 	
    if(bit==1) 
    SET_1WIRE; 
    
    owire_delay(320); 
    SET_1WIRE; 
    //sei();
    } 
    
    unsigned char read(void) 
    { 
    unsigned char PRESENCE=0; 
    //cli();
    CLEAR_1WIRE; 
     owire_delay(8); 
    SET_1WIRE; 
    owire_delay(60); 
    if (bit_is_set(PORT_1WIRE, WE)) PRESENCE=1; else PRESENCE=0; 
    return (PRESENCE); 
    //sei();
    } 
    
    unsigned  send_byte(char wartosc) 
    { 
    unsigned char i; 
    unsigned char pom; 
    for (i=0; i<8; i++) 
    { 
    pom = wartosc>>i; 
    pom &= 0x01; 
    send(pom); 
    } 
    
     owire_delay(400); 
    } 
    
    
    
    
    unsigned char read_byte(void) 
    { 
    unsigned char i; 
    unsigned char wartosc = 0; 
    for (i=0; i<8; i++) 
    { 
    if(read()) wartosc|=0x01<<i; 
    
    owire_delay(60); 	
    } 
    return (wartosc); 
    } 
    char *tp="                  ";
    
    
    int main (void) 
    { 
    
    unsigned char sprawdz; 
    char temp1=0, temp2=0; 
    
    for(;;) { 
    sprawdz=RESET_PULSE(); 
    if (sprawdz == 1) 
    { 
    
    send_byte(0xCC); 
    send_byte(0x44); 
    owire_delay(3000); 
    
    sprawdz = RESET_PULSE();
    send_byte(0xCC); 
    send_byte(0xBE); 
    temp1=read_byte(); 
    temp2=read_byte(); 
    
    sprawdz=RESET_PULSE(); 
    float temp=0; 
    temp=(float)(temp1+(temp2*256))/16; 
    dtostrf(temp,1,1,buf); 
    
    
    
    LCD_clr();
    lcd_init();
    write_text("Temperatura"); 
    	LCD_xy(0,1);
    	write_text(buf);
    waitms(254);
    
    } 
    else 
    { 
    
    LCD_clr();
    	lcd_init();
    	write_text("brak pomiaru");
    waitms(190);
    } 
    
    } 
    } 

    >

    czujnik zasilany normalnie( nie pasożytniczo).
    W załączniku plik skompilowany


    inventco.eu - proszę używać znaczników CODE. Poprawiłem.
  • #8 8767851
    simoon87
    Poziom 10  
    a2d2a2m wielkie dzięki za pomoc! Dzięki tobie odnalazłem błąd w moim kodzie który polegał na braku } w jednym miejscu:P

    Całej reszcie "psełdopomagaczy" dziękuje za posty nie wnoszące nic do tego tematu (oby jak najmniej takich ludzi na elektrodzie)
REKLAMA