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

Atmega16 problem z transmisja 1-Wire

zebra_elaktra 05 Mar 2009 16:19 1677 2
  • #1 6239903
    zebra_elaktra
    Poziom 10  
    Mam podlaczony do Atmegi16 LCD HD44780 i DS18B20 (pod pin PD0). Nie dziala mi poprawnie transmisja 1-wire. Caly czas na wyswietlaczu wyswietlona temperatura to -16.1 (a powinno wskazywac ok. 25). Prosze o jakas podpowiedz
    
    #include <avr/io.h>
    #include <avr/delay.h>
    #include <stdlib.h>
    
    //LCD
    #define LCD  PORTA
    #define E  3
    #define RS  2
    #define SET_E   LCD |= _BV(E)
    #define CLR_E   LCD &= ~_BV(E)
    #define SET_RS  LCD |= _BV(RS)
    #define CLR_RS  LCD &= ~_BV(RS)
    //1-WIRE
    #define WE 0
    #define SET_1wire DDRD&=~_BV(WE)
    #define CLEAR_1wire DDRD|=_BV(WE)
    #define PORT_1wire PIND
    #define F_CPU 16000000UL
    float temp=0;
    char buf[8];
    
    
    void write_to_lcd(char x){
    	SET_E; 
    	LCD = ((LCD & 0x0F) | (x & 0xF0)); 
    	CLR_E; 
    	SET_E; 
    	LCD = ((LCD & 0x0F) | ((x & 0x0F) << 4)); 
    	CLR_E; 
    }
    
    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){
    	write_command(0x01); //1 czysci
    	_delay_ms (10);
    	while(*s){
    		write_char(*s); 
    	  	s++; 
    		_delay_ms (1);
    	}
    }
    
    void lcd_init(void){
    	int x;
    	int i; 
    
    	for(i = 0; i < 3; i++){
    		write_command(0x3F); 
    		_delay_ms (10);
    	}
    	for(i = 0; i < 2; i++){
    		write_command(0x2E); 
    		_delay_ms (10);
       }
    
    	write_command(0x2C); //DL=0, N=1, F=0, 101100
    	_delay_ms (10);
    	write_command(0x06); // i/d=1,s=0,   110
    	_delay_ms (10);
    	write_command(0x01); //1 czysci
    	_delay_ms (10);
    	write_command(0x0C); //d=1.c=1,b=0, 1110
    	_delay_ms (10);
    	write_command(0x80); //d=1.c=1,b=0, 1110
    	_delay_ms (10);
    
    }
    
    
    //---------------------------------1-WIRE-----------------------------
    unsigned char RESET_PULSE(void){
    
    unsigned char PRESENCE;
    	CLEAR_1wire;
    	//opoznienie(500);
    	_delay_us (500);
    	SET_1wire;
    	//opoznienie(30);
    	_delay_us (30);
    	if(bit_is_clear(PORT_1wire, WE)){PRESENCE=1;} else {PRESENCE=0;}
    	//opoznienie(470);
    	_delay_us (470);
    	if(bit_is_set(PORT_1wire, WE)){PRESENCE=1;} else {PRESENCE=0;}
    
    	return PRESENCE;
    }
    
    void send(char bit){
    
    	CLEAR_1wire;
    	//opoznienie(5);
    	_delay_us (5);
    	if(bit==1)
    		SET_1wire;
    		_delay_us (80);
    		SET_1wire;
    
    }
    
    unsigned char read (void){
    	unsigned char PRESENCE=0;
    
    	CLEAR_1wire;
    //	opoznienie(2);
    	_delay_us (2);
    	SET_1wire;
    	//opoznienie(15);
    	_delay_us (15);
    	if(bit_is_set(PORT_1wire, WE)) PRESENCE=1; else PRESENCE=0;
    
    	return (PRESENCE);
    }
    
    void send_byte(char wartosc){
    	unsigned char i;
    	unsigned char pom;
    
    	for(i=0;i<8;i++){
    		pom=wartosc>>i;
    		pom&=0x01;
    		send(pom);
    	}
    
    //	opoznienie(100);
    	_delay_us (100);
    }
    
    unsigned char read_byte(void){
    	unsigned char i;
    	unsigned char wartosc=0;
    
    	for(i=0;i<8;i++){
    		if(read()) wartosc|=0x01<<i;
    	//	opoznienie(15);
    		_delay_us (15);
    	}
    
    	return (wartosc);
    }
    
    
    
    
    int main(void){
    	unsigned char sprawdz;
    	char temp1=0, temp2=0;
    
    	int e;
    	char buf[8];
    	_delay_ms (40);
    	
    	DDRA = 0xFF;
    	PORTA = 0xFF;
    
    	lcd_init();
    	_delay_ms (200);
    
    	while(1){
    		sprawdz=RESET_PULSE();
    			if(sprawdz==1){
    				send_byte(0xCC);
    				send_byte(0x44);
    				for(e=0;e<25;e++) 
    				_delay_ms (30);
    			
    				sprawdz=RESET_PULSE();
    				send_byte(0xCC);
    				send_byte(0xBE);
    
    				temp1=read_byte();
    				temp2=read_byte();
    				sprawdz=RESET_PULSE();
    	
    
    				temp=0;
    				temp=(float)(temp1+(temp2*256))/16;
    				dtostrf(temp,1,1,buf);
    				write_text(buf);
    				_delay_ms (200);
    		}else{
    			write_text("NICZ");
    		}
    		
    		
    		
    	}
    }


    Proszę używać znaczników [code] - uzupełniłem.
    [zumek]
  • #2 6240259
    kaktus_c++
    Poziom 18  
    niedawno stworzyłem sobie programik do przetestowania programu na pc zanim wgram go do avr. i masz tu go zmodyfikowanego (dev c++)
    #include <cstdlib>
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    
    using namespace std;
    
    //-------------------------------------
    int main(int argc, char *argv[])
    {
        int typ_czujnika;
        unsigned char msb;
        unsigned char lsb;
        unsigned int suma;//
        unsigned int itmp;//zmienna tymczasowa
        float temp;
        cout<<"podaj wartosc dziesietna MS Byte : ";
        cin>>itmp;
        msb = itmp;
        cout<<endl;
        cout<<"podaj wartosc dziesietna LS Byte : ";
        cin>>itmp;
        lsb = itmp;
        cout<<endl;
        char temp1 = lsb;
        char temp2 = msb;
        
            cout<<"---DS18B20---"<<endl;
            if(msb&0x80)//!=0 ujemna temp
            {
                lsb=~lsb +1;
                msb=~msb;
                suma =lsb+ (((unsigned int)(msb))<<8);
                temp = float(suma) * -0.0625;
            }
            else//dodatnia
            {
                suma = lsb + (((unsigned int)msb)<<8);
                temp = float(suma) * 0.0625;
            }
    
        cout<<"temperatura ( metoda 1 ) = "<<temp<<endl;
        float temp_ = (float)(temp1+(temp2*256))/16 ;
        cout <<"temperatura ( metoda 2) = "<<temp_<<endl;
    
        system("PAUSE");
        return EXIT_SUCCESS;
    }

    Twoja metoda liczenia temperatury mi nie działa jak powinna
    Na przykład : wzięte z noty katalogowej t=-25.0625 będzie zapisana 0xFE 0x6F( czyli dziesiętnie 254 i 111), sprawdź sobie wyniki są takie same obiema metodami , ale dla temperatury +25.0625 0x01 i 0x91 (wpisujesz wartości dziesiętne 1 i 145) już są różne a mój sposób (metoda 1) działa ok.
    Może to sprawa kompilatora...
    Ale jeśli termometr pokazuje cały czas tą tamą temperaturę mimo że ona się w rzeczywistości zmienia to problem musi być jeszcze gdzieś indziej.

    No i jeszcze zastanawiające są dla mnie argumenty w funkcji dtostrf(), te dwie jedynki - to będzie działać?
  • #3 6246848
    saul
    Poziom 12  
    uC Masz oczywiście ustawiony na 16 MHz ? Korzystasz z zewnętrznego oscylatora ? Spróbuj wrzucić tę linijkę na sam początek:
    Cytat:

    #define F_CPU 16000000UL

    avr/delay.h zamień na util/delay.h, Sprawdź czy Twoje czasy (opóźnienia) zgadzają się z czasami z dokumentacji, w 1-wire są krytyczne. Do czego Wykorzystujesz zmienną x ?
REKLAMA