реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Прерывание по таймеру - поможите, после срабатывания прерывания возврат не на то место
dedded
сообщение Apr 25 2007, 07:45
Сообщение #1


Участник
*

Группа: Свой
Сообщений: 35
Регистрация: 28-01-06
Из: Ванино
Пользователь №: 13 712



Ребят, в большом проекте попался кусок, над которым я уже туплю. Среда 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); сюда не доходит
}
}

кусок выдрал аккуратно вроде, точнее заново оформил
что же я не так делаю?
Go to the top of the page
 
+Quote Post
arttab
сообщение Apr 25 2007, 08:56
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 432
Регистрация: 7-12-04
Из: Новосибирск
Пользователь №: 1 371



перед заносом в TCNT0 таймер не остановлен. это может повлиять на работу таймера.
а если возврат идет не туда откуда был переход, надо стек проверить. не переполняется ли он.


--------------------
OrCAD, Altium,IAR, AVR....
Go to the top of the page
 
+Quote Post
Валентиныч
сообщение Apr 25 2007, 09:38
Сообщение #3


Профессионал
****

Группа: Свой
Сообщений: 553
Регистрация: 17-02-05
Из: Свердловская обл.
Пользователь №: 2 712



Цитата(arttab @ Apr 25 2007, 11:56) *
перед заносом в TCNT0 таймер не остановлен. это может повлиять на работу таймера. а если возврат идет не туда откуда был переход, надо стек проверить. не переполняется ли он.

И при входе/выходе в/из прерывание сохранять/восстанавливать программный счетчик.


--------------------
Закономерность: Чем больше узнаю, тем меньше знаю...
Любые мнения, даже ошибочные, имеют право на существование.
Чем лучше узнаю людей, тем больше нравятся собаки...
Go to the top of the page
 
+Quote Post
GDI
сообщение Apr 25 2007, 10:21
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



Кусок кода приведенный автором написан криво, очень криво, но я спишу это на трудности переноса сути вопроса из большого проекта smile.gif
А вот что я заметил:
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 секунд, но данный кусок этого просто не может обеспечить.


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
tag
сообщение Apr 25 2007, 10:27
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 151
Регистрация: 21-02-06
Пользователь №: 14 561



Цитата(dedded @ Apr 25 2007, 07:45) *
кусок выдрал аккуратно вроде, точнее заново оформил
что же я не так делаю?


...в глаза бросается использование watchdog-а, нет явной настройки (а по умолчанию он не запущен) и вдруг он стартуется #asm(wdr) ... а затем пауза вставлена delay_ms(5000); довольно продолжительная...может быть проблема в этом?
Go to the top of the page
 
+Quote Post
Snaky
сообщение Apr 25 2007, 10:48
Сообщение #6


Mute Beholder
***

Группа: Свой
Сообщений: 260
Регистрация: 4-04-07
Из: Третья планета от Солнца
Пользователь №: 26 754



Цитата(GDI @ Apr 25 2007, 13:21) *
3) далее зачем то ждем 1000 циклов таймера чтобы сбросить WatchDog.

он не ждет - он его сбрасывает 1000 раз пока ste_kol не накопит до 1000 smile.gif
Хотя код и кривой, но проблема скорее всего в инициализации 8 битного регистра значением 0x100, как ты заметил.

P.S. Кстати, PC-Lint такие ошибки легко отлавливает, а компиляторы игнорируют.


--------------------
Common sense is not so common.
Go to the top of the page
 
+Quote Post
dedded
сообщение Apr 25 2007, 11:28
Сообщение #7


Участник
*

Группа: Свой
Сообщений: 35
Регистрация: 28-01-06
Из: Ванино
Пользователь №: 13 712



Отвечу сразу всем: написано действительно криво, потому как весь код сюда ложить смысла нет. просто по быстрой оформил проектик с этим злополучным куском, чтобы сюда положить.
Задача общая, - сформировать посылку № на ногу, тут 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 раз должен отработать( в данном случае) после этого паузы и прочее.
До пауз дело не доходит
Стек переполняется


Цитата(Валентиныч @ Apr 25 2007, 17:38) *
И при входе/выходе в/из прерывание сохранять/восстанавливать программный счетчик.

Глупый , наверное , вопрос - а CVAVR это не делает? можете бросать в меня гнилыми апельсинами

Цитата(GDI @ Apr 25 2007, 18:21) *
Кусок кода приведенный автором написан криво, очень криво, но я спишу это на трудности переноса сути вопроса из большого проекта smile.gif
А вот что я заметил:

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 сек - это с запасом, чтобы в эмуляторе картинка была

а после выполнения прерывания - чаще всего начинает работать сначала проги, но в проекте - не с начала, т.е не сброс, но с достаточно конкретного места
Go to the top of the page
 
+Quote Post
Валентиныч
сообщение Apr 25 2007, 11:31
Сообщение #8


Профессионал
****

