// RTC DS1307 I2C address
#define DS1307_ADDRESS 0x68
// Initialize ports for seven-segment display
void init_ports() {
DDRF = 0xFF; // Set PORTF as output (for the segments)
DDRK = 0x1F; // Set lower 5 bits of PORTK as output (for digit select)
}
// Function to start I2C communication
void i2c_start() {
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
while (!(TWCR & (1 << TWINT))); // Wait for start to be transmitted
}
// Function to stop I2C communication
void i2c_stop() {
TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN);
}
// Function to write a byte over I2C
void i2c_write(uint8_t data) {
TWDR = data;
TWCR = (1 << TWINT) | (1 << TWEN);
while (!(TWCR & (1 << TWINT))); // Wait for the transmission to complete
}
// Function to read a byte from I2C (ack = 1 to acknowledge, ack = 0 for NACK)
uint8_t i2c_read(uint8_t ack) {
TWCR = (1 << TWINT) | (1 << TWEN) | (ack << TWEA);
while (!(TWCR & (1 << TWINT))); // Wait for the data to be received
return TWDR;
}
// Convert decimal to BCD
uint8_t dec_to_bcd(uint8_t val) {
return ((val / 10 * 16) + (val % 10));
}
// Convert BCD to decimal
uint8_t bcd_to_dec(uint8_t val) {
return ((val / 16 * 10) + (val % 16));
}
// Function to set time to 12:34:56 on the RTC DS1307
void rtc_set_time(uint8_t hours, uint8_t minutes, uint8_t seconds) {
i2c_start();
i2c_write(DS1307_ADDRESS << 1); // Send address + write bit
i2c_write(0x00); // Start at register 0x00 (seconds)
i2c_write(dec_to_bcd(seconds)); // Set seconds in BCD format
i2c_write(dec_to_bcd(minutes)); // Set minutes in BCD format
i2c_write(dec_to_bcd(hours)); // Set hours in BCD format
i2c_stop();
}
// Function to read time from RTC DS1307
void rtc_get_time(uint8_t *hours, uint8_t *minutes, uint8_t *seconds) {
i2c_start();
i2c_write(DS1307_ADDRESS << 1); // Send address + write bit
i2c_write(0x00); // Start reading at register 0x00 (seconds)
i2c_start();
i2c_write((DS1307_ADDRESS << 1) | 1); // Send address + read bit
*seconds = i2c_read(1); // Read seconds
*minutes = i2c_read(1); // Read minutes
*hours = i2c_read(0); // Read hours
i2c_stop();
}
// Seven-segment display digit patterns for 0-9
long seven_segment[] = {
0x3F, // 0
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
0x07, // 7
0x7F, // 8
0x6F // 9
};
// Function to display a number on 4-digit seven-segment display
void display_time(uint8_t hours, uint8_t minutes) {
int digits[4] = {0};
digits[0] = seven_segment[hours / 10];
digits[1] = seven_segment[hours % 10];
digits[2] = seven_segment[minutes / 10];
digits[3] = seven_segment[minutes % 10];
int digit_select[4] = {0x1E, 0x1D, 0x1B, 0x17};
for (int i = 0; i < 4; i++) {
PORTF = digits[i]; // Output digit to seven-segment
PORTK = digit_select[i]; // Select corresponding digit
delay(5); // Short delay to allow multiplexing
PORTK = 0x1F; // Turn off all digits
}
}
void setup() {
init_ports(); // Initialize ports
Serial.begin(9600); // Initialize Serial for debugging
// Set time to 12:34:56
rtc_set_time(12, 34, 56);
Serial.println("Time set to 12:34:56");
}
void loop() {
uint8_t hours, minutes, seconds;
// Get the current time from the RTC
rtc_get_time(&hours, &minutes, &seconds);
// Convert BCD to decimal
hours = bcd_to_dec(hours);
minutes = bcd_to_dec(minutes);
seconds = bcd_to_dec(seconds);
// Debug output to Serial to verify time
Serial.print("Time: ");
Serial.print(hours);
Serial.print(":");
Serial.print(minutes);
Serial.print(":");
Serial.println(seconds);
// Display time on the 4-digit seven-segment display (hours and minutes)
display_time(hours, minutes);
delay(1000); // Update every second
}