#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <util/delay.h>
volatile uint32_t milliseconds = 0;
volatile uint8_t running = 0; // 1 = running, 0 = stopped
void USART_init(unsigned int ubrr) {
// Set baud rate
UBRR0H = (unsigned char)(ubrr >> 8);
UBRR0L = (unsigned char)ubrr;
// Enable transmitter
UCSR0B = (1 << TXEN0);
// Set frame format: 8-bit data, 1 stop bit
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
}
void USART_send(char data) {
while (!(UCSR0A & (1 << UDRE0))); // Wait for empty buffer
UDR0 = data;
}
void USART_print(const char *str) {
while (*str) {
USART_send(*str++);
}
}
void Timer1_init() {
TCCR1B |= (1 << WGM12); // CTC mode
OCR1A = 15624; // 1s interval (16MHz clock, prescaler 1024)
TCCR1B |= (1 << CS12) | (1 << CS10); // Prescaler 1024
TIMSK1 |= (1 << OCIE1A); // Enable Timer1 Compare Match Interrupt
sei(); // Enable global interrupts
}
ISR(TIMER1_COMPA_vect) {
if (running) {
milliseconds += 1000; // Increment time in ms
}
}
ISR(INT0_vect) { // Start/Stop button
running = !running;
}
ISR(INT1_vect) { // Reset button
milliseconds = 0;
running = 0;
}
void INT0_INT1_init() {
EICRA |= (1 << ISC01) | (1 << ISC11); // Falling edge for INT0, INT1
EIMSK |= (1 << INT0) | (1 << INT1); // Enable external interrupts
}
int main() {
char buffer[20];
USART_init(103); // 9600 baud rate for 16MHz
Timer1_init();
INT0_INT1_init();
while (1) {
sprintf(buffer, "Time: %lu ms\r\n", milliseconds);
USART_print(buffer);
_delay_ms(500);
}
}