Группа: Свой
Сообщений: 553
Регистрация: 17-02-05
Из: Свердловская обл.
Пользователь №: 2 712



Цитата(dedded @ Apr 25 2007, 14:28) *
Глупый , наверное , вопрос - а CVAVR это не делает? можете бросать в меня гнилыми апельсинами

Не знаю... Работаю в другой среде. Поэтому и предположил.


--------------------
Закономерность: Чем больше узнаю, тем меньше знаю...
Любые мнения, даже ошибочные, имеют право на существование.
Чем лучше узнаю людей, тем больше нравятся собаки...
Go to the top of the page
 
+Quote Post
dedded
сообщение Apr 25 2007, 11:54
Сообщение #9


Участник
*

Группа: Свой
Сообщений: 35
Регистрация: 28-01-06
Из: Ванино
Пользователь №: 13 712



Цитата(Валентиныч @ Apr 25 2007, 19:31) *
Не знаю... Работаю в другой среде. Поэтому и предположил.


Предположение смахивает на правду, кста, алгоритм брал из когда - то работающего проекта. Тот писался тоже на CVAVR только какой-то ранней версии. Ребят, у кого есть - CVAVR 1.25 и VMLAB проверьте, плиз. что-то я читал у них на сайте насчет работы с лицензией, сделанной кейгеном. Кто-то же выложил это на фтп. Ну и еще вопрос - купить то есть где CVAVR? Поиск результатов не дал.

Цитата(tag @ Apr 25 2007, 18:27) *
...в глаза бросается использование watchdog-а, нет явной настройки (а по умолчанию он не запущен) и вдруг он стартуется #asm(wdr) ... а затем пауза вставлена delay_ms(5000); довольно продолжительная...может быть проблема в этом?

да, тут маленько неправильно, WD срабатывает каждые 2 секунды, в это месте он конечно сработает, но он не доходит до этого места. Правильнее конечно время задержки поставить 1.8 секунды, только проблема балин не тут.
Go to the top of the page
 
+Quote Post
GDI
сообщение Apr 25 2007, 12:02
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



step все равно лучше сделать char или const char или вообще #define STEP 0x10 чтоб память не занимать.
инит таймера из главного цикла убрать - поставить ДО while(1)
delay_ms(5000) заменить на delay_ms(1000), но поставить 5 раз а между ними разместить сброс Сторожевого таймера
Перед делеями запретить прерывания от таймера - после делеев - разрешить.
Стек увеличить - может где то в другом месте он переполняется.


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
dedded
сообщение Apr 25 2007, 12:15
Сообщение #11


Участник
*

Группа: Свой
Сообщений: 35
Регистрация: 28-01-06
Из: Ванино
Пользователь №: 13 712



Цитата(GDI @ Apr 25 2007, 20:02) *
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 - кусок подобный, все работает, чувствую, что просто туплю.
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
aesok
сообщение Apr 25 2007, 12:33
Сообщение #12


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Проанализируйте окошко "Call stack" и вот эту строку вашей программы:

TIMSK=0x3;

Анатолий.
Go to the top of the page
 
+Quote Post
dedded
сообщение Apr 25 2007, 12:52
Сообщение #13


Участник
*

Группа: Свой
Сообщений: 35
Регистрация: 28-01-06
Из: Ванино
Пользователь №: 13 712



Цитата(aesok @ Apr 25 2007, 20:33) *
Проанализируйте окошко "Call stack" и вот эту строку вашей программы:

TIMSK=0x3;

Анатолий.


TIMSK=0x1 решило все проблемы, всем спасибо за участие, особое - Анатолию, просто заработался уже, глаза мимо смотрели smile.gif
Go to the top of the page
 
+Quote Post
GDI
сообщение Apr 25 2007, 12:57
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



TCCR0 = 0x00; //stop
TCNT0 = step; //set count
TCCR0 = 0x05; //start timer
Зачем это в главном цикле? вынесите за while(1) чтоб один раз при запуске это работало

step_kol сделайте int-ом


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
dedded
сообщение Apr 25 2007, 13:08
Сообщение #15


Участник
*

Группа: Свой
Сообщений: 35
Регистрация: 28-01-06
Из: Ванино
Пользователь №: 13 712



Цитата(GDI @ Apr 25 2007, 20:57) *
TCCR0 = 0x00; //stop
TCNT0 = step; //set count
TCCR0 = 0x05; //start timer
Зачем это в главном цикле? вынесите за while(1) чтоб один раз при запуске это работало

step_kol сделайте int-ом


да в самой проге нет цикла - это я для отладки состряпал, чтобы себе наглядней было, да и вам потом показал.
косяк был - поднял флаги и по переполнению и по совпадению
а step_kol - большой потому что шагов может быть много, а сколько много - еще не известно

пора отдыхать сегодня, завершить ответ этот пытался по SHIFT-F9
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 18:26
Рейтинг@Mail.ru


Страница сгенерированна за 0.01495 секунд с 7
ELECTRONIX ©2004-2016