ในโครงการนี้เราจะแสดงให้เห็นถึงการทำนาฬิกา RTC 8051 โดยใช้ไมโครคอนโทรลเลอร์ หากคุณต้องการที่จะทำโครงการนี้กับ Arduino ตรวจสอบนี้นาฬิกาดิจิตอลใช้ Arduino ส่วนประกอบที่สำคัญของโครงการนี้คือ DS1307 ซึ่งเป็น IC นาฬิกาดิจิตอลแบบเรียลไทม์ ให้รายละเอียดเกี่ยวกับ IC นี้ 

RTC DS1307 :
นาฬิกาเรียลไทม์แบบอนุกรม DS1307 (RTC) เป็นนาฬิกา / ปฏิทินทศนิยมแบบไบนารี (codec-coded) (BCD) ที่ใช้พลังงานต่ำและบวกกับ NV SRAM 56 ไบต์ ชิปนี้ทำงานบนโปรโตคอลI²C นาฬิกา / ปฏิทินแสดงข้อมูลวินาที, นาที, ชั่วโมง, วัน, วันที่, เดือนและปี วันที่สิ้นสุดของเดือนจะถูกปรับโดยอัตโนมัติสำหรับเดือนที่น้อยกว่า 31 วันรวมถึงการแก้ไขสำหรับปีอธิกสุรทิน นาฬิกาทำงานในรูปแบบ 24 ชั่วโมงหรือ 12 ชั่วโมงพร้อมตัวบ่งชี้ AM / PM DS1307 มีวงจรตรวจจับพลังงานในตัวซึ่งตรวจจับความล้มเหลวของพลังงานและสลับไปยังแหล่งสำรองข้อมูลโดยอัตโนมัติ การดำเนินการจับเวลาจะดำเนินต่อไปในขณะที่ชิ้นส่วนทำงานจากแหล่งสำรองข้อมูล ชิป DS1307 สามารถทำงานต่อเนื่องได้ถึง 10 ปี
DS1307
นาฬิกาเรียลไทม์ที่ใช้8051เป็นนาฬิกาดิจิตอลเพื่อแสดงเวลาจริงโดยใช้  RTC DS1307ซึ่งทำงานบนโปรโตคอล I2C นาฬิกาเรียลไทม์หมายความว่ามันทำงานแม้หลังจากไฟฟ้าดับ เมื่อเชื่อมต่อสายไฟใหม่จะแสดงเวลาจริงโดยไม่คำนึงถึงเวลาและระยะเวลาที่อยู่ในสถานะปิด ในโครงการนี้เราใช้โมดูล LCD ขนาด 16x2 เพื่อแสดงเวลาในรูปแบบ - (ชั่วโมง, นาที, วินาที, วันที่, เดือนและปี) นาฬิกาเรียลไทม์มักใช้ในคอมพิวเตอร์บ้านสำนักงานและอุปกรณ์อิเล็กทรอนิคส์ของเราเพื่อให้พวกเขาอัพเดทตามเวลาจริง

โพรโทคอ I2C เป็นวิธีการที่จะเชื่อมต่อสองคนหรือมากกว่าอุปกรณ์ที่ใช้สองสายจะเป็นระบบเดียวและเพื่อโปรโตคอลนี้จะเรียกว่าเป็น  โปรโตคอลลวดสอง มันสามารถใช้ในการสื่อสาร 127 อุปกรณ์ไปยังอุปกรณ์เดียวหรือโปรเซสเซอร์ อุปกรณ์ I2C ส่วนใหญ่ทำงานด้วยความถี่ 100Khz

ขั้นตอนสำหรับ data master master to slave (โหมดการรับ slave)
  1. ส่งเงื่อนไขเริ่มต้นไปเป็นทาส
  2. ส่งที่อยู่ทาสไปเป็นทาส
  3. ส่งบิตการเขียน (0) ถึงทาส
  4. ได้รับ ACK bit จาก slave
  5. ส่งที่อยู่คำไปเป็นทาส
  6. ได้รับ ACK bit จาก slave
  7. ส่งข้อมูลไปเป็นทาส
  8. ได้รับ ACK bit จาก slave
  9. และสุดท้ายส่งเงื่อนไข STOP ไปเป็นทาส

