по аппаратному прерыванию
- Войдите на сайт для отправки комментариев
Пт, 30/08/2013 - 00:20
никак не соображу по этому вопросу, нужен генератор низких частот, и решил воткуть в свою прогу.
Надо - частота от 1 Гц до 300 Гц, и её можно менять с помощью кнопок, и ширину импульса. Операции с меню не должны заикать звук. Пока написал это
#include <LiquidCrystal.h> LiquidCrystal lcd(8, 9, 10, 11, 12, 13); // инициализируем LCD, указывая контакты данных #define TOGGLE_IO 40 //Arduino pin to toggle in timer ISR unsigned int latency; unsigned int latencySum; unsigned int sampleCount; unsigned char timerLoadValue; int freq=500; int analogkey2; #define TIMER_CLOCK_FREQ 2000000.0 //2MHz for /8 prescale from 16MHz unsigned char SetupTimer2(float timeoutFrequency){ unsigned char result; result=(int)((257.0-(TIMER_CLOCK_FREQ/timeoutFrequency))+0.5); TCCR2A = 0; TCCR2B = 0<<CS22 | 1<<CS21 | 0<<CS20; TIMSK2 = 1<<TOIE2; TCNT2=result; return(result); } //Timer2 overflow interrupt vector handler ISR(TIMER2_OVF_vect) { digitalWrite(TOGGLE_IO,!digitalRead(TOGGLE_IO)); latency=TCNT2; TCNT2=latency+timerLoadValue; digitalWrite(49,HIGH); delay (freq); digitalWrite(49,LOW); } void setup(void) { pinMode(TOGGLE_IO,OUTPUT); pinMode(49,OUTPUT); // LED TESTER lcd.begin(20, 4); // указываем размерность экрана и начинаем работать lcd.clear(); lcd.setCursor(0, 0); lcd.print("Timer2 Test"); lcd.setCursor(10, 0); lcd.print(timerLoadValue); delay(1000); timerLoadValue=SetupTimer2(44100); // Serial.println(timerLoadValue,HEX); } void loop(void) { delay(1000); //Accumulate ISR latency every 10ms. latencySum+=latency; sampleCount++; if(sampleCount>99) { float latencyAverage; float loadPercent; latencyAverage=latencySum/100.0; sampleCount=0; latencySum=0; loadPercent=latencyAverage/(float)(256.0-timerLoadValue); loadPercent*=100; //Scale up from ratio to percentage; latencyAverage-=(int)latencyAverage; spy: analogkey2 = analogRead (2); if (analogkey2>650 && analogkey2<750){ // ->> if (freq>30) { freq=freq-10; }; };// if if (analogkey2>300 && analogkey2<380) { // <-- if (freq<1000) { freq=freq+10; }; }; // if lcd.setCursor(5,1); lcd.print (freq); goto spy; } }
вырезал со статьи по прерывание, читаю и не очень понимаю, в коде много мусора, не понятно как на ходу менять частоту срабатывания прерывания и её расчитать.
В Delphi к примеру в основной программе достаточно было вызвать CreateThread и в теле потока написать подобие ВКЛ.LED, пауза1,ВЫКЛ.LED,пауза2. и управляя переменными пауз из основного потока программы достигли бы нужного.
нашел лучший пример,всё обернуто в обертку и вынесено в cpp, хотя не рабочий, с помощью библиотеки MsTimer2.cpp (добавил в либры, плата 2560, среда 1.0.1)
по коду должно через каждые 5 секунд включатся светодиод на 1 секунду, но этого не происходит.Кнопки в коде подключены, но пока не учавствуют в изменении параметров.
Бздынь.....
1. Что у вас с форматирование кода? Нажмите хотя-бы CTRL-T в Arduino IDE
2. GOTO - забудте про существование этого оператора ВООБЩЕ. Пишите так как будто не такого слова. Обходитесь другими средствами.
3. Раз нехотите заикание - откажитесь от функции delay(). И уж тем более в обработчике прервыния (тут нет многопоточности). Только millis() и таймеры (и то, аккуратно с ней обработчике). Вообщем начинайте с базовых примеров в разделе Программирование. Мигаем светодиодом без delay() , а не сразу "экраны", "генераторы" и т.п.
http://arduino.ru/forum/programmirovanie/arduino-push-pull
ага спасибо, чуток доходит, жалко железной мультипоточности нет.
Goto если правильно использовать, то ничего в этом нет,боятся только новички. Заместо него используют команды условного перехода, if (0==0) проверяя, то что всегда равно чему-то. loop тот же безусловный переход к адресу первого оператора loop.
3. Раз нехотите заикание - откажитесь от функции delay(). И уж тем более в обработчике прервыния (тут нет многопоточности).
таки есть многопоточность :) в DUE можно запустить несколько loop в одной программе..
это уже другая дурина) там чип другой.
Ещё про GOTO - иногда надо часть кода пропустить (перепрыгнуть), в DELPHI можно было ненужный блок взять в {} и он заремится, в этом языке это служебное слово, придется или на каждой строчке печатать // или брать весь ненужный код в блок условного кода тупо if (0==0), а быстрее добавить пару строк
ну если вы не обратили внимания то есть еще вариант
/* .... строчки которые ремарките..... */
и можеет хоть весь код так отметить
не знал, но иногда не надо заремить, а сохранить следующий код, так размер виден при компиляции ( в том числе в exe, правда сейчас размер программы в ехе уже не имеет значения, ранее приходилось на WinApi писать, используя встроенные фунции в dll виндовс)...
Ну вот не нужно тут петь диферамбы GOTO. Как раз новички его и не боятся. Обычно наличие GOTO говорит либо о том что это новичок который плохо знает синтаксис языка и лепить "костыль GOTO" куда угодно. Либо это писал человек привыкший к ASM и опять-таки ленящейся освоится с новым языком. Действующий по принципу "заработало и ладно".
Я не новичок. Про GOTO знаю. Моим первым языком был GW-BASIC с нумерацией строк. Где-то 1988-1989 году. Там без GOTO - было вообще никак :)
Но с переходом TurboPascal 3.0 (упоминаемая вами Delphi, на котором тоже не один год писали - его потомок) - надобность в GOTO отпала совершенно. Нет никаких "правильных использований GOTO". Само его использование - уже неправильно. Резко падает сопровождаемость и читабельность кода.
Ваш пример с комментированием, готорит не о том, GOTO нужен, а о том что вы плохо знаете синтаксис языка.
Во первых есть есть блочные коментаии которые спокойно решают вашу проблему. Коментировать можно не только одну строку, а сразу сколько захочешь
Во вторых само существование большого блока кода который нужно "закментить" говорит о низком качестве кода. Почему он не вынесен в отдельную функцию, вызов которой можно закоментировать одним пальцем?
Есть еще условная компиляция. Директивы препроцессора #if #ifdef #ifndef. Которая позволяет "включить/выключить" сразу несколько кусков кода. Не занимать не нужным кодом такты процессора и память. А не решать это в runtime
В третьих само "хранение старого кода" в закоментированом виде, типа "авось пригодится" говорит о том, что вы не знакомы с ситемами контроля версии (git, mercural, svn и т.п.). Которые спокойно решают эту задачу и сохраняют код чистым и опрятным, без "исторического мусора".
Ну и в конце концов. if(0==0) - никак не поможет в вашей ситуации. Код будет выполнен. Эту условие - всегда истино. Вам нужно было if(0==1) или более удобочитаем if(false) или аскетчино if(0)
Вообщем любое использование GOTO говорит либо о недостатке знаний пишущего, либо о крайне низком качестве кода (ошибках архитектуры и т.п.). Поэтому и говорится "забудте про него". Что-бы вы вынуждены были решать задачи более адекватными средствами.
Конечно плохо знаю, в пределах сайта по контроллеру, на другие не захожу - из специфики языка. И учеба по мере задач - если нужно прерывание их и разбираю, а не как работает функция tone().
ASM да было (jnz). BASIC был, ZX-SPECTRUM - там действительно никак, переход на строчку. GOSUB ещё был....Delphi начал с 4.0 (там уже VCL элементы) goto удобно использовать во врезках asm код end; благо язык позволяет в любом месте перейти на asm."существование большого блока кода " - это важный код который охота пропустить при отладке, это меню, вместо нудного и долгого выбора пункта в меню и выбора значения кнопками, достаточно прописать в начале эти настроенные переменные, в том числе номер меню и сделать переход) Но уговаривать не буду, кому как легче, после отладки данные команды затираются.
Кстати на Mega2560 не работает библиотека <MsTimer2.h>
не зажигает светодиод, если в сетап вынести - digitalWrite(49,HIGH); лед горит, исправен.
Залезте в библиотеку, поробуйте найти все условия содержащие
И заменить/дописать на
Про GOTO - ну как хотите. Желание использовать GOTO - не дает вам развиватся. По очередному вашему примеру видно что событийная архитектура у вас в приложении была "так себе", разделение логики и UI - плохое, Unit Testing-гом не пахло и т.п.
В конце концов, что вы ходите доказать? Даже задачу "обойти большой кусок кода" (хотя и задачи такой в нормальном приложении быть не должно, само наличие "большой кусок кода" - уже фигня) - можно решить без GOTO и более красиво. Я вам упоминал уже какими средствами? Вы хоть погуглили их?
Впрочем - каждый сам себе злобный буратино. В любой приличной конторе (и даже не очень приличной), при намеке на GOTO - собеседование сразу заканчивается. Если кто-то уже из работников будет использовать - ну очень удивятся. Объяснят (и скорее всего сделают выводы о компетенции), если же будет "упорствовать" - скорее всего сразу укажут на дверь. Никому потом не улыбается сопровождать код написаный таким "програмистом".
P.S. Стыдно "не отсуствие знание", а упроствование в этом.
не собираюсь быть платным программистом, или работать на дядю - главное написать работающий контроллер и забыть.
Уже дошло - взяв библиотеку FlexiTimer2, там ATmega2560 уже прописано, надо заглядывать в *.cpp, родное IDE 1.0.1 не хочет открывать, а в блокноте каша.
Ну что ж с профи говорить, извините.
Доброго времени суток !
1) Таймер 2 - 8-ми битный и по этому от 1 до 300 не получится, если только Вы не собираетесь таймером просто вести счет для CPU
2) Оператор GOTO использовать никто не запрещает, НО среди С-шников это считается дурным тоном. Когда это началось я не знаю, но когда я в 1992 переходил на С это уже было.
3) Паралельных потоков на 1 CPU не бывает - это просто быстрое переключение по прерыванию от таймера (сам когдато делал многозадачность 286/386)
4) Вы хотите использовать LCD и генерировать реалтайм сигнал - для этого необходимо хотябы что то одно делать по прерыванию (в фоне). Так как Вы используете LiquidCrystal который использует паузы (delay delayMicroseconds) то остается сделать генератор сигнала в фоне. Так как у Вас 300 градаций то таймеры 0/2 Вам не подходят. Используйте 1/3 они 16-ти битные. К примеру выберите режим FastPWM с ограничением по OCRA настройте делитель на /256 таким образом 1 сек = 62500 счетов скважность в примеру 50% 62500 / 2. Длительность заносим в OCRA скважность в OCRB и запускаем таймер. Более высокую частоту можете расчитать сами.
Доброго.
1) оказалось до 100 гц, далее просто не надо. Для LED например такая частота мерцаний сливается в почти ровное свечение.
2) да и в паскале. В бейсике обязательно, т.к там не было функций-процедур (про ZX-BASIC), в надстройках в виде BETA-BASIC,LASER,MEGA-BASIC было слабое подобие, уже не помню. Поэтому там и этот оператор был необходим.
Выбор - по какой-то нажатой клавише - GOTO строка. Вот когда полноценные процедуры-функции появились, тогда отпала не обходимость скакать по единой программе по кускам.
3) конечно, это прозрачно для программиста.
4) пока работает. Отдельный генератор помимо программы.