Страница 1 из 1

Помогите с таймером

Добавлено: Чт фев 05, 2009 05:31:12
rush
Возможно ли реализовать таймер на тини13? Надо чтобы в еепром писалось время с момента включения контроллера в формате типа ЧЧ:ММ:СС. Нашел много исходников, но они на асме и под другие контроллеры. так и не смог разобраться так как асма не знаю :( Может есть у кого нибудь примеры на С. Буду очень благодарен :)

Добавлено: Чт фев 05, 2009 14:53:42
Krik99
Алгоритм прост. Настраиваеш тайме чтобы тикал с частотой в одну секунду, потом от него начинаеш считать минуты, часы , дни и т.д. Создаёш в eeprom три переменные и записуеш сравниваемое значения, когда значения совпадают, зажигаеш светодиод к примеру.

Добавлено: Пт фев 06, 2009 00:12:02
rush
А как таймер настроить чтоб так тикал не подскажешь? :)

Добавлено: Пт фев 06, 2009 02:22:15
Тарас
Привет, вот здесь посмотри :)
http://my-avr.at.ua/publ/1-1-0-17

Добавлено: Пт фев 06, 2009 08:40:27
rush
этот мануал неподходит. если я все правильно понял то clock value можно выставить любой. дальше надо поставить в "compare A" частоту выбранную в "clock value" в 16-ричном виде. и вот тут проблема. число у меня получилось F42, а написать туда можно только 2 символа. И как я понял тини будет выходить раз в секунду из спящего режима чтобы обработать прерывание по таймеру. мне бы этого не хотелось :)) можно как-нибудь подругому сделать?

Добавлено: Пт фев 06, 2009 13:51:23
Krik99
Вот небольшой FAQ.

Настройка таймера.

У таймера есть счётчик "Prescaler" который делит тактовую частоту МК. Произвольное значение счётчика задать нельзя, есть только фиксированые: Fclk/8; Fclk/64; Fclk/256; Fclk/1024;
Если использовать таймер 0, то он может делить, максимум, на 256. Ели таймер1, то можно делить уже на 65536.
Пример настройки таймера для часов, при частоте МК 4мгц., и тикание с частотой 1раз в секунду.
Воспользуемся такими подщётами:
4 000 000 / 256 = 15625 Гц

Где:
4 000 000 - тактовая частота МК
256 - прескалер, взят из таблицы допустимых значений
15625 - конечное значение частоты прерывания
Конечное значение частоты надо подобрать так чтобы после подщётов выходтло целое число без десятичных, иначе будет большая погрешность.

Также надо загнать таймер в режим "Clear Timer on Compare Match (CTC) Mode" и в регистр сравнения
(Output Compare Register) прописать 15625. И некаких ошибок в сутки! :)

Код (писался для тини2313, думаю переписать не составит труда):
// установка режимов и прескалера
TCCR1A=0x00;
TCCR1B=0x0C;
// загрузка регистра сравнения
OCR1A=15625;
// разрешаем прерывания по совпадению с регистром сравнения
TIMSK=0x40;

Добавлено: Пт фев 06, 2009 15:11:09
sachok
Я наверное покажусь наглым:) но можете показать расчет для кварца 11,0592МГц что бы тоже тикало 1 раз в секунду. таймер0 восьми битный. нужно что бы прерывание вызывались приблизительно 1 раз в секунду дальше я считать их количество умею. :)

Добавлено: Пт фев 06, 2009 17:39:53
Krik99
sachok писал(а):Я наверное покажусь наглым:) но можете показать расчет для кварца 11,0592МГц что бы тоже тикало 1 раз в секунду. таймер0 восьми битный. нужно что бы прерывание вызывались приблизительно 1 раз в секунду дальше я считать их количество умею. :)
Да что там считать ?! :)

11 059 200 / 256 = 43200

Если нечего не напутал, должно получиться типа того (для тини2313):

// Timer/Counter 0 initialization
// Clock value: 43,200 kHz
// Mode: CTC top=OCR0A
TCCR0A=0x02;
TCCR0B=0x04;

OCR0A=43200;

TIMSK=0x02;

Добавлено: Сб фев 07, 2009 12:05:45
smac
Krik99 писал(а): Если нечего не напутал, должно получиться типа того (для тини2313)...
Напутали, в tiny2313 Timer0 - восьмибитный, соответсвенно в OCR0A 43200 ничего не запишется, в данном случае следует либо увеличить делитель либо использовать Timer1.

Добавлено: Сб фев 07, 2009 23:46:45
sachok
Господа проверьте меня пожалуйста!!! Нужно настроить таймер0 (восьмибитный) так что бы от делал прерывание с частотой в 50Гц - 50раз в секунду. Тактовая частота контролера - 11,0592МГц используя предделитель на 1024 получаем частоту работы таймера - 10,8кГц. Я считал в ICCAVR и у меня вышло такое значение регистра -

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

TCNT0=0x28;
. Прошу Вас проверьте правильность моих и программных расчетов всё ли правильно.

Добавлено: Вс фев 08, 2009 00:05:15
smac
sachok писал(а):Господа проверьте меня пожалуйста!!! Нужно настроить таймер0 (восьмибитный) так что бы от делал прерывание с частотой в 50Гц - 50раз в секунду. Тактовая частота контролера - 11,0592МГц используя предделитель на 1024 получаем частоту работы таймера - 10,8кГц. Я считал в ICCAVR и у меня вышло такое значение регистра -

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

