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

[Atmega16][C] Lcd i komunikacja z DS18b20.

no-one 25 Cze 2008 16:02 2370 5
  • #1 5284157
    no-one
    Poziom 1  
    Witam.
    Od paru dni próbuje uruchomić czujnik temperatury niestety bezskutecznie (w ogóle nie jest wykrywany przez funkcje ow_reset). Dlatego tez byłbym bardzo wdzięczny za wszelkie sugestie.
    Atmega pracuje z częstotliwością 1Mhz. Czujnik jest podpięty pod 6 pin portu d.
    Z góry dziękuje.
    
    #include <avr/io.h>
    #include <util/delay.h>
    #include <stdlib.h>
    
    // rejestry linii DB4 
    #define DDR_DB4  DDRA 
    #define PORT_DB4 PORTA 
    #define DB4      PA3 
    
    // rejestry linii DB5 
    #define DDR_DB5  DDRA 
    #define PORT_DB5 PORTA 
    #define DB5      PA2 
    
    // rejestry linii DB6 
    #define DDR_DB6  DDRA 
    #define PORT_DB6 PORTA 
    #define DB6      PA1 
    
    // rejestry linii DB7 
    #define DDR_DB7  DDRA 
    #define PORT_DB7 PORTA 
    #define DB7      PA0 
    
    // rejestry linii RS 
    #define DDR_RS   DDRA 
    #define PORT_RS  PORTA 
    #define RS       PA7 
      
    // rejestry linii E 
    #define DDR_E    DDRA 
    #define PORT_E   PORTA 
    #define E        PA5 
    
    #define SET_DB4 PORT_DB4 |= (1 << DB4) 
    #define CLR_DB4 PORT_DB4 &= ~(1 << DB4) 
    
    #define SET_DB5 PORT_DB5 |= (1 << DB5) 
    #define CLR_DB5 PORT_DB5 &= ~(1 << DB5) 
    
    #define SET_DB6 PORT_DB6 |= (1 << DB6) 
    #define CLR_DB6 PORT_DB6 &= ~(1 << DB6) 
    
    #define SET_DB7 PORT_DB7 |= (1 << DB7) 
    #define CLR_DB7 PORT_DB7 &= ~(1 << DB7) 
    
    #define SET_E PORT_E |= (1 << E) 
    #define CLR_E PORT_E &= ~(1 << E) 
    
    #define SET_RS PORT_RS |= (1 << RS) 
    #define CLR_RS PORT_RS &= ~(1 << RS)
    
    #define OSC 1	//Wartosc w MHZ
    
    //************************************************************************************
    // rejestry linii DQ 
    #define DDR_DQ  DDRD 
    #define PORT_DQ PORTD 
    #define DQ      PD6 
    
    #define SET_DQ DDRD &= ~_BV(6) 
    #define CLR_DQ DDRD |= _BV(6) 
    
    union {
    int tds;
    char nds[2];
    }ds; 
    
    char buf[6]; 
    
    //************************************************************************************
    
    void waitms(unsigned int x) 
    { 
    	unsigned int a; 
    	for( ; x > 0; --x)  
    	for(a = 196 * OSC; a > 0; --a) 
    	__asm("nop"); 
    }
    
    
    void delay_1(unsigned int t) 
    { 
       do 
       { 
          asm("nop"); 
       } 
       while(--t); 
    
    }
    
    // funkcja wystawiająca na szynę danych połówkę bajtu 
    // pod uwagę brana jest młodsza połówka parametru 
    void out_nibble(char x) 
    { 
    	CLR_DB4; CLR_DB5; CLR_DB6; CLR_DB7; 
    	if(x & (1 << 0)) SET_DB4; 
    	if(x & (1 << 1)) SET_DB5; 
    	if(x & (1 << 2)) SET_DB6; 
    	if(x & (1 << 3)) SET_DB7; 
    } 
    
    // funkcja zapisująca do LCD bajt danych 
    void write_to_lcd(char x) 
    { 
    	SET_E; 
    	out_nibble(x >> 4);    // wystawienie na szynę danych starszej połówki bajtu 
    	CLR_E;                   // opadające zbocze na E powoduje zapis do wyświetlacza 
    
    	SET_E; 
       	out_nibble(x);          // wystawienie na szynę danych młodszej połówki bajtu 
    	CLR_E;                   // opadające zbocze na E powoduje zapis do wyświetlacza 
    	waitms(1);
    } 
    
    // funkcja zapisująca do LCD rozkaz 
    void write_command(char x) 
    { 
       CLR_RS;   // niski stan na RS -> zapis instrukcji 
       write_to_lcd(x); 
    } 
    
    // funkcja zapisujaca do LCD znak 
    void write_char(char x) 
    { 
       SET_RS;   // wysoki stan na RS -> zapis danej 
       write_to_lcd(x); 
    } 
    
    // funkcja zapisu tekstu do wyświetlacza LCD 
    void write_text(char * s) 
    { 
       while(*s)             // do napotkania 0 
       { 
          write_char(*s);     // zapisz znak wskazywany przez s na LCD    
          s++;             // zwiększ s (przygotuj nastepny znak) 
       } 
    } 
    
    void lcd_xy(uint8_t x, uint8_t y) 
    { 
       switch(y) 
       { 
          case 1: y=0x00; break; 
          case 2: y=0x40; break; 
       } 
       write_command(0x80+y+x); 
    } 
    
    
    void lcd_init(void) 
    { 
    
    DDR_DB4 |= (1 << DB4); 
    DDR_DB5 |= (1 << DB5); 
    DDR_DB6 |= (1 << DB6); 
    DDR_DB7 |= (1 << DB7); 
    DDR_E   |= (1 << E); 
    DDR_RS  |= (1 << RS); 
    
    waitms(15);
    CLR_E; 
    CLR_RS; 
    
    char i; 
       for(i = 0; i < 3; i++)   //to wynika z data sheet page46, figure24 
       { 
          SET_E; 
             out_nibble(0x03); 
          CLR_E;
    	  waitms(5); 
       } 
        
    	SET_E; 
       	out_nibble(0x02); 
    	CLR_E; 
    	waitms(1);
     
    	write_command(0x0C);       
    
    	waitms(5);
    
    	write_command(0x28);       
    	waitms(5); 
    	write_command(0x01); 
    	waitms(5);
    } 
    
    void clrscr (void) 
    { 
       	write_command(0x01); 
    	waitms(5);          
    } 
    //termometr
    //*************************************************************************************
    
    unsigned char ow_reset(void) 
    { 
    	unsigned char presence=1; 
       	DDRD |= _BV(6);
       	_delay_loop_1(155);
       	DDRD &= ~_BV(6);          // allow line to return high 
        // wait for presence 70us TO MUSI BYC dokladnie <63;78>us 
        _delay_loop_1(23);
    	if(bit_is_clear(PIND,6)) presence=0; //odczytujemy co wystawił na linię DS
       	_delay_loop_1(133);// wait for end   	   
        // wait for end of timeslot > 410us 
    	return(presence);   // presence signal returned 
    }                   // 0=presence, 1 = no part 
    
    // READ_BIT - reads a bit from the one-wire bus. 
    
    unsigned char read_bit(void) 
    { 
    	
    	unsigned char bit = 0; 
       	DDRD |= _BV(6);               // pull DQ low to start timeslot 5,79us a moze byc od <5;15>us 
       	DDRD &= ~_BV(6);              // then return high 
       	_delay_loop_1(5);						
                			// delay 5us to 12us from start of timeslot 
    	if(bit_is_clear(PIND,6)) bit=0;
       	if(bit_is_set(PIND,6)) bit=1;	// 57,9us, a może być od 50 do n/a us 
    	return(bit);            	// return value of DQ line 
    } 
    
    unsigned char read_byte(void) 
    { 
       unsigned char loop  = 0; 
       unsigned char value = 0; 
       
     
       for ( loop= 0 ;loop<8 ;loop++ ) 
       { 
    		if( read_bit() ) 
          		value |= 0x01 << loop;      // reads byte in, one byte at a time and then shifts it left 
    		_delay_loop_1(40);
    
       } 
       return(value); 
    }
    
    void write_bit(char bitval) 
    { 
    	DDRD |= _BV(6);	 	// pull DQ low to start timeslot 
    	if(bitval==1)   // zapis jedynki 
    		DDRD &= ~_BV(6); 
    
    	_delay_loop_1(34);
    	DDRD &= ~_BV(6);
       	       
    }
    
    // WRITE_BYTE - writes a byte to the one-wire bus. 
    
    void write_byte(char val) 
    { 
       unsigned char loop=0; 
       unsigned char temp=0; 
        
       for ( loop=0; loop<8; loop++ )     // writes byte, one bit at a time 
       { 
          temp = val>>loop;               // shifts val right 'i' spaces 
          temp &= 0x01;                    // copy that bit to temp 
          write_bit(temp);                 // write bit in temp into. Mozna zastapic te dwie linijki jedna taka: write_bit( temp &= 0x01 ); 
       } 
       _delay_loop_1(34);
    }
    
    void Read_Temperature(void)
    {
       clrscr();	
       if(ow_reset()) {lcd_xy(0,0); write_text("lipa");}
       else
       {
          write_byte(0xCC); //Skip ROM
          write_byte(0x44); // Start Conversion
          _delay_loop_1(255);
          _delay_loop_1(50);   //wyjdzie ok 950us
          ow_reset();
          write_byte(0xCC); // Skip ROM
          write_byte(0xBE); // Read Scratch Pad
          
          ds.nds[0]=read_byte();
             ds.nds[1]=read_byte();
             itoa(ds.tds/16,buf,10);//temper. całkowita
             write_text(buf); 
    
    	}
    } 
    
    //**************************************************************************************
    
    int main()
    {	
    
    	DDRC = 0xFF;
    	
    	DDRA |= _BV(6);
    	PORTA &= ~_BV(6);
    	lcd_init();
    	lcd_xy(0,1); 
    
    	DDRD =0x00;
       	PORTD =0x00;
    
       	/*
    	clrscr();
    	write_text("test");
       	_delay_ms(250);
    	_delay_ms(250);
    	_delay_ms(250);*/
    	
    	Read_Temperature();
    	while(1)
    	{
    	} 
    	return 1;
    }
    
    
    




    Poprawiłem tytuł:
    https://www.elektroda.pl/rtvforum/topic1015361.html
    [c_p]
  • #2 5348046
    wikktor
    Poziom 12  
    Mam taki sam problem...
    czy przy 1MHz czasy nie są za mało dokładne?
  • #4 5351908
    Dr.Vee
    VIP Zasłużony dla elektroda
    Rada dla no-one - skróć program do niezbędnego minimum (to, co Ci nie działa), to może większej ilości osób będzie chciało się go przeczytać...

    Poza tym dlaczego nie użyjesz funkcji _delay_us() z <util/delay.h>?

    Pozdrawiam,
    Dr.Vee
  • #5 5420017
    kred
    Poziom 20  
    Witam,

    Taka uwaga:

    // funkcja wystawiająca na szynę danych połówkę bajtu
    // pod uwagę brana jest młodsza połówka parametru
    void out_nibble(char x)
    {
       CLR_DB4; CLR_DB5; CLR_DB6; CLR_DB7;
       if(x & (1 << 0)) SET_DB4;
       if(x & (1 << 1)) SET_DB5;
       if(x & (1 << 2)) SET_DB6;
       if(x & (1 << 3)) SET_DB7;
    }


    da się skrócić do:

    
    void out_nibble(char x)
    {
        PORTB &= 0x0f;
        PORTB |= x << 4;
    }
    


    Pozdrawiam,
    Krzysztof
  • #6 6373468
    student8b
    Poziom 11  
    Proponował bym jeszcze zwiększenie zegara do 8MHz
REKLAMA