Главная › Форумы › Программирование микроконтроллеров › Программирование МК AVR › Ответ в теме: Программирование МК AVR
Декабрь 12, 2017 в 6:08 пп
#13628
Pavel
Участник
Братцы!Проблема! ATTiny13 не выходит из спящего режима по прерыванию о переполнении таймера. Help me! Контроллеры из Китая.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
#define F_CPU 16000UL #define fwd PORTB |=(1<<PB2); PORTB &=~(1<<PB0); // fwd - вперед #define bwd PORTB |=(1<<PB0); PORTB &=~(1<<PB2); // bwd - назад #define stp PORTB &=~(1<<PB0); PORTB &=~(1<<PB2); // stp - стоп #define pause1 4 // 6ч - 1350 #define pause2 3 // 3ч - 675 #define pause3 2 // 90мин - 330 #define pause4 1 // 45 мин - 165 #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include <avr/sleep.h> // - Varriable -// unsigned int timer=0; // счетчик таймера (увеличивается в прерывании каждые 16 сек) void movie () { fwd // включаем двигатель вперед _delay_ms(600); // пауза 0,5 секунды stp _delay_ms(100); bwd _delay_ms(300); stp timer = 0; } unsigned int pause () // время между пшиками (pause*16.25)секунд { ADMUX = (0<<REFS0)| // Bit 6 – Источник опорного напряжения (0 - VCC, как источник опорного напряжения, 1 - Встроенный источник опорного напряжения) (1<<ADLAR)| (1<<MUX1)| // Bit 1 – Analog Channel and Gain Selection Bits (Выбор канала ADC (см. datasheet)) в данном случае выбираем ADC2 (0<<MUX0); // Bit 0 – Analog Channel and Gain Selection Bits (Выбор канала ADC (см. datasheet)) ADCSRA |= (1 << ADSC); // Начинаем преобразование while ((ADCSRA & (1 << ADIF)) == 0); // Ждем флага окончания преобразования ADCSRA|=(1<<ADIF); if (ADCH <= 53) // в зависимости от АЦП изменяем величину переменной pause { return (pause4); } if ((ADCH <= 89) && (ADCH >= 54)) { return (pause3); } if ((ADCH <= 125) && (ADCH >= 90)) { return (pause2); } return (pause1); } bool light () { ADMUX = (0<<REFS0)| // Bit 6 – Источник опорного напряжения (0 - VCC, как источник опорного напряжения, 1 - Встроенный источник опорного напряжения) (1<<ADLAR)| (1<<MUX1)| // Bit 1 – Analog Channel and Gain Selection Bits (Выбор канала ADC (см. datasheet)) в данном случае выбираем ADC2 (1<<MUX0); // Bit 0 – Analog Channel and Gain Selection Bits (Выбор канала ADC (см. datasheet)) ADCSRA |= (1 << ADSC); // Начинаем преобразование while ((ADCSRA&(1 << ADIF))== 0); // Ждем флага окончания преобразования ADCSRA|=(1<<ADIF); if ((ADCH <= 176)) // в зависимости от АЦП изменяем light { return false; } else { return true; } } ISR (TIM0_OVF_vect) { timer++; //Увеличение timer на 1 каждые 16 секунд if (timer >= pause()) // если timer больше полученного значения pause { if (light()) // и "светло" { movie(); // пшикаем timer = 0; // обнуляем timer } else // а если timer больше полученного значения pause и "темно" { timer = 0; // обнуляем таймер } } } ISR (INT0_vect) { movie(); timer = 0; } int main(void) { DDRB = 0b00101; //0 - Назад (выход), 1 - Кнопка (вход), 2 - вперед (выход), 3 - датчик света (вход), 4 - датчик режима(вход) PORTB = 0b00010; TCCR0A |=(0<<COM0A0) //Инициализация таймера |(0<<COM0A1) |(0<<COM0B0) |(0<<COM0B1) |(0<<WGM01) |(0<<WGM00); TCCR0B |=(0<<FOC0A) |(0<<FOC0B) |(0<<WGM02) |(1<<CS02) |(0<<CS01) |(1<<CS00); TCNT0 =0; ADMUX = (0<<REFS0)| // Bit 6 – Источник опорного напряжения (0 - VCC, как источник опорного напряжения, 1 - Встроенный источник опорного напряжения) (1<<ADLAR); // Bit 5 – ADC Left Adjust Result (1 - левое выравнивание результата; 0 - правое выравнивание результата измерения) ADCSRA = (1<<ADEN)| // Bit 7 – ADC включатель (1- включен, 0 - выключен) (0<<ADATE)| // Bit 5 – ADC постоянное преобразование (1 - включено, 0 - выключено) (1<<ADPS2)| // Bit 2 – ADC Prescaler Select Bits Выбор частоты преобразования (см. datasheet) (1<<ADPS1)| // Bit 1 – ADC Prescaler Select Bits Выбор частоты преобразования (см. datasheet) (1<<ADPS0); // Bit 0 – ADC Prescaler Select Bits Выбор частоты преобразования (см. datasheet) TIMSK0 |=(1<<TOIE0); // Разрешение прерывания по переполнению таймера 0 GIMSK |=(1<<INT0); // включение внешних прерываний sei(); // Общее разрешение прерываний while (1) { set_sleep_mode(SLEEP_MODE_IDLE); sleep_enable(); sleep_cpu(); if (timer >= 5000) { cli(); // общий запрет прерываний TIMSK0 &=~(1<<TOIE0); // отключение прерываний по таймеру (1 раз в 16 секунд) sei(); // общее разрешение прерываний set_sleep_mode(SLEEP_MODE_PWR_DOWN); // установка "летаргического сна" sleep_enable(); // разрешение спящего режима sleep_cpu(); // сон sleep_disable(); // запрет сна cli(); // общий запрет прерываний TIMSK0 |=(1<<TOIE0); // включение прерываний по переполнению таймера (1 раз в 16 секунд) sei(); // общее разрешение прерываний TCNT0 =0; // сброс счетчика timer = 0; } } } |