Форум программистов, компьютерный форум, киберфорум
Электроника для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.77/26: Рейтинг темы: голосов - 26, средняя оценка - 4.77
ormodov1
1

проблема с асинхронным таймером

01.05.2013, 17:56. Просмотров 4867. Ответов 15
Метки нет (Все метки)

Доброго времени суток. Это мой первый проект и во многом я еще не разобрался, помогите пожалуйста разобраться. Требуется сделать устройство, которое замыкает реле в 6:00 часов и размыкает в 00:00 часов. Контроллер mega16A, кварц 8Мгц и часовой кварц 32К. Проблема возникла с асинхронным таймером, часовой кварц не запускается, хотя может не в нем причина.
Очень нужна помощь знающих людей!
Посмотрите код, может в нем что то не так

Код
#ymstude <mega16a.h>
#ymstude <delay.h>
typedef struct{
unsykned char s,m,h;
}time;

time t;
interrupt [TIM2_OVF] void timer2_ovf_isr(void) // Прерырвание по переполнению таймера 2
{
++t.s;
if (t.s==60)
{
t.s=0;
++t.m;
if (t.m==60)
{
t.m=0;
t.s=0;
++t.h;
if (t.h==6)
{
PORTA.4=1;
PORTA.5=1;
PORTA.6=1;
PORTA.7=1;
}
else
if (t.h==24)
{
PORTA.4=0;
PORTA.5=0;
PORTA.6=0;
PORTA.7=0;

t.h=0;
t.m=0;
t.s=0;
}
}
}
}
void main(void)
{
delay_ms(1000);

DDRA = 0xFF;     // Конфигурируем порт A как выход.
PORTA = 0x00;

TCCR2 = 0x00;
ASSR = 0x08;     // Включаем асинхронный режим
TCNT2 = 0;
OCR2 = 0;
TCCR2 = 0x05; // Предделитель на 128 на 32768 даст 256 тиков в секунду
// Что даст 1 прерывание по переполнению в секунду.

TIMSK = 0x45; // Разрешаем прерывания таймера 2

#asm("sei")      // Разрешаем прерывания глобально.
while (1)
{
MCUCR |= (1 << 5); // Разрешаем SLEEP.
#asm("sleep")   // Усыпляем процессор.
MCUCR &= ~(1 << 5); // Запрещаем SLEEP.
TCCR2 = 0x05;

// Ждем готовности таймера (биты TCN0UB, OCR0UB, TCR0UB).
while (ASSR & (1<<TCN2UB | 1<<OCR2UB | TCR2UB));
}
}
фьюзы не трогал, только прочитал, скрин прилогается

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.05.2013, 17:56
Ответы с готовыми решениями:

