Forum: Mikrocontroller und Digitale Elektronik I2C mit DS3132 - Peter Fleury I2C implementierung


von Julius (Gast)


Lesenswert?

Hi,


habe bereits das DS1307 erfolgreich mit dem Library von Fleury 
angesprochen jetzt weigert sich der DS3131 aber Daten auszugeben.

Die Schaltung funktioniert mit diesem Arduino Sketch:
http://tronixstuff.com/2014/12/01/tutorial-using-ds1307-and-ds3231-real-time-clock-modules-with-arduino/

-> Hardware richtig verdrahtet.



Mein eigener Code hängt allerdings bei Zeile 165 (// this line is never 
reached), der LED Aufruf danach wird nicht mehr ausgeführt.
Hier der Code als Kopie auf bpaste.net mit Zeilennummern:
https://bpaste.net/show/019dacb8221c



Da die Fleury Funktion einen Rückgabewert liefert der entweder Aussagt 
das eine Verbindung zustande kam oder nicht verstehe ich nicht warum er 
dabei hängt?
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <i2cmaster.h> 
4
5
6
#define BAUD 9600
7
#define MYUBRR ((uint16_t) ((F_CPU / ((BAUD) * 16.0)) + .5) - 1)
8
9
#define rtc_clock 0x68
10
11
// contains what the bluetooth module received
12
uint8_t data;
13
14
void USART_Init(unsigned int ubrr) {
15
    // set baud rate
16
    UBRR0H = (unsigned char)(ubrr>>8);
17
    UBRR0L = (unsigned char)(ubrr);
18
    // enable receiver, transmitter and interrupts for rx/tx
19
    UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0) | (1<< TXCIE0);
20
}
21
22
23
24
void USART_transmit(char c) {
25
    while ( !(UCSR0A & (1<<UDRE0)) ) {}
26
    UDR0 = c;
27
}
28
29
30
31
void transmit_char(char c) {
32
    USART_transmit(c);
33
    USART_transmit('\r');
34
    USART_transmit('\n');
35
}
36
37
38
39
void send_string(char s[]) {
40
    int i =0;
41
42
    while (s[i] != 0x00) {
43
        USART_transmit(s[i]);
44
        i++;
45
    }
46
    USART_transmit('\r');
47
    USART_transmit('\n');
48
49
}
50
51
52
// code for two status leds, to signal error and ok states
53
// please dont look to closely....needs rewriting
54
55
#define ERROR_LED_2 PB1
56
#define ERROR_LED PB0
57
#define OK_LED PB2
58
59
#define ERROR_LED_2_PORT PORTB
60
#define ERROR_LED_PORT PORTB
61
#define OK_LED_PORT PORTB
62
63
64
// turn the error led on and keep it on
65
void error_led_on() {
66
    ERROR_LED_PORT |= (1 << ERROR_LED);
67
}
68
69
// turn it off
70
void error_led_off() {
71
    ERROR_LED_PORT &= ~(1 << ERROR_LED);
72
}
73
74
75
void error_led2_on() {
76
    ERROR_LED_2_PORT |= (1 << ERROR_LED_2);
77
}
78
79
// turn it off
80
void error_led2_off() {
81
    ERROR_LED_2_PORT &= ~(1 << ERROR_LED_2);
82
}
83
84
85
// flash the error led, fast
86
void flash_fast(uint8_t count) {
87
    for (int n=1; n<=count; n++) {
88
        error_led_on();
89
        _delay_ms(300);
90
        error_led_off();
91
        _delay_ms(300);
92
    }
93
}
94
95
// ...normal
96
void flash_normal(uint8_t count) {
97
    for (int n=1; n<=count; n++) {
98
        error_led_on();
99
        _delay_ms(1000);
100
        error_led_off();
101
        _delay_ms(1000);
102
    }
103
}
104
105
// second led to have more indicator for where we are stuck in the code
106
void flash_normal_error_led_2(uint8_t count) {
107
    for (int n=1; n<=count; n++) {
108
        error_led2_on();
109
        _delay_ms(1000);
110
        error_led2_off();
111
        _delay_ms(1000);
112
    }
113
}
114
// ...slow
115
void flash_slow(uint8_t count) {
116
    for (int n=1; n<=count; n++) {
117
        error_led_on();
118
        _delay_ms(3000);
119
        error_led_off();
120
        _delay_ms(3000);
121
    }
122
}
123
124
// a third led, can be used to signal ok states
125
void flash_ok_led(uint8_t count) {
126
    for (uint8_t n=1; n <= count; n++) {
127
        OK_LED_PORT |= (1 << OK_LED);
128
        _delay_ms(1000);
129
        OK_LED_PORT &= ~(1 << OK_LED);
130
        _delay_ms(1000);
131
    }
132
}
133
134
// ---------------------------------- led code end
135
136
137
138
139
140
141
142
uint8_t decToBcd(uint8_t val)
143
{
144
  return( (val/10*16) + (val%10) );
145
}
146
// Convert binary coded decimal to normal decimal numbers
147
uint8_t bcdToDec(uint8_t val)
148
{
149
  return( (val/16*10) + (val%16) );
150
}
151
152
153
154
155
void setTime(uint8_t second, uint8_t minute, uint8_t hour, uint8_t dayOfWeek, 
156
        uint8_t dayOfMonth, uint8_t month, uint8_t year) {
157
158
    flash_normal(1);
159
    // initialize, taken from peter fleurys i2c example (he wrote the i2c code)
160
    i2c_init();
161
    // connect to the device and tell it that we want to write to it
162
    
163
    uint8_t ret;
164
    //ret = i2c_start(rtc_clock+I2C_WRITE);  // set device address and write mode
165
    ret = i2c_start(rtc_clock);
166
    // this line is never reached
167
    flash_normal(1);
168
169
    if ( ret ) {
170
        flash_normal(3);
171
        /* failed to issue start condition, possibly no device found */
172
        i2c_stop();
173
        // we can issue an error message here if the device failed to respond
174
175
     } else {
176
        flash_ok_led(3);
177
        // tell the device where we want to write to (address in ram)
178
        i2c_write(0x00);
179
180
        // set time
181
        i2c_write(decToBcd(second)); // set seconds
182
        i2c_write(decToBcd(minute)); // set minutes
183
        i2c_write(decToBcd(hour)); // set hours
184
        i2c_write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
185
        i2c_write(decToBcd(dayOfMonth)); // set date (1 to 31)
186
        i2c_write(decToBcd(month)); // set month
187
        i2c_write(decToBcd(year)); // set year (0 to 99)    
188
        i2c_stop();     
189
    }                    
190
}
191
 