ขั้นตอนสำหรับการอ่านข้อมูลจาก slave ถึง master (โหมดการส่ง slave)
  1. ส่งเงื่อนไขเริ่มต้นไปเป็นทาส
  2. ส่งที่อยู่ทาสไปเป็นทาส
  3. ส่งบิตการอ่าน (1) ไปเป็นทาส
  4. ได้รับ ACK bit จาก slave
  5. รับข้อมูลจากบ่าว
  6. ได้รับ ACK bit จาก slave
  7. ส่งเงื่อนไข STOP ไปเป็นทาส

แผนภาพวงจรและคำอธิบาย

ในวงจรเราใช้ส่วนประกอบมากที่สุด 3 ตัวคือ DS1307, AT89S52 และ LCD ที่นี่ AT89S52 ใช้สำหรับการอ่านเวลาจาก DS1307 และแสดงบนหน้าจอ LCD ขนาด 16x2 DS1307 ส่งเวลา / วันที่โดยใช้ 2 สายไปยังไมโครคอนโทรลเลอร์
 8051 วงจรนาฬิกาดิจิตอล
การเชื่อมต่อวงจรนั้นง่ายต่อการเข้าใจและแสดงในแผนภาพด้านบน DS1307 chip pin SDA และ SCL เชื่อมต่อกับ P2.1 และ P2.0 พินของไมโครคอนโทรลเลอร์ 89S52 พร้อมตัวต้านทานแบบดึงขึ้นที่เก็บค่าเริ่มต้นสูงที่ข้อมูลและสายนาฬิกา และคริสตัลออสซิลเลเตอร์ 32.768KHz เชื่อมต่อกับ DS1307chip เพื่อสร้างความล่าช้า 1 วินาทีที่แน่นอน และแบตเตอรี่ขนาด 3 โวลต์ก็เชื่อมต่อกับ pin 3 rd (BAT) ของ DS1307 ซึ่งช่วยให้เวลาทำงานหลังจากไฟฟ้าขัดข้อง 16x2 LCD เชื่อมต่อกับ 8051  ในโหมด 4 บิต หมุดควบคุม RS, RW และ En เชื่อมต่อโดยตรงกับ 89S52 พิน P1.0, GND และ P1.1 และ data pin D0-D7 เชื่อมต่อกับ P1.4-P1.7 จาก 89S52

ปุ่มสามปุ่มคือ SET, INC / CHANGE และถัดไปใช้สำหรับตั้งค่าเวลาของนาฬิกาเพื่อยึดพิน P2.4, P2.3 และ P2.2 ของ 89S52 (แอคทีฟต่ำ) เมื่อเรากด SET โหมดการตั้งค่าเวลาจะเปิดใช้งานและตอนนี้เราต้องตั้งเวลาโดยใช้ปุ่ม INC / CHANGE และปุ่มถัดไปจะใช้สำหรับการย้ายไปยังตัวเลข หลังจากการตั้งค่านาฬิกาเวลาทำงานอย่างต่อเนื่อง

คำอธิบายโปรแกรม

ในรหัสเราได้รวมไลบรารี่ตระกูล 8051 และไลบรารี่เอาต์พุตมาตรฐาน และกำหนดพินที่เราใช้และนำตัวแปรมาคำนวณ
#include <reg51.h>
#include <stdio.h>
#define lcdport P1

sbit rs = P1 ^ 0;
sbit en = P1 ^ 1;

sbit SDA = P2 ^ 1;              
sbit SCL = P2 ^ 0;

sbit next = P2 ^ 2; // ตัวเลขที่เพิ่มขึ้น
sbit inc = P2 ^ 3; // ค่าที่เพิ่มขึ้น
sbit set = P2 ^ 4; //ตั้งเวลา

ถ่านแอ๊;
ถ่าน day1 ที่ไม่ได้ลงนาม 1 = 1;
ถ่าน k, x;
unsigned int date = 1, mon = 1, ชั่วโมง = 0, min = 0, sec = 0;
int ปี = 0; 

 โมฆะล่าช้า (int itime)
{
    int i, j;
    สำหรับ (i = 0; i <iTime; i ++)
    สำหรับ (ญ = 0; J <1275; J ++);
}
และฟังก์ชั่นที่กำหนดนั้นใช้สำหรับขับ LCD 
โมฆะ daten ()
{
    อาร์เอส = 1;
    en = 1;
    ล่าช้า (1);
    en = 0;
}

