Sign in Join
Wiki copytemporary

AVR Embedded Tutorial - I²C External-Clock: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: AVR Embedded Tutorial - I²C External-Clock

OldNewLine
1+# I²C external clock DS3231
2+
3+This code is for an Atmega328 / Arduino with 16MHz clock and a [DS3231 clock module](https://www.maximintegrated.com/en/products/analog/real-time-clocks/DS3231.html).
4+
5+The following functions are described in other tutorials:
6+
7+- [[AVR Embedded Tutorial - Delays|Delays]]
8+- [[AVR Embedded Tutorial - UART|UART - serial interface]]
9+- [[AVR Embedded Tutorial - I²C, TWI|Activate I²C bus]] or [[AVR Embedded Tutorial - Software I2C, TWI]]
10+
11+This example shows how to address the DS3231 clock module, which is connected to the I²C bus.
12+
13+**PullUp resistors are necessary**, the DS3231 does not contain any itself.
14+
15+## Functions for the DS3231 control
16+
17+### Constants
18+
19+``` pascal
20+ const
21+ I2CAddr = $68; // Default address of the DS3231.
22+ TWI_Write = 0;
23+ TWI_Read = 1;
24+```
25+
26+### Record for time storage
27+
28+``` pascal
29+ type
30+ TDate = record
31+ year : uint16;
32+ month, day, hour, minute, second, dayOfTheWeek : uint8;
33+ end;
34+ var
35+ Date : TDate;
36+```
37+
38+### BCD to BIN, BIN to BCD
39+
40+These conversion functions are required because the time is in BCD format.
41+
42+``` pascal
43+ function bcd2bin(val : uint8) : uint8;
44+ begin
45+ Result := val - 6 * (val shr 4);
46+ end;
47+
48+ function bin2bcd(val : uint8) : uint8;
49+ begin
50+ Result := val + 6 * (val div 10);
51+ end;
52+```
53+
54+### Write the time
55+
56+Write the block with a time. You can see that you have to convert the format.
57+
58+``` pascal
59+ procedure WriteDS3231(addr : UInt16);
60+ begin
61+ TWIStart((addr shl 1) or TWI_Write);
62+ TWIWrite(0);
63+ TWIWrite(bin2bcd(Date.Second));
64+ TWIWrite(bin2bcd(Date.Minute));
65+ TWIWrite(bin2bcd(Date.Hour));
66+ TWIWrite(bin2bcd(0));
67+ TWIWrite(bin2bcd(Date.Day));
68+ TWIWrite(bin2bcd(Date.Month));
69+ TWIWrite(bin2bcd(Date.Year - 2000));
70+ TWIStop;
71+ end;
72+```
73+
74+### Read the time
75+
76+Read the time from the block. You can see that you have to convert the format.
77+
78+``` pascal
79+ procedure ReadDS3231(addr : UInt16);
80+ begin
81+ TWIStart((addr shl 1) or TWI_Write);
82+ TWIWrite(0);
83+ TWIStop;
84+
85+ TWIStart((addr shl 1) or TWI_Read);
86+ Date.second := bcd2bin(TWIReadACK_Error and $7F);
87+ Date.minute := bcd2bin(TWIReadACK_Error);
88+ Date.hour := bcd2bin(TWIReadACK_Error);
89+
90+ TWIReadACK_Error;
91+
92+ Date.day := bcd2bin(TWIReadACK_Error);
93+ Date.month := bcd2bin(TWIReadACK_Error);
94+ Date.year := bcd2bin(TWIReadNACK_Error) + 2000;
95+
96+ TWIStop;
97+ end;
98+```
99+
100+## Example program
101+
102+### Variables
103+
104+``` pascal
105+ var
106+ s : ShortString;
107+```
108+
109+### Main program
110+
111+You only have to write the time to the DS3231 to if you want to set the clock.
112+
113+``` pascal
114+ begin
115+ UARTInit; // initialize UART
116+ TWIInit; // initialize I²C
117+ asm Sei end; // enable interrupts
118+
119+ // Write a time from the DS3231.
120+ Date.second := 33;
121+ Date.minute := 22;
122+ Date.hour := 11;
123+
124+ WriteDS3231(I2CAddr);
125+
126+ // Read time and output via UART
127+ repeat
128+ ReadDS3231(I2CAddr);
129+
130+ str(Date.second : 6, s);
131+ UARTSendString('Sec:' + s);
132+ str(Date.minute : 6, s);
133+ UARTSendString('Minute:' + s);
134+ str(Date.hour : 6, s);
135+ UARTSendString('hours:' + s);
136+
137+ UARTSendString(#13#10);
138+ until 1 = 2;
139+ end.
140+```
141+
142+# See also
143+
144+- Overview page - [[AVR Embedded Tutorials]].
145+
146+---
147+*From the Free Pascal wiki, page "AVR Embedded Tutorial - I²C External-Clock", as it stood on 2020-03-08 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history