RTC Digital Clock not working

I'm working on a RTC Digital clock project to run a 24-hour format clock using a 4-digit 7-segment LED with a DS1302 module and 3 buttons as the figure below:



Button on the right is button 1, to the left is button 2 and 3 accordingly. The LED pins are connected to Arduino as: pin A - G use PORTD0 to PORTD6, Digit1-Digit4 pins use PORTB0 to PORTB3 accordingly. Button 1, 2, 3 use PORTC0, C1, C2, and DS1302 Clock pin use PORTC4, Data pin use PORTC5 and Reset pin use PORTC6. Instead of using DS1302 library, I wrote the logic code myself.
Press button 1 turn into Set time mode or press again to run the clock. Press button 2 to choose the number I want to change, button 3 to increase the chosen number. However, it's not work as intended, the clock doesn't run at all, just flickering 0 or 1, and the buttons are messsed up.

#ifndef F_CPU
#define F_CPU 16000000UL
#endif

#include <avr/io.h>
#include <avr/interrupt.h>

#define DS1302_CLK PC3 
#define DS1302_CLK_DDR DDRC
#define DS1302_CLK_PORT PORTC

#define DS1302_DIO PC4 
#define DS1302_DIO_DDR DDRC
#define DS1302_DIO_PORT PORTC
#define DS1302_DIO_PIN PINC

#define DS1302_CE PC5 
#define DS1302_CE_DDR DDRC
#define DS1302_CE_PORT PORTC

#define DS1302_DELAY_USEC 3


void DS1302_Init(void) {
  // CE - output, set low
  DS1302_CE_DDR |= (1 << DS1302_CE);
  DS1302_CE_PORT &= ~(1 << DS1302_CE);

  // CLK - output, set low
  DS1302_CLK_DDR |= (1 << DS1302_CLK);
  DS1302_CLK_PORT &= ~(1 << DS1302_CLK);

  // DIO - output, set low (for now)
  DS1302_DIO_DDR |= (1 << DS1302_DIO);
  DS1302_DIO_PORT &= ~(1 << DS1302_DIO);
}

void DS1302_TransmitByte(uint8_t byte) 
{
  // DIO - output, set low
  DS1302_DIO_DDR |= (1 << DS1302_DIO);
  DS1302_DIO_PORT &= ~(1 << DS1302_DIO);

  // transmit byte, lsb-first
  for (uint8_t i = 0; i < 8; i++) 
  {
    if ((byte >> i) & 0x01) 
    {
      // set high
      DS1302_DIO_PORT |= (1 << DS1302_DIO);
    } 
    else 
    {
      // set low
      DS1302_DIO_PORT &= ~(1 << DS1302_DIO);
    }

    // send CLK signal
    DS1302_CLK_PORT |= (1 << DS1302_CLK);
    _delay_us(DS1302_DELAY_USEC);
    DS1302_CLK_PORT &= ~(1 << DS1302_CLK);
  }
}

uint8_t DS1302_ReceiveByte(void) {
  // DIO - input
  DS1302_DIO_DDR &= ~(1 << DS1302_DIO);

  // receive byte, lsb-first
  uint8_t byte = 0;
  for (uint8_t i = 0; i < 8; i++) 
  {
    if (DS1302_DIO_PIN & (1 << DS1302_DIO)) 
    {
      byte |= (1 << i);
    }

    // send CLK signal
    DS1302_CLK_PORT |= (1 << DS1302_CLK);
    _delay_us(DS1302_DELAY_USEC);
    DS1302_CLK_PORT &= ~(1 << DS1302_CLK);
  }

  return byte;
}

uint8_t dec2bcd(uint8_t dec) 
{
  return ((dec / 10 * 16) + (dec % 10));
}

uint8_t bcd2dec(uint8_t bcd) 
{
  return ((bcd / 16 * 10) + (bcd % 16));
}


volatile int timer = 0;
volatile bool one_minute = false;
volatile bool one_second = false;

int hour1 = 0;
int hour2 = 0;
int minute1 = 0;
int minute2 = 0;

int main (void)
{
  DS1302_Init();
  DDRD = 0xFF;

  DDRB |= (1 << 0); //Digit 1
  DDRB |= (1 << 1); //Digit 2
  DDRB |= (1 << 2); //Digit 3
  DDRB |= (1 << 3); //Digit 4

  DDRC &= ~(1 << 0); // BUTTON 1
  DDRC &= ~(1 << 1); // BUTTON 2
  DDRC &= ~(1 << 2); // BUTTON 3

  TCCR1B |= (1 << WGM12); // Turn on the CTC mode for Timer 1
  TCCR1B |= (1 << CS12 ) | (1 << CS10); // Set up Timer 1 with the prescaler of 1024
  OCR1A = 15624; // Set CTC compare value to 0.125Hz at 16 MHz AVR clock , with a prescaler of 1024
  TIMSK1 = 1 << OCIE1A; // Enable Output Compare A Match Interrupt
  sei(); // Enable the Global Interrupt Bit

  while (1)
  {
    if (!(PINC & (1 << PINC2))) // Button 4 is used to switch from 'time mode' to 'set time mode' for the system
    {
      _delay_ms(250);
      set_time();
    }
    if (one_second)
    {
      uint8_t bytes[8];

      DS1302_CE_PORT |= (1 << DS1302_CE);
      DS1302_TransmitByte(0xBF);
      for (uint8_t i = 0; i < sizeof(bytes); i++) 
      {
        bytes[i] = DS1302_ReceiveByte();
      }
      DS1302_CE_PORT &= ~(1 << DS1302_CE);

      int minute = bcd2dec(bytes[1]);
      int hour = bcd2dec(bytes[2]);

      hour1 = hour / 10;
      hour2 =  hour % 10;
      minute1 =  minute / 10;
      minute2 =  minute % 10;
      one_second = false;
    }
    display_time();
    time_system();
  }
}

ISR (TIMER1_COMPA_vect)
{
  one_second = true;
  timer++;
  if (timer > 59)
  {
    timer = 0;
    one_minute = true;
  }
}

void time_system()
{
  if (one_minute)
  {
    minute2++;
    one_minute = false;
  }

  if (minute2 > 9)
  {
    minute2 = 0;
    minute1++;
  }

  if (minute1 > 5)
  {
    minute1 = 0;
    minute2 = 0;

    if (hour1 == 0 && hour2 > 9)
    {
      hour2 = 0;
      hour1++;
    }

    if (hour1 == 1 && hour2 > 9)
    {
      hour2 = 0;
      hour1++;
    }

    if (hour1 == 2 && hour2 >= 3)
    {
      hour1 = 0;
      hour2 = 0;
    }

    else
    {
      hour2++;
    }
  }
}

void set_time()
{
  int set_h1 = hour1;
  int set_h2 = hour2;
  int set_m1 = minute1;
  int set_m2 = minute2;
  int change_digit = 1;

  bool button_3_pressed = false;

  while (button_3_pressed == false)
  {
    if (!(PINC & (1 << PINC2)))
    {
      _delay_ms(250);
      uint8_t bytes[8];
      uint8_t minute = dec2bcd(set_m1 * 10 + set_m2);
      uint8_t hour = dec2bcd(set_h1 * 10 + set_h2);
      bytes[1] = minute;
      bytes[2] = hour;
      DS1302_CE_PORT |= (1 << DS1302_CE);
      DS1302_TransmitByte(0xBE);
      for (uint8_t i = 0; i < sizeof(bytes); i++) 
      {
        DS1302_TransmitByte(bytes[i]);
      }
      DS1302_CE_PORT &= ~(1 << DS1302_CE);
    }

    if (change_digit == 1)
    {
      hour1_display(set_h1);
    }

    if (change_digit == 2)
    {
      hour2_display(set_h2);
    }

    if (change_digit == 3)
    {
      minute1_display(set_m1);
    }

    if (change_digit == 4)
    {
      minute2_display(set_m2);
    }

    if (!(PINC & (1 << PINC1)))
    {
      _delay_ms(250);
      if (change_digit == 1)
      {
        change_digit = 2;
      }
      else if (change_digit == 2)
      {
        change_digit = 3;
      }
      else if (change_digit == 3)
      {
        change_digit = 4;
      }
      else if (change_digit == 4)
      {
        change_digit = 1;
      }
    }

    if (!(PINC & (1 << PINC2)))
    {
      _delay_ms(250);
      timer = 0;
      button_3_pressed = true;
    }

    if (!(PINC & (1 << PINC0)) && change_digit == 1 )
    {
      _delay_ms(250);
      if ( set_h1 < 1 && set_h2 >= 5)
      {
        set_h1++;
      }
      else if ( set_h1 < 2 && set_h2 <= 4)
      {
        set_h1++;
      }
      else
      {
        set_h1 = 0;
      }
    }

    else if (!(PINC & (1 << PINC0)) && change_digit == 2)
    {
      _delay_ms(250);
      if ( (set_h1 == 0 || set_h1 == 1) && set_h2 < 9)
      {
        set_h2++;
      }
      else if (set_h1 == 2 && set_h2 < 3)
      {
        set_h2++;
      }
      else
      {
        set_h2 = 0;
      }
    }

    else if (!(PINC & (1 << PINC0)) && change_digit == 3 )
    {
      _delay_ms(250);
      set_m1++;
      if (set_m1 > 5)
      {
        set_m1 = 0;
      }
    }

    else if (!(PINC & (1 << PINC0)) && change_digit == 4)
    {
      _delay_ms(250);
      set_m2++;
      if (set_m2 > 9)
      {
        set_m2 = 0;
      }
    }
  }
  button_3_pressed = false;
  hour1 = set_h1;
  hour2 = set_h2;
  minute1 = set_m1;
  minute2 = set_m2;
}

void display_time()
{
  hour1_display(hour1);
  _delay_ms(5);
  hour2_display(hour2);
  _delay_ms(5);
  minute1_display(minute1);
  _delay_ms(5);
  minute2_display(minute2);
  _delay_ms(5);
}

void hour1_display(int i)
{
  PORTB |= (1 << 0);
  PORTB &= ~(1 << 1);
  PORTB &= ~(1 << 2);
  PORTB &= ~(1 << 3);
  if (i == 0)
  {
    number_0();
  }
  else if (i == 1)
  {
    number_1();
  }
  else if (i == 2)
  {
    number_2();
  }
}

void hour2_display(int i)
{
  PORTB |= (1 << 1);
  PORTB &= ~(1 << 0);
  PORTB &= ~(1 << 2);
  PORTB &= ~(1 << 3);
  if (i == 0)
  {
    number_0();
  }
  else if (i == 1)
  {
    number_1();
  }
  else if (i == 2)
  {
    number_2();
  }
  else if (i == 3)
  {
    number_3();
  }
  else if (i == 4)
  {
    number_4();
  }
  else if (i == 5)
  {
    number_5();
  }
  else if (i == 6)
  {
    number_6();
  }
  else if (i == 7)
  {
    number_7();
  }
  else if (i == 8)
  {
    number_8();
  }
  else if (i == 9)
  {
    number_9();
  }
}

void minute1_display(int i)
{
  PORTB |= (1 << 2);
  PORTB &= ~(1 << 0);
  PORTB &= ~(1 << 1);
  PORTB &= ~(1 << 3);
  if (i == 0)
  {
    number_0();
  }
  else if (i == 1)
  {
    number_1();
  }
  else if (i == 2)
  {
    number_2();
  }
  else if (i == 3)
  {
    number_3();
  }
  else if (i == 4)
  {
    number_4();
  }
  else if (i == 5)
  {
    number_5();
  }
}

void minute2_display(int i)
{
  PORTB |= (1 << 3);
  PORTB &= ~(1 << 0);
  PORTB &= ~(1 << 1);
  PORTB &= ~(1 << 2);
  if (i == 0)
  {
    number_0();
  }
  else if (i == 1)
  {
    number_1();
  }
  else if (i == 2)
  {
    number_2();
  }
  else if (i == 3)
  {
    number_3();
  }
  else if (i == 4)
  {
    number_4();
  }
  else if (i == 5)
  {
    number_5();
  }
  else if (i == 6)
  {
    number_6();
  }
  else if (i == 7)
  {
    number_7();
  }
  else if (i == 8)
  {
    number_8();
  }
  else if (i == 9)
  {
    number_9();
  }
}

void number_0()
{
  PORTD = 0b11000000;
}

void number_1()
{
  PORTD = 0b11111001;
}

void number_2()
{
  PORTD = 0b10100100;
}

void number_3()
{
  PORTD = 0b10110000;
}

void number_4()
{
  PORTD = 0b10011001;
}

void number_5()
{
  PORTD = 0b10010010;
}

void number_6()
{
  PORTD = 0b10000010;
}

void number_7()
{
  PORTD = 0b11111000;
}

void number_8()
{
  PORTD = 0b10000000;
}

void number_9()
{
  PORTD = 0b10010000;
}

Holy carp- you went from this:

.... yesterday to that code within a day.

That's a load of complex code to have produced in a day- impressive! Did you test each segment of that code as you went?

If you want help on that code (it won't be from me- it's way above my programming level for now) you will need to be more specific than:

Yeah, a lot of effort. I have to read the datasheet of DS1302, ask my tutor, other friends to get to those codes. But not even sure if the code is correct :slight_smile:

Well if it doesn't work as intended, it clearly isn't :wink:

I can't help without catching up a lot, like studying the datasheet as I suggested you had to yesterday. That's very very complex code for a beginner... I hope you can get some help here.

But, did you test it as you go... does any of it do what it's supposed to?

I found a huge chunk of your code in a git repository from 2018 so I'm thinking you lifted most if not all of it from there with no attribution. If you use other's code it's at least good manners to say so in your comments, not to mention that it may actually be a licence requirement.

If it doesn't work and or you don't understand it, perhaps you should take that up with the author/s of the code you presented.

Oh, I got most the code for DS1302 from a friend, and I didn't know that it's from GitHub. Anyway, the clock logic to count the time ( second, minute, hour) seems to be correct, but the hardware doesn't display properly: instead of showing all 4 digits at the same time, the LED displays each digit at a time :v So i mostly think the problem is in the code other than DS1302. Still working on it or I'm just being silly and missing something significant.

Then your code should at least have had attribution to them surely? Especially since you acknowledged in your original thread yesterday that this is a homework assignment, and sources should always be given.

edit: I'm wondering if your instructor will ask for a line-by-line explanation of the sketch you hand in?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.