โมฆะ lcddata (ไม่ได้ลงนาม ch ch)
{
    lcdport = ch & 0xf0;
    Daten ();
    lcdport = (ch << 4) & 0xf0;
    Daten ();
}

โมฆะ cmden (เป็นโมฆะ)
{
    อาร์เอส = 0;
    en = 1;
    ล่าช้า (1);
    en = 0;
}

โมฆะ lcdcmd (ไม่ได้ลงนาม ch ch)
ฟังก์ชันนี้ใช้สำหรับเริ่มต้น RTC และและอ่านเวลาและวันที่จากแบบฟอร์ม RTC IC
I2CStart ();
  I2CSend (0xD0);
  I2CSend (0x00);
  I2CStart ();
  I2CSend (0xD1);
  วินาที = BCDToDecimal (I2CRead (1));
  นาที = BCDToDecimal (I2CRead (1));
  ชั่วโมง = BCDToDecimal (I2CRead (1));
  Day1 = BCDToDecimal (I2CRead (1));
  วัน = BCDToDecimal (I2CRead (1));
  mon = BCDToDecimal (I2CRead (1));
  ปี = BCDToDecimal (I2CRead (1));
  I2CStop ();
   เวลาแสดง(); // แสดงเวลา / วันที่ / วัน
   ล่าช้า (1);
ฟังก์ชันเหล่านี้ใช้สำหรับแปลงทศนิยมเป็น BCD และ BCD เป็นทศนิยม
int BCDToDecimal (ถ่าน bcdByte)
{
       ถ่าน a, b, ธ.ค. ;
    a = (((bcdByte & 0xF0) >> 4) * 10);
    b = (bcdByte & 0x0F);
    ธันวาคม = A + B;
    กลับธันวาคม
}

ถ่าน DecimalToBCD (int decimalByte)
{
  ถ่าน a, b, bcd;
  a = ((ฐานสิบ / 10) << 4);
  b = (ฐานสิบไบต์% 10);
  BCD = a | b;
  คืน bcd;
}
ฟังก์ชั่นด้านล่างนี้ใช้สำหรับการสื่อสาร I2C
เป็นโมฆะ I2CStart () {SDA = 1; SCL = 1, SDA = 0, SCL = 0;} // ฟังก์ชั่น "เริ่มต้น" สำหรับการสื่อสารกับ ds1307 RTC
เป็นโมฆะ I2CStop () {SDA = 0, SCL = 1, SDA = 1;} // ฟังก์ชั่น "หยุด" เพื่อสื่อสารกับ ds1307 RTC
 
ถ่าน I2CSend ที่ไม่ได้ลงชื่อ (Data char ที่ไม่ได้ลงชื่อ) // ส่งข้อมูลไปยัง ds1307 
{
ถ่านฉัน;
ถ่าน ack_bit;
สำหรับ (i = 0; i <8; i ++)
{
if (ข้อมูล & 0x80) SDA = 1;
อื่น SDA = 0;
SCL = 1;
ข้อมูล << = 1;
SCL = 0;
}
SDA = 1 SCL = 1;
ack_bit = SDA;
SCL = 0;
ส่งคืน ack_bit
}
 
