delay_ms & interrupts

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Встал на лапы
Аватара пользователя
Сообщения: 117
Зарегистрирован: Вс апр 12, 2009 22:40:37

Сообщение zebrox »

Всем привет!

Вот столкнулся с таой проблемой.
Есть у меня таймер, тикает с частотой 1 гц, происходит прерывание, а в этом прерывании мне нужно мигать светодиодом, частота его мигания достаточно низкая, что-бы можно было посчитать количество вспышек (от 1 до 12). Вспышки формирую функциями delay_ms()

Код: Выделить всё

void blink_led(char num, char time_on, int time_off){
char i = 0;
    for(i = 0; i< num; i++)
    {
        LED_pin = 0;
        delay_ms(time_on);
        LED_pin = 1;
        delay_ms(time_off);
    }
}
т.е. эта функция вызывается из прерывания таймера. И оказалось, что когда выполняется этот участок кода, прерывания от ЮАРТА не приходят вообще.
На каком-то заморском форуме вычитал, что вызывать delay_ms() в прерывании нельзя, но почему не понятнь. Хотя какая разница, delay_ms() это вроде обычный пустой цикл, и все прерывания должны приходить.
Может я чего напутал или недопонял....
В чем может быть причина НЕприхода юарт прерываний???
Реклама
Прорезались зубы
Аватара пользователя
Сообщения: 223
Зарегистрирован: Вт окт 02, 2007 14:43:23
Откуда: Ростов-на-Дону

Сообщение GRafGRay »

Если я не ошибаюсь, то в момент запуска прерывания, флаг I в регистре SREG сбрасывается, запрещая другие прерывания.

У вас цикл выполняется внутри обрабочика прерывания, соответственно, пока весь цикл не отработает, все остальные прерывания будут запрещены.

По выходу из обработчика необходимо установить флаг для разрешения прерывний.
При наличии отсутствия пропитанных шпал - это будет не трамвай а одно горе!
Контактная информация:
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 117
Зарегистрирован: Вс апр 12, 2009 22:40:37

Сообщение zebrox »

вот смотрю асм код, при вызове прерывания первым делом вызывается эта процедура

Код: Выделить всё

;OPTIMIZER ADDED SUBROUTINE, CALLED 3 TIMES, CODE SIZE REDUCTION:19 WORDS
SUBOPT_0x1DA:
	ST   -Y,R0
	ST   -Y,R1
	ST   -Y,R15
	ST   -Y,R22
	ST   -Y,R23
	ST   -Y,R24
	ST   -Y,R25
	ST   -Y,R26
	ST   -Y,R27
	ST   -Y,R30
	ST   -Y,R31
	IN   R30,SREG
	ST   -Y,R30
	RET
я в асме не очень силен, а точнее очень не силен, IN R30,SREG
это и есть сброс флага т.е. запрет других прерываний?
Получается, что из прерывания нельзя уйти в прерывание?
А как можно это решить?
Держит паяльник хвостом
Аватара пользователя
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Сообщение Goodefine »

zebrox писал(а): ...Получается, что из прерывания нельзя уйти в прерывание?
А как можно это решить?
Разрешить вложенные прерывания. Но в вашем случае это не надо. Алгоритм программы необходимо пересмотреть. Не нужно делать делай в прерывании. Причину вы уже выяснили - не работают другие прерывания, до выхода из обработчика. Вложенные делать тоже не выход - стек не бесконечный, да и временная диаграмма не очевидная получается.
Лучший выход - в обработчике ставьте флаг, а в основном цикле по флагу выполняйте определенные действия. И лучше вместо делая также работать по флагам от таймера - МК вместо тупого ожидания может заняться работой...
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Реклама
Эиком - электронные компоненты и радиодетали
Прорезались зубы
Аватара пользователя
Сообщения: 223
Зарегистрирован: Вт окт 02, 2007 14:43:23
Откуда: Ростов-на-Дону

Сообщение GRafGRay »

<b>zebrox </b>
настоятельно рекомендую почитать обучалку и со стеком разобраться

in R30,SREG - это в регистре R30 сохраняется значение регистра SREG, по выходу из прерывания необходимо SREG восстаналивать

