Interfacing DS1307/DS3231 RTC with PIC MCU | MPLAB Projects

This post shows how to build a simple real time clock using PIC16F887 microcontroller and DS1307 (or DS3231) RTC chip. Time and date are displayed on 16×2 LCD screen and they can be set with two push buttons connected to the MCU.
The compiler used in this project is Microchip MPLAB XC8 (MPLAB X IDE with MPLAB XC8 compiler).

and the below image shows the same circuit but with DS3231 board instead of DS1307:

(All grounded terminals are connected together)

The two push buttons in the circuit are used to set time and date of the real time clock, button 1 (B1) is connected to RB0 pin (#33) and button 2 (B2) is connected to RB1 pin (#34) of the PIC16F887 MCU.

VEE pin is used to control the contrast of the LCD. A (anode) and K (cathode) are the back light LED pins.

In this project the PIC16F887 microcontroller runs with its internal oscillator @ 8 MHz, MCLR pin is configured as an input pin.

Interfacing DS1307/DS3231 RTC with PIC microcontroller C code:
The C code below is for MPLAB XC8 compiler, it was tested with version 2.00 installed on MPLAB X IDE version 5.05.

To be able to compile the C code, a small LCD library for MPLAB XC8 compiler is required which can be downloaded from the following link:MPLAB XC8 LCD Library

after the download, add the library file (LCD_Lib.c) to project folder.

I2C Functions:
The MPLAB XC8 compiler doesn’t have any I2C library for the PIC16F887 microcontroller which means we’ve to write own I2C function codes.
The PIC16F887 has one MSSP module which can work in I2C mode. For that I wrote some functions which allowed me to communicate with the RTC chip using the MSSP module:void I2C_Init(uint32_t i2c_clk_freq) : initializes the MSSP module in I2C mode (master mode) with a clock frequency of i2c_clk_freq.void I2C_Start() : this function sends a start signal to the I2C slave device.void I2C_Repeated_Start() : sends a repeated start signal.void I2C_Stop() : sends a stop signal.void I2C_Write(uint8_t i2c_data) : writes data (i2c_data) to the I2C device.uint8_t I2C_Read(uint8_t ack) : reads (& returns) data from I2C device, this function sends acknowledge pulse if ack = 1.

RTC Functions:
The RTC chip (DS1307 or DS3231) works with BCD format only, to convert the BCD to decimal and vise versa I used the 2 functions below. Before displaying (after reading from RTC IC), the data have to be converted from BCD to decimal, and before writing to the RTC IC (after editing the parameters) the data have to be converted from decimal to BCD:uint8_t bcd_to_decimal(uint8_t number)uint8_t decimal_to_bcd(uint8_t number)
Each function returns the converted value of the variable number.

void RTC_display() : displays time and date, before printing them on the LCD, time and date data are converted from BCD format to decimal format using the function bcd_to_decimal(uint8_t number) .

uint8_t edit(uint8_t x, uint8_t y, uint8_t parameter) : I used this function to edit time and date parameters (minutes, hours, date, month and year). I used a variable named i to distinguish between the parameters:
i = 0, 1 : hours and minutes respectively
i = 2, 3, 4: date, month and year respectively

After the edit of time and date, the data have to be converted back to BCD format using the function decimal_to_bcd(uint8_t number) and written to the RTC chip.

void blink() : this small function works as a delay except that it can be interrupted by buttons B1 (connected to RB0) and B2 (connected to RB1). When called and without pressing any button the total time is 100 x 5ms = 500ms. With this function we can see the blinking of the selected parameter with a frequency of 1 Hz. So a delay of 500ms comes after the print of the selected parameter and after that delay, 2 spaces are printed which make the parameter disappears from the screen and another 500ms delay comes after the print of the 2 spaces.

The microcontroller used in this example is PIC16F887, configuration words are: