1
\$\begingroup\$

I am trying to stop the RTC clock by setting the CH bit in it's second register. I read the second register, mask the 7th bit to 1, rewrite this to the second register. But for some reason, this approach is not working.

I want to stop/start the RTC according to my needs. Can you guide me in this problem?

The schematic is:

enter image description here

My code is:

// LCD module connections
sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;

sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
// End LCD module connections

unsigned short read_ds1307(unsigned short address)
{
  unsigned short r_data;
  I2C1_Start();
  I2C1_Wr(0xD0); //address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0
  I2C1_Wr(address);
  I2C1_Repeated_Start();
  I2C1_Wr(0xD1); //0x68 followed by 1 --> 0xD1
  r_data=I2C1_Rd(0);
  I2C1_Stop();
  return(r_data);
}

void write_ds1307(unsigned short address,unsigned short w_data)
{
  I2C1_Start(); // issue I2C start signal
  //address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0
  I2C1_Wr(0xD0); // send byte via I2C (device address + W)
  I2C1_Wr(address); // send byte (address of DS1307 location)
  I2C1_Wr(w_data); // send data (data to be written)
  I2C1_Stop(); // issue I2C stop signal
}

unsigned char BCD2UpperCh(unsigned char bcd)
{
  return ((bcd >> 4) + '0');
}

unsigned char BCD2LowerCh(unsigned char bcd)
{
  return ((bcd & 0x0F) + '0');
}

int Binary2BCD(int a)
{
   int t1, t2;
   t1 = a%10;
   t1 = t1 & 0x0F;
   a = a/10;
   t2 = a%10;
   t2 = 0x0F & t2;
   t2 = t2 << 4;
   t2 = 0xF0 & t2;
   t1 = t1 | t2;
   return t1;
}

int BCD2Binary(int a)
{
   int r,t;
   t = a & 0x0F;
   r = t;
   a = 0xF0 & a;
   t = a >> 4;
   t = 0x0F & t;
   r = t*10 + r;
   return r;
}

int second;
int minute;
int hour;
int hr;
int day;
int dday;
int month;
int year;
int ap;

unsigned short set_count = 0;
short set;

char time[] = "0000:00:00 P";
char date[] = "00-00-00";

char toggle = 'P';
char str[10];

void main()
{
   I2C1_Init(100000);                 //DS1307 I2C is running at 100KHz

   CMCON = 0x07;                      // To turn off comparators
   ADCON1 = 0x06;                     // To turn off analog to digital converters

   TRISA = 0x07;
   PORTA = 0x00;

   Lcd_Init();                        // Initialize LCD
   Lcd_Cmd(_LCD_CLEAR);               // Clear display
   Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off

   second = read_ds1307(0);           // To stop the ds1307 oscillator
   second &= ~(1 << 7);               // Setting CH bit
   write_ds1307(0, second);

   Lcd_out(1,1,"Time:");
   Lcd_out(2,1,"Date:");

   do
   {
      second = read_ds1307(0);
      minute = read_ds1307(1);
      hour = read_ds1307(2);
      hr = hour & 0b00011111;
      ap = hour & 0b00100000;
      dday = read_ds1307(3);
      day = read_ds1307(4);
      month = read_ds1307(5);
      year = read_ds1307(6);

      time[2] = BCD2UpperCh(hr);
      time[3] = BCD2LowerCh(hr);
      time[5] = BCD2UpperCh(minute);
      time[6] = BCD2LowerCh(minute);
      time[8] = BCD2UpperCh(second);
      time[9] = BCD2LowerCh(second);

      date[0] = BCD2UpperCh(day);
      date[1] = BCD2LowerCh(day);
      date[3] = BCD2UpperCh(month);
      date[4] = BCD2LowerCh(month);
      date[6] = BCD2UpperCh(year);
      date[7] = BCD2LowerCh(year);

      if(ap)
      {
         time[10] = 'P';
      }
      else
      {
         time[10] = 'A';
      }

      Lcd_out(1, 6, time);
      Lcd_out(2, 6, date);
      Delay_ms(100);


   }while(1);
}
\$\endgroup\$
  • 1
    \$\begingroup\$ "second &= ~(1 << 7)" doesn't set the bit to 1, it clears it to 0. \$\endgroup\$ – brhans Aug 9 '16 at 13:59
  • \$\begingroup\$ (minor) the index of A/P in the time array is 11. \$\endgroup\$ – Eugene Sh. Aug 9 '16 at 14:02
  • \$\begingroup\$ Thank you @brhans Used second |= (1<<7); and the clock stops. But it sets some garbage value in the seconds register as well, one time it was =4 then <5 then 92. \$\endgroup\$ – Mohsin Aug 9 '16 at 14:02
  • \$\begingroup\$ Do you ignore the bit you just set there? You should mask out the control bits to get the time. \$\endgroup\$ – Eugene Sh. Aug 9 '16 at 14:04
  • \$\begingroup\$ The index of A/P in the time array is 10. I checked that. I don't understand your second comment. Please clearify. Sorry I am new to all this. \$\endgroup\$ – Mohsin Aug 9 '16 at 14:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.