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

[Atmega32]AVR_brd_I i 2xDS18B20

mazi35 11 Cze 2008 20:56 1674 8
  • #1 5236846
    mazi35
    Poziom 17  
    Witam
    Problem z tym, że dopiero zaczynam przygodę z uK. Chodzi o to, że na stronie
    http://mikrosterowniki.pl/dokumentacje/AVR_brd_I_v10_instr.pdf jest uwzględnione miejsce na czujnik (opisany jako 7) i moje pytanie brzmi gdzie podłączyć drugi czujnik? Wiadomo napięcie i masa, ale co z linią danych? Bo na środku tej płytki jest oznaczenie PD7 i przy nim przypisane 1wire czy tam mogę podpiąć 2 czujnik z pewnością, że nie będzie nic sie gryźć z 1 czujnikiem przy pomiarze? I czy trzeba pod nóżkę napięcia podciągnąć rezystor 4k7?
    Pozdrawiam

    Poprawiłem tytuł https://www.elektroda.pl/rtvforum/topic1015361.html
    [zumek]
  • #2 5237044
    wdogli
    Poziom 18  
    Witam.
    Oczywiście do jednej linii danych 1Wire możesz podpiąć kilka czujników jednak w takim przypadku trochę zmieni ci sie program. Bo będziesz musiał każdy z nich wywoływać po ich unikalnym adresie.
    Pozdrawiam
  • #3 5237082
    mazi35
    Poziom 17  
    Czyli to dodatkowe PD7 oznaczone jako 1wire to tak czy tak jedna i ta sama linia? A ewentualny "brzęczek" do sygnalizacji przekroczenia danej temperatury pod co podpiąć? Właśnie do jednego z tych dodatkowych wyjść?
  • #4 5237251
    wdogli
    Poziom 18  
    Dokładnie drugą trzecią i jeśli będziesz chciał czwartą czujkę podpinasz pod wyjście na listwie nr17 pod pin oznaczony 1Wire PD7. plus do plusa i masa do masy. Jeśli chodzi o brzęczek to jedną nogę podpinasz pod zasilanie a drugą pod którykolwiek wolny pin mikrokontrolera. Wtedy sterujesz nim za pomocą masy czyli pin mikrokontrolera do którego będzie on podpięty ustawiasz jako wyjście w stanie niskim gdy ma on sie odezwać.
    Acha istotne jest to ażeby ten brzęczek był z wewnętrznym generatorem dźwięku.
  • #5 5610733
    mazi35
    Poziom 17  
    Witam odświeżam temat (w końcu czas żeby przysiąść do uC)
    Otóż chciałbym zapytać czy ta deklaracja jest ok:
    
    #include <avr/io.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <util/delay.h>
    
    
    //==========================================DS18B20================================================== 
    #define F_CPU 16000000
    #define PORT D-7
    
    #define SET_DQ DDRD &= ~_BV(DQ)
    #define CLR_DQ DDRD |= _BV(DQ)
    
    #define IN_DQ PIND & _BV(DQ)
    //==========================================LCD==================================================
    #define LCD  PORTA
    #define DLCD DDRA
    #define LCD1  PORTC
    #define DLCD1 DDRC
    #define E  6
    #define RS  7
    //
    #define SET_E   LCD |= _BV(E)
    #define CLR_E   LCD &= ~_BV(E)
    //
    #define SET_RS  LCD |= _BV(RS)
    #define CLR_RS  LCD &= ~_BV(RS)
    

    http://mikrosterowniki.pl/dokumentacje/AVR_brd_I_v10_instr.pdf piszę na podstawie informacji znalezionych na forum i z dokumentacji. Niestety w C nie jestem biegły więc proszę o pomoc.
    pozdrawiam
  • #6 5610881
    wdogli
    Poziom 18  
    Witam.

    Nie wiem co ten program ma robić ale tak na pierwszy rzut oka masz błąd a sekcji DS18B20 a mianowicie :

    
    //==========================================DS18B20==================================================
    #define F_CPU 16000000
    #define PORT D-7
    
    #define SET_DQ DDRD &= ~_BV(DQ)
    #define CLR_DQ DDRD |= _BV(DQ)
    
    #define IN_DQ PIND & _BV(DQ) 
    
    


    powinno być raczej:

    
    //==========DS18B20=================
    #define F_CPU 16000000UL
    #define DQ 7
    
    #define SET_DQ DDRD &= ~_BV(DQ)
    #define CLR_DQ DDRD |= _BV(DQ)
    
    #define IN_DQ PIND & _BV(DQ) 
    
    


    Oczywiście jeśli linią danych termometru będzie pin.7

    Jeśli chodzi o wyświetlacz to nie wiem jaki to będzie wyświetlacz ale podejrzewam że masz zwykły wyświetlacz LCD 2x16 znaków z czternastoma wyprowadzeniami . A więc do sterowania nim wystarczy ci jeden port na przykład:


    
    //==========================================LCD==================================================
    #define LCD PORTA
    #define DLCD DDRA
    
    #define E 6
    #define RS 7
    //
    #define SET_E LCD |= _BV(E)
    #define CLR_E LCD &= ~_BV(E)
    //
    #define SET_RS LCD |= _BV(RS)
    #define CLR_RS LCD &= ~_BV(RS) 
    
    


    Pozdrawiam


    P.S.

    Po więcej zaglądnij tutaj:

    http://mikrokontrolery.net/avr_c_08.htm
  • #7 5611408
    mazi35
    Poziom 17  
    Witam co do zegara to rzeczywiście miałem 16000000UL, ale wkleiłem 2 kod który nie miał zmiany naniesionej. A co do samego sprzętu to rzeczywiście jest zwykły wyświetlacz HD44780+DS18B20 cel to wyświetlanie temperatury. Większość programów z tego forum opiera się na kodzie ze strony, którą wymieniłeś.
    
    #include <avr/io.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <util/delay.h>
    
    
    //==========================================DS18B20================================================== 
    #define F_CPU 16000000UL
    #define DQ 7
    
    #define SET_DQ DDRD &= ~_BV(DQ)
    #define CLR_DQ DDRD |= _BV(DQ)
    
    #define IN_DQ PIND & _BV(DQ)
    //==========================================LCD==================================================
    //#define LCD  PORTA
    //#define DLCD DDRA
    #define LCD  PORTC
    #define DLCD DDRC
    #define E  6
    #define RS  7
    //
    #define SET_E   LCD |= _BV(E)
    #define CLR_E   LCD &= ~_BV(E)
    //
    #define SET_RS  LCD |= _BV(RS)
    #define CLR_RS  LCD &= ~_BV(RS)
    
    short int x;
    
    
    //==========================================LCD==================================================
    
    void dl(unsigned char x)
    {
    TCCR0=0x02;
    OCR0=x;
    while(1)
    {
    if(TCNT0>=OCR0)
    break;
    }
    TCCR0=0;
    TCNT0=0;
    }
    
    void dlms(unsigned char x)
    {
     
    TCCR0=0x05;
    OCR0=8;
    for(;x>0;x--)
    {
    TCNT0=0;
    while(1)
    {
    if(TCNT0>=OCR0)
    break;
    }
    }
    TCCR0=0;
    TCNT0=0;
    
    }
    // funkcja opóźniająca o x*1ms
    
    
    // pcodedura zapisu bajtu do wyświetlacza LCD
    // bez rozróżnienia instrukcja/dana
    void write_to_lcd(char x)
    {
    SET_E; // ustaw na E stan wysoki
    LCD = ((LCD & 0x0F) | (x & 0xF0)); // zapis pierwszej połówki bajtu
    CLR_E; // opadające zbocze na E -> zapis do wyświetlacza
    SET_E; // ustaw na E stan wysoki
    LCD = ((LCD & 0x0F) | ((x & 0x0F) << 4)); // zapis drugiej połowki bajtu
    CLR_E; // opadające zbocze na E -> zapis do wyświetlacza
    dlms(1); // czekaj 1ms
    }
    
    // procedura zapisu instrukcji do wyświetlacza LCD
    void write_command(char x)
    {
    CLR_RS; // niski stan na RS -> zapis instrukcji
    write_to_lcd(x); // zapis do LCD
    }
    
    // procedura zapisu danej do wyświetlacza LCD
    void write_char(char x)
    {
    SET_RS; // wysoki stan na RS -> zapis danej
    write_to_lcd(x); // zapis do LCD
    }
    
    // procedura 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)
      }
    }
    
    // procedura inicjalizacji wyświetlacza LCD
    void lcd_init(void)
    {
    dlms(15); // czekaj 15ms na ustabilizowanie się napięcia zasilającego
    CLR_E; // E = 0
    CLR_RS; // RS = 0
    char i; // zmianna licznikowa
    for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
      {
      SET_E; // E = 1
      LCD &= 0x3F; //
      CLR_E; // E = 0
      dlms(5); // czekaj 5ms
      }
    SET_E; // E = 1
    LCD &= 0x2E; //
    CLR_E; // E = 0
    dlms(1); // czekaj 1ms
    write_command(0x28); // interfejs 4-bity, 2-linie, znak 5x7
    write_command(0x08); // wyłącz LCD, kursor i miganie
    write_command(0x01); // czyść LCD
    write_command(0x06); // bez przesuwania w prawo
    write_command(0x0C); // włącz LCD, bez kursora i mrugania
    }
    
    
    void LCD_xy(char x, char 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);
       dlms(1);
       
       LCD_xy(0,0);
    }
    //==========================================================================================//
    
    
    //---------------------------1-wire------------------------------
    
    
    ////////////////////////////////////////////////////////////////////////////////////
    unsigned char ow_reset__(void) // reset lini one wire
    {
       unsigned char presence=1;
       CLR_DQ; //DQ = 0; //pull DQ line
     
     dl(250);
     dl(250);//   450 us
     
       SET_DQ; //DQ = 1; // allow line to //powrót lini 1w do trybu wejścia
    
     dl(55);       //    31,88 us   wait for presence pulse(pochodzący od DS-a) //czekamy na ustab. lini
       
       if(IN_DQ) presence=1;
       else presence=0; //odczytujemy co wystawił na linię DS
    
      dl(200);
      dl(200);
       if(IN_DQ&&(presence==0)) presence=0;
       else presence=1;
       return(presence); // presence signal
    } // 0=presence, 1 = no part
    
    
    void test(void) // test na oecnosc DALLASA
    {
    LCD_clr();
    LCD_xy(0,0);
    write_text("TEST");
    LCD_xy(0,1);
    if(ow_reset__()==0)
    {
    write_text("Czujnik ok");
    }
    else
    {
    write_text("Brak czujnika");
    }
    dlms(200);
    dlms(200);
    dlms(200);
    dlms(200);
    dlms(200);         
    }
    
    
    //===========================================================================================//
    //===========================================================================================//
    
    
    
    
     
     // READ_BIT - reads a bit from the one-wire bus. The delay
    // required for a read is 15us, so the DELAY routine won't work.
    // We put our own delay function in this routine in the form of a
    // for() loop.
    unsigned char read_bit(void)
    {
       unsigned char presence=0;
       CLR_DQ;    //DQ = 0; // pull DQ low to start timeslot
       for(x=0;x<5;x++);
       asm ("nop");
       
       SET_DQ;   //DQ = 1; // then return high
       dl(15);; // delay 15us from start of timeslot
       
       if(IN_DQ) presence=1;
       else presence=0;
       return(presence); // return value of DQ line
    }
    ///---------------------------------------------------------
    
    void write_bit(char bitval) //WRITE_BIT - writes a bit to the one-wire bus, passed in bitval.
    {
       CLR_DQ;    //DQ = 0; // pull DQ low to start timeslot
       for(x=0;x<10;x++);
       asm ("nop"); 
       if(bitval==1)
       SET_DQ; //DQ =1; // return DQ high if write 1
       dl(100); // hold value for remainder of timeslot - delay 104us
       SET_DQ;//DQ = 1;
    }
    
    ///---------------------------------------------------------
    
    unsigned char read_byte(void) // READ_BYTE - reads a byte from the one-wire bus
    {
       unsigned char i;
       unsigned char value = 0;
       for (i=0;i<8;i++)
       {
          if(read_bit()) value|=0x01<<i; // reads byte in, one byte at a time and then
          dl(70);    // ??shifts it left wait for rest of timeslot 120us
       }
       return(value);
    }
    
    
    
    
    
    ///---------------------------------------------------------
    
    void write_byte(char val) // WRITE_BYTE - writes a byte to the one-wire bus.
    {
       unsigned char i;
       unsigned char temp;
       for (i=0; i<8; i++) // writes byte, one bit at a time
       {
          temp = val>>i; // shifts val right 'i' spaces
          temp &= 0x01; // copy that bit to temp
          write_bit(temp); // write bit in temp into
       }
    dl(50);
    
    }
     
    
    
    
    
    
    //////////////////////////////////////////////////////////////////////////////////
    
    void Read_Temperature(void)
    {
    char tmp[6];
    tmp[5]=0;
     
    char temp1=0, temp2, temp3, temp4;
    short int t, u;
    if (ow_reset__())
    {test();}
    else
    {
    ow_reset__();
    
    write_byte(0xCC); //Skip ROM
    write_byte(0x44); // Start Conversion
    
    dlms(200);
    dlms(200);
    dlms(200);
    dlms(200);
    dlms(200);
     
    ow_reset__();
    write_byte(0xCC); // Skip ROM
    write_byte(0xBE); // Read Scratch Pad
    temp1=read_byte();
    temp2=read_byte();
    if (ow_reset__())
    {test();}
    temp4=((temp2<<4)&0xF0);
    temp3=((temp1>>4)&0x0F);                 
    t = (temp4)|(temp3);
    u = temp1&0x0F;
    if(t<0)
    {
    t=~t;
    if(u==0)
    t++;
    else
    {
    short int k=0;
    while( ( u & _BV(k) )==0)
    {
    k++;
    }
    
    char q=0xFF;
    u=~u;
    u&=(q<<k);
    u|= _BV(k);
    u&=0x0F;
    }
    }
    
    tmp[0]=t/100+48;
    tmp[1]=((t/10)-(10*(t/100)))+48;
    tmp[2]=t%10+48;
    tmp[3]='.';
    tmp[4]=(u*10/16)+48;
    
    if(temp2<0)
    {
    tmp[0]='-';
    if(tmp[1]==48)
    {
    for(x=1;x<5;x++)
    tmp[x]=tmp[x+1];
    }
    }
    else
    {
    
    if(tmp[0]==48)
    {
    short int d=0;
    if(tmp[1]==48)
    d=1;
    for(x=0;x<(6-d);x++)
    tmp[x]=tmp[x+1+d];
    }
    
    
    }
    
    LCD_clr();
    LCD_xy(0,0);
    write_text("Temp: ");
    write_text(tmp);
    }
    }
    
    
    
    int main (void)
    
     
    {
    
    // konfiguracja portów we/wy
    //DLCD1 = 0xF0;
    //LCD1 = 0xF0;
    DLCD = 0xC0;
    LCD = 0xC0;
       lcd_init();
       LCD_clr();
       
    test();
    
    
       while(1)
       {
       
    Read_Temperature();
    dlms(200);
    dlms(200);
    dlms(200);
    dlms(200);
    dlms(200);
    }
     }    
    
    
    Wybrałem port C jako ten dla LCD. Tak zresztą jak w dokumentacji. Konfiguracja portów we/wy zmieniona tak że
    
    //DLCD1 = 0xF0;
    //LCD1 = 0xF0;
    DLCD = 0xC0;
    LCD = 0xC0;
    
    2 wyświetlacze miały 
    DLCD = 0xF0;
    LCD = 0xF0;
    DLCD1 = 0xC0;
    LCD1 = 0xC0;
    

    Po wgraniu programu nic się nie wyświetla.Co jest jeszcze nie tak?

    Pozdrawiam

    Na przyszłość , proszę używać znaczników [code]
    [zumek]
  • #8 5613468
    wdogli
    Poziom 18  
    Witam ponownie :)

    Niestety taka ilość kodu do zanalizowania jest ponad moje siły ;). Poza tym bez urządzenia dla którego piszesz ten kod też niewiele ci pomogę.
    Jednak w związku z tym iż piszesz że wyświetlacz nic ci nie wyświetla nasuwa się wniosek że masz coś pokićkane z czasami. A więc jak mi się wydaje w/w kod był pisany dla mikrokontrolera taktowanego 4 lub 8 MHz kwarcem natomiast z twojego kodu wynika że swój taktujesz kwarcem o częstotliwości 16 MHz a to już nie to samo. Jak sam przyznasz.
    Moja propozycja:

    Zapoznaj się z tą częścią kodu i zastanów się czy dla twojej częstotliwości taktowania opóźnienia które zadajesz w poniższym kodzie w rzeczywistości są takie jak ci się wydają.

    
    void dl(unsigned char x)
    {
    TCCR0=0x02;
    OCR0=x;
    while(1)
    {
    if(TCNT0>=OCR0)
    break;
    }
    TCCR0=0;
    TCNT0=0;
    }
    
    void dlms(unsigned char x)
    {
     
    TCCR0=0x05;
    OCR0=8;
    for(;x>0;x--)
    {
    TCNT0=0;
    while(1)
    {
    if(TCNT0>=OCR0)
    break;
    }
    }
    TCCR0=0;
    TCNT0=0;
    
    } 
    



    Masz jeszcze jedno wyjście skorzystać z biblioteki <avr/delay.h> którą załączasz do kodu jednak nie wykorzystujesz.
    tutaj masz linka do opisu tej i wielu innych bibliotek. http://avr.elektroda.eu/?q=node/15

    Serdecznie Pozdrawiam
  • #9 5613559
    mazi35
    Poziom 17  
    OK.Spoko rozumiem, ale wg Ciebie to kwestia czasów? Bo kombinowałem własnie w tym fragmencie kodu
    #define LCD  PORTA
    #define DLCD DDRA
    #define LCD2  PORTC
    #define DLCD2 DDRC
    #define E  6
    #define RS  7
    //
    #define SET_E   LCD2 |= _BV(E)
    #define CLR_E   LCD2 &= ~_BV(E)
    //
    #define SET_RS  LCD2 |= _BV(RS)
    #define CLR_RS  LCD2 &= ~_BV(RS)


    oraz

    // konfiguracja portów we/wy
    DLCD2 = 0xC0;
    LCD2 = 0xC0;
    DLCD = 0xFF;
    //LCD = 0xC0;
       lcd_init();
       LCD_clr();
       
    test();
REKLAMA