#define AA PB6
volatile bool flag_INT0 = 0;
volatile bool flag_INT1 = 0;
volatile bool flag_bounce = 0;
volatile int motion = 10;
volatile int count = 0;
int GPIO_INIT()
{
DDRB |= (1 << AA) | (1 << PB7);
// EICRA = (0 << ISC01) | (1 << ISC00) | // Any logical change on ISC0 generates an interrupt request
// (0 << ISC11) | (1 << ISC10); // Any logical change on ISC1 generates an interrupt request
// EIMSK = (1 << INT0) | // Enable external interrupt request 0
// (1 << INT1); // Enable external interrupt request 1
}
int8_t EXTERNAL_IRQ_0_init()
{
EICRA = (0 << ISC01) | (1 << ISC00) | // Any logical change on ISC0 generates an interrupt request
(0 << ISC11) | (1 << ISC10); // Any logical change on ISC1 generates an interrupt request
EIMSK = (1 << INT0) | // Enable external interrupt request 0
(1 << INT1); // Enable external interrupt request 1
return 0;
}
/**
таймер для ШИМ, его не трогаем, тут всё четко
*/
int8_t TIMER_PWM_init()
{
/* Enable TC1 */
PRR0 &= ~(1 << PRTIM1);
TCCR1A = (0 << COM1A1) | (0 << COM1A0) /* Normal port operation, OCA disconnected */
| (1 << COM1B1) | (0 << COM1B0) /* Clear OCB on Compare Match, set OCB on BOTTOM (non-inverting mode) */
| (1 << WGM11) | (1 << WGM10); /* TC16 Mode 15 Fast PWM */
TCCR1B = (1 << WGM13) | (1 << WGM12) /* TC16 Mode 15 Fast PWM */
| 0 << ICNC1 /* Input Capture Noise Canceler: disabled */
| 0 << ICES1 /* Input Capture Edge Select: disabled */
| (0 << CS12) | (1 << CS11) | (0 << CS10); /* IO clock divided by 8 */
// ICR1 = 0x0; /* Input capture value, used as top counter value in some modes: 0x0 */
OCR1A = 0x9c44; /* Output compare A: 0x9c44 */
OCR1B = 0x7ff; /* Output compare B: 0x3ff */ //оптимальные значения для твоего предделителя - dec 999 и 4999
// GTCCR = 0 << TSM /* Timer/Counter Synchronization Mode: disabled */
// | 0 << PSRASY /* Prescaler Reset Timer/Counter2: disabled */
// | 0 << PSRSYNC; /* Prescaler Reset: disabled */
TIMSK1 = 1 << OCIE1B /* Output Compare B Match Interrupt Enable: enabled */
| 1 << OCIE1A /* Output Compare A Match Interrupt Enable: enabled */
| 0 << ICIE1 /* Input Capture Interrupt Enable: disabled */
| 0 << TOIE1; /* Overflow Interrupt Enable: disabled */
return 0;
}
/**
Вот этот нафиг не нужён, обойдемся тем что имеем.
*/
int8_t TIMER_bounce()
{
/* Enable TC3 */
PRR1 &= ~(1 << PRTIM3);
// TCCR3A = (1 << COM3A1) | (0 << COM3A0) /* Normal port operation, OCA disconnected */
// | (1 << COM3B1) | (0 << COM3B0) /* Normal port operation, OCB disconnected */
// | (0 << WGM31) | (0 << WGM30); /* TC16 Mode 4 CTC */
TCCR3B = (0 << WGM33) | (1 << WGM32) /* TC16 Mode 4 CTC */
| 0 << ICNC3 /* Input Capture Noise Canceler: disabled */
| 0 << ICES3 /* Input Capture Edge Select: disabled */
| (0 << CS32) | (0 << CS31) | (0 << CS30); /* No clock source (Timer/Counter stopped) */
// ICR3 = 0x0; /* Input capture value, used as top counter value in some modes: 0x0 */
OCR3A = 0x7ff; /* Output compare A: 0x1bf */
// GTCCR = 0 << TSM /* Timer/Counter Synchronization Mode: disabled */
// | 0 << PSRASY /* Prescaler Reset Timer/Counter2: disabled */
// | 0 << PSRSYNC; /* Prescaler Reset: disabled */
TIMSK3 = 0 << OCIE3B /* Output Compare B Match Interrupt Enable: disabled */
| 1 << OCIE3A /* Output Compare A Match Interrupt Enable: enabled */
| 0 << ICIE3 /* Input Capture Interrupt Enable: disabled */
| 0 << TOIE3; /* Overflow Interrupt Enable: disabled */
return 0;
}
/**
а вот этот таймер будет отсеживать длительное нажатие кнопки //1 секунда примерно
по умолчанию ОТКЛЮЧЕН
*/
int8_t TIMER_long_press_init()
{
/* Enable TC4 */
PRR1 &= ~(1 << PRTIM4);
// TCCR4A = (0 << COM4A1) | (0 << COM4A0) /* Normal port operation, OCA disconnected */
// | (0 << COM4B1) | (0 << COM4B0) /* Normal port operation, OCB disconnected */
// | (0 << WGM41) | (0 << WGM40); /* TC16 Mode 4 CTC */
TCCR4B = (0 << WGM43) | (1 << WGM42) /* TC16 Mode 4 CTC */
| 0 << ICNC4 /* Input Capture Noise Canceler: disabled */
| 0 << ICES4; /* Input Capture Edge Select: disabled */
// | (1 << CS42) | (0 << CS41) | (1 << CS40); /* IO clock divided by 1024 */
// ICR4 = 0x0; /* Input capture value, used as top counter value in some modes: 0x0 */
OCR4A = 0x30d4; /* Output compare A: 0x30d4 */ //1 секунда примерно
// OCR4B = 0x0; /* Output compare B: 0x0 */
// GTCCR = 0 << TSM /* Timer/Counter Synchronization Mode: disabled */
// | 0 << PSRASY /* Prescaler Reset Timer/Counter2: disabled */
// | 0 << PSRSYNC; /* Prescaler Reset: disabled */
TIMSK4 = 0 << OCIE4B /* Output Compare B Match Interrupt Enable: disabled */
| 1 << OCIE4A /* Output Compare A Match Interrupt Enable: enabled */
| 0 << ICIE4 /* Input Capture Interrupt Enable: disabled */
| 0 << TOIE4; /* Overflow Interrupt Enable: disabled */
return 0;
}
int main(void)
{
Serial.begin(115200);
/**
всё нужное инициализоровываием
*/
EXTERNAL_IRQ_0_init();
TIMER_PWM_init();
TIMER_long_press_init();
TIMER_bounce();
GPIO_INIT();
sei();
// sei();
// TIMER_0_init();
// TIMER_1_init();
while (1)
{
// Serial.println(TCNT3); //смотрим как считает таймер то
_delay_ms(10);
}
}
ISR(INT0_vect)
{ motion = 10;//на всякий
// flag_INT0 = !flag_INT0;
//НЕ ЗДЕСЬ НАДО ИНВЕРТИРОВАТЬ ФЛАГ, А ПОСЛЕ ДРЕБЕЗГА!!1
TCNT3 = 0; // обнуляем таймер
TCCR3B |= (1 << CS32) | (0 << CS31) | (0 << CS30);
TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20); // запуськаем поганенький таймер дебаунса, как было раньше
// if (!(PIND & (1 << PD0)))
{ // проверяем НОРМАЛЬНО нажатие кнопки, после дребезга
if (flag_INT0)
{
/*
*/
//таймер дебаунса сам переполнится и отключится, не мешаем
//flag_INT0 установиться после окончания дребезга сам
TCCR4B &= ~( (1 << CS42) | (1 << CS41) | (1 << CS40)); //когда кнопка отжата - отключаем таймер 1с
// а вот длительное нажатие уже не свершится
}
// else
// {
// TCCR3B &= ~( (1 << CS32) | (1 << CS31) | (1 << CS30));
// }
}
}
ISR(INT1_vect)
{TCNT3 = 0; // обнуляем таймер
TCCR3B |= (1 << CS32) | (0 << CS31) | (0 << CS30);
motion = 10;//на всякий
//НЕ ЗДЕСЬ НАДО ИНВЕРТИРОВАТЬ ФЛАГ, А ПОСЛЕ ДРЕБЕЗГА!!1
// flag_INT1 = !flag_INT1;
if (flag_INT1)
{
// тут тоже самое
TCCR4B &= ~( (1 << CS42) | (1 << CS41) | (1 << CS40)); //когда кнопка отжата - отключаем таймер 1с
}
}
ISR(TIMER1_COMPB_vect)//тут всё четко
{
/* Insert your TIMER_PWM compare channel B interrupt handling code here */
}
ISR(TIMER1_COMPA_vect)//тут всё четко
{
if ((flag_INT0) && (OCR1B <= 0x12ff))
{
OCR1B = OCR1B + motion;
}
if ((flag_INT1) && (OCR1B >= 0x3fd))
{
OCR1B = OCR1B - motion;
}
// TCCR3B = 0;
if (OCR1B >= 0x12ff)
{
Serial.println("Достиг предельной точки");//лучше устанавливать флаг, а грязь делать в while(1), надолго в прерывании нахордится опасно
}
if (OCR1B <= 0x3fd)
{
Serial.println("Достиг предельной точки");//лучше устанавливать флаг, а грязь делать в while(1), надолго в прерывании нахордится опасно
}
//PORTB ^= (1 << PB7); //для наглядности посмотри в pulse view когда происходит это прерывание, думаю всё будет понятно
}
/*ОБРАТИ ВНИМАНИЕ*/
ISR(TIMER3_COMPA_vect)
{ PORTB ^= (1 << PB7); //следим что дребезг всяко уже прошел
TCCR3B &= ~( (1 << CS32) | (1 << CS31) | (1 << CS30)); //дребезг прошел, таймер не нужён
TCNT3 = 0;
TCNT4 = 0; //запускаем таймер 1с с нуля
count = 0;//запускаем таймер с нуля
TCCR4B |= (1 << CS42) | (0 << CS41) | (0 << CS40);
/*а вот ТУТ теперь надо менять флаг - ПОСЛЕ того, как прошел весь дребезг
И мы увидели что кнопка ещё нажата
*/
if (((PIND)&(1<<PD1))==0)// если всё ещё нажата синяя кнопка (PD1)
{
flag_INT1 = 1; //фиксируем нормальное НАЖАТИЕ кнопки
}
else
{flag_INT1 =0;//фиксируем нормальное ОТПУСКАНИЕ кнопки
}
if (((PIND)&(1<<PD0))==0)//если всё ещё нажата красная кнопка (PD0)
{
flag_INT0 = 1;
}
else
{ flag_INT0 = 0; // кнопку отпустили и мы не досчитали 1с
}
}
ISR(TIMER4_COMPA_vect)
{
// срабатывает раз в секунду, нраица
count++;
if (count >= 3)
{
motion = 50;
}
/* Insert your TIMER_2 compare channel A interrupt handling code here */
}