ถ่าน I2CRead ที่ไม่ได้ลงนาม (ถ่าน ack) // รับข้อมูลจาก ds1307
{
ถ่านฉันไม่ได้ลงนาม Data = 0;
SDA = 1;
สำหรับ (i = 0; i <8; i ++)
{
 ข้อมูล << = 1;
 ทำ {SCL = 1;}
 ในขณะที่ (SCL == 0);
 if (SDA) Data | = 1;
 SCL = 0;
}
ถ้า (แอ๊) SDA = 0;
อื่น SDA = 1;
SCL = 1;
SCL = 0;
SDA = 1;
ส่งคืนข้อมูล
}
ฟังก์ชั่น set_time ใช้เพื่อตั้งค่าเวลาในนาฬิกาและฟังก์ชั่น show_time ด้านล่างใช้เพื่อแสดงเวลาบน LCD
 ถือเป็นโมฆะ show_time () // ฟังก์ชั่นเพื่อแสดงเวลา / วันที่ / วันบน LCD
{
  ถ่าน var [5];
  lcdcmd (0x80);
  lcdprint ( "วันที่:");
  sprintf (var "% d", วันที่);
  lcdprint (var);
  sprintf (var "/% d", mon);
  lcdprint (var);
  sprintf (var "/% d" ปี + 2000)
  lcdprint (var);
  lcdprint ("");
  lcdcmd (0xc0);
  lcdprint ( "เวลา:");
  sprintf (var "% d" ชั่วโมง);
  lcdprint (var);
  sprintf (var ":% d" นาที);
  lcdprint (var);
  sprintf (var ":% d" วินาที);
  lcdprint (var);
  lcdprint ("");
  // วัน (day1);
   lcdprint ("");
 }
รหัส
#include <reg51.h> 
#include <stdio.h> 
#define lcdport P1
sbit rs = P1 ^ 0; 
sbit en = P1 ^ 1;
sbit SDA = P2 ^ 1;                
sbit SCL = P2 ^ 0;
sbit next = P2 ^ 2; // เพิ่ม
บิต sbit inc = P2 ^ 3; // เพิ่มค่า
sbit set = P2 ^ 4; //ตั้งเวลา 
ถ่านแอ๊; 
ถ่าน day1 ที่ไม่ได้ลงนาม 1 = 1; 
ถ่าน k, x; 
unsigned int date = 1, mon = 1, ชั่วโมง = 0, min = 0, sec = 0;  
int ปี = 0; 
 void delay (int itime) 

    int i, j; 
    สำหรับ (i = 0; i <itime; i ++) 
    สำหรับ (j = 0; j <1275; j ++); 
}
เป็นโมฆะ daten () 

    rs = 1; 
    en = 1; 
    ล่าช้า (1); 
    en = 0; 
}
โมฆะ lcddata (ch ถ่านที่ไม่ได้ลงชื่อ) 

    lcdport = ch & 0xf0; 
    Daten (); 
    lcdport = (ch << 4) & 0xf0; 
    Daten (); 
}
เป็นโมฆะ cmden (เป็นโมฆะ) 

    rs = 0; 
    en = 1; 
    ล่าช้า (1); 
    en = 0; 
}
โมฆะ lcdcmd (ch ถ่านที่ไม่ได้ลงชื่อ) 

    lcdport = ch & 0xf0; 
    cmden (); 
    lcdport = (ch << 4) & 0xf0; 
    cmden (); 
}
lcdprint เป็นโมฆะ (char * str) 

    ในขณะที่ (* str) 
    { 
        lcddata (* str); 
        STR ++; 
    } 
}
โมฆะ lcd_init (เป็นโมฆะ) 

    lcdcmd (0x02); 
    lcdcmd (0x28); 
    lcdcmd (0x0c); 
    lcdcmd (0x01); 
}
โมฆะ I2CStart () {SDA = 1; SCL = 1, SDA = 0, SCL = 0;} // "เริ่มต้น" ฟังก์ชั่นสำหรับการสื่อสารกับ ds1307 RTC 
เป็นโมฆะ I2CStop () {SDA = 0, SCL = 1, SDA = 1; } // // ฟังก์ชั่น "หยุด" สำหรับการสื่อสารด้วยปัญญา ds1307 RTC 
 
ถ่าน I2CSend ที่ไม่ได้ลงชื่อ (ถ่านข้อมูลที่ไม่ได้ลงชื่อ) // ส่งข้อมูลไปยัง ds1307  

ถ่าน i; 
ถ่าน ack_bit; 
สำหรับ (i = 0; i <8; i ++) 

ถ้า (ข้อมูล & 0x80) SDA = 1; 
อื่น SDA = 0; 
SCL = 1; 
ข้อมูล << = 1; 
SCL = 0; 

SDA = 1, SCL = 1; 
ack_bit = SDA; 
SCL = 0; 
ส่งคืน ack_bit 

 
ถ่าน I2CRead ที่ไม่ได้ลงนาม (ถ่าน ack) // รับข้อมูลจาก ds1307 

