я вообще ничего не понял, как связаны программные извраты с количеством внешних прерываний...
но дам вам пару советов:
1. когда пишите код - будьте внимательны и анализируйте то, что вы НАПИСАЛИ, а не то, ЧТО ХОТИТЕ получить, т.к. часто это не одно и то же.
2. наплюйте на "черточки" в протеусе - раз компилятор что-то выкинул, значит, оно было лишним. случаев, чтобы компилятор выкинул то, что нельзя, не замечено. зато полно случаев, когда написанное ведет себя не так, как хотелось - см.п.1
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
С Новым Годом ВСЕМ!!! Я за всегда рад выслушать совет. А вот мысли свои выложить не могу. Но то чего я хотел у меня получилось, может кому надо:
int fol=0x0F;
ISR(TIMER0_OVF_vect){ // Timer/Counter0 Overflow
wip=PIND|fol;
if(wip==0X1F){
PORTD&=~(1<<0);
fol|=(1<<5);
_delay_ms(50);PORTD|=(1<<0);
}
if(PIND&0X20) fol&=~(1<<5);
wip=PIND|fol;
if(wip==0X2F){
PORTD&=~(1<<0);
fol|=(1<<4);
_delay_ms(50);PORTD|=(1<<0);
}
if(PIND&0X10) fol&=~(1<<4);
Это для двух кнопок. А вот только на счёт задержки сомневаюсь,надо ли она.
всегда плохо, когда в обработчике прерываний делаются задержки... так же не хорошо, когда из обработчика прерывания вызываются сторонние функции (не статические, а библиотечные). не знаю, какая у вас конкретная задача, но лично я никогда в прерываниях кнопки не обслуживаю - нет нужды. по мне, так самое простое - это в главном цикле время от времени проверять состояние кнопок, вот и все.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Начал переходить с асма на Си и тут же уперся в нежелание незатейливой программки работать.
В отладчике командой sei флаг прерываний не устанавливается, в тоже время программа крутится не в главном цикле, а вокруг прерывания.. Собственно не работает прерывание..
Что здесь может не работать - ума не приложу??
вы совершили традиционную для начинающих ошибку. avr-gcc (оно же WinAVR) не прощает вольностей по отношению к стандарту языка Си. ваша переменная cnt_S используется и в обработчике прерывания и в главной функции, а значит, она обязательно должна объявляться volatile-переменной! иначе компилятор считает, что эта переменная внутри основного цикла никогда не изменит свое значение, а значит, ни на что повлиять не сможет. бесполезные переменные и код для их обслуживания компилятор выбрасывает - у вас получается черти что: есть прерывание, но оно ничего не делает!
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
ARV писал(а): она обязательно должна объявляться volatile-переменной! иначе компилятор считает, что эта переменная внутри основного цикла никогда не изменит свое значение, а значит, ни на что повлиять не сможет. !
Спасибо, буду знать !!
Объявил как volatile unsigned int cnt_S; - не помогло...
Пернес проверку счетчика в само прерывание - тоже не работает..
ARV писал(а):ничего там мудреного. вы что хотите сделать?
Да у меня есть прогграмма, написанная на асме. Я ее решил переписмать на Си, для изучения последнего. Вот попытался вести в программу прерывание - не работает. Теперь просто хочу его запустить - помигать хотя бы светодиодом.. ))) Ничего не выходит. Где-то что-то упускаю.
Спасибо, разберу ваши примеры. Но мне мигание нужно для того в данный момент, чтобы включить прерывание. А в рабочем варианте в прерывании у меня выставляется флаг 1мс, по которому в основном цикле уже отсчитываются всевозможные интервалы..
Прошу прощения, а какая частота мигания будет в вашем варианте с прерыванием?? Мне кажется туда счетчик все-равно надо вводить.. Иначе частота будет намного выше визуально видимой..
Последний раз редактировалось R_ura Пн янв 03, 2011 23:49:52, всего редактировалось 1 раз.
R_ura писал(а):Прошу прощения, а какая частота мигания будет в вашем варианте с прерыванием?? Мне кажется туда счетчик все-равно надо вводить.. Иначе частота будет намного выше визуально видимой..
откуда ж мне знать. какая у вас тактовая частота? для таймера я включил делитель на 1024, переполнение возникнет спустя 256 этих тиков, т.е. итоговое деление тактовой частоты получается на 262144... если тактовая 1 МГц, то период мигания будет почти 8 секунд... ну а при тактовой 8 МГц - соответственно, 1 секунда (почти)... глазом ОООООЧЕНЬ заметно будет
я вам просто показал, как помигать, раз у вас даже это не выходило. а счетчик и т.п. - это уже от вашей задачи зависит...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
R_ura писал(а):Прошу прощения, а какая частота мигания будет в вашем варианте с прерыванием?? Мне кажется туда счетчик все-равно надо вводить.. Иначе частота будет намного выше визуально видимой..
откуда ж мне знать. какая у вас тактовая частота? для таймера я включил делитель на 1024, переполнение возникнет спустя 256 этих тиков, т.е. итоговое деление тактовой частоты получается на 262144... если тактовая 1 МГц, то период мигания будет почти 8 секунд... ну а при тактовой 8 МГц - соответственно, 1 секунда (почти)... глазом ОООООЧЕНЬ заметно будет
я вам просто показал, как помигать, раз у вас даже это не выходило. а счетчик и т.п. - это уже от вашей задачи зависит...
Прошу прощения, я не хотел вас уколоть. Я не думал, что на 8 битном таймере можно организовать секундные задержки.. Спасибо, вы правы..
я толстокожий, об меня не один ёжик иголки обломал (типа лицар) так что ваши опасения напрасны.
просто тонкости настройки таймеров не имеют прямого отношения к WinAVR... а по сути WinAVR вы пока не сильно вопросы задаете...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
ARV писал(а):я толстокожий, об меня не один ёжик иголки обломал (типа лицар) : .
Так то ж вы в одном месте толстокожий - для їжаків)))))
Задам еще, дай бог прерывание включить.. Создам проект заново, а то и ваш пример не работает нифига..((
ARV писал(а):всегда плохо, когда в обработчике прерываний делаются задержки... так же не хорошо, когда из обработчика прерывания вызываются сторонние функции (не статические, а библиотечные). не знаю, какая у вас конкретная задача, но лично я никогда в прерываниях кнопки не обслуживаю - нет нужды. по мне, так самое простое - это в главном цикле время от времени проверять состояние кнопок, вот и все.
Спасибо. Вы не первый кто мне это говорит, но я не понимаю, ведь программа дойдя до замкнутого цикла стоит там ждёт прерываний, она же не может вернутся в начало.
а вы продумайте алгоритм своей программы так, чтобы она в цикле не стояла, а что-то делала. и как раз опрос кнопок тут самое подходящее занятие. я уже не раз говорил: для чего нужно прерывание? для немедленной и мгновенной реакции на какое-то событие. а кнопка, которую нажимает человек, ну никак не может требовать такой реакции, ибо человек не в состоянии заметить задержку в реакции на свое действие, если эта задержка менее 0,02 секунды, а его тело вообще не в состоянии совершить какое-то действие быстрее, чем за 0,15 секунды - и то такая скорость реакции у специально тренированных людей. а 0,15 секунд для МК - это дико много, и строить работу с кнопками по прерываниям от них - это нелогично. практически любая программа любительского уровня может делаться по такому скелету:
uint8_t get_key(void); // эта функция опрашивает порт с кнопками и возвращает код, соответствующий комбинации нажатых кнопок
void indicate(uint8_t mode); // эта функция обеспечивает индикацию в соответствии с режимом работы mode
static void init(void); // эта функция инициализирует всю аппаратуру МК
int main(void){
uint8_t mode = 0;
uint8_t key;
init();
while(1){
indicate(mode);
key = get_key();
switch(key){
case KEY1 : // тут обрабатываем нажатие первой кнопки
// если нужно - переключаем режим mode
break;
case KEY2 : // тут обрабатываем нажатие второй кнопки
// и так далее все возможные комбинации нажатий кнопок
}
}
}
как видите, основной цикл занят делом: он работает с кнопками и занимается изменением режима индикации. а вот все прочие функции могут делаться и по прерываниям - особенно хорошо укладывается в это динамическая индикация. можно проводить какие-товычисления и т.п. работу, а в прерываниях делать только то, что требует МГНОВЕННОЙ НЕЗАМЕДЛИТЕЛЬНОЙ реакции - например, принимать ИК-команды с пульта, следить за переходом сети через 0, принимать из USART и т.п. кстати, принимать из USART так же далеко не всегда требуется по прерываниям - иной раз проще делать это в основном цикле.
вот как-то так.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
и вправду, чертовщина у вас какая-то... пригласите попа с кадилом, пусть освятит вашу лабораторию, ибо я вот только что в студии просимулировал этот код (только поменял PORTA на PORTB, т.к. у меня заточено на atmega8) - работает, ё! как и было обещано. так что это у вас лыжи неправильные
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...