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