проблема в том, что вы в прерывание, которое выполняется очень короткий промежуток времени запихнули цикл который выполняеся много - очень много дольше, соответственно основная программа с другими прерываниями не выполняется пока не выйдет из текущего прерывания.
Последний раз редактировалось GRafGRay Вт авг 18, 2009 11:17:14, всего редактировалось 2 раза.
При наличии отсутствия пропитанных шпал - это будет не трамвай а одно горе!
Контактная информация:
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 117
Зарегистрирован: Вс апр 12, 2009 22:40:37

Сообщение zebrox »

Goodefine писал(а): Лучший выход - в обработчике ставьте флаг, а в основном цикле по флагу выполняйте определенные действия.
Понял, так наверное и сделаю, конечно прийдется повозиться...
А для общего развития, как можно разрешить вложенные прерывания, где? Еще вроде есть иерархия прерываний, как можно руками добавить приоритета прерываниям от юарта? Сделать свой вектор прерываний?
Реклама
Держит паяльник хвостом
Аватара пользователя
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Сообщение Goodefine »

zebrox писал(а): //А для общего развития, как можно разрешить вложенные прерывания, где? Еще вроде есть иерархия прерываний, как можно руками добавить приоритета прерываниям...
Просто в обработчике написать #asm ("sei") (CVAVR), если компилятор другой, смотреть документацию. Либо бит глобального разрешения установить руками (то бишь маской).
Иерархию изменить нельзя - выполнится то прерывание, вектор которого имеет младше адрес...
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Встал на лапы
Аватара пользователя
Сообщения: 117
Зарегистрирован: Вс апр 12, 2009 22:40:37

Сообщение zebrox »

Goodefine писал(а):Просто в обработчике написать #asm ("sei")
все гениальное просто!
Вот с вектором бы еще разобраться, в CAVR в настройках проэкта можно задать вектор во внешнем файле, надо хелп почитать.

Сейчас тему думаю создать про веб сервер на СИМ300 и МК, может кто сталкивался...
Держит паяльник хвостом
Аватара пользователя
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Сообщение Goodefine »

zebrox писал(а):...Вот с вектором бы еще разобраться, в CAVR в настройках проэкта можно задать вектор во внешнем файле, надо хелп почитать. ...
А чего с ним разбираться? От компилятора это не зависит. Вектора заданы аппаратно в самом контроллере - в даташите приоритеты прерываний подробно описаны. То что во внешнем файле - просто исполняемый код, вынесенный отдельно.
А вообще, пропуска прерываний не случится (только если прерывание два раза произойдет без входа в обработчик) - выполнятся все, но в определенной последовательности...
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Встал на лапы
Аватара пользователя
Сообщения: 117
Зарегистрирован: Вс апр 12, 2009 22:40:37

Сообщение zebrox »

вот-вот, эту страничку я и читал, что это не очень хорошая идея вызывать delay_ms() в прерывании...
Собутыльник Кота
Аватара пользователя
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев

Сообщение BCluster »

char flag =0;

...//обработчик прерывания
{
flag = 1;
}

...
while (1)
{
if (flag) blink_led(num,time_on,time_off);
flag=0;
}
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 335
Зарегистрирован: Вт сен 11, 2007 10:27:08
Откуда: Киев

Сообщение __Alexander »

А при чем тут delay? Прерывание от уапп никак не выполнится в любом другом прерывании, вектор которого выше. Пусть там даже одна команда.




------------------
Держит паяльник хвостом
Аватара пользователя
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Сообщение Goodefine »

__Alexander писал(а):...Прерывание от уапп никак не выполнится в любом другом прерывании, вектор которого выше. Пусть там даже одна команда.
Оно не выполнится в ЛЮБОМ обработчике, хоть ниже, хоть выше. Зато после выхода пожалуйста...
__Alexander писал(а): А при чем тут delay?
Делай делает обработчик долгим, притупляя реакцию МК... Потому и "причем"...

Код: Выделить всё

...
if (flag) blink_led(num,time_on,time_off);
flag=0; 
..
Не совсем так:

Код: Выделить всё

...
if (flag) {blink_led(num,time_on,time_off);
            flag=0;} 
...
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Встал на лапы
Аватара пользователя
Сообщения: 117
Зарегистрирован: Вс апр 12, 2009 22:40:37

Сообщение zebrox »

Спасибо всем, что отозвались!
Для себя сделал вывод, что нужно учить матчасть...И делей в прерывании не есть правильно.
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»