Официальный сайт компании Arduino по адресу arduino.cc
Как связана работа таймера с функцией цикла
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Ср, 20/05/2020 - 22:53
Доброго времени суток. Что то уперся в одну вещь, но все попорядку.
собираю генератор на таймере Т1, с регулировкой скважности, этим занимается энкодер, токже его значение выводится на двух символьный семисегментный индикатор от нуля до 99.
Как бы все работает, но как оказалось что не все.
энкодер работает по прерыванию и на индикаторе все хорошо показывается, но при этом таймер 1 отказывается работать, как только выключаю функцию вывода на индикатор (void CellLed(int digit)), то таймер работает.
в функции вывода два цикла, они не бесконечные, что не так не пойму.
volatile int enc = 400; bool Array [10] [8]= { {1, 1, 0, 1, 1, 1, 1 }, //0 {1, 0, 0, 1, 0, 0, 0 }, //1 {1, 0, 1, 0, 1, 1, 1 }, //2 {1, 0, 1, 1, 1, 0, 1 }, //3 {1, 1, 1, 1, 0, 0, 0 }, //4 {0, 1, 1, 1, 1, 0, 1 }, //5 {0, 1, 1, 1, 1, 1, 1 }, //6 {1, 0, 0, 1, 0, 0, 1 }, //7 {1, 1, 1, 1, 1, 1, 1 }, //8 {1, 1, 1, 1, 1, 0, 1 } //9 }; byte DigSect1= 0; byte DigSect2= 0; void setup() { pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); pinMode(8, OUTPUT); pinMode(12, OUTPUT); pinMode(11, OUTPUT); pinMode(13, OUTPUT); pinMode(A5, INPUT); digitalWrite(2,LOW); digitalWrite(3,LOW); digitalWrite(4,LOW); digitalWrite(5,LOW); digitalWrite(6,LOW); digitalWrite(7,LOW); digitalWrite(8,LOW); digitalWrite(12,HIGH); digitalWrite(11,HIGH); digitalWrite(13,LOW); //digitalWrite(A5,HIGH); Serial.begin(9600); pinMode(A0,INPUT_PULLUP); pinMode(A1,INPUT_PULLUP); PCIFR=PCIFR; PCICR=1<<PCIE1; //разрешить прерывание PCMSK1=1<<PCINT8 | 1<<PCINT9; //выбрать вход на котором сработает прерывание pinMode(9, OUTPUT); // установка порта на выход TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(0<<COM1B1)|(1<<WGM11); TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10); //mode14 FastPwm*/ ICR1=800; //изменяет частоту // установленно 20кГц OCR1A=400; //изменяет скважность delay(2000); //pinMode(A3, OUTPUT); //digitalWrite(A3,HIGH); } void CellLed(int digit){ if(digit<=9){DigSect1 = 0; DigSect2= digit;} else { DigSect1= (digit/10) % 10; DigSect2= digit % 10; } digitalWrite(11,LOW); digitalWrite(12,HIGH); for(byte i=0; i<8; i++){ if (Array[DigSect1][i] == 0) digitalWrite(i+2, LOW); else digitalWrite(i+2,HIGH); } delay(5); digitalWrite(11,HIGH); digitalWrite(12,LOW); for(byte i=0; i<7; i++){ if (Array[DigSect2][i] == 0) digitalWrite(i+2, LOW); else digitalWrite(i+2,HIGH); } delay(5); } ISR(PCINT1_vect){ static char EncPrev=0; //предыдущее состояние энкодера static char EncPrevPrev=0; //пред-предыдущее состояние энкодера char EncCur = 0; if(!(PINC & (1 << PC0))){EncCur = 1;} //опрос фазы 1 энкодера if(!(PINC & (1 << PC1))){ EncCur |= 2;} //опрос фазы 2 энкодера if(EncCur != EncPrev) //если состояние изменилось, { if(EncPrev == 3 && //если предыдущее состояние 3 EncCur != EncPrevPrev ) //и текущее и пред-предыдущее не равны, { if(EncCur == 2) //если текущее состояние 2, enc--; //шаг вверх else //иначе enc++; //шаг вниз } EncPrevPrev = EncPrev; //сохранение пред-предыдущего состояния EncPrev = EncCur; //сохранение предыдущего состояния } } void loop() { if (digitalRead(A5)==1) {enc=0; digitalWrite(A3,HIGH);} if (enc<0){ enc=0;digitalWrite(A3,HIGH);} if (enc>0){digitalWrite(A3,LOW);} if (enc>99) enc=99; //OCR1A = 800-(enc*4); OCR1A = (enc*4); CellLed(enc); }
Похоже нашел.
Ошибка в условии цикла for, по условию цикла он делает 8 шагов, а надо делать 6 в противном случае 9 и 10 выводы перекрываются рабочим телом цикла.
У Вас в коде очень много ошибок и вылезти может всё, что угодно. Например, в строке №111 Вы выводите на экран коэффициент заполнения. Он у Вас от 0 до 99. При этом Вы в OCR1A пихаете его же, умноженный на 4 (строка №110). И что Вы при этом надеетесь получить? Реально Вы получаете, что при enc==0 у Вас коэффициент заполнения почти 100%, а при enc==99 - примерно 50%. Проверьте осциллографом.
Это то, что Вы хотели получить?
Если нет, то ... знаете, я постоянно говорю новичкам - ЕШЬТЕ СЛОНА ПО ЧАСТЯМ - не валите всё в кучу! Вот у Вас тут и PCINT, и таймер, и вывод на экран - всё в одной куче и, если что-то не работает, то хрен его разберёт что и почему - чёрт ногу сломает.
Давайте, я покажу Вам как это делается.
Я просто взял Вашу программу и за полминуты (не более) выбросил из неё ВСЁ, что не касается непосредственно регулировки коэффициента заполнения - ВСЁ ВЫБРОСИЛ. А вместо энкодера вставил потенциометр с пересчётом его значений из 0-1023 в 0-99 как у Вас (чтобы убрать PCINT и всю байду, заменив на единственную строку чтения потенциометра). В итоге получил КОРОТЕНЬКУЮ программу в которой нет ничего, кроме регулировки коэффициента заполнения. Вот она
Это Ваша программа, только в ней удалено всё, кроме одной операции.
Теперь Вы можете спокойно отладить эту программу - Вам ничто не мешает, никакие циклы ни на что не влияют, всё на одном экране. Потом Вы её вставите в большую, когда уже будете в ней полностью уверены.
Точно также следует поступить и с работой с энкодером - выбросить ВСЁ, кроме неё, отладить, и только потом использовать.
Вы думаете профессионалы сразу пишут огромные портянки и они у них работают? Нет - профессионалы не настолько круты - они по частям отлаживают. Только начинающие настолько круты, чтобы писать и отлаживать всё и сразу :-)
Неистово плюсую предыдущего аратора.
Спасибо за ответы.
Мне больше 50% заполнения не надо. И то в последствии может придется уменьшать (ограничивать).
Отлаживал разумеется по отдельности, по этому и говорю что "как бы все работает, но не все".
Изначально так и было как привили вы в своем примере, просто генератор с изменением скважности переменным резистором.
Ну, если Вы именно так и хотите (при реальном 100 показывать 0, а при реальном 50 показывать 99), значит всё нормально, я просто хотел обратить Ваше внимание на это.
Я вас понял :)
Таким образом я ограничиваю мощность своего устройства (чтобы избежать взрывов транзисторов и прочей периферии), а пользователь будет видеть то что она задал от 0 до 99 % мощности.
Мой пост в большей степени говорит о невнимательности. С этим наверное столкнулся не только я.
Строки 52-55 и 56 не противоречат друг другу? Таймер 1 используется для работы с delay и millis и изменение его регистров прямо влияет на счёт времени.
Вроде как Т0 работает с функциями delay и millis. Или нет?
Точно! Извини, что то с просыпу первый таймер первым в списке пригрезился. Забыл что ещё ноль в ряду есть.
del