Atmega8 Timer0 отключение ноги
- Войдите на сайт для отправки комментариев
Ср, 12/02/2020 - 13:29
Добрый день, скажите пожалуйста, можно ли в Atmega8 использовать ногу PD4 (arduino - 4 нога), независимо от таймера T0, если он запущен, если такое возможно как это можно сделать?
А что Вы понимаете под "он запущен"? Давайте-ка код, а то всё утонет в уточнениях, заявлениях, что "у меня не так" и, в результате, перейдёт в срач.
Используйте. Если только никто не запретил.)
ISR(TIMER1_COMPA_vect) { } //настройка таймера1 void setup() { TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode TIMSK |= (1 << OCIE1A); // Enable CTC interrupt OCR1A = 15624; // Set CTC compare value to 1Hz at 1MHz AVR clock, with a prescaler of 64 TCCR1B |= ((1 << CS10) | (1 << CS11)); // Start timer at Fcpu/64 } void loop() { }Вот, когда он работает он дергает в момент прерывания указанную ногу, можно ли как-нибудь, это отключить и использовать порт по другому назначению, но при этом необходимо чтобы таймер работал.
Ну так не дёргайте ногу, какие проблемы?
как?
Как, как и будет кучка. Читайте описание работы таймера 1.
Это активация, а как деактивировать
Ну до чего ж народ то ленивый... /* TCCR1A - Timer/Counter1 Control Register A 7 6 5 4 3 2 1 0 COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10 #define WGM10 0 // Waveform Generation Mode #define PWM10 WGM10 // For compatibility #define WGM11 1 // Waveform Generation Mode #define PWM11 WGM11 // For compatibility #define FOC1B 2 // Force Output Compare 1B #define FOC1A 3 // Force Output Compare 1A #define COM1B0 4 // Compare Output Mode 1B, bit 0 #define COM1B1 5 // Compare Output Mode 1B, bit 1 #define COM1A0 6 // Compare Ouput Mode 1A, bit 0 #define COM1A1 7 // Compare Output Mode 1A, bit 1 Clock Select Bit Description CS12 CS11 CS10 Description 0 0 0 No clock source. (Timer/Counter stopped) 0 0 1 clk io /1 (No prescaling) 0 1 0 clk io /8 (From prescaler) 0 1 1 clk io /64 (From prescaler) 1 0 0 clk io /256 (From prescaler) 1 0 1 clk io /1024 (From prescaler) 1 1 0 External clock source on T1 pin. Clock on falling edge. 1 1 1 External clock source on T1 pin. Clock on rising edge. Non PWM: COM1A1, COM1A0 - Compare match Output A Mode: 00 - Normal port operation, OC0A disconnected 01 - Toggle OC0A on compare match 10 - Clear OC0A on compare match 11 - Set OC0A on compare match. COM1B1, COM1B0 - Compare match Output B Mode: 00 - Normal port operation, OC0B disconnected 01 - Toggle OC0B on compare match 10 - Clear OC0B on compare match 11 - Set OC0B on compare match. */Вот, измененный, упрощенный код библиотеки, он работает, но дергает в прерывании порт, не пойму почему:
TimerMy TimerNew; // preinstatiate ISR(TIMER1_OVF_vect) // interrupt service routine that wraps a user defined function supplied by attachInterrupt { TimerNew.isrCallback(); } void TimerMy::initialize(long microseconds) { TCCR1A = 0; // clear control register A TCCR1B = _BV(WGM13); // set mode 8: phase and frequency correct pwm, stop the timer setPeriod(microseconds); } void TimerMy::setPeriod(long microseconds) // AR modified for atomic access { long cycles = (F_CPU / 2000000) * microseconds; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2 if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8 else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64 else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256 else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024 else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum oldSREG = SREG; cli(); // Disable interrupts for 16 bit register access ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f correct pwm mode SREG = oldSREG; TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); TCCR1B |= clockSelectBits; // reset clock select register, and starts the clock } void TimerMy::attachInterrupt(void (*isr)(), long microseconds) { if(microseconds > 0) setPeriod(microseconds); isrCallback = isr; // register the user's callback with the real ISR TIMSK = _BV(TOIE1); // sets the timer overflow interrupt enable bit // might be running with interrupts disabled (eg inside an ISR), so don't touch the global state sei(); resume(); } void TimerMy::detachInterrupt() { TIMSK &= ~_BV(TOIE1); // clears the timer overflow interrupt enable bit // timer continues to count without calling the isr } void TimerMy::resume() // AR suggested { TCCR1B |= clockSelectBits; } void TimerMy::restart() // Depricated - Public interface to start at zero - Lex 10/9/2011 { start(); } void TimerMy::start() // AR addition, renamed by Lex to reflect it's actual role { unsigned int tcnt1; //TIMSK1 &= ~_BV(TOIE1); // AR added TIMSK &= ~_BV(TOIE1); // AR added //GTCCR |= _BV(PSRSYNC); // AR added - reset prescaler (NB: shared with all 16 bit timers); oldSREG = SREG; // AR - save status register cli(); // AR - Disable interrupts TCNT1 = 0; SREG = oldSREG; // AR - Restore status register resume(); do { // Nothing -- wait until timer moved on from zero - otherwise get a phantom interrupt oldSREG = SREG; cli(); tcnt1 = TCNT1; SREG = oldSREG; } while (tcnt1==0); // TIFR1 = 0xff; // AR - Clear interrupt flags // TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit // TIFR&= _BV(TOIE1); } void TimerMy::stop() { TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // clears all clock selects bits }тут же при инициализации стоит TCCR1A = 0; // clear control register A
получается он не должен дергать порт.
вот из-за этой строки такое поведение, но если ее убрать то таймер перестает работать
Я Вас уже спрашивал, повторю ещё раз, что Вы понимаете под выражением "таймер работает"? Что Ва от него надо? Чтобы он дёргал ногу? Или чиобы срабатывало прерывание(я)? Какое(ие)? Объяснитесь толком.
Мне нужно чтобы срабатывало прерывание (по переполнению), а ногой я мог отдельно управлять, независимо от таймера.
Мне нужно чтобы срабатывало прерывание (по переполнению), а ногой я мог отдельно управлять, независимо от таймера.
Тогда нахрена Вы вообще конфигурите режим СТС (строки №№7-10 в посте #3 ???
Если Вам не нужен СТС - не конфигурируйте его вообще. Откройте прерывание по переполнению и обрабатывайте на здоровье. Или Вы откуда-то сдули тот код не понимая, что в нём написано? Так?
Мега то какая? Просто 8 или ишшо чё есть? (просто на 8 меге на 0 таймере ничо нет, ШИМ имеется ввиду.
Вот для инита с прерываниями по переполнению:
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 8000.000 kHz
TCCR0=0x01;
TCNT0=0x00;
Мне нужно чтобы срабатывало прерывание (по переполнению), а ногой я мог отдельно управлять, независимо от таймера.
Тогда нахрена Вы вообще конфигурите режим СТС (строки №№7-10 в посте #3 ???
Если Вам не нужен СТС - не конфигурируйте его вообще. Откройте прерывание по переполнению и обрабатывайте на здоровье. Или Вы откуда-то сдули тот код не понимая, что в нём написано? Так?
так мне нужно выставить свой интервал же
так мне нужно выставить свой интервал же
Так и выставляйте, а СТС то тут при чём?
Какой Вам нужен интервал?
40 мкс
йоптель, вы чокурите? фтеме таймер_0 а в коде таймер_1... дауЖ... )))
40 мкс
UPDATE
только сейчас заметил, что у Вас 40мкс, а я написал для 40мс :-( Сами сумеете переделать? Идея-то та же самая.
Ну, и какие проблемы? При тактовой частоте 16МГц, для 40мс подойдёт один из трёх делителей
Берите какой Вам удобнее, допустим 256. Стало быть в 40мс у нас 2500 тиков. Чтобы прерывание по переполнению случилось через 2500 тиков, в регистр счётчика надо записать 65536 - 2500 = 63036
Вот и всё. При настройке таймера и в обработчике прерывания по переполнению надо запихать это число в TCNT1. и всего делов.
И никаких СТС близко не нужно. Вот пример на 40мс. Каждые 40мс он меняет уровень на PB5 на противоположный. Можете проверить осциллографом.
#include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #define F_CPU 16000000UL constexpr uint16_t timeStartValue = 63036u; void setupTimer1(void) { cli(); TCCR1A = 0; // нормальный режим TCCR1B = (1 << CS12); // делитель 256 TIMSK |= (1 << TOIE1); // прерывание по переполнению TCNT1 = timeStartValue; sei(); } ISR(TIMER1_OVF_vect) { TCNT1 = timeStartValue; // // ниже "переворачиваем" уровень на PB5 static bool pb5Val = false; pb5Val = !pb5Val; if (pb5Val) PORTB |= (1 << PB5); else PORTB &= ~(1 << PB5); } int main() { DDRB |= (1 << PB5); // PB5 в OUTPUT setupTimer1(); while (1); return 0; }Если у Вас другая тактовая или нужно не 40 - пересчитайте число timeStartValue так, как мы Выше его считали.
Большое спасибо, буду разбираться