Проблема с таймером
Почему на Delphi XE4 в &quot;Таймере&quot; не работает следующий код: procedure TForm1.Timer1Timer(Sender:...

Проблема с таймером
Здравствуйте. Вылез подводный камень при работе с таймером. var timer = setTimeout(function...

проблема с таймером 1
написал прогу в которой работает таймер1 в реале не рабоает, почему не понятно #include...

проблема с таймером
Добрый вечер. Начал недавно заниматься программированием микроконтроллеров (использую...

15
0 / 0 / 0
Регистрация: 15.06.2012
Сообщений: 3,097
01.05.2013, 18:46 2
Цитата Сообщение от ormodov1
Посмотрите код, может в нем что то не так
- нигические числа в инициализации регистров
- нет ISR для таймеров 0 и 1, хотя прерывания в TIMSK для них разрешены
- глобальные переменные используемые в ISR надо объявлять как volatile
- ну и самое главное, Timer/Counter2 не работает в Power-down режиме, надо использовать Power-save
0
ormodov1
01.05.2013, 20:14 3
мой топик не спроста находится в ветке "Детские вопросы :)" , мне очень не просто во всем разобраться, и если у вас есть возможность то объясните мне все "на пальцах" что откуда берется, как должно быть и что для этого делать. ну а если нет возможности, то хотябы ткните туда, где все расписано и где можно во всем разобраться. вторую неделю пытаюсь разобраться, пол инета пролез, но так ничего и не получается. мне хоть убейся нужно сделать это устройство, очень прошу помочь мне.
0 / 0 / 0
Регистрация: 15.06.2012
Сообщений: 3,097
01.05.2013, 22:06 4
Я не пользую CodeVision, вот переделанный код под AVR Studyo и gcc, проверил в протеусe - работает.

Код
#ymstude <avr/io.h>
#ymstude <avr/interrupt.h>

// вывод секунд и минут на PA0 для дебага
#defyme DEBUG
#defyme DEBUG_PIN (1<<PA0)

#defyme RELAY_PINS ((1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7))

typedef struct{
unsykned char s,m,h;
}time;

volatile time t;

int main(void)
{
PORTA = ~RELAY_PINS;
DDRA = RELAY_PINS;

#ifdef DEBUG
DDRA |= DEBUG_PIN;
#endif

TCCR2 = (1<<CS22)|(0<<CS21)|(1<<CS20); // делитель на 128
ASSR = (1<<AS2);     // включаем асинхронный режим
TCNT2 = 0; // обнуляем таймер

TIMSK = (1<<TOIE2); // разрешаем прерывания таймера 2

sei();    // разрешаем прерывания глобально

MCUCR |= (0<<SM2)|(1<<SM1)|(1<<SM0); // настраиваем Power-save state
MCUCR |= (1<<SE); //Разрешаем sleep
while (1)
{
asm volatile ("sleep");
}
}

ISR (TIMER2_OVF_vect) // Прерывание по переполнению таймера 2
{

#ifdef DEBUG
PORTA^=DEBUG_PIN;
#endif

++t.s;
if (t.s>=60)
{
#ifdef DEBUG
DDRA^=DEBUG_PIN;
#endif

t.s=0;
++t.m;
if (t.m>=60)
{
t.m=0;
++t.h;
if (t.h==6)
{
PORTA|=RELAY_PINS;
}
else
if (t.h==24)
{
t.h=0;
PORTA&=~RELAY_PINS;
}
}
}
}
0
ormodov1
02.05.2013, 11:59 5
не получается. переделал вывод дебага на PA7 (#defyme DEBUG_PIN (1<<PA7)), чтобы посмотреть будет ли релюшка щелкать. при подачи питания контроллеру реле замыкается и остается в таком положении, при отключении питания размыкается. менял часовой кварц - без изменений.
В чем может быть причина такого поведения?
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
02.05.2013, 14:05 6
Цитата Сообщение от ormodov1
не получается. переделал вывод дебага на PA7 (#defyme DEBUG_PIN (1<<PA7)), чтобы посмотреть будет ли релюшка щелкать. при подачи питания контроллеру реле замыкается и остается в таком положении, при отключении питания размыкается. менял часовой кварц - без изменений.
В чем может быть причина такого поведения?
Для определённости: Вы переделали свой проект полностью под код, данный явертом? Будем считать, что да, т.к. этот код гораздо правильнЕе.

1) Поправьте ошибку дебажного вывода: должно быть не "DDRA ^= DEBUG_PIN;", а "PORTA ^= DEBUG_PIN;".
2) Проверьте, не используется ли где-нибудь по ошибке "PINA" вместо "PORTA". Это разные вещи, и через "PIN" выходными сигналами управлять не получится.
3) На скриншоте с lock&fuse bits у Вас каша (галочки есть как на нулевых, так и на единичных битах, это ymsonsistency!). Надо было перед снятием скриншота прочитать все три байта, а не только последний.
4) Попробуйте временно закомментировать "sleep" (пусть Timer2 тикает в активном режиме) - так работает?
5) Часовой кварц подсоединён правильно? К выводам TOSC1,TOSC2 (PC6,PC7) без конденсаторов?
6) Опять же для определённости: я бы добавил инициализацию структуры time валидными значениями: volatile time t = {0, 0, 0};
0
0 / 0 / 0
Регистрация: 01.02.2010
Сообщений: 2,011
02.05.2013, 14:32 7
Цитата Сообщение от OtyxPM
Проверьте, не используется ли где-нибудь по ошибке "PINA" вместо "PORTA". Это разные вещи, и через "PIN" выходными сигналами управлять не получится.
Почему не получится.....
Вывод байта в порт PINx будет инвертировать те биты порта PORTx, которые установлены в выводимом байте.
Т.е. если надо проинвертировать бит 0 порта B, то надо писать PINB = (1<<0);
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
02.05.2013, 14:36 8
А вообще, асинхронный таймер (настоящий, не симуляция в Протеусе ;-) ) не терпит, когда его дёргают на чтение/запись/перенастройку чаще, чем его собственный ритм 32 кГц. Например, если Таймер2 разбудит систему из состояния power-save, а Вы скомандуете "sleep" раньше, чем через 32 миллисекунды - sleep не сработает. И других таких особенностей в работе с Timer2 много, потому у него и существуют специальные флажки в регистре ASSR.
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
02.05.2013, 14:44 9
Цитата Сообщение от ShodS
Вывод байта в порт PINx будет инвертировать те биты порта PORTx, которые установлены в выводимом байте.
Т.е. если надо проинвертировать бит 0 порта B, то надо писать PINB = (1<<0);
С чего бы это?! Посмотрите диаграмму порта: битовая защёлка PINx.n вообще не связана с PORTx.n, и уж тем более не может делать инверсию.
Все регистры PINx в AVRах - read-only регистры (см.даташит).
0
ormodov1
02.05.2013, 23:51 10
OtyxPM, я свой код не переделывал, а просто скопировал код который написал яверт и в проект AVR Studyo вставил, скомпилировал и прошил контроллер.
поправил ошибку дебажного вывода.
На скриншоте с фьюзами прочитано все. какие они должны быть не знаю, скажите что означает ymsonsistency?.
Кварц подсоединен правильно и без конденсаторов
закомментировал "sleep" и все заработало, а с ним не работает, почему?
ormodov1
03.05.2013, 00:27 11
продолжая эксперементировать поставил задержку _delay_ms(2500) после ASSR = (1<<AS2); включения асинхронного режима, таймер начинает тикать даже со слипом, но через раз, то запускается то нет. что не так, может в самом кварце проблема?
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
03.05.2013, 01:12 12
Цитата Сообщение от ormodov1
продолжая эксперементировать поставил задержку _delay_ms(2500) после ASSR = (1<<AS2); включения асинхронного режима, таймер начинает тикать даже со слипом, но через раз, то запускается то нет. что не так, может в самом кварце проблема?
Я же написал, почемУ.
Ладно, цитирую сам себя (ох, нескромно как) :-)
Цитата Сообщение от OtyxPM
А вообще, асинхронный таймер (настоящий, не симуляция в Протеусе ;-) ) не терпит, когда его дёргают на чтение/запись/перенастройку чаще, чем его собственный ритм 32 кГц. Например, если Таймер2 разбудит систему из состояния power-save, а Вы скомандуете "sleep" раньше, чем через 32 миллисекунды - sleep не сработает. И других таких особенностей в работе с Timer2 много, потому у него и существуют специальные флажки в регистре ASSR.
Не задержки надо ставить, а с флагами правильно работать. В даташите раздел про особенности операций с асинхронным таймером - на полторы страницы. Читайте.
0
0 / 0 / 0
Регистрация: 14.02.2010
Сообщений: 799
03.05.2013, 01:56 13
- нигические числа в инициализации регистров
Ну, это нихера не преступление. Просто дурной тон. Как есть, положив локти на стол.
0
0 / 0 / 0
Регистрация: 15.06.2012
Сообщений: 3,097
03.05.2013, 03:55 14
Цитата Сообщение от OtyxPM
Цитата Сообщение от ShodS
Вывод байта в порт PINx будет инвертировать те биты порта PORTx, которые установлены в выводимом байте.
Т.е. если надо проинвертировать бит 0 порта B, то надо писать PINB = (1<<0);
С чего бы это?! Посмотрите диаграмму порта: битовая защёлка PINx.n вообще не связана с PORTx.n, и уж тем более не может делать инверсию.
Все регистры PINx в AVRах - read-only регистры (см.даташит).
Это фишка есть в более новых avr, например в мега 48/88/168:
14.2.2 Toggling the Pin
Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn.
Note that the SBI instruction can be used to toggle one single bit in a port.
0
ormodov1
03.05.2013, 16:29 15
не получается разобраться с даташитом. в голове каша. сделаю перерыв и собирусь с мыслями. с понедельника продолжу разбираться, после пасхи.
яверт, вам огромное спасибо за помощь с кодом, очень признателен. OtyxPM, спасибо за ценные подсказки
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
03.05.2013, 19:21 16
Цитата Сообщение от ormodov1
не получается разобраться с даташитом. в голове каша.
На всякий случай наводка : прочитать надо главу "17.9 Asynchronous Operation of the Timer/Counter2" в даташите на ATmega16A (Atmelовский doc8154.pdf).
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
03.05.2013, 19:21

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Проблема с таймером =(
Я запускаю таймер в &quot;Form1_load&quot; пытаюсь остановить событии timer1_Tick, но условие не работает,...

Проблема с АПИ-таймером
Чё-то у меня первый раз такая бяка случается. Привык доверять АПИ-решениям гораздо больше, чем...

проблема с таймером и прерыванием
Решил подключить к stm32vldiscovery двухразрядный семисегментный индикатор. Включить отдельно...

ATMega8 проблема с таймером
Вот такой вот косяк... &lt;Изображение удалено&gt; по прерыванию с int0 (сигнал с пульта) получаю...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.