#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
uint8_t seconds = 0;
uint8_t minutes = 0;
// 7-segment display patterns
uint8_t digit[] = {0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110, 0b01101101,
0b01111101, 0b00000111, 0b01111111, 0b01101111};
volatile uint8_t blink_DP = 0; // Flag to blink the decimal point (on/off)
void init_ports() {
DDRA = 0xFF; // Set PORTA as output (ones place of seconds)
DDRC = 0xFF; // Set PORTC as output (tens place of seconds)
DDRL = 0xFF; // Set PORTL as output (ones place of minutes, DP on the 7-segment display)
DDRK = 0xFF; // Set PORTK as output (tens place of minutes)
}
void display(uint8_t mins, uint8_t secs) {
PORTK = digit[mins / 10]; // Tens place of minutes
PORTL = digit[mins % 10] | (blink_DP << 7); // Ones place of minutes, blink DP (MSB)
PORTC = digit[secs / 10]; // Tens place of seconds
PORTA = digit[secs % 10]; // Ones place of seconds
}
ISR(TIMER1_COMPA_vect) {
static uint8_t blink_counter = 0;
// Toggle the decimal point LED every second
blink_counter++;
if (blink_counter == 1) { // Every 1 second toggle
blink_DP = !blink_DP; // Toggle the DP (decimal point)
blink_counter = 0; // Reset counter
}
// Increment the second counter
seconds++;
if (seconds == 60) {
seconds = 0;
minutes++;
if (minutes == 60) {
minutes = 0;
}
}
display(minutes, seconds); // Update the display every second
}
void init_timer() {
TCCR1B |= (1 << WGM12); // CTC mode
OCR1A = 15624; // Set compare value for 1 second (assuming 16 MHz clock)
TIMSK1 |= (1 << OCIE1A); // Enable interrupt on compare match
sei(); // Enable global interrupts
TCCR1B |= (1 << CS12) | (1 << CS10); // Prescaler 1024
}
int main() {
init_ports();
init_timer();
while (1) {
// Main loop, do nothing as everything is handled by interrupt
}
}