Library 15- DS1307 Real Time Clock for STM32F4
In my 15th library, I will show you, how to operate with DS1307 Real Time Clock I2C module from maxim integrated.
The DS1307 serial real-time clock (RTC) is a lowpower, full binary-coded decimal (BCD) clock/calendar plus 56 bytes f NV SRAM. Address and data are transferred serially through an I2C, bidirectional bus. The clock/calendar provides seconds, minutes, hours, day, date, month, and year information. The end of the month date is automatically adjusted for months with fewer than 31 days, including corrections for leap year. The clock operates in either the 24-hour or 12- hour format with AM/PM indicator. The DS1307 has a built-in power-sense circuit that detects power failures and automatically switches to the backup supply. Timekeeping operation continues while the part operates from the backup supply.
I have DS1307 Shield from ebay. They are almost free and you get battery too.
Do not use this library for future projects. Use internal RTC on STM32F4xx instead.
DS1307 features
- Real time clock
- Counts seconds, minutes, hours, day in a week, date, month and year
- I2C interface
- External oscillator 32.768kHz required
- Binary-coded numbers
- Square wave output pin
Library
Features
- Set and get date and time from DS1307
- Set/Get date/time from DS1307 separatelly
- Enable/disable square wave output pin
- Version 1.1 – July 30, 2014
- Square wave output pin can be enabled
- Version 1.2 – September 21, 2014
- You can now check on iintialization if device is connected
Dependencies
- CMSIS
- STM32F4xx
- STM32F4xx RCC
- STM32F4xx GPIO
- STM32F4xx I2C
- TM
- TM DELAY
- TM I2C
- defines.h
- TM DELAY
DS1307 | STM32F4xx | Description |
---|---|---|
VCC | 5V | Positive voltage |
GND | GND | Ground |
SDA | PB7 | I2C1, PinsPack 1 |
SCL | PB6 | I2C1, PinsPack 1 |
In case, you want custom I2C pins, you can set it in defines.h file (for corresponding pins look at my I2C library):
1 2 3 |
/* Select custom I2C pins */ #define TM_DS1307_I2C I2C1 #define TM_DS1307_I2C_PINSPACK TM_I2C_PinsPack_1 |
Datetime struct
There is a struct for date and time you are working with. It is used to set and to get time to/from DS1307.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
/** * Struct for date/time * * Parameters: * - uint8_t seconds: * Seconds parameter, from 00 to 59 * - uint8_t minutes: * Minutes parameter, from 00 to 59 * - uint8_t hours: * Hours parameter, 24Hour mode, 00 to 23 * - uint8_t day: * Day in a week, from 1 to 7 * - uint8_t date: * Date in a month, 1 to 31 * - uint8_t month: * Month in a year, 1 to 12 * - uint8_t year: * Year parameter, 00 to 99, 00 is 2000 and 99 is 2099 */ typedef struct { uint8_t seconds; //Seconds, 00-59 uint8_t minutes; //Minutes, 00-59 uint8_t hours; //Hours, 00-23 uint8_t day; //Day in a week, 1-7 uint8_t date; //Day in a month 1-31 uint8_t month; //Month, 1-12 uint8_t year; //Year 00-99 } TM_DS1307_Time_t; |
Write date/time
You can write all (date and time) to DS1307 or you can write each thing separatelly.
1 2 3 4 5 6 7 8 9 10 |
//Set date and time all in one packet //Day 7, 26th May 2014, 02:05:00 time.hours = 2; time.minutes = 05; time.seconds = 0; time.date = 26; time.day = 7; time.month = 5; time.year = 14; TM_DS1307_SetDateTime(&time); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//Set seconds only to 0 TM_DS1307_SetSeconds(0); //Set minutes only to 5 TM_DS1307_SetMinutes(5); //Set hours only to 2 TM_DS1307_SetHours(2); //Set day in a week only to 7 TM_DS1307_SetDay(7); //Set date only to 26 TM_DS1307_SetDate(26); //Set month only to 5 TM_DS1307_SetMonth(5); //Set year only to 14 (2014) TM_DS1307_SetYear(14); |
Read date/time
You can read all (date and time) from DS1307 or you can read each thing separatelly.
1 2 3 4 |
//Time struct TM_DS1307_Time_t time; //Get date and time TM_DS1307_GetDateTime(&time); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//Get only seconds seconds = TM_DS1307_GetSeconds(); //Get only minutes minutes = TM_DS1307_GetMinutes(); //Get only hours hours = TM_DS1307_GetHours(); //Get only day in a week day = TM_DS1307_GetDay(); //Get only date date = TM_DS1307_GetDate(); //Get only month month = TM_DS1307_GetMonth(); //Get only year year = TM_DS1307_GetYear(); |
SQW/OUT pin
DS1307 has one pin, which can be used to output frequency. This frequency can be 1Hz, 4096Hz, 8192Hz or 32768Hz. Also, pin can be set high or low. Pin has open-drain circuit, that means you need external pull up resistor to get pin working properly.
For this purpose I made 2 new functions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
/** * DS1307 has SQW/OUT pin, which can be enabled in various modes. * It can output 32768Hz, 8192Hz, 4096Hz, 1Hz, Low or High state. * This is useful if you need interrupts on MCU. 1Hz can be used to increment time by software each time. * This is faster than look for date and time each time. * * Also, this pin is Open-Drain. This means that pin cannot supply positive power supply, * for that you need external pull up resistor (or pull up from MCU). * * Parameters: * - TM_DS1307_OutputFrequency_t frequency: * Member of TM_DS1307_OutputFrequency_t typedef * * No returns */ extern void TM_DS1307_EnableOutputPin(TM_DS1307_OutputFrequency_t frequency); /** * Disable SQW/OUT pin. * * This function basically set pin to high state. * To get high state you need external pull up resistor (or use pull up from MCU) * * No returns */ extern void TM_DS1307_DisableOutputPin(void); |
To use this functions, you also need enumeration typedef
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/** * Typedef enumerations for SQW/OUT pin * * - TM_DS1307_OutputFrequency_1Hz: * Set SQW/OUT pin to 1Hz output frequency * - TM_DS1307_OutputFrequency_4096Hz * Set SQW/OUT pin to 4096Hz output frequency * - TM_DS1307_OutputFrequency_8192Hz * Set SQW/OUT pin to 8192Hz output frequency * - TM_DS1307_OutputFrequency_32768Hz * Set SQW/OUT pin to 32768Hz output frequency * - TM_DS1307_OutputFrequency_High * Set SQW/OUT pin high. Because this pin is open-drain, you will need external pull up resistor * - TM_DS1307_OutputFrequency_Low * Set SQW/OUT pin low */ typedef enum { TM_DS1307_OutputFrequency_1Hz = 0, TM_DS1307_OutputFrequency_4096Hz, TM_DS1307_OutputFrequency_8192Hz, TM_DS1307_OutputFrequency_32768Hz, TM_DS1307_OutputFrequency_High, TM_DS1307_OutputFrequency_Low } TM_DS1307_OutputFrequency_t; |
Why use this pin? If you set this pin to 1Hz, then you can with your software update clock, no need to constantly check DS1307’s registers, because this takes loong time for one STM32F4xx device. Seconds are updated on falling edge of SQW/OUT pin, if it is set to 1Hz output.
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
/** * Keil project for DS1307 RTC library * * Before you start, select your target, on the right of the "Load" button * * @author Tilen Majerle * @email tilen@majerle.eu * @website http://stm32f4-discovery.net * @ide Keil uVision 5 */ /* Include core modules */ #include "stm32f4xx.h" /* Include my libraries here */ #include "defines.h" #include "tm_stm32f4_ds1307.h" #include "tm_stm32f4_ili9341.h" #include "tm_stm32f4_disco.h" #include <stdio.h> int main(void) { char str[100]; TM_DS1307_Time_t time; uint8_t last; /* Initialize system */ SystemInit(); /* Initialize LEDS */ TM_DISCO_LedInit(); /* Initialize ILI9341 LCD on board */ TM_ILI9341_Init(); TM_ILI9341_Fill(ILI9341_COLOR_ORANGE); TM_ILI9341_Rotate(TM_ILI9341_Orientation_Portrait_2); TM_ILI9341_Puts(90, 310, "stm32f4-discovery.net", &TM_Font_7x10, ILI9341_COLOR_BLACK, ILI9341_COLOR_ORANGE); /* Initialize DS1307 */ if (TM_DS1307_Init() != TM_DS1307_Result_Ok) { /* Red LED on */ TM_DISCO_LedOn(LED_RED); /* Show on LCD */ TM_ILI9341_Puts(10, 10, "ERROR", &TM_Font_11x18, ILI9341_COLOR_BLACK, ILI9341_COLOR_ORANGE); while (1); } /* Set date and time */ /* Day 7, 26th May 2014, 02:05:00 */ time.hours = 21; time.minutes = 18; time.seconds = 0; time.date = 26; time.day = 1; time.month = 5; time.year = 14; TM_DS1307_SetDateTime(&time); /* Set output pin to 4096 Hz */ TM_DS1307_EnableOutputPin(TM_DS1307_OutputFrequency_4096Hz); while (1) { /* Get date and time */ TM_DS1307_GetDateTime(&time); /* Display on LCD */ sprintf(str, "Day: %d\nDate: %02d\nMonth: %02d\nYear: %04d\nHours: %02d\nMinutes: %02d\nSeconds: %02d", time.day, time.date, time.month, time.year + 2000, time.hours, time.minutes, time.seconds); TM_ILI9341_Puts(10, 15, str, &TM_Font_11x18, ILI9341_COLOR_ORANGE, 0x0000); /* Toggle GREEN led if needed */ if (last != time.seconds) { last = time.seconds; /* Toggle GREEN LED */ TM_DISCO_LedToggle(LED_GREEN); } } } |
Project available on Github, downlaod library here.
DS1307 External I2C RTC Clock library
Recent comments