San_75 0 13 февраля, 2017 Опубликовано 13 февраля, 2017 (изменено) · Жалоба привет All. Подскажите в чем проблема. Контроллер Attiny 2313 используется для генерации сигнала на ножке PD6 ~ несколько сотен Гц. Таймер 0 используется в режиме сброса при совпадении и генерирует нужный сигнал , таймер 1 в нормальном режиме и используется для опроса кнопок. По нажатию на кнопку на пине PD3 происходит смена предделителя таймера 0. Однако, при выполнении программы , делитель меняется только один раз с 256 до 1024 , больше смена почему то не происходит. проверял в протеусе и на контролере, все абсолютно одинаково - "по нажатию" на PD3 один раз устанавливается больший предделитель и больше чип на кнопку не реагирует, частота сигнала понижается. Контроллер работает от внешнего кварца на 16 МГц. #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> volatile uint8_t flags; #define KeysF 2 #define StopS 3 void init_timers(void){ cli(); // TCCR0A : com0A1 com0A0 com0B1 com0B0 - - WGM01 WGM00 // TCCR0B : FOC0A FOC0B - - WGM02 CS02 CS01 CS00 // TCCR1A : COM1A1 COM1A0 COM1B1 COM1B0 – – WGM11 WGM10 // TCCR1B : ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10 // TCCR1C : FOC1A FOC1B – – – – – – // TIMSK : TOIE1 OCIE1A OCIE1B - ICIE1 OCIE0B TOIE0 OCIE0A // TIFR : TOV1 OCF1A OCF1B – ICF1 OCF0B TOV0 OCF0A TCCR0A = (1<<WGM01); TCCR0B = (1<<CS02); OCR0A = 254; TCCR1A = 0; TCCR1B = (1<<CS12); TIMSK = (1<<OCIE0A) | (1<<TOIE1) ; sei(); } /* Table 41. Clock Select Bit Description CS02 CS01 CS00 Description 0 0 0 No clock source (Timer/Counter stopped) 0 0 1 clkI/O/(No prescaling) 0 1 0 clkI/O/8 (From prescaler) 0 1 1 clkI/O/64 (From prescaler) 1 0 0 clkI/O/256 (From prescaler) 1 0 1 clkI/O/1024 (From prescaler) 1 1 0 External clock source on T0 pin. Clock on falling edge. 1 1 1 External clock source on T0 pin. Clock on rising edge. */ ISR(TIMER0_COMPA_vect){ flags |= 1; } ISR(TIMER1_OVF_vect){ flags |= (1<<KeysF); TCNT1 = 65536 - 31250; } int main(void){ DDRB = 0; PORTB = 0; DDRD = 1<<PD6; PORTD = (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) ; init_timers(); sleep_enable(); while(1){ sleep_cpu(); if ((flags & 1) && !(flags & (1<<StopS))) { PORTD |= 1<<PD6 ; asm("nop"); asm("nop"); PORTD &= ~(1<<PD6) ; flags &= ~1 ; } if (flags & (1<<KeysF)) { // 2 раза в секунду опрашиваем кнопки flags &= ~(1<<KeysF) ; // увеличиваем частоту таймер 0 if (bit_is_clear(PIND,PD0) && OCR0A > 2) OCR0A --; // уменьшаем частоту таймер 0 if (bit_is_clear(PIND,PD1) && OCR0A < 255) OCR0A ++; if (bit_is_clear(PIND,PD2)){ if ( flags & (1<<StopS) ) flags &= ~(1<<StopS) ; else flags |= (1<<StopS) ; } if (bit_is_clear(PIND,PD3)){ cli(); if (TCCR0B & (1<CS00)) TCCR0B = (1<<CS02); else TCCR0B = (1<<CS02) | (1<<CS00); sei(); } } } } Изменено 13 февраля, 2017 пользователем San_75 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Den64 0 13 февраля, 2017 Опубликовано 13 февраля, 2017 · Жалоба if (TCCR0B & (1<CS00)) Вы сравниваете адрес TCCR0B с 0x01. Значение адреса TCCR0B равно 0x2E(0b00101110). Результат всегда 0. Отладка же есть, там сразу должно быть видно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
San_75 0 13 февраля, 2017 Опубликовано 13 февраля, 2017 · Жалоба Хмм, почему тогда volatile uint8_t c = TCCR0B; вставленная перед началом цикла в отладке с == 4 ? И вообще у меня что-то шаблон порвался, как же мне добраться до содержимого TCCR0B ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Den64 0 13 февраля, 2017 Опубликовано 13 февраля, 2017 · Жалоба Может я и не прав в посте выше. я не проверял. Попробуйте в симуляторе прогнать или отладкой. Можно попробовать if (*TCCR0B & (1<CS00)) или if (*(char*)TCCR0B & (1<CS00)) или if (*(uint8_t*)TCCR0B & (1<CS00)) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aiwa 0 13 февраля, 2017 Опубликовано 13 февраля, 2017 · Жалоба Для чистоты эксперимента уберите засыпание. Из кода не видно в какой режим SLEEP входит тинька. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gerber 8 13 февраля, 2017 Опубликовано 13 февраля, 2017 · Жалоба if (TCCR0B & (1<CS00)) Вероятно, тут ошибка, нужно if (TCCR0B & (1<<CS00)) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 13 февраля, 2017 Опубликовано 13 февраля, 2017 · Жалоба Den64, вы хотите сказать, что if (TCCR0B & (1<CS00)) не работает, а TCCR0B = (1<<CS02); работает именно потому, что TCCR0B - это адрес? Ну-ну. gerber прав, банальная опечатка. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
San_75 0 13 февраля, 2017 Опубликовано 13 февраля, 2017 · Жалоба Черт , так опростоволоситься - не напечатать одну < и не заметить глядя в упор. Всем спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться