Atmega16_DS18S20.c


1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#define F_CPU 8000000  //-> bereits unter Project->Configuration Options-> als 8000000 definiert
4
#include <util/delay.h>
5
#include <inttypes.h>
6
#include <stdint.h>
7
8
#define TRUE 1
9
#define FALSE 0
10
11
// Anchlussbelegung: An welchen Pins h?ngt der DS1820 bzw die LED Anzeige
12
#define W1_PIN  PC0                 //PC0 Pin soll der W1_PIN sein - in diesem Fall ist es der DataPin vom DS1820
13
#define W2_PIN  PC1                 //PC0 Pin soll der W1_PIN sein - in diesem Fall ist es der DataPin vom DS1820
14
#define W1_IN   PINC                //Pin abfragen
15
#define W1_OUT  PORTC               //Ausg?nge ansteuern
16
#define W1_DDR  DDRC                //Datenrichtung jeweils festlegen - je nach dem ob Daten zum DS gesedent, oder vom DS empfangen werden sollen
17
#define LED_OUTB PORTB        //PORT für die LED Anzeige
18
#define LED_DDRB DDRB        //DDR für die LED Anzeige
19
#define LED_OUTA PORTA        //PORT für die LED Anzeige
20
#define LED_DDRA DDRA        //DDR für die LED Anzeige
21
#define LED_OUTD PORTD        //PORT für die LED Anzeige
22
#define LED_DDRD DDRD        //DDR für die LED Anzeige
23
24
// Kommandos an den DS1820
25
#define MATCH_ROM     0x55      //64 Bit code wird vom Master an ale DS gesendet - nur der DS mit dem Passenden 64Bit "namen" antwortet
26
#define SKIP_ROM      0xCC        //Master spricht alle DS simultan an - gefollgt von einem Convert_t beginnen alle mit der Temp. Konvertierung
27
#define SEARCH_ROM    0xF0        //identifizieren aller 64Bit adressen der angeschlosenen DS
28
#define CONVERT_T     0x44        //startet eine Temperaturkonvertierung und legt die daten im scratchpad (2byte gro?er Speicher im DS) ab
29
#define READ          0xBE        //scratchpad auslesen (Read Befehl an DS schicken)
30
#define WRITE         0x4E        //master beschreibt scratchpad (Write Befehl an den DS schicken)
31
#define EE_WRITE      0x48      //scratchpad daten in den EEPROM kopieren
32
#define EE_RECALL     0xB8      //
33
34
//Reset bei DS1820 ausl?sen (d.h. Master sendet min. 480?s low, dann high,
35
//nach 60...240?s sendet der DS1820 ein low zur?ck)
36
uint8_t w1_reset( void )
37
{
38
        uint8_t err;
39
40
        W1_OUT &= ~(1<<W1_PIN);                //C0 = W1-PIN als Ausgang mit einem low ansteuern
41
        W1_DDR |= 1<<W1_PIN;                   //W1_PIN als Ausgang alle anderen bleiben unangetastet
42
        _delay_us( 480 );                      //mindestens 480?s warten
43
        cli();                                 //das Global Interrupt Enable Bit im Status Register wird gel?scht
44
        W1_DDR &= ~(1<<W1_PIN);                //W1_PIN als Eingang
45
        _delay_us( 66 );                       //66?s warten
46
        err = W1_IN & (1<<W1_PIN);             //in err den Zustand von W1_IN speichern (im besten Fall ein low vom DS1820)
47
        sei();                                 //das Global Interrupt Enable Bit im Status Register wird gesetzt
48
        _delay_us( 480 - 66 );                 //warten
49
        if( (W1_IN & (1<<W1_PIN)) == 0 )       // Vergleich -> ist er genau 0 dann err=1
50
        err = 1;
51
        return err;                            //d.h. ist nun in err eine 1 so hat der DS1820 geantwortet
52
}
53
54
//schreibt ein Bit in den IC, gleichzeitig wird ein Bit vom DS empfangen
55
uint8_t w1_bit_io( uint8_t b )
56
{
57
        cli();                                 //das Global Interrupt Enable Bit im Status Register wird gel?scht
58
        W1_DDR |= 1<<W1_PIN;                   //W1_PIN als Ausgang
59
        _delay_us( 1 );                        //warten
60
        if( b )
61
        W1_DDR &= ~(1<<W1_PIN);                //falls W1_PIN als Eingang geschaltet
62
        _delay_us( 15 - 1 );                   //warten
63
        if( (W1_IN & (1<<W1_PIN)) == 0 )       //falls das logische & von ==0 ergibt
64
        b = 0;                                 //b=0
65
        _delay_us( 60 - 15 );                  //warten
66
        W1_DDR &= ~(1<<W1_PIN);                //W1_PIN als Eingang
67
        sei();                                 //das Global Interrupt Enable Bit im Status Register wird gesetzt
68
        return b;
69
}
70
71
//benutzt w1_bit_io um nacheinander 8 Bit zum IC zu schicken bzw. umgekehrt gleichzeitig 8 Bit vom IC zu holen
72
uint8_t w1_byte_wr( uint8_t b )
73
{
74
        uint8_t i = 8, j;                      //8Bit lang
75
76
        do {
77
            j = w1_bit_io( b & 1 );            //das Ergebniss aus w1_bit_io
78
            b >>= 1;
79
            if( j )
80
               b |= 0x80;                      //b oder= 0b10000000  
81
        } while( --i );
82
        return b;
83
}
84
85
//liest ein Byte vom DS1820
86
uint8_t w1_byte_rd( void )
87
{
88
        return w1_byte_wr( 0xFF );                
89
}
90
91
//?bertrag?t ein Kommando zu IC
92
void w1_command( uint8_t command )
93
{
94
        w1_reset();                             //zuerst die restet prozedur
95
        w1_byte_wr( SKIP_ROM );                 //dann alle DS1820 simultan ansprechen
96
        w1_byte_wr( command );                  //dann das Kommando
97
}
98
99
//Messung starten
100
uint8_t start_meas( void )
101
{
102
        if( W1_IN & ( 1 << W1_PIN ) ) {        //kleine Fehlererkennung - pr?ft ob der Pegel high ist (Ist der Pin daher auf Eingang geschaltet, dann muss es n?glich sein, beiinaktivem Bus einen HighPegel auszulesen) wird ein high gelesen ist alles True sonst False
103
           w1_command( CONVERT_T );            //(then)fals high ausgelesen wurde zum Konvertierungsschritt ?bergehen
104
           W1_OUT |= 1 << W1_PIN;              //(else) ein high zum ausgang senden
105
           return TRUE;
106
        }
107
        return FALSE;
108
}
109
110
//Temperatur vom DS abholen
111
int16_t read_meas_fast( void )
112
{
113
        uint16_t temp;
114
        w1_command( READ );                    // read command
115
        temp = w1_byte_rd();                   // low byte wird nach temp gespeichert
116
        temp |= (uint16_t)w1_byte_rd() << 8;   // high byte wird nach temp gespeichert
117
        //  if( id[0] == 0x10 )                // 9 -> 12 bit
118
        temp <<= 3;
119
        return temp;
120
}
121
122
int main(void)
123
{          
124
        const uint16_t pause = 1000;
125
126
      int8_t p;
127
    int8_t tC;
128
        int16_t t;
129
    int8_t pp;
130
    int8_t ttC;
131
        int16_t tt;
132
    uint8_t t_ist =0;
133
    uint8_t tt_ist =0;
134
    int8_t aa = 0b00000000;
135
    int8_t bb = 0b11111111;
136
137
    DDRC = 0xff;                  //C als Output
138
    PORTC = 0x00;                     //fangen alle bei 0V an
139
        DDRA = 0xff;                                    //alle A Port Pins sind Output
140
        PORTA = 0x00;                     //fangen alle bei 0V an
141
        DDRB = 0xff;                                    //alle B Port Pins sind Output
142
        PORTB = 0x00;                     //fangen alle bei 0V an
143
        DDRD = 0xff;                                    //alle D Port Pins sind Output
144
        PORTD = 0x00;                     //fangen alle bei 0V an
145
146
        // Initialisierung der LED (Prüfen ob alle leuchten)
147
        for(int a=0; a<10; a++)
148
        {
149
                PORTA = aa;
150
        PORTB = ~aa;
151
        PORTD = ~aa;
152
        for(int a=0; a<1; a++){ _delay_ms(pause);}
153
                PORTA = bb;
154
        PORTB = ~aa;
155
        PORTD = ~aa;
156
                for(int b=0; b<1; b++){ _delay_ms(pause);}
157
    }
158
    
159
160
161
        // Port x, alle Pins als Ausgang schalten (Grundeinstellung)
162
      W1_DDR = 0xFF;
163
        // Port x, Pins initialisieren (low)
164
        W1_OUT = 0x00;
165
        // Sensor initialisieren
166
        // >>Notiz>> Wir gehen einfach von einem Erfolg aus <<
167
        w1_reset();
168
        // Hauptschleife
169
        do
170
        {
171
172
                // Kommando an den Sensor (Messung starten)
173
                // >>Notiz>> Wir gehen einfach von einem Erfolg aus <<
174
                start_meas();
175
        
176
                // Temperatur vom Sensor holen
177
                t = read_meas_fast();
178
        t = t/8;
179
180
                // Temperatur in Grad Celsius:
181
                tC = (t >> 1) | (t & 0xFF00);
182
183
                if(tC < 0) tC = -tC; //Vorzeichen entfernen      
184
185
                //reset (alle LEDs aus)
186
                p = 0x00;
187
        
188
           //Konfiguration der Pins für LEDs setzen
189
                // (0 = LED an, 1 = LED aus)
190
                if(tC >= 80) { p |=(1<<7); tC -= 80; } //Pin7 f?r 80?C an
191
                if(tC >= 40) { p |=(1<<6); tC -= 40; } //Pin6 f?r 40?C an
192
                if(tC >= 20) { p |=(1<<5); tC -= 20; } //Pin5 f?r 20?C an
193
                if(tC >= 10) { p |=(1<<4); tC -= 10; } //Pin4 f?r 10?C an
194
                if(tC >= 8)  { p |=(1<<3); tC -= 8;  } //Pin3 f?r 8?C  an
195
                if(tC >= 4)  { p |=(1<<2); tC -= 4;  } //Pin2 f?r 4?C  an
196
                if(tC >= 2)  { p |=(1<<1); tC -= 2;  } //Pin1 f?r 2?C  an
197
                if(tC >= 1)  { p |=(1<<0); tC -= 1;  } //Pin0 f?r 1?C  an
198
199
           t_ist = p;
200
        //p = p-0,5;        //Eichung des Thermometers
201
        
202
        LED_OUTA = p;
203
        LED_OUTD = p;
204
        p = ~p;            //LED Signal invertieren weil LED falsch angelötet
205
        LED_OUTB = p;
206
207
        // ein wenig warten verhindert,
208
                // dass der Sensor durch Selbsterw?rmung
209
                // falsche Ergebnisse liefert
210
                _delay_ms(1000);
211
212
         
213
214
215
216
        }while(1);
217
218
}