Wiki copymirror

This is a mirror of the wiki at pascal.chat. Editing, history and sign-in are there.

AVR Embedded Tutorial - I²C External-Clock

Deutsch · English

I²C external clock DS3231

This code is for an Atmega328 / Arduino with 16MHz clock and a DS3231 clock module.

The following functions are described in other tutorials:

This example shows how to address the DS3231 clock module, which is connected to the I²C bus.

PullUp resistors are necessary, the DS3231 does not contain any itself.

Functions for the DS3231 control

Constants

pascal
 const
   I2CAddr   = $68;  // Default address of the DS3231.
   TWI_Write = 0;
   TWI_Read  = 1;

Record for time storage

pascal
 type
   TDate = record
     year : uint16;
     month, day, hour, minute, second, dayOfTheWeek : uint8;
   end;
 var
   Date : TDate;

BCD to BIN, BIN to BCD

These conversion functions are required because the time is in BCD format.

pascal
  function bcd2bin(val : uint8) : uint8;
   begin
     Result := val - 6 * (val shr 4);
   end;

   function bin2bcd(val : uint8) : uint8;
   begin
     Result := val + 6 * (val div 10);
   end;

Write the time

Write the block with a time. You can see that you have to convert the format.

pascal
  procedure WriteDS3231(addr : UInt16);
   begin
     TWIStart((addr shl 1) or TWI_Write);
     TWIWrite(0);
     TWIWrite(bin2bcd(Date.Second));
     TWIWrite(bin2bcd(Date.Minute));
     TWIWrite(bin2bcd(Date.Hour));
     TWIWrite(bin2bcd(0));
     TWIWrite(bin2bcd(Date.Day));
     TWIWrite(bin2bcd(Date.Month));
     TWIWrite(bin2bcd(Date.Year - 2000));
     TWIStop;
   end;

Read the time

Read the time from the block. You can see that you have to convert the format.

pascal
  procedure ReadDS3231(addr : UInt16);
   begin
     TWIStart((addr shl 1) or TWI_Write);
     TWIWrite(0);
     TWIStop;

     TWIStart((addr shl 1) or TWI_Read);
     Date.second := bcd2bin(TWIReadACK_Error and $7F);
     Date.minute := bcd2bin(TWIReadACK_Error);
     Date.hour   := bcd2bin(TWIReadACK_Error);

     TWIReadACK_Error;

     Date.day    := bcd2bin(TWIReadACK_Error);
     Date.month  := bcd2bin(TWIReadACK_Error);
     Date.year   := bcd2bin(TWIReadNACK_Error) + 2000;

     TWIStop;
   end;

Example program

Variables

pascal
  var
   s : ShortString;

Main program

You only have to write the time to the DS3231 to if you want to set the clock.

pascal
  begin
   UARTInit;     // initialize UART
   TWIInit;      // initialize I²C
   asm Sei END;  // enable interrupts

   // Write a time from the DS3231.
   Date.second := 33;
   Date.minute := 22;
   Date.hour   := 11;

   WriteDS3231(I2CAddr);

   // Read time and output via UART
   repeat
     ReadDS3231(I2CAddr);

     str(Date.second : 6, s);
     UARTSendString('Sec:' + s);
     str(Date.minute : 6, s);
     UARTSendString('Minute:' + s);
     str(Date.hour : 6, s);
     UARTSendString('hours:' + s);

     UARTSendString(#13#10);
   until 1 = 2;
 end.

See also


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.

Revision 1, last changed by WikiArchive .