TCNT0=0x28;
. Прошу Вас проверьте правильность моих и программных расчетов всё ли правильно.
Расчеты правильные, но я бы рекомендовал Вам использовать режим CTC и записать в регстр сравнения число 0xD7.

Добавлено: Вс фев 08, 2009 00:08:50
sachok
Ну там кажись ровненько выходит, а в общем мне супер точность не нужна это не часы:) СПАСИБО!!!

Добавлено: Вс фев 08, 2009 06:12:29
rush
Всеравно не получается :( Частота у меня 4мгц. Делитель 1024. Получается: 4000000/1024=3906. И как мне это 3906 записать, если таймер восьмибитный, а 1024 это максимальный делитель?

Добавлено: Вс фев 08, 2009 10:55:08
Pippeytz
А зачем щитать прерывания по перполнению таймера от тактового генератора, если можно прицепить на щетные вывода щетчиков часовой кварц на ~32кгц , поставить коэф деления 128 , и ты получиш ровно 1 прерывание в секунду, дльаше наращиваеш переменные в нужном формате и запихиваеш их в EEPROM

Добавлено: Вс фев 08, 2009 22:09:46
smac
Pippeytz писал(а):А зачем щитать прерывания по перполнению таймера от тактового генератора, если можно прицепить на щетные вывода щетчиков часовой кварц на ~32кгц , поставить коэф деления 128 , и ты получиш ровно 1 прерывание в секунду, дльаше наращиваеш переменные в нужном формате и запихиваеш их в EEPROM
Если вы отвечали предыдущему оратору, то не можно, поскольку у него тини2313, к счетным выходам которой нельзя просто так прицепить часовой кварц, нужно как минимум сделать генератор.
rush писал(а):Всеравно не получается Sad Частота у меня 4мгц. Делитель 1024. Получается: 4000000/1024=3906. И как мне это 3906 записать, если таймер восьмибитный, а 1024 это максимальный делитель ?
Один из выходов использовать timer1 - он 16-ти битный,
второй выход - в прерывании по переполнению timer1 декрементировать переменную, как только она будет равна 0, записывать в нее новое значение и выставлять флаг- секунда прошла.
Рассчет начального значения переменной 4 000 000 (тактовая частота)/(1024(делитель)*256(переполнение таймера))=15,258 поскольку значение не целое, то будет набегать довольно приличная погрешность
третий выход (для уменьшения погрешности) - использование режима сброса таймера по совпадению с регистром сравнения (Clear Tiner on Compare). Подобно второму способу организуем переменную счетчик, но не в прерывании по переполнению а в прерывании по совпадению таймера с регистром сравнения.
Методика расчета значения OCR0A (или OCR0B) - Нужно так выбрать делители чтобы при делении тактовой частоты получались целые числа
4 000 000 (тактовая частота)/(256(делитель) = 15625
Теперь нужно подобрать число, такое, чтобы при делени 15625 на него получалось бы целове число, второе условие - число должно быть не больше 255, и желательно не очень маленкое, ну например
125 - это будет значение, которое мы будем записывать в регистр OCR0A
Итак получаем значение декрементируемого счетчика, который нужно организовать в прерывании по совпадению таймера с регистром OCR0A
4 000 000 (тактовая частота)/(256(делитель)/125(Значение OCR0A)=125. Теперь в прерывании нужно сделать примерно так
код немного исправлен с момента первого редактирования.

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

...
if (--soft_presc==0){
     soft_presc=125;
     flag1sek=1; // выставить флаг что прошла секунда - обработать можно в лучше в майне, имо прерывание должно быть коротким
}
                       // хотя можно здесь увеличивать значения счетчиков секунд, минут и т.д.
...
к сожалению я плохо разбираюсь в C (надеюсь пока), поэтому не могу сказать какие квалификаторы нужны переменной soft_presc, но она должна сохраняться от прерывания к преныванию, т. е. по идее должна быть внешней, а значит объявленной до майн, переменная flag1sek должна быть с квалификатором volatile т. е. может изменяться непонятным для компилятора образом (в прерываниях). В общем пусть меня более знающие товарищи поправят

Добавлено: Пн фев 09, 2009 05:04:31
rush
smac, спасибо огромное. наконецто я допер :))

Добавлено: Пн фев 09, 2009 09:43:29
Bird55
Есть отличный on-line ресурс, который позволяет 2-3 "кликами" мышки получить необходимый для программирования таймера кусок код. С этого же сайта доступен AvrWiz - a little code generation wizard for Atmel-AVR. Причем, что мне особенно понравилось, так это то, что все это заточено под WinAVR.

Добавлено: Пн фев 09, 2009 12:38:53
smac
Bird55 писал(а):Есть отличный on-line ресурс, который позволяет 2-3 "кликами" мышки получить необходимый для программирования таймера кусок код. ...
Категорически против код-визардов, не добавляет понимания работы таймера и из-за этого появляются вопросы, подобные предыдущему, причем таких вопросов тьма.

Добавлено: Вс фев 15, 2009 04:11:57
smac
smac писал(а): Итак получаем значение декрементируемого счетчика, который нужно организовать в прерывании по совпадению таймера с регистром OCR0A
4 000 000 (тактовая частота)/(256(делитель)/125(Значение OCR0A)=125.
Прошу у всех прощения, ошибочка вышла, в OCR0A нужно записывать не 125 а 124, формулу приведенную в процитированном посте нужно читать как
4 000 000 (тактовая частота)/(256(делитель)/125(Значение OCR0A +1)=125