#define F_CPU 16000000UL // CPU Frequency 16 MHz
#define SCL_CLOCK 100000L // I2C clock frequency 100 kHz
#define DS1307_ADDRESS 0xD0 // DS1307 address for write (0x68 << 1)
#define DS1307_READ 0xD1 // DS1307 address for read (0x68 << 1 | 1)
void I2C_Init(void);
void I2C_Start(void);
void I2C_Stop(void);
void I2C_Write(uint8_t data);
uint8_t I2C_Read_ACK(void);
uint8_t I2C_Read_NACK(void);
void DS1307_Read_DateTime(uint8_t *seconds, uint8_t *minutes, uint8_t *hours, uint8_t *day, uint8_t *date, uint8_t *month, uint8_t *year);
void Print_Day_of_Week(uint8_t day);
uint8_t BCD_to_Decimal(uint8_t bcd);
int main(void) {
uint8_t seconds, minutes, hours, day, date, month, year;
// Initialize I2C and Serial communication
I2C_Init();
Serial.begin(9600); // Initialize Serial at 9600 baud rate
while (1) {
// Read the time and date from DS1307
DS1307_Read_DateTime(&seconds, &minutes, &hours, &day, &date, &month, &year);
// Convert BCD to decimal
seconds = BCD_to_Decimal(seconds);
minutes = BCD_to_Decimal(minutes);
hours = BCD_to_Decimal(hours);
day = BCD_to_Decimal(day);
date = BCD_to_Decimal(date);
month = BCD_to_Decimal(month);
year = BCD_to_Decimal(year);
// Serial.print("Current time: ");
Serial.print("Current time: 20"); // Printing year (e.g., 20XX)
if (year < 10) Serial.print("0"); // Add leading zero for single digit year
Serial.print(year);
// Print Date in format YYYY/MM/DD
Serial.print('/');
if (month < 10) Serial.print("0"); // Add leading zero for single digit month
Serial.print(month);
Serial.print('/');
if (date < 10) Serial.print("0"); // Add leading zero for single digit date
Serial.print(date);
// Print Day of the Week
Serial.print(" (");
Print_Day_of_Week(day); // Convert numeric day to text (e.g., Friday)
Serial.print(") ");
// Print Time in format HH:MM:SS
if (hours < 10) Serial.print("0");
Serial.print(hours);
Serial.print(':');
if (minutes < 10) Serial.print("0");
Serial.print(minutes);
Serial.print(':');
if (seconds < 10) Serial.print("0");
Serial.print(seconds);
Serial.println(); // Move to the next line for the next reading
_delay_ms(1000); // Wait for 1 second before reading again
}
return 0;
}
// I2C Initialization
void I2C_Init(void) {
TWSR = 0x00; // Set prescaler bits to 0
TWBR = ((F_CPU / SCL_CLOCK) - 16) / 2; // Set bit rate register
}
// I2C Start Condition
void I2C_Start(void) {
TWCR = (1 << TWSTA) | (1 << TWEN) | (1 << TWINT); // Send START condition
while (!(TWCR & (1 << TWINT))); // Wait for TWINT flag to be set
}
// I2C Stop Condition
void I2C_Stop(void) {
TWCR = (1 << TWSTO) | (1 << TWEN) | (1 << TWINT); // Send STOP condition
while (TWCR & (1 << TWSTO)); // Wait until STOP condition is executed
}
// I2C Write Byte
void I2C_Write(uint8_t data) {
TWDR = data; // Load data into data register
TWCR = (1 << TWEN) | (1 << TWINT); // Start transmission
while (!(TWCR & (1 << TWINT))); // Wait for TWINT flag to be set
}
// I2C Read Byte with ACK
uint8_t I2C_Read_ACK(void) {
TWCR = (1 << TWEN) | (1 << TWINT) | (1 << TWEA); // Enable ACK generation
while (!(TWCR & (1 << TWINT))); // Wait for TWINT flag to be set
return TWDR; // Return received data
}
// I2C Read Byte with NACK
uint8_t I2C_Read_NACK(void) {
TWCR = (1 << TWEN) | (1 << TWINT); // No ACK after reception
while (!(TWCR & (1 << TWINT))); // Wait for TWINT flag to be set
return TWDR; // Return received data
}
// DS1307 Read Date and Time Function
void DS1307_Read_DateTime(uint8_t *seconds, uint8_t *minutes, uint8_t *hours, uint8_t *day, uint8_t *date, uint8_t *month, uint8_t *year) {
I2C_Start(); // Start I2C communication
I2C_Write(DS1307_ADDRESS); // DS1307 address + write bit
I2C_Write(0x00); // Set register pointer to seconds (0x00)
I2C_Start(); // Repeated start
I2C_Write(DS1307_READ); // DS1307 address + read bit
*seconds = I2C_Read_ACK(); // Read seconds with ACK
*minutes = I2C_Read_ACK(); // Read minutes with ACK
*hours = I2C_Read_ACK(); // Read hours with ACK
*day = I2C_Read_ACK(); // Read day with ACK
*date = I2C_Read_ACK(); // Read date with ACK
*month = I2C_Read_ACK(); // Read month with ACK
*year = I2C_Read_NACK(); // Read year with NACK
I2C_Stop(); // Stop I2C communication
}
// BCD to Decimal Conversion
uint8_t BCD_to_Decimal(uint8_t bcd) {
return ((bcd / 16) * 10) + (bcd % 16); // Convert BCD to decimal
}
// Function to Print Day of the Week
void Print_Day_of_Week(uint8_t day) {
switch(day) {
case 1: Serial.print("Sunday"); break;
case 2: Serial.print("Monday"); break;
case 3: Serial.print("Tuesday"); break;
case 4: Serial.print("Wednesday"); break;
case 5: Serial.print("Thursday"); break;
case 6: Serial.print("Friday"); break;
case 7: Serial.print("Saturday"); break;
default: Serial.print("Invalid"); break;
}
}