#include <avr/io.h>
#include <util/delay.h>
// Definicje do łatwiejszej obsługi bitów
#ifndef _BV
#define _BV(bit) (1<<(bit))
#endif
#ifndef sbi
#define sbi(reg,bit) reg |= (_BV(bit))
#endif
#ifndef cbi
#define cbi(reg,bit) reg &= ~(_BV(bit))
#endif
#define CZAS 1
#define DEBOUNCE_TIME 50 // czas anty-drganiowy w ms
uint16_t czasDoOdliczenia = 0;
uint8_t obecnieWyswietlana = 0;
void init(){
DDRD = 0xFF; // Ustawia wszystkie piny portu D jako wyjścia
sbi(DDRC, PC0); // PC0 jako wejście
sbi(DDRC, PC1); // PC1 jako wejście
sbi(DDRC, PC2); // PC2 jako wejście
sbi(DDRC, PC3); // PC3 jako wejście
sbi(DDRC, PC4); // PC4 dla buzzera
DDRB = 0x00; // Ustaw piny portu B jako wejścia (przyciski)
PORTB = 0xFF; // Włącz wewnętrzne rezystory podciągające dla portu
/*
PB0 - dodaj sekunde
PB1 - odejmij sekunde
PB2 - uruchom
PB3 - kasuje czas/przerywa
*/
}
const uint8_t cyfry[10] = {
0b11000000, //0
0b11111001, //1
0b10100100, //2
0b10110000, //3
0b10011001, //4
0b10010010, //5
0b10000010, //6
0b11111000, //7
0b10000000, //8
0b10010000, //9
};
void timerInit() {
cbi(TCCR1A,WGM10);
cbi(TCCR1A,WGM11);
sbi(TCCR1B,WGM12);
cbi(TCCR1B,WGM13);
cbi(TCCR1B,CS10);
cbi(TCCR1B,CS11);
sbi(TCCR1B,CS12);
OCR1A = 62500/32; // co sekunde
sbi(TIMSK1, OCIE1A);
}
// Czyta stan przycisku z eliminacją drgań styków
uint8_t readButton(uint8_t buttonPin) {
if (!(PINB & _BV(buttonPin))) {
_delay_ms(DEBOUNCE_TIME); // Odczekaj DEBOUNCE_TIME ms
if (!(PINB & _BV(buttonPin))) { // Ponowne sprawdzenie stanu przycisku
return 1; // Przycisk naciśnięty
}
}
return 0; // Przycisk nie został naciśnięty
}
uint8_t ustawCyfry(uint8_t cyfra[], uint16_t czasDoUstawienia){
for(int i = 3; i >= 0; i--){
cyfra[i] = (czasDoUstawienia % 10);
czasDoUstawienia = czasDoUstawienia / 10;
}
return cyfra;
}
void wyswietlCyfry(uint8_t cyfraDoWyswietlenia, uint8_t i){
cbi(PORTC, 0);
cbi(PORTC, 1);
cbi(PORTC, 2);
cbi(PORTC, 3);
PORTD = cyfraDoWyswietlenia;
sbi(PORTC, i);
}
int main(void) {
init();
timerInit();
sei(); //Uruchamia przerwania globalne
uint16_t pomocnicza = 0;
while(1){
//Ustawianie czasu
while (!readButton(PB2)) {
//Dodawanie Sekundy
if(readButton(PB0)){
czasDoOdliczenia++;
}
//Odejmowanie Sekundy
if(readButton(PB1) && czasDoOdliczenia != 0){
czasDoOdliczenia--;
}
//Zerowanie
if(readButton(PB3)){
czasDoOdliczenia = 0;
}
}
while(czasDoOdliczenia != 0 && !readButton(PB3)) {
if(pomocnicza == 250){
czasDoOdliczenia--;
pomocnicza = 0;
} else {
pomocnicza = pomocnicza + 1;
}
_delay_ms(4);
}
if(czasDoOdliczenia == 0){
sbi(PORTC, PC4);
_delay_ms(2000);
cbi(PORTC, PC4);
czasDoOdliczenia = 0; // Reset timera
}
}
}
ISR(TIMER1_COMPA_vect) {
uint8_t cyfra[4] = {0, 0, 0, 0};
ustawCyfry(cyfra, czasDoOdliczenia);
wyswietlCyfry(cyfry[cyfra[obecnieWyswietlana]],obecnieWyswietlana);
obecnieWyswietlana = (obecnieWyswietlana + 1) % 4;
}