Форум РадиоКот https://radiokot.ru/forum/ |
|
прерывание от таймера 0 https://radiokot.ru/forum/viewtopic.php?f=57&t=161596 |
Страница 1 из 1 |
Автор: | wws63 [ Сб мар 16, 2019 15:05:55 ] |
Заголовок сообщения: | прерывание от таймера 0 |
Прошу специалистов помочь разобраться с проблемой. В программке 3 ШИМа для управления RGB диодом. Скважность зависит от частоты входного сигнала на входе INT0. ШИМ работает номрально, а для счета импульсов за период времени задействовал Таймер 0. Но не считате, Где то ошибочка. Код: #include <avr/io.h>
#define F_CPU 8000000UL //8MHz #include <util/delay.h> #include <avr/interrupt.h> volatile unsigned char Tic_Count = 0; volatile unsigned char i = 0; volatile unsigned char i_Count = 10; #define BLUE_PB 1 #define BLUE_PWM OCR1A #define RED_PB 2 #define RED_PWM OCR1B #define GREEN_PB 3 #define GREEN_PWM OCR2 ISR( INT0_vect ) // прерывание по внешнему сигналу { Tic_Count ++; } ISR (TIMER0_OVF_vect) { TCNT0 = 60; // переполнение через 25мС i_Count--; if(i_Count == 0) { i_Count = 10; i = Tic_Count; Tic_Count = 0x00; } } int main(void) { //---------- настройка пинов МК DDRB |= (1<<BLUE_PB) | (1<<RED_PB) | (1<<GREEN_PB); // на выход RGB PORTB &= ~((1<<BLUE_PB) | (1<<RED_PB) | (1<<GREEN_PB)); DDRD |= (1<<2); // PD2 на вход (INT0) PORTD |= (1 << 2); // Включение подтягивающего резистора MCUSR |= (1 << ISC00) | (1 << ISC01); // Передний фронт сигнала GICR = (1 << INT0); // Включение входа прерывания sei(); /* Общее разрешение прерываний */ //---------- Таймер 1--------------- TCCR1A |= (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); TCCR1B |= (1 << WGM13) | (1 << WGM12) | (1 << CS10); TCNT1 = 0x00; ICR1 = 0xFF; OCR1A = 0x00; OCR1B = 0x00; //---------- Таймер 2---------------------------- TCCR2 |= (1 << COM21) | (1 << WGM21) | (1 << WGM20) | (1 << CS20); TCNT2 = 0x00; OCR2 = 0x00; //---------- Таймер 0-------------------------------- TCCR0 = 0b00000101; // Т0 на внутр.такт, делитель 1024 TCNT0 = 60; // переполнение через 25мС i_Count = 10; TIMSK |= (1 << TOIE0); /* Разрешить прерывание по переполн.Т0*/ sei(); while(1) { //---------- if (i>26) { BLUE_PWM = 0; RED_PWM = 255; GREEN_PWM = 0; } //---------- if (i>15) { BLUE_PWM = 250; RED_PWM = 250; GREEN_PWM = 250; } if (i<8) { BLUE_PWM = 0; RED_PWM = 0; // зеленый GREEN_PWM = 250; } } } |
Автор: | VALNER [ Вс мар 17, 2019 02:00:29 ] |
Заголовок сообщения: | Re: прерывание от таймера 0 |
У вас pin INT0 настроен на выход, а не на вход. Ну и в замен подтяжки вы просто держите на D2 высокий лог. уровень. Следовательно из за неправильной настройки порта не срабатывают прерывания на INT0. Цитата: DDRD |= (1<<2); // PD2 на вход (INT0) <--(это убрать) PORTD |= (1 << 2); // Включение подтягивающего резистора Надеюсь это единственная причина и это вам поможет, если вы сами это еще не нашли. И да. Та часть что в бесконечном цикле тоже будет работать не правильно Цитата: while(1) { //---------- if (i>26) { BLUE_PWM = 0; RED_PWM = 255; GREEN_PWM = 0; } //---------- if (i>15) { BLUE_PWM = 250; RED_PWM = 250; GREEN_PWM = 250; } if (i<8) { BLUE_PWM = 0; RED_PWM = 0; // зеленый GREEN_PWM = 250; } } Так как если і больше 26, то оно и больше 15, а по скольку у вас три независимых условия то оно всегда будет принимать значение того что выполняется последним. Их лучше расписать через else if() |
Автор: | wws63 [ Вс мар 17, 2019 04:09:21 ] |
Заголовок сообщения: | Re: прерывание от таймера 0 |
Да, я с направлением порта напутал. Привык, что в ПИКушках 1- вход. А по поводу цикла программы, если else будет громоздко. Можно ли обойтись таким нелюбимым всеми оператором goto ? Код: while(1)
{ //---------- m: if (i>26) { BLUE_PWM = 0; RED_PWM = 255; GREEN_PWM = 0; goto m; } //---------- if (i>15) { BLUE_PWM = 250; RED_PWM = 250; GREEN_PWM = 250; goto m; } if (i<8) { BLUE_PWM = 0; RED_PWM = 0; // зеленый GREEN_PWM = 250; goto m; } } |
Автор: | bafomet911 [ Вс мар 17, 2019 06:31:14 ] |
Заголовок сообщения: | Re: прерывание от таймера 0 |
А если так: Спойлерif(i<8){...}if(i>8&&i<15){...} if(i>15&&i<26){...} if(i>26){...} Не устроит? |
Автор: | wws63 [ Вс мар 17, 2019 07:34:19 ] |
Заголовок сообщения: | Re: прерывание от таймера 0 |
А если так: Не устроит? Я приводил упрощенный пример. В реальном проекте проверка идет от 8 до 26 каждое целое значение. Т.е 8, 9, 10...26 Наверное правильнее будет сделать мне сравнение с число if (i>26) {} if (i==26) {} if (i==25) {} ..... if(i==8) {} if(i<8) {} |
Автор: | Ivanoff-iv [ Вс мар 17, 2019 09:26:17 ] |
Заголовок сообщения: | Re: прерывание от таймера 0 |
ну, если это последовательный ряд чисел, то я бы применил массив... Код: if (i>26) i=26; или свитч кейс:if (i<=8) {i=0;} else {i-=8;}; Blue=BLUE_PWM[i]; Red=RED_PWM[i]; Green=GREEN_PWM[i]; Код: if (i>26) i=26;
switch (i) { case 26: ..... break; case 25: ..... break; ..............,.......... case 9: ...... break; default: ....... }; |
Автор: | ARV [ Вс мар 17, 2019 09:52:06 ] |
Заголовок сообщения: | Re: прерывание от таймера 0 |
wws63 писал(а): если else будет громоздко интересно, с чего вдруг?Код: if(cond_1){ // первый выбор } else if(cond_2){ // второй выбор } else if (cond_3){ // третий выбор } else { // если ничего не подошло } Добавлено after 3 minutes 36 seconds: если сравнивате "цепочкой" по условию "больше" - начинайте с наибольшего. т.е. если сравниваем с числами 5, 10, 15 и 20, то надо писать в такой последователньости Код: if(x > 20){
// x более 20 } else if(x > 15){ // х более 15, но менее или равно 20 } else if(x > 10){ // х более 10, но менее или равно 15 } else if(x > 5){ // х более 5, но менее или равно 10 } else { // х менее или равно 5 } |
Автор: | wws63 [ Вс мар 17, 2019 11:31:34 ] |
Заголовок сообщения: | Re: прерывание от таймера 0 |
если сравнивате "цепочкой" по условию "больше" - начинайте с наибольшего. А выход из процедуры при условии совпадения без goto ? Код: if (i>26) // больше 3100 об/мин
{ BLUE_PWM = 0; RED_PWM = 255; // красный GREEN_PWM = 0; goto m; //----- убрать? } |
Автор: | ARV [ Вс мар 17, 2019 11:38:03 ] |
Заголовок сообщения: | Re: прерывание от таймера 0 |
какой выход? цепочка if - else if срабатывает только в одном месте, все остальные проходят мимо. "выход" не требуется, вся цепочка - это как бы один оператор. |
Автор: | wws63 [ Вс мар 17, 2019 12:16:53 ] |
Заголовок сообщения: | Re: прерывание от таймера 0 |
вся цепочка - это как бы один оператор. Спасибо, завтра посмотрю как в "железе" работает. |
Автор: | Ivanoff-iv [ Вс мар 17, 2019 12:33:07 ] |
Заголовок сообщения: | Re: прерывание от таймера 0 |
поправил прошлое сообщение (дописал код на кейсах)... сейчас нет возможности проверить, но мне кажется, если массивы во флеш разместить то по ресурсоемкости метод "иф-елзе" будет самым громоздким... а может и нет, если оптимизатор правильно сработает... (может кто промерит объём кода и скорость выполнения) |
Автор: | wws63 [ Вс мар 17, 2019 14:39:01 ] |
Заголовок сообщения: | Re: прерывание от таймера 0 |
поправил прошлое сообщение (дописал код на кейсах)... Буду пробовать все варианты |
Автор: | wws63 [ Пн мар 18, 2019 16:05:26 ] |
Заголовок сообщения: | Re: прерывание от таймера 0 |
Застрял на ровном месте. В Протеусе все работает на УРА, скважность с каждого канала ШИМ меняется в заданных параметрах, строго по частоте входного сигнала. А в "железе" одни глюки. Светодиоды мигают хаотично, при этом изменение частоты входного сигнала не дает почти никаких изменений. Перепробовал все. Снижал частоту генерации ШИМ (менее сотни Гц), думал может РЖБ - лента, изменял фронты сигнала на входе INT0, менял контроллер, игрался с тактовой частотой, менял пороги срабатывания ... Короче все , что можно. Разумеется, проверил монтаж на плате (сопли, обрывы). ![]() В общем не знаю, в какую сторону копать ![]() |
Автор: | Ivanoff-iv [ Пн мар 18, 2019 16:20:15 ] |
Заголовок сообщения: | Re: прерывание от таймера 0 |
питание мк стабльное? блокировочные конденсаторы имеются? ресет к плюсу притянут? как разведены ключи лент? схему давай! |
Автор: | wws63 [ Пн мар 18, 2019 16:55:37 ] |
Заголовок сообщения: | Re: прерывание от таймера 0 |
питание мк стабльное? блокировочные конденсаторы имеются? ресет к плюсу притянут? как разведены ключи лент? схему давай! Причина найдена! |
Автор: | wws63 [ Вт мар 19, 2019 16:43:15 ] |
Заголовок сообщения: | Re: прерывание от таймера 0 |
Вместо регистра MCUCR было записано MCUSR. Студия 6 (как впрочем и 4) на ноутбуке нормально компилировала в хекс, приносил проект на другой комп там прошивал и ступор. Когда попытался внести изменения в программу и заново откомпилировать уже на компе, студия 6 начала ругаться на MCUSR. Мистика! ![]() Едем дальше ![]() |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |