RTC DS1307 8051
Trong hướng dẫn này, chúng ta sẽ xem cách giao tiếp giữa DS1307 (RTC) với 8051.Đầu tiên, chúng ta sẽ xem nội dung của DS1307 và sau đó là cách đọc và ghi ngày giờ.
DS1307 Basics
IC đồng hồ thời gian thực DS1307 về cơ bản là đồng hồ thời gian độc lập với các tính năng sau.
-Đồng hồ thời gian thực (RTC) đếm giây, phút, giờ, ngày trong tháng, ngày trong tuần và năm với mức bù năm nhuận có giá trị lên đến 2100.
-Đồng hồ hoạt động ở định dạng 24 giờ hoặc 12 giờ với chỉ báo AM / PM.
-RAM 56 byte, được hỗ trợ bằng pin, không bay hơi (NV) để lưu trữ dữ liệu
-Giao diện nối tiếp hai dây (I2C)
- Tín hiệu đầu ra sóng vuông có thể lập trình
-Mạch chuyển mạch và phát hiện lỗi nguồn tự động
-Tiêu thụ ít hơn 500nA ở chế độ dự phòng pin với bộ dao động đang chạy
-Phạm vi nhiệt độ công nghiệp tùy chọn: -40 ° C đến + 85 ° C
- VCC, GND: Các chân này dùng để cung cấp nguồn cho chip. Khi áp dụng 5V trong giới hạn bình thường, thiết bị hoàn toàn có thể truy cập và dữ liệu có thể được ghi và đọc. Khi pin 3V được kết nối với thiết bị và VCC dưới 1,25 x VBAT, việc đọc và ghi sẽ bị hạn chế. Tuy nhiên, chức năng chấm công vẫn tiếp tục mà không bị ảnh hưởng bởi điện áp đầu vào thấp hơn. Khi VCC giảm xuống dưới VBAT, RAM và máy chấm công được chuyển sang nguồn điện bên ngoài (3.0V DC danh nghĩa) tại VBAT.
- X1-X2: Các chân để kết nối bộ dao động 32,768kHz bên ngoài cung cấp nguồn xung nhịp cho chip.
-Vbat: Pin Lithium 3.3v có thể được kết nối với chân này để cung cấp nguồn điện khi không có điện áp nguồn bên ngoài. Điện áp pin phải được giữ trong khoảng từ 2.0V đến 3.5V để hoạt động tốt.
-SCL: Chân này phải được kết nối với chân SCL của I2C Bus / Master.
-SDA: Chân này phải được kết nối với chân SDA của I2C Bus / Master.
-SQW / OUT: Khi được bật, bit SQWE được đặt thành 1, chân SQW / OUT xuất ra một trong bốn tần số sóng vuông (1Hz, 4kHz, 8kHz, 32kHz).
-Lưu ý: SCL, SDA và SQW là cống hở và phải được kéo lên bằng các điện trở kéo lên thích hợp như trong hình.
Bộ nhớ DS1307
RTC giữ ngày và giờ được sắp xếp trong bộ nhớ của nó như hình dưới đây:
OUT: Bit này điều khiển mức đầu ra của chân SQW / OUT khi đầu ra sóng vuông bị vô hiệu hóa. Nếu SQWE = 0, mức logic trên chân SQW / OUT là 1 nếu OUT = 1 và là 0 nếu OUT = 0. Theo mặc định, chân này sẽ là 0.
SQWE: Bit này, khi được đặt ở mức logic 1, sẽ kích hoạt đầu ra của bộ dao động. Tần số của đầu ra sóng vuông phụ thuộc vào giá trị của các bit RS0 và RS1.
RS1-RS0: Các bit này điều khiển tần số của đầu ra sóng vuông khi đầu ra sóng vuông đã được bật.
R / W là 0 thì dữ liệu được ghi vào RTC
R / W là 1 thì dữ liệu được Đọc từ RTC
Điều này được định nghĩa trong mã là:
- #define C_Ds1307ReadMode_U8 0xD1u // DS1307 ID in read mode
- #define C_Ds1307WriteMode_U8 0xD0u // DS1307 ID in write mode
Các bước khởi tạo DS1307
1 Bắt đầu giao tiếp I2C.
2 Gửi địa chỉ DS1307 và chọn thao tác ghi
3Gửi địa chỉ của thanh ghi điều khiển để gửi lệnh.
4 Gửi lệnh để vô hiệu hóa SQW Out.
5 Dừng giao tiếp.
- void RTC_Init(void)
- {
- I2C_Init(); // Initialize the I2c module.
- I2C_Start(); // Start I2C communication
- I2C_Write(C_Ds1307WriteMode_U8); // Connect to DS1307 by sending its ID on I2c Bus
- I2C_Write(C_Ds1307ControlRegAddress_U8);// Select the Ds1307 ControlRegister to configure Ds1307
- I2C_Write(0x00); // Write 0x00 to Control register to disable SQW-Out
- I2C_Stop(); // Stop I2C communication after initializing DS1307
- }
Steps to Write Date and Time
- void RTC_SetDateTime(rtc_t *rtc)
- {
- I2C_Start(); // Start I2C communication
- I2C_Write(C_Ds1307WriteMode_U8); // connect to DS1307 by sending its ID on I2c Bus
- I2C_Write(C_Ds1307SecondRegAddress_U8); // Request sec RAM address at 00H
- I2C_Write(rtc->sec); // Write sec from RAM address 00H
- I2C_Write(rtc->min); // Write min from RAM address 01H
- I2C_Write(rtc->hour); // Write hour from RAM address 02H
- I2C_Write(rtc->weekDay); // Write weekDay on RAM address 03H
- I2C_Write(rtc->date); // Write date on RAM address 04H
- I2C_Write(rtc->month); // Write month on RAM address 05H
- I2C_Write(rtc->year); // Write year on RAM address 06h
- I2C_Stop(); // Stop I2C communication after Setting the Date
- }
Steps to Read Date and Time
1 Bắt đầu giao tiếp I2C.
2 Gửi địa chỉ DS1307 và chọn thao tác ghi
3 Gửi địa chỉ của SECOND Đăng ký để đọc giá trị thứ hai.
4 Dừng giao tiếp.
5 Gửi địa chỉ DS1307 và chọn Thao tác đọc
6 Đọc từng giây, phút, giờ, tuần, ngày, tháng và gửi xác nhận tích cực.
7 Đọc Năm và gửi Lời cảm ơn Phủ định / Không.
8 Dừng giao tiếp.
- void RTC_GetDateTime(rtc_t *rtc)
- {
- I2C_Start(); // Start I2C communication
- I2C_Write(C_Ds1307WriteMode_U8); // connect to DS1307 by sending its ID on I2c Bus
- I2C_Write(C_Ds1307SecondRegAddress_U8); // Request Sec RAM address at 00H
- I2C_Stop(); // Stop I2C communication after selecting Sec Register
- I2C_Start(); // Start I2C communication
- I2C_Write(C_Ds1307ReadMode_U8); // connect to DS1307(Read mode) by sending its ID
- rtc->sec = I2C_Read(1); // read second and return Positive ACK
- rtc->min = I2C_Read(1); // read minute and return Positive ACK
- rtc->hour= I2C_Read(1); // read hour and return Negative/No ACK
- rtc->weekDay = I2C_Read(1); // read weekDay and return Positive ACK
- rtc->date= I2C_Read(1); // read Date and return Positive ACK
- rtc->month=I2C_Read(1); // read Month and return Positive ACK
- rtc->year =I2C_Read(0); // read Year and return Negative/No ACK
- I2C_Stop(); // Stop I2C communication after reading the Date
- }
Cả hai hàm trên đều sử dụng cấu trúc đơn giản được hiển thị bên dưới để dễ dàng truy cập.
- typedef struct
- {
- uint8_t sec;
- uint8_t min;
- uint8_t hour;
- uint8_t weekDay;
- uint8_t date;
- uint8_t month;
- uint8_t year;
- }rtc_t;
Kết nối phần cứng
Mã Code:
Bây giờ, hãy tập hợp tất cả những gì chúng ta đã thảo luận trong một ví dụ đơn giản để đọc và hiển thị thời gian trên màn hình LCD ký tự.
Lưu ý: Ngày và giờ đọc từ Ds1307 sẽ có định dạng BCD, như:
0x12,0x39,0x26 trong 12 giờ, 39 phút và 26 giây.
0x15,0x08,0x47 cho ngày thứ 15, tháng thứ 8 và năm thứ 47
#include "rtc.h"
#include "lcd.h"
int main()
{
rtc_t rtc;
/*Connect RS->P2.0, RW->P2.1, EN->P2.2 and data bus to P2.4 to P2.7*/
LCD_SetUp(P2_0,P2_1,P2_2,P_NC,P_NC,P_NC,P_NC,P2_4,P2_5,P2_6,P2_7);
LCD_Init(2,16);
/*Connect SCL->P0.6, SDA->P0.7*/
RTC_Init();
rtc.hour = 0x10; // 10:40:20 am
rtc.min = 0x40;
rtc.sec = 0x00;
rtc.date = 0x01; //1st Jan 2016
rtc.month = 0x01;
rtc.year = 0x16;
rtc.weekDay = 5; // Friday: 5th day of week considering monday as first day.
/*##### Set the time and Date only once. Once the Time and Date is set, comment these lines
and reflash the code. Else the time will be set every time the controller is reset*/
RTC_SetDateTime(&rtc); // 10:40:20 am, 1st Jan 2016
/* Display the Time and Date continuously */
while(1)
{
RTC_GetDateTime(&rtc);
LCD_GoToLine(0);
LCD_Printf("time:%2x:%2x:%2x \nDate:%2x/%2x/%2x",(uint16_t)rtc.hour,(uint16_t)rtc.min,(uint16_t)rtc.sec,(uint16_t)rtc.date,(uint16_t)rtc.month,(uint16_t)rtc.year);
}
return (0);
}