ถ่าน i ที่ไม่ได้ลงนาม Data = 0; 
SDA = 1;
สำหรับ (i = 0; i <8; i ++) 

 Data << = 1; 
 ทำ {SCL = 1;} 
 ในขณะที่ (SCL == 0); 
 if (SDA) Data | = 1; 
 SCL = 0; 

ถ้า (ack) SDA = 0; 
อื่น SDA = 1; 
SCL = 1; 
SCL = 0; 
SDA = 1; 
ส่งคืนข้อมูล 
}
/ * void day (char d) // ฟังก์ชั่นสำหรับวันที่แสดงบน LCD 

switch (d) 

  case 0: 
  lcdprint ("DAY"); 
  ทำลาย;
  กรณีที่ 1: 
  lcdprint ("SUN"); 
  ทำลาย;
  กรณีที่ 2: 
  lcdprint ("MON"); 
  ทำลาย;
  กรณีที่ 3: 
  lcdprint ("TUE"); 
  ทำลาย;
  กรณีที่ 4: 
  lcdprint ("WED"); 
  ทำลาย;
  กรณีที่ 5: 
  lcdprint ("THU"); 
  ทำลาย;
  กรณีที่ 6: 
  lcdprint ("FRI"); 
  ทำลาย;
  กรณีที่ 7: 
  lcdprint ("SAT"); 
  ทำลาย; 
 } 
 } * /
int BCDToDecimal (ถ่าน bcdByte) 

       ถ่าน a, b, ธันวาคม; 
    a = (((bcdByte & 0xF0) >> 4) * 10); 
    b = (bcdByte & 0x0F); 
    ธันวาคม = A + B; 
    กลับธันวาคม 
}
ถ่าน DecimalToBCD (int decimalByte) 

  ถ่าน a, b, bcd; 
  a = ((ฐานสิบ / 10) << 4); 
  b = (ฐานสิบไบต์% 10); 
  BCD = a | b; 
  คืน bcd; 
}

 ถือเป็นโมฆะ show_time () // ฟังก์ชั่นเพื่อแสดงเวลา / วันที่ / วันบนจอแอลซีดี

  char var [5]; 
  lcdcmd (0x80); 
  lcdprint ( "วันที่:"); 
  sprintf (var "% d", วันที่); 
  lcdprint (var); 
  sprintf (var "/% d", mon); 
  lcdprint (var); 
  sprintf (var "/% d" ปี + 2000) 
  lcdprint (var); 
  lcdprint (""); 
  lcdcmd (0xc0); 
  lcdprint ( "เวลา:"); 
  sprintf (var "% d" ชั่วโมง); 
  lcdprint (var); 
  sprintf (var ":% d" นาที); 
  lcdprint (var); 
  sprintf (var ":% d" วินาที); 
  lcdprint (var); 
  lcdprint (""); 
  // วัน (day1); 
   lcdprint (""); 
 }
 เป็นโมฆะ set_time () // ฟังก์ชั่นการตั้งเวลา

 lcdcmd (0x0e); 
 ในขณะที่ (k <7) 
 { 
  ในขณะที่ (k == 3) // กำหนดวันที่
  { 
   x = ปี% 4; 
   if (inc == 0) 
   {date ++; ในขณะที่ (inc == 0); 
   if (x == 1 && mon == 2 && date == 28) {date = 1;} // ตรวจสอบวันที่ 28 ของวันที่ febuary 
   ถ้า (x == 0 && mon == 2 && date == 29) {date = 1;} // ตรวจสอบ febuary 29 วัน
   หาก ((date == 31) && (จันทร์ == 4) || (จันทร์ == 6) || (จันทร์ == 9) || (จันทร์ == 17)) {date = 1;} // ตรวจสอบ 30 วันเดือน
   หาก (date == 32) {date = 1;} // ตรวจสอบเดือน 31 วัน
   show_time ();}
   if (next == 0) 
   { 
     k = 5; 
     
     ในขณะที่ (== ถัดไป 0); 
     } // ตรวจสอบ
   lcdcmd หลักถัดไป(0x85); 
  }             
  ในขณะที่ (k == 2) // กำหนดเดือน
  { 
   ถ้า (inc == 0) 
   {จันทร์ ++; ในขณะที่ (inc == 0); 
   if (mon == 13) {mon = 1;} // ตรวจสอบสิ้นปี
   show_time (); 
   if (next == 0) {k = 3; 
   ในขณะที่ (== ถัดไป 0);
   } 
   lcdcmd (0x88); 
  }
  ในขณะที่ (k == 1) // กำหนดปี
  { 
   ถ้า (inc == 0) 
   {ปี ++ ขณะที่ (inc == 0);  
   if (year == 30) {year = 0;}                             
   show_time (); 
   ถ้า (ถัดไป == 0) {k = 2;
   ในขณะที่ (ถัดไป == 0);} 
   lcdcmd (0x8d); 
  }
  ในขณะที่ (k == 5) // กำหนดชั่วโมง
  { 
   ถ้า (inc == 0) 
   {ชั่วโมง ++; ในขณะที่ (inc == 0); 
   if (hour == 24) {hour = 0;} 
   show_time ();} 
   ถ้า (next == 0) {k = 6; 
   ในขณะที่ (ถัดไป == 0);} 
   lcdcmd (0xc5); 
  }
  ในขณะที่ (k == 6) // กำหนดขั้นต่ำ
  { 
   ถ้า (inc == 0) 
   {นาที ++; ในขณะที่ (inc == 0); 
   if (min == 60) {min = 0;} 
   show_time ();} 
   ถ้า (next == 0) {k = 10; 
   ในขณะที่ (ถัดไป == 0);} 
   lcdcmd (0xc8); 
  } 
 } 
เป็นโมฆะหลัก () 

    lcd_init (); 
    lcdprint ("นาฬิกาดิจิตอล"); 
    lcdcmd (0xc0); 
    lcdprint ("ใช้ 8051"); 
    ล่าช้า (400); 
    lcdcmd (1); 
    lcdprint ("Circuit Digest"); 
    lcdcmd (192); 
    lcdprint ("Saddam Khan"); 
    ล่าช้า (400); 
    ในขณะที่ (1) 
 { 
 if (set == 0) // ตรวจสอบเวลากดปุ่ม set 
 { 
 I2CStart (); 
 I2CSend (0xD0); 
 I2CSend (0x00); 
 I2CSend (0x00); 
 I2CSend (0x00); 
 I2CSend (0x00); 
 I2CSend (0x01); 
 I2CSend (0x01); 
 I2CSend (0x01); 
 I2CSend (0x00);    
 I2CSend (0x80);    
 I2CStop (); 
  k = 1; 
  ตั้งเวลา(); // ฟังก์ชั่นการตั้งเวลาโทร
     min = DecimalToBCD (นาที); 
   วินาที = DecimalToBCD (0); 
      ชั่วโมง = DecimalToBCD (ชั่วโมง); 
      ปี = DecimalToBCD (ปี); 
      mon = DecimalToBCD (จันทร์); 
   วัน = DecimalToBCD วันที่ ();                                    
  I2CStart (); 
  I2CSend (0xD0); 
  I2CSend (0x00); 
  I2CSend (0x00); 
  I2CSend (นาที); 
  I2CSend (ชั่วโมง); 
  I2CSend (Day1); 
  I2CSend วันที่ (); 
  I2CSend (จันทร์); 
  I2CSend (ปี);    
  I2CSend (0x80);    
  I2CStop (); 
  lcdcmd (1); 
  lcdcmd (0x0c);
  }
  I2CStart (); 
  I2CSend (0xD0); 
  I2CSend (0x00); 
  I2CStart (); 
  I2CSend (0xD1); 
  วินาที = BCDToDecimal (I2CRead (1)); 
  นาที = BCDToDecimal (I2CRead (1)); 
  ชั่วโมง = BCDToDecimal (I2CRead (1)); 
  Day1 = BCDToDecimal (I2CRead (1)); 
  วัน = BCDToDecimal (I2CRead (1)); 
  mon = BCDToDecimal (I2CRead (1)); 
  ปี = BCDToDecimal (I2CRead (1)); 
  I2CStop (); 
   เวลาแสดง(); // แสดงเวลา / วันที่ / วัน  
   ล่าช้า (1); 
 } 
}