dedded 0 25 апреля, 2007 Опубликовано 25 апреля, 2007 · Жалоба Ребят, в большом проекте попался кусок, над которым я уже туплю. Среда CVAVR 1.25. Нужно выдать на ногу, неважно какую, количество импульсов, с определенной частотой. После обработки прерывания по таймеру, где меняется сигнал на ноге, возвращается тупо не туда, где прерывание прервало работу проги. #include <mega16.h> #include <stdio.h> #include <delay.h> long int step_kol; int step; interrupt [TIM0_OVF] void timer0_ovf_isr(void) { // Reinitialize Timer 0 value TCNT0=step // загрузили константу step_kol++; //счетчик количества шагов PORTC.0^=1; // дернули ногой } void main(void){ // уже не до красоты - переписал, чтобы понятно было порт С - выход DDRC = 255; PORTC = 0; TIMSK=0x3; #asm("sei") while(1){ было step=0x100; //константа для задания частоты поправил, это просто описка step=0x10; TCCR0 = 0x00; //stop TCNT0 = step; //set count TCCR0 = 0x05; //start timer с предделителем на 1024 while (step_kol<1000){ //жду, когда в таймере пройдет 1000 циклов #asm("wdr"); } step_kol=0; delay_ms(5000); сюда не доходит } } кусок выдрал аккуратно вроде, точнее заново оформил что же я не так делаю? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
arttab 0 25 апреля, 2007 Опубликовано 25 апреля, 2007 · Жалоба перед заносом в TCNT0 таймер не остановлен. это может повлиять на работу таймера. а если возврат идет не туда откуда был переход, надо стек проверить. не переполняется ли он. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Валентиныч 0 25 апреля, 2007 Опубликовано 25 апреля, 2007 · Жалоба перед заносом в TCNT0 таймер не остановлен. это может повлиять на работу таймера. а если возврат идет не туда откуда был переход, надо стек проверить. не переполняется ли он. И при входе/выходе в/из прерывание сохранять/восстанавливать программный счетчик. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GDI 0 25 апреля, 2007 Опубликовано 25 апреля, 2007 · Жалоба Кусок кода приведенный автором написан криво, очень криво, но я спишу это на трудности переноса сути вопроса из большого проекта :) А вот что я заметил: 1) константа step ( которая обьявлена вовсе не как константа) объявлена как int и занесено туда значение 0х100, а затем этой "константой" автор инициализирует 8 битный счетчик TMR0 2) зачем в главном цикле while(1){} производится постоянно переинициализация таймера(останов, загрузка опять же 16 битным значением 8 битного регистра счета, старт с предделителем)? 3) далее зачем то ждем 1000 циклов таймера чтобы сбросить WatchDog, причем используется переменная long int step_kol. хотя тут хватило бы и простого int. 4) затем задержка на 5 сек во время которой продолжаются прерывания таймера. В итоге, автор не написал как работает данный кусок, но я предположу, что происходит постоянная генерация на ноге PortC.0 с частотой переполнения 8 битного таймера на частоте XTAL/1024, т.е. частота XTAL/1024/256, возможно , с короткими перерывами. Также предположу что автор хотел генерировать 1000 импульсов с перерывом в 5 секунд, но данный кусок этого просто не может обеспечить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tag 0 25 апреля, 2007 Опубликовано 25 апреля, 2007 · Жалоба кусок выдрал аккуратно вроде, точнее заново оформил что же я не так делаю? ...в глаза бросается использование watchdog-а, нет явной настройки (а по умолчанию он не запущен) и вдруг он стартуется #asm(wdr) ... а затем пауза вставлена delay_ms(5000); довольно продолжительная...может быть проблема в этом? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Snaky 0 25 апреля, 2007 Опубликовано 25 апреля, 2007 · Жалоба 3) далее зачем то ждем 1000 циклов таймера чтобы сбросить WatchDog. он не ждет - он его сбрасывает 1000 раз пока ste_kol не накопит до 1000 :) Хотя код и кривой, но проблема скорее всего в инициализации 8 битного регистра значением 0x100, как ты заметил. P.S. Кстати, PC-Lint такие ошибки легко отлавливает, а компиляторы игнорируют. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dedded 0 25 апреля, 2007 Опубликовано 25 апреля, 2007 · Жалоба Отвечу сразу всем: написано действительно криво, потому как весь код сюда ложить смысла нет. просто по быстрой оформил проектик с этим злополучным куском, чтобы сюда положить. Задача общая, - сформировать посылку № на ногу, тут PORTC.2 для управления ШД. срезал все лишнее, чтобы идею понять можно было. interrupt [TIM0_OVF] void timer0_ovf_isr(void) { TCCR0 = 0x00; //stop TCNT0=step; step_kol++; PORTC.0^=1; TCCR0 = 0x05; } так тоже - самое step = описался, равен 10 WDT - оставил из большого куска, чтобы в этом цикле собака не срабатывала. Алгоритм - запустили таймер, который 1000 раз должен отработать( в данном случае) после этого паузы и прочее. До пауз дело не доходит Стек переполняется И при входе/выходе в/из прерывание сохранять/восстанавливать программный счетчик. Глупый , наверное , вопрос - а CVAVR это не делает? можете бросать в меня гнилыми апельсинами Кусок кода приведенный автором написан криво, очень криво, но я спишу это на трудности переноса сути вопроса из большого проекта :) А вот что я заметил: 2) зачем в главном цикле while(1){} производится постоянно переинициализация таймера(останов, загрузка опять же 16 битным значением 8 битного регистра счета, старт с предделителем)? 3) далее зачем то ждем 1000 циклов таймера чтобы сбросить WatchDog, причем используется переменная long int step_kol. хотя тут хватило бы и простого int. 4) затем задержка на 5 сек во время которой продолжаются прерывания таймера. В итоге, автор не написал как работает данный кусок, но я предположу, что происходит постоянная генерация на ноге PortC.0 с частотой переполнения 8 битного таймера на частоте XTAL/1024, т.е. частота XTAL/1024/256, возможно , с короткими перерывами. Также предположу что автор хотел генерировать 1000 импульсов с перерывом в 5 секунд, но данный кусок этого просто не может обеспечить. этот кусок в таком виде должен через каждые 5 сек выдавать 1000 импульсов, на выдачу импульсов при 11,0592 уходит примерно 2 секудны, 5 сек - это с запасом, чтобы в эмуляторе картинка была а после выполнения прерывания - чаще всего начинает работать сначала проги, но в проекте - не с начала, т.е не сброс, но с достаточно конкретного места Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Валентиныч 0 25 апреля, 2007 Опубликовано 25 апреля, 2007 · Жалоба Глупый , наверное , вопрос - а CVAVR это не делает? можете бросать в меня гнилыми апельсинами Не знаю... Работаю в другой среде. Поэтому и предположил. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dedded 0 25 апреля, 2007 Опубликовано 25 апреля, 2007 · Жалоба Не знаю... Работаю в другой среде. Поэтому и предположил. Предположение смахивает на правду, кста, алгоритм брал из когда - то работающего проекта. Тот писался тоже на CVAVR только какой-то ранней версии. Ребят, у кого есть - CVAVR 1.25 и VMLAB проверьте, плиз. что-то я читал у них на сайте насчет работы с лицензией, сделанной кейгеном. Кто-то же выложил это на фтп. Ну и еще вопрос - купить то есть где CVAVR? Поиск результатов не дал. ...в глаза бросается использование watchdog-а, нет явной настройки (а по умолчанию он не запущен) и вдруг он стартуется #asm(wdr) ... а затем пауза вставлена delay_ms(5000); довольно продолжительная...может быть проблема в этом? да, тут маленько неправильно, WD срабатывает каждые 2 секунды, в это месте он конечно сработает, но он не доходит до этого места. Правильнее конечно время задержки поставить 1.8 секунды, только проблема балин не тут. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GDI 0 25 апреля, 2007 Опубликовано 25 апреля, 2007 · Жалоба step все равно лучше сделать char или const char или вообще #define STEP 0x10 чтоб память не занимать. инит таймера из главного цикла убрать - поставить ДО while(1) delay_ms(5000) заменить на delay_ms(1000), но поставить 5 раз а между ними разместить сброс Сторожевого таймера Перед делеями запретить прерывания от таймера - после делеев - разрешить. Стек увеличить - может где то в другом месте он переполняется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dedded 0 25 апреля, 2007 Опубликовано 25 апреля, 2007 · Жалоба step все равно лучше сделать char или const char или вообще #define STEP 0x10 чтоб память не занимать. инит таймера из главного цикла убрать - поставить ДО while(1) delay_ms(5000) заменить на delay_ms(1000), но поставить 5 раз а между ними разместить сброс Сторожевого таймера Перед делеями запретить прерывания от таймера - после делеев - разрешить. Стек увеличить - может где то в другом месте он переполняется. все исправил вот так сие выглядит #include <mega16.h> #include <stdio.h> long int step_kol; char step; // delay functions #include <delay.h> interrupt [TIM0_OVF] void timer0_ovf_isr(void) { TCCR0 = 0x00; //stop TCNT0=step; step_kol++; PORTC.0^=1; } void main(void){ DDRC = 255; PORTC = 0; TIMSK=0x3; #asm("sei") step=0x10; while(1){ TCCR0 = 0x00; //stop TCNT0 = step; //set count TCCR0 = 0x05; //start timer while (step_kol<1000){ #asm("wdr"); } step_kol=0; delay_ms(1000); #asm("wdr"); delay_ms(1000); #asm("wdr"); delay_ms(1000); #asm("wdr"); delay_ms(1000); #asm("wdr"); delay_ms(1000); #asm("wdr"); } } но вот так в отладчике в прицепе 300 кил Нифига не понимаю совсем, нашел старый проект, он на AT90s8535 - кусок подобный, все работает, чувствую, что просто туплю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aesok 0 25 апреля, 2007 Опубликовано 25 апреля, 2007 · Жалоба Проанализируйте окошко "Call stack" и вот эту строку вашей программы: TIMSK=0x3; Анатолий. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dedded 0 25 апреля, 2007 Опубликовано 25 апреля, 2007 · Жалоба Проанализируйте окошко "Call stack" и вот эту строку вашей программы: TIMSK=0x3; Анатолий. TIMSK=0x1 решило все проблемы, всем спасибо за участие, особое - Анатолию, просто заработался уже, глаза мимо смотрели :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GDI 0 25 апреля, 2007 Опубликовано 25 апреля, 2007 · Жалоба TCCR0 = 0x00; //stop TCNT0 = step; //set count TCCR0 = 0x05; //start timer Зачем это в главном цикле? вынесите за while(1) чтоб один раз при запуске это работало step_kol сделайте int-ом Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dedded 0 25 апреля, 2007 Опубликовано 25 апреля, 2007 · Жалоба TCCR0 = 0x00; //stop TCNT0 = step; //set count TCCR0 = 0x05; //start timer Зачем это в главном цикле? вынесите за while(1) чтоб один раз при запуске это работало step_kol сделайте int-ом да в самой проге нет цикла - это я для отладки состряпал, чтобы себе наглядней было, да и вам потом показал. косяк был - поднял флаги и по переполнению и по совпадению а step_kol - большой потому что шагов может быть много, а сколько много - еще не известно пора отдыхать сегодня, завершить ответ этот пытался по SHIFT-F9 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться