Saturday, February 1, 2020

Real Time Clock (DS1307) Interfacing with PIC Microcontroller

Hello Guys, first of all, I am really very sorry that I am not able to post anything for approximately 2 years. I was totally occupied with some other stuff and that's why I didn't get time to post anything, but during this time I have worked on a lot of different projects and learned a lot of tools and new technologies, which includes UML, Sparx EA, emWin, STM32, Git, etc.
In this post, I will start with a very simple and one of the most common topics in the field of Embedded System and is interfacing a real-time clock integrated circuit with the most common pic micro-controller.
In the past I have faced a lot of problems in handling the software (source code) written by me, every time I started a new project, I have to re-write the libraries again or copying pasting the libraries from one place to another. So, this time I will be more professional and will keep my all libraries on GitHub, and use these libraries into the project as a submodule. This will help in maintaining and updating the libraries and also issue fixing and feature enhancement all at the same place.
In this project, I am going to use RTC DS1307 and interface it with PIC18F4550 microcontroller, and display the time and date fetched from the RTC.
For this project, I have created three libraries and they are as follow:
LCD Library
I2C Library
DS1307 Library

The complete project can be downloaded or clones by clicking here.
I have also done this similar type of task in the past and you can have a look at that by clicking here.
The software written in the older post is working but it is not maintainable, now I will try to move everything to GitHub, this will give the flexibility to maintain the software.
Please have a look at the video for the post and please subscribe to my YouTube channel also.

The following is the snippet from the code from main.c file.

/*
 * @file i2.c
 * @author xpress_embedo
 * @date 1 Feb, 2020
 * 
 * @brief Main File of the Project
 *
 */

#include "main.h"
#include "lcd_16x2.h"
#include "ds1307.h"

/* Local Variables */
static uint32_t millisecond = 0;

/* Local Function */
void timer0_init( void );
void system_init( void );

/* Start From Here*/
void main(void) 
{
  char lcd_msg[LCD_BUFFER_LEN] = {0};
  uint32_t timestamp = 0;
  system_init();
  sprintf(lcd_msg, "Embedded");
  LCD_Print_Line (0, lcd_msg);
  sprintf(lcd_msg, "      Laboratory");
  LCD_Print_Line (1, lcd_msg);
  LCD_Update();
  Delay_ms(1000);
  while(1)
  {
    // Task-1 (500ms)
    if( millis() - timestamp > 500ul )
    {
      uint8_t year, month, date, hour, minute, second;
      static uint8_t sec_blink;
      timestamp = millis();
      second = DS1307_Read (DS1307_SEC);
      minute = DS1307_Read (DS1307_MIN);
      hour   = DS1307_Read (DS1307_HOUR);
      date   = DS1307_Read (DS1307_DATE);
      month  = DS1307_Read (DS1307_MONTH);
      year   = DS1307_Read (DS1307_YEAR);
      // The value Read are in BCD Format, which needs to be converted into char
      if( sec_blink )
      {
        sec_blink = FALSE;
        sprintf (lcd_msg, "TIME: %c%c:%c%c:%c%c", \
                 BCD2UpperCh (hour), BCD2LowerCh (hour), \
                 BCD2UpperCh (minute), BCD2LowerCh (minute), \
                 BCD2UpperCh (second), BCD2LowerCh (second) );
      }
      else
      {
        sec_blink = TRUE;
        sprintf (lcd_msg, "TIME: %c%c:%c%c %c%c", \
                 BCD2UpperCh (hour), BCD2LowerCh (hour), \
                 BCD2UpperCh (minute), BCD2LowerCh (minute), \
                 BCD2UpperCh (second), BCD2LowerCh (second) );
      }
      LCD_Print_Line (0, lcd_msg);
      sprintf (lcd_msg, "DATE: %c%c/%c%c/%c%c", \
               BCD2UpperCh (date), BCD2LowerCh (date), \
               BCD2UpperCh (month), BCD2LowerCh (month), \
               BCD2UpperCh (year), BCD2LowerCh (year) );
      LCD_Print_Line (1, lcd_msg);
      LCD_Update ();
    }
  }
  return;
}

/* Function Definitions */

/**
 * @breif Initialize the system
 */
void system_init( void )
{
  // Initialize 1ms Timer
  timer0_init ();
  // Initialize DS1307 and Start Time
  DS1307_Init ();
  // Initialize LCD
  LCD_Init();
  Delay_ms(100);
}

/**
 * @brief Counts milliseconds till startup
 * @return This function returns the number of milliseconds elapsed till the 
 * system is powered up.
 */
uint32_t millis( void )
{
  uint32_t time = 0;
  GIE = 0;
  time = millisecond;
  GIE = 1;
  return time;
}

/**
 * @brief Initialize Timer0 Module to generate 1ms interrupt
 */
void timer0_init( void )
{
  // Code Generated Using mikroC Timer Calculator
  T0CON = 0x88;
  TMR0H = 0xD1;
  TMR0L = 0x20;
  ENABLE_INT();
  TMR0IE = 1;
}

/**
 * PIC18F Interrupt Service Routine
 */
void __interrupt() ISR_ROUTINE( void )
{
  if( TMR0IF )
  {
    TMR0IF = 0;
    TMR0H = 0xD1;
    TMR0L = 0x20;
    millisecond++;
  }
}

I am still working on improvements and with the use of a version control system like Git, hosting services like GitHub, I can keep my source code updated.
The Proteus simulation file is also updated in the SIM folder and can be found under the GitHub project.


Working Simulation Snapshot
The above image illustrates the working of the simulation.
Thank You guys, in case of any question, please feel free to contact me.

No comments:

Post a Comment