192
193
194
uint8_t result;
195
196
typedef struct {
197
    uint8_t sec;
198
    uint8_t min;
199
    uint8_t hour;
200
    uint8_t weekDay;
201
    uint8_t date;
202
    uint8_t month;
203
    uint8_t year;  
204
} rtc_t;
205
206
207
208
rtc_t rtc;
209
210
void getTime(void) {
211
    // receive 1 byte (seconds)
212
    flash_normal(3);
213
214
    uint8_t ret;
215
    ret = i2c_start(rtc_clock+I2C_WRITE);  // set device address and write mode
216
    if ( ret ) {
217
        flash_normal(3);
218
        /* failed to issue start condition, possibly no device found */
219
        i2c_stop();
220
        // we can issue an error message here if the device failed to respond
221
222
     } else {
223
        flash_ok_led(1);
224
        /* issuing start condition ok, device accessible 
225
        we can now use i2c_write() to talk to the device*/
226
          
227
228
229
        // request second ram adress (tell the chip at what adress we want to start reading)
230
        // 0x00 = 
231
        i2c_write(0x00);
232
        i2c_stop();
233
234
        // _rep_start or _start? whats the difference?
235
        i2c_rep_start(rtc_clock);
236
        result = i2c_readAck();
237
        rtc.sec = i2c_readAck();                // read second and return Positive ACK
238
        rtc.min = i2c_readAck();                 // read minute and return Positive ACK
239
        rtc.hour= i2c_readAck();               // read hour and return Negative/No ACK
240
        rtc.weekDay = i2c_readAck();           // read weekDay and return Positive ACK
241
        rtc.date= i2c_readAck();              // read Date and return Positive ACK
242
        rtc.month=i2c_readAck();            // read Month and return Positive ACK
243
        rtc.year =i2c_readNak();             // read Year and return Negative/No ACK
244
        i2c_stop();
245
    }
246
}
247
248
249
250
251
int main(void) {
252
    DDRB |= (1 << ERROR_LED);
253
    DDRB |= (1 << ERROR_LED_2);
254
255
    DDRB |= (1 << OK_LED);
256
257
    // test leds to see if they are connected and working
258
259
    flash_normal(1);
260
    flash_normal_error_led_2(1);
261
    flash_ok_led(1);    
262
263
264
    i2c_init();
265
    uint8_t count = 0;
266
    setTime(30,42,21,4,26,11,14);
267
    
268
    while (1) {
269
        
270
        
271
        _delay_ms(3000);
272
        
273
        getTime();
274
        // flash the led for the ammount of seconds
275
        for (uint8_t n=0; n <= rtc.sec; n++) {
276
            flash_ok_led(1);
277
        }
278
        flash_normal(2);
279
            
280
    }
281
}

von Johnny S. (sgt_johnny)


Lesenswert?

Hast du die möglichkeit die Variable "ret" irgendwie auszugeben?

von Julius (Gast)


Lesenswert?

Bin davon ausgegangen das ret nie etwas enthalten wird da die nächste 
Zeile "flash_normal(1)" nie ausgeführt wird.
Also das i2c_start irgendwie hängt...liege ich da falsch?

von Julius (Gast)


Lesenswert?

Also setTime() hängt bereites bis zu getTime() kommt der Code erst gar 
nicht.

von Gerhard O. (gerhard_)


Lesenswert?

Hallo Julius,

Deine I2C Adresse ist um eine Stelle falsch

Im Datenblatt des DS3231 ist die Adresse als "1101000" angegeben, das 
sind nur 7 bits. Da fehlt das W/R Bit. Die angegebene Adresse muß für 
Peters Bibliothek entweder als "0xC0 für Writes ausgeben werden und als 
0xC1 zum Lesen.

Also 0b11010000 zum Schreiben und zum lesen 0b11010001

Ich verwende Peter Fleurys Bibliothek auch und sende die Slave Adresse 
für den DS3231 immer als 0xC0(schreiben) oder 0xC1(lesen)

Guck mal hier:

http://homepage.hispeed.ch/peterfleury/doxygen/avr-gcc-libraries/group__pfleury__ic2master.html


#define rtc_clock 0x0xC0

Und verwende es so wie in seinem Beispiel angegeben:

ret = i2c_start(rtc_clock+I2C_WRITE);  // set device address

Bei der Arduino Bibliothek mußt Du tatsächlich 0x68 verwenden.

: Bearbeitet durch User
von Julius (Gast)


Lesenswert?

Ist 1101000(2) nicht 0x68(16) ?

Dann wäre doch das als rtc_clock richtig und dann kombiniert mit 
I2C_READ was ja eine 1 mehr ist:

11010001 = D1

und Lesen:
11010000 = D0

Oder warum verwendest du C0 und C1?

von Gerhard O. (gerhard_)


Lesenswert?

Julius schrieb:
> Ist 1101000(2) nicht 0x68(16) ?
Nein, da fehlt das LSB , 0x68 ist ja in Wirklichkeit nur 0b01101000

es muss 0b1101000(x) sein, wo x=0 -> Write, x=1 -> Read
>
> Dann wäre doch das als rtc_clock richtig und dann kombiniert mit
> I2C_READ was ja eine 1 mehr ist:
>
> 11010001 = D1
Lesen
>
> und Lesen: - Falsch
> 11010000 = D0
Schreiben
>
Das stimmt, aber 0x68 + 1 wäre 0x69 und nicht 0xD1

Beim Lesen wird 1 auf die 0xD0 addiert und es wird daraus 0xD1

> Oder warum verwendest du C0 und C1?

Oh, da habe ich mich verhaut. 0xD0/D1 ist natuerlich richtig. Danke für 
die Richtigstellung.

: Bearbeitet durch User
von Gerhard O. (gerhard_)


Angehängte Dateien:

Lesenswert?

Falls von Interesse, ein paar RTC Beispiele Schnipsel im Anhang für den 
DS3231 und DS1307.

von Julius (Gast)


Lesenswert?

Habe jetzt mit D1 für lesen und D0 für Schreiben noch einmal getestet, 
leider wird die Zeile:
1
// ------------------------------this line is never reached

