#define F_CPU (1000000L) //Тактовая частота в герцах
#include <avr/io.h> //Работа с портами и регистрами
#include <avr/interrupt.h> //Работа с прерываниями
#define LED (2) //Номер бита, к которому подключен светодиод
#define POLA (0) //Первый бит управления полярностью
#define POLB (1) //Второй бит управления полярностью
#define BUTTON (3) //Бит, к которому подключена кнопка
typedef uint8_t BYTE; //Беззнаковый байт, хранит 0..255
volatile BYTE fdiv=0; //счетчик для деления таймера 125Гц на 125
volatile BYTE fdiv60=0; //счетчик для деления на 60 секунд
volatile BYTE status=0; //состояние выходных линий
inline BYTE invert(BYTE a,BYTE no) //в байте а меняем бит no на противоволожный
{
const BYTE b=1<<no; //получаем байт, в котором на месте инвертируемого бита стоит 1, остальные 0
return((a|b)&((~a)|(~b))); //вычисляем новый байт
// a b
// 0 0 0
// 0 1 1
// 1 0 1
// 1 1 0
}
ISR(TIMER0_OVF_vect) //прерывание от таймера 125 Гц
{
fdiv++; //инкремент счетчика
if(fdiv==125) //если счетчик достиг 125, имеем событие, возникающее 1 раз в секунду
{
fdiv=0; //сброс счетчика - делителя
status=invert(status,LED); //переключаем светодиод
fdiv60++; //увеличиваем счетчик секунд
if(fdiv60==1) //если прошла 1 секунда после сброса
{
status=invert(status,POLB); //смена полярности B
}
if((fdiv60==60)||(!(PINB&(1<<BUTTON)))) //если прошло 60 секунд или нажата кнопка
{
fdiv60=0; //сброс счетчика секунд
status=invert(status,POLA); //смена полярности A
}
PORTB=status; //устанавливаем пины в новое состояние
}
TCNT0=5; //устанавливаем внутренний счетчик на 5, получая тем самым деление
//частоты инкремента таймера 31250 Гц на 250 = 125 Гц
}
int main() //начало работы
{
BYTE mask=0; //маска для установки битов режима работы порта
mask=invert(mask,POLA); //бит 1 управления полярностью на вывод
mask=invert(mask,POLB); //бит 2 управления полярностью на вывод
mask=invert(mask,LED); //бит управления светодиодом на вывод
DDRB=mask; //установка значений
status=invert(status,POLA); //установка 1 полярности в 1
status=invert(status,BUTTON); //подключение подтягивающего резистора для кнопки
PORTB=status; //установка пинов
TCCR0B=(1<<CS00)|(1<<CS01); //установка деления тактовой частоты 2000000Гц на 64 для полачения частоты инкремента таймера 31250 Гц
TIMSK=1<<TOIE0; //разрешение прерывания от таймера
sei(); //разрешение прерываний
while(1); //зацикливание программы, ожидание прерываний по таймеру
}