и HL и LL тоже, потому что в момент одного прерывания по захвату другое такое же прерывание случится не может - и значит величина ICR1 за время копирования не изменится
однако для моей цели мне нужно чтобы считывание ШИМ сигнала производилось не на одном пине как в примере (пин D2) а на двух (D2 и D3). Возможно ли это сделать? Буду очень признателен за ответ.
однако для моей цели мне нужно чтобы считывание ШИМ сигнала производилось не на одном пине как в примере (пин D2) а на двух (D2 и D3). Возможно ли это сделать? Буду очень признателен за ответ.
да, вам сегодня повезло :) - как раз на пинах 2 и 3 это возможно и ни на каких других.
Просто напишите еще одну пару обработчиков , таких же как log0 и log1 - и повесьте их на прерывание EXT1
да, вам сегодня повезло :) - как раз на пинах 2 и 3 это возможно и ни на каких других.
Просто напишите еще одну пару обработчиков , таких же как log0 и log1 - и повесьте их на прерывание EXT1
Так оно точно работать не будет.
TCNT1 он же общий будет, для 4 функций
Нужно на другом таймере измерялку городить, для двух каналов и точность уже не та будет.
Так оно точно работать не будет. TCNT1 он же общий будет, для 4 функций Нужно на другом таймере измерялку городить, для двух каналов и точность уже не та будет.
не нужен второй таймер, достаточно TCNT1 не обнулять и считать разницу междц двумя прерываниями
не нужен второй таймер, достаточно TCNT1 не обнулять и считать разницу междц двумя прерываниями
Об этом я тоже думал, но так вообще сильно точность пострадает.
К тому же иногда будут совпадать по времени сигналы переключений. В общем спорный вариант.
решил поднять старую тему, чтобы на форуме было больше примеров кода
Понравился пример Кактуса, чуть поправил - теперь все работает
uint16_t volatile LL,HL; int FRQ,DUTY; void log1(){ LL=TCNT1; TCNT1=0; attachInterrupt(0,log0,FALLING); } void log0(){ HL=TCNT1; TCNT1=0; attachInterrupt(0,log1,RISING); } void setup(){ Serial.begin(9600); attachInterrupt(0,log1,RISING); TCCR1A=0;TCCR1B=0;TCNT1=0; TCCR1B =(1<<CS00)|(1<<CS01);//тик таймера 4мкс } void loop(){ int _HL,_LL; cli(); _HL=HL; _LL=LL; sei(); FRQ=250000/(_HL+_LL); DUTY=(_HL*100)/(_HL+_LL); Serial.println(FRQ); Serial.println(DUTY); delay(1000); }Проверка - если добавить в setup()
и соединить вывод 6 с INT0 - пином 2, получим в консоли
что точно отражает частоту и скважность в процентах
вдохновленный кодом выше, переделал его на использование прерывания Таймера1 в режиме захвата счетчика:
uint16_t volatile LL,HL; bool volatile up_edge = true; int FRQ,DUTY; void setup(){ Serial.begin(9600); TCCR1A=0;TCCR1B=0;TCNT1 = 0; TCCR1B =(1<<CS00)|(1<<CS01);//тик таймера 4мкс //First capture on rising edge TCCR1B |= (1 << ICES1); //Enable input capture interrupt TIMSK1 |= (1 << ICIE1); } ISR(TIMER1_CAPT_vect){ if (up_edge) { LL = ICR1; TCCR1B =(1<<CS00)|(1<<CS01); up_edge = false; } else { HL = ICR1; TCCR1B =(1<<CS00)|(1<<CS01)|(1 << ICES1); up_edge = true; } TCNT1 = 0; } void loop(){ int _HL,_LL; cli(); _HL=HL; _LL=LL; sei(); FRQ=250000/(_HL+_LL); DUTY=(_HL*100)/(_HL+_LL); Serial.println(FRQ); Serial.println(DUTY); delay(1000); }для проверки опять добавлем генерацию ШИМ на пине 6, как в предыдущем случае. Только теперь выход 6 нужно соединять с пином 8 - это вход ICP Таймера 1
Результат:
Как будто от того, что на форуме будет больше примеров кода, их кто-то начнет читать.
Не надо забывать про атомарность чтения двубайтовые volatile переменных.
не заглядывая в книжку - насколько помню, во втором коде этой проблемы нет, при захвате счетчик копируется безопасно.
Счётчик - да, а HL и LL?
и HL и LL тоже, потому что в момент одного прерывания по захвату другое такое же прерывание случится не может - и значит величина ICR1 за время копирования не изменится
Хорошо, иначе: в строке 31 гарантирована непрерывность копирования обеих двубайтовые переменных?
понял.... поправил.
Всем доброго дня! Я новичок в программировании arduino, по крайней мере таймеры для меня это темный лес. Мне очень помог ваш код,
uint16_t volatile LL,HL; int FRQ,DUTY; void log1(){ LL=TCNT1; TCNT1=0; attachInterrupt(0,log0,FALLING); } void log0(){ HL=TCNT1; TCNT1=0; attachInterrupt(0,log1,RISING); } void setup(){ Serial.begin(9600); attachInterrupt(0,log1,RISING); TCCR1A=0;TCCR1B=0;TCNT1=0; TCCR1B =(1<<CS00)|(1<<CS01);//тик таймера 4мкс } void loop(){ int _HL,_LL; cli(); _HL=HL; _LL=LL; sei(); FRQ=250000/(_HL+_LL); DUTY=(_HL*100)/(_HL+_LL); Serial.println(FRQ); Serial.println(DUTY); delay(1000); }однако для моей цели мне нужно чтобы считывание ШИМ сигнала производилось не на одном пине как в примере (пин D2) а на двух (D2 и D3). Возможно ли это сделать? Буду очень признателен за ответ.
однако для моей цели мне нужно чтобы считывание ШИМ сигнала производилось не на одном пине как в примере (пин D2) а на двух (D2 и D3). Возможно ли это сделать? Буду очень признателен за ответ.
да, вам сегодня повезло :) - как раз на пинах 2 и 3 это возможно и ни на каких других.
Просто напишите еще одну пару обработчиков , таких же как log0 и log1 - и повесьте их на прерывание EXT1
Насколько понял так? Теперь какую то чушь выдаёт на втором пине(( частота со знаком минус, а скважность 50 постоянно.
uint16_t volatile LL,HL,LL1,HL1; int FRQ,DUTY,FRQ1,DUTY1; void log1(){ LL=TCNT1; TCNT1=0; attachInterrupt(0,log0,FALLING); } void log0(){ HL=TCNT1; TCNT1=0; attachInterrupt(0,log1,RISING); } void log3(){ LL1=TCNT1; TCNT1=0; attachInterrupt(1,log2,FALLING); } void log2(){ HL1=TCNT1; TCNT1=0; attachInterrupt(1,log3,RISING); } void setup(){ Serial.begin(9600); attachInterrupt(0,log1,RISING); attachInterrupt(1,log2,RISING); TCCR1A=0;TCCR1B=0;TCNT1=0; TCCR1B =(1<<CS00)|(1<<CS01);//тик таймера 4мкс } void loop(){ int _HL,_LL,_HL1,_LL1; cli(); _HL=HL; _HL1=HL1; _LL=LL; _LL1=LL1; sei(); FRQ=250000/(_HL+_LL); FRQ1=250000/(_HL1+_LL1); DUTY=(_HL*100)/(_HL+_LL); DUTY1=(_HL1*100)/(_HL1+_LL1); Serial.println(FRQ); Serial.println(FRQ1); Serial.println(DUTY); Serial.println(DUTY1); delay(1000); }http://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukommentarii
да, вам сегодня повезло :) - как раз на пинах 2 и 3 это возможно и ни на каких других.
Просто напишите еще одну пару обработчиков , таких же как log0 и log1 - и повесьте их на прерывание EXT1
Так оно точно работать не будет.
TCNT1 он же общий будет, для 4 функций
Нужно на другом таймере измерялку городить, для двух каналов и точность уже не та будет.
Ладно, в любом случае спасибо за ответы. Буду писать видимо в рубрику "Ищу исполнителя".
Так оно точно работать не будет. TCNT1 он же общий будет, для 4 функций Нужно на другом таймере измерялку городить, для двух каналов и точность уже не та будет.
не нужен второй таймер, достаточно TCNT1 не обнулять и считать разницу междц двумя прерываниями
не нужен второй таймер, достаточно TCNT1 не обнулять и считать разницу междц двумя прерываниями
Об этом я тоже думал, но так вообще сильно точность пострадает.
К тому же иногда будут совпадать по времени сигналы переключений. В общем спорный вариант.
Мне супер точность не нужна. Может быть сможете подсказать что не так в коде который я выше написал? (Или проще сказать что там так?))
не нужен второй таймер, достаточно TCNT1 не обнулять и считать разницу междц двумя прерываниями
уж не знаю, с чего там должна страдать точность...
Вот такой код
uint16_t volatile LL,HL,LL1,HL1; uint16_t volatile CNT0, CNT1; int FRQ,DUTY,FRQ1,DUTY1; void log1(){ LL= TCNT1 - CNT0; CNT0 = TCNT1; attachInterrupt(0,log0,FALLING); } void log0(){ HL= TCNT1 - CNT0; CNT0 = TCNT1; attachInterrupt(0,log1,RISING); } void log3(){ LL1= TCNT1 - CNT1; CNT1 = TCNT1; attachInterrupt(1,log2,FALLING); } void log2(){ HL1= TCNT1 - CNT1; CNT1 = TCNT1; attachInterrupt(1,log3,RISING); } void setup(){ Serial.begin(9600); pinMode(6, OUTPUT); analogWrite(6,25); pinMode(11, OUTPUT); analogWrite(11,180); attachInterrupt(0,log1,RISING); attachInterrupt(1,log3,RISING); TCCR1A=0;TCCR1B=0;TCNT1=0; TCCR1B =(1<<CS00)|(1<<CS01);//тик таймера 4мкс } void loop(){ uint16_t _HL,_LL,_HL1,_LL1; cli(); _HL=HL; _HL1=HL1; _LL=LL; _LL1=LL1; sei(); FRQ=250000/(_HL+_LL); FRQ1=250000/(_HL1+_LL1); DUTY=(_HL*100)/(_HL+_LL); DUTY1=(_HL1*100)/(_HL1+_LL1); Serial.println(FRQ); Serial.println(FRQ1); Serial.println(DUTY); Serial.println(DUTY1); delay(1000); }если соединить выход PWM пин 6 cо входом EXT0 пин 2, а пин 11 соответвеннос пином 3 - то получаем в Мониторе
что очень даже неплохо соответвует частоте и заполнению сигнала ШИМ, заданных в setup()
Спасибо тебе добрый человек!