nie erreicht :( Also die LED blinkt nicht.

Ideen?



Ausschnitt:
1
#define READ 0xD1
2
#define WRITE 0xD0
3
4
5
void setTime(uint8_t second, uint8_t minute, uint8_t hour, uint8_t dayOfWeek, 
6
        uint8_t dayOfMonth, uint8_t month, uint8_t year) {
7
8
    flash_normal(2);
9
    // initialize, taken from peter fleurys i2c example (he wrote the i2c code)
10
    i2c_init();
11
    // connect to the device and tell it that we want to write to it
12
    flash_ok_led(1);
13
14
    uint8_t ret;
15
    //ret = i2c_start(rtc_clock+I2C_WRITE);  // set device address and write mode
16
    ret = i2c_start(WRITE);
17
18
    // ------------------------------this line is never reached
19
    flash_ok_led(1);
20
21
    //ret = i2c_start(0xD0);
22
    
23
    
24
    if ( ret ) {
25
        flash_normal(3);
26
        /* failed to issue start condition, possibly no device found */
27
        i2c_stop();
28
        // we can issue an error message here if the device failed to respond
29
30
     } else {
31
        flash_ok_led(3);
32
        // tell the device where we want to write to (address in ram)
33
        i2c_write(0x00);
34
35
        // set time
36
        i2c_write(decToBcd(second)); // set seconds
37
        i2c_write(decToBcd(minute)); // set minutes
38
        i2c_write(decToBcd(hour)); // set hours
39
        i2c_write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
40
        i2c_write(decToBcd(dayOfMonth)); // set date (1 to 31)
41
        i2c_write(decToBcd(month)); // set month
42
        i2c_write(decToBcd(year)); // set year (0 to 99)    
43
        i2c_stop();     
44
    }                    
45
}
46
47
 
48
49
50
uint8_t result;
51
52
typedef struct {
53
    uint8_t sec;
54
    uint8_t min;
55
    uint8_t hour;
56
    uint8_t weekDay;
57
    uint8_t date;
58
    uint8_t month;
59
    uint8_t year;  
60
} rtc_t;
61
62
63
64
65
int main(void) {
66
    DDRB |= (1 << ERROR_LED);
67
    DDRB |= (1 << ERROR_LED_2);
68
69
    DDRB |= (1 << OK_LED);
70
71
    // test leds to see if they are connected and working
72
73
    flash_normal(1);
74
    flash_normal_error_led_2(1);
75
    flash_ok_led(1);    
76
77
78
    i2c_init();
79
    uint8_t count = 0;
80
    setTime(30,42,21,4,26,11,14);
81
    
82
    while (1) {
83
        
84
        count = count + 1;
85
        _delay_ms(3000);
86
        
87
        getTime();
88
        for (uint8_t n=0; n <= rtc.sec; n++) {
89
            flash_ok_led(1);
90
        }
91
        flash_normal(2);
92
            
93
    }
94
}

von Gerhard O. (gerhard_)


Angehängte Dateien:

Lesenswert?

Julius schrieb:
> Habe jetzt mit D1 für lesen und D0 für Schreiben noch einmal getestet,
> leider wird die Zeile:

Julius schrieb:
> Habe jetzt mit D1 für lesen und D0 für Schreiben noch einmal getestet,
> leider wird die Zeile:
> // --------------------

Ich kann Dir im Augenblick wegen Zeitmangel (Arbeit) nicht wirklich 
helfen. Wenn es vorher mit anderer Software funktioniert hat, schlage 
ich vor die dazugehörigen I2C_init() Einstellungen sorgfältig zu 
überprüfen. Dein I2C_Write hängt den uC. Das kann Hardware technisch 
bedingt sein oder falsche Einstellung der INIT Funktion. Wie gross sind 
die I2C Pullup Widerstände? ICh nehme standardmäßig immer 3.9KOhm bei 
5V.

Ich sehe, dass Deine LIB nicht die von mir versendete ist. Mit Deiner 
habe ich noch keine Erfahrung weil ich bis jetzt immer nur die 
I2CSoftMAster Bibl. verwendete. Vielleicht kennt sich jemand anders hier 
wirklich damit aus.

Im Anhang ist die Bibl. die ich bei mir verwende. Sie ist auch von 
Fleury und funktionierte bis jetzt immer einwandfrei.

von Julius (Gast)


Lesenswert?

Oh mist, habe ganz vergessen die Ports/Pins auf den atmega328 
anzupassen.

Danke für die vielen Antworten :)

von Gerhard O. (gerhard_)


Lesenswert?

Julius schrieb:
> Oh mist, habe ganz vergessen die Ports/Pins auf den atmega328
> anzupassen.
>
> Danke für die vielen Antworten :)

Funktionierts jetzt?

Gruß,
Gerhard

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.