Таймеры/счётчики в AVR

Обсуждаем контроллеры компании Atmel.
kotriks
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Re: Таймеры/счётчики в AVR

Сообщение kotriks »

COKPOWEHEU писал(а):
OCR2A = 0x1E85;
А ничего что у m168 таймер T2 восьмибитный?
Да и остальная логика на первый взгляд странная.
TCCR2A |= (1 << WGM21);
Чему равны остальные биты этого регистра? Лучше при настройке делать прямое присваивание.
TCCR2B |= (1 << CS21); делитель F_CPU/8 = 125 кГц
OCR2A = 0x1E85; если предположить, что этот регистр 16-битный, делитель равен 7814
Тогда прерывание возникает с частотой F_CPU/8/7814 = 16 Гц, то есть с интервалом 62,5 мс.

делаю так

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

TCCR2A = (1<<WGM21);    // Режим CTC (сброс по совпадению)
//TCCR2B = (1<<CS20);     // Тактирование от CLK.
TCCR2B = (1<<CS20)|(1<<CS21)|(1<<CS22);                         // Если нужен предделитель :
// TCCR2B = (1<<CS21);                     // CLK/8
// TCCR2B = (1<<CS20)|(1<<CS21);           // CLK/32
// TCCR2B = (1<<CS22);                     // CLK/64
// TCCR2B = (1<<CS20)|(1<<CS22);           // CLK/128
// TCCR2B = (1<<CS21)|(1<<CS22);           // CLK/256
// TCCR2B = (1<<CS20)|(1<<CS21)|(1<<CS22); // CLK/1024

OCR2A = 255;            // Верхняя граница счета. Диапазон от 0 до 255.
                        // Частота прерываний будет = Fclk/(N*(1+OCR2A))
                        // где N - коэф. предделителя (1, 8, 32, 64, 128, 256 или 1024)
TIMSK2 = (1<<OCIE2A);   // Разрешить прерывание по совпадению

срабатывает через секунду ((
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Таймеры/счётчики в AVR

Сообщение COKPOWEHEU »

Через секунду?! Должно быть через четверть секунды. Если нужна какая-то точность, настройте предделитель на 1:64, модуль счета на 125, тогда частота прерываний будет 125 Гц, дальше программно.
kotriks
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Re: Таймеры/счётчики в AVR

Сообщение kotriks »

Разобрался

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

TCNT1H=0xA473 >> 8;
TCNT1L=0xA473 & 0xff;

TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (1<<CS12) | (0<<CS11) | (0<<CS10);
TCNT1H=0xA4;
TCNT1L=0x73;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;


interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
соде();
 
}

TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (1<<TOIE1);

Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Таймеры/счётчики в AVR

Сообщение COKPOWEHEU »

TCNT1H=0xA473 >> 8;
TCNT1L=0xA473 & 0xff;
Извращение. У Т1 так же как у Т2 есть режим CTC, то есть можно не дергать TCNT1 в каждом прерывании (что вы и так не делаете, как оно у вас тогда работает?).

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

OCR1A = 15624; //F_CPU/64-1  //здесь лучше десятичная запись, а еще лучше - формула
TCCR1B = (1<<WGM12 | 0b011<<CS10); //CTC-mode ; F_CPU/64
TIMSK = (1<<OCIE1A);
kotriks
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Re: Таймеры/счётчики в AVR

Сообщение kotriks »

Не знаю как но работает :))
kotriks
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Re: Таймеры/счётчики в AVR

Сообщение kotriks »

COKPOWEHEU писал(а):
TCNT1H=0xA473 >> 8;
TCNT1L=0xA473 & 0xff;
Извращение. У Т1 так же как у Т2 есть режим CTC, то есть можно не дергать TCNT1 в каждом прерывании (что вы и так не делаете, как оно у вас тогда работает?).

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

OCR1A = 15624; //F_CPU/64-1  //здесь лучше десятичная запись, а еще лучше - формула
TCCR1B = (1<<WGM12 | 0b011<<CS10); //CTC-mode ; F_CPU/64
TIMSK = (1<<OCIE1A);

ошибочка, достаточно этого

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

TCCR1B=(1<<CS12);
TCNT1H=0xA4;
TCNT1L=0x73;
Аватара пользователя
mixon46
Говорящий с текстолитом
Сообщения: 1644
Зарегистрирован: Сб фев 18, 2012 15:42:29
Откуда: Курск

Re: Таймеры/счётчики в AVR

Сообщение mixon46 »

хочу сделать часы. САМ :) . к МК тини 2313 подключить кварц 32.768 гц. подать сигнал на 16 битный таймер. в регистре сравнения пропишу 32768. по сравнению вызвать прерывание что бы записать следующую секунду в переменную unsigned int. по расчетам ее хватит что бы показывать время в 12 часов. на 24 часа не хватит. мне как организовать сброс таймера? прям в прерывании. или можно как то по совпадению с регистром сравнения произвести сброс. потому что если я в прерывании буду сбрасывать то таймер же уже пойдет считать дальше чем 32768. или как :facepalm:

все он сбросится я понял :)) ну нуб точно
в режиме СТС он сбросится по совпадению точняк
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Таймеры/счётчики в AVR

Сообщение akl »

Замечу. У tiny2313 нет режима работы с часовым кварцем. Даже если удастся получить генерацию от кварца 32'768, контроллер будет шагать по программе именно с такой частотой. Быстродействия наверняка не хватит .
Аватара пользователя
Z_h_e
Собутыльник Кота
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Re: Таймеры/счётчики в AVR

Сообщение Z_h_e »

Ну можно собрать внешний генератор с нужной частотой и уровнем сигнала и подать ее на вход T1 (PD5). Она же выход таймера 0 OC0B, это тоже можно как то использовать (объединить счетчики).
Можно затактировать МК кварцем 3.2768МГц, не знаю есть такие в продаже или нет. В инете попадались упоминания.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Аватара пользователя
mixon46
Говорящий с текстолитом
Сообщения: 1644
Зарегистрирован: Сб фев 18, 2012 15:42:29
Откуда: Курск

Re: Таймеры/счётчики в AVR

Сообщение mixon46 »

ну я тогда соберу на обычной кмоп логике генератор. подам на вход счетчика. а сам МК пусть работает от внутреннего RC на частоте 8 мгЦ.


Я подумал а что я буду страдать ерундой. делать генератор. возьму кварц на 4 Мгц и через делитель 64 как раз четное подам на вход таймера. как раз 62500 тиков входит в 16 битный регистр таймера.
Аватара пользователя
Z_h_e
Собутыльник Кота
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Re: Таймеры/счётчики в AVR

Сообщение Z_h_e »

mixon46 писал(а):Я подумал а что я буду страдать ерундой.
Раз у Вас, оказывается, нет ограничений по частоте, лучше уж тогда кварц на 20МГц. Используйте МК по быстродействию по максимуму. Ну или хотя бы 16МГц, если 20 не получится точно разделить до секунды.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Аватара пользователя
mixon46
Говорящий с текстолитом
Сообщения: 1644
Зарегистрирован: Сб фев 18, 2012 15:42:29
Откуда: Курск

Re: Таймеры/счётчики в AVR

Сообщение mixon46 »

а зачем мне такое большое быстродействие. мне нужно просто часы :)
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Таймеры/счётчики в AVR

Сообщение Jack_A »

Ну если делать часы на МК, а не на жесткой логике, значит, в МК будет программа :) , и вопрос частоты кварца - не вопрос вовсе. Можно сделать начальную настройку на чуть более "быстрый" ход - 5...10с в сутки. А в программе предусмотреть периодическое - раз в несколько десятков минут - "выкусывание" лишней доли секунды. Поэтому кварц можно ставить любой, не заморачиваясь его кратностью. А изменяя интервал этого "выкусывания", осуществляем цифровую подстройку точности хода. Так сделано в наручных часах фирмы Интеграл ( я схемы не видел, но думаю, по логике - так ) .
Изображение
Вложения
N-1.JPG
(5.5 КБ) 1058 скачиваний
Изображение
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Таймеры/счётчики в AVR

Сообщение akl »

mixon46 писал(а):а зачем мне такое большое быстродействие...
Всё равно понадобится какая-то индикация; точность хода часов с кварцем выше чем с "часовыми". Ну и вообще часы на ATtiny2313 c любым, в допустимом диапазоне, кварцем делаются на одном таймере Т1. Пример ниже.
Вложения
freq_8MHz 001_1.jpg
(25.61 КБ) 630 скачиваний
CLOCK_FULL.rar
(49.64 КБ) 206 скачиваний
Последний раз редактировалось akl Пт сен 23, 2016 00:52:28, всего редактировалось 1 раз.
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Таймеры/счётчики в AVR

Сообщение Jack_A »

Да кто спорит ? А не совсем понял - индикация чего ? Раз это часы, то индикация у них присутствует по определению. А индикация состояния корректора точности хода - можно, как в наручных часах, загнать ее в отдельный пункт менюшки. Можно и по другому - например, при настройке записать константу в EEPROM - я не думаю, что ее придется часто менять. И наконец - цифровая коррекция точности хода делается все на том же одном таймере Т1 :) - десяток добавочных строк в обработчике.
Изображение
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Таймеры/счётчики в AVR

Сообщение akl »

mixon46 писал(а):...возьму кварц на 4 Мгц и через делитель 64 как раз четное подам на вход таймера. как раз 62500 тиков входит в 16 битный регистр таймера.
Типовое и очень хреновое решение. Реалии таковы, что кварц с надписью 4МГц совсем не обязан иметь частоту 4'000'000Гц. К примеру, частота генерации системы кварц-контроллер 4'009'543Гц будучи поделенной на 64/62500 даст период 997 619,93мкс ну очень мало напоминающий 1 секунду. Вскакивает необходимость в цифровом корректоре, состояние которого нужно как-то устанавливать; где-то хранить. Значит нужно меню, что сразу выбрасывает часы из разряда "простых". В программе, приведённой выше, нужно просто записать 4009543 и, в течение полугода, быть пунктуальным с точностью до 1 секунды.
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Таймеры/счётчики в AVR

Сообщение Jack_A »

Если бы мне пришла блажь делать часы ( как проект - это неинтересно, как способ сэкономить вместо покупки 2..3$ - это несерьезно ), я бы цифровой корректор делал в виде 5..6 джамперов, задающих 32..64 ступени коррекции с шагом, к примеру 100мс в сутки. На Тиньке, конечно, не получится - нужны дополнительные пины - но у меня на антресоли для такого случая завалялось бы пару Мегов-32 :) И менюшка не понадобилась бы.
Ну а 9 kHz (0,2%) отклонение от номинала для 4MHz-вого кварца - это вроде многовато на пару порядков. :( Что ж это за кварц ?
Изображение
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Таймеры/счётчики в AVR

Сообщение akl »

Написал же, к примеру. :) Чтобы пример был более убедителен симулировал в студии один из вариантов часов с таким кварцем, показывающий что без джамперов цифровой коррекции на ATtiny2313 можно сделать простые точные часы на любом кварце.
Изображение
Аватара пользователя
mixon46
Говорящий с текстолитом
Сообщения: 1644
Зарегистрирован: Сб фев 18, 2012 15:42:29
Откуда: Курск

Re: Таймеры/счётчики в AVR

Сообщение mixon46 »

сейчас не о точности. думаю как реализовать динамическую индикацию. мне не помогать! сам уже почти придумал. :)


все сдаюсь что то не получается :))
Спойлер#include <tiny2313.h>
#include <delay.h>

unsigned int se; //объявление глобальной переменной
//для хранения времени
flash unsigned char digits [10] =
{0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111 // 9
};

interrupt [TIM1_COMPA] void sec (void)//вызов прерывания по совпадению
{
se++; //прибавление единицы каждую секунду в регистр se
if (se==43200) //проверка регистра на истинность
{se=0;}; //обнуление регистра
if (PIND.6==0) //опрос кнопки
{delay_ms (3); //задержка анти дребезга
se=se+600; //прибавление 10 мин к регистру se
}
}

void main(void)
{
unsigned int discharge [6] = {4,4,4,0,0,0};

PORTB=0x00;
DDRB=0xFF;

PORTD=0b01000000;
DDRD=0b00111111;

TCCR1A=0x00; //регистр настройки таймера
TCCR1B=(1<<WGM12)|(0<<CS12)|(1<<CS11)|(1<<CS10); //режим СТС делитель 64
TCNT1H=0x00; // старший счетный регистр
TCNT1L=0x00; //младший счетный регистр
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0xF4; // старший регистр сравнения А
OCR1AL=0x24; // младший регистр сравнения А или 62500 импульсов
OCR1BH=0x00;
OCR1BL=0x00;

GIMSK=0x00;
MCUCR=0x00;

TIMSK=(1<<OCIE1A); //прерывание по совпадению TCNT1 и OCR1A

USICR=0x00;

UCSRB=0x00;

ACSR=0x80;
DIDR=0x00;

while (1)
{#asm ("sei"); //глобальное разрешение прерывания
discharge [0]=se/36000; //запись десятков часов разряда в ячейку 1
discharge [1]=se%36000/3600; //запись единиц часов разряда в ячейку 2
discharge [2]=se%3600/600; //запись десятков минут разряда в ячейку 3
discharge [3]=se%600/60; //запись единиц минут разряда в ячейку 4
discharge [4]=se%60/10; //запись десятков секунд разряда в ячейку 5
discharge [5]=se%10; //запись единиц секунд в ячейку 6
PORTB=digits[discharge[0]]; //вывод цифры в порт B
PORTD=0b01100000;
delay_ms(3);
PORTB=digits[discharge[1]];
PORTD=0b01010000;
delay_ms(3);
PORTB=digits[discharge[2]];
PORTD=0b01001000;
delay_ms(3);
PORTB=digits[discharge[3]];
PORTD=0b01000100;
delay_ms(3);
PORTB=digits[discharge[4]];
PORTD=0b01000010;
delay_ms(3);
PORTB=digits[discharge[5]];
PORTD=0b01000001;
delay_ms(3);


}
}

помогите а то совсем не показывает как надо :)

ну вроде работает. правда протеус кривоват
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Таймеры/счётчики в AVR

Сообщение akl »

Не нравится отсутствие синхронности между отсчетом 1 секунды и выводом на индикатор. В часах должно быть всё синхронно.
Например
- 6 индикаторов полноразмерных часов
- длительность индикации каждого разряда 1'600мкс
- период индикации всех индикаторов 6*1'600мкс=9'600мкс, что составляет 1'000'000/9600~104Гц
- в регистр сравнения таймера при предделителе 64 записано 100-1
- ***число прерываний сравнения таймера 1'000'000/1'600=625, которое заносится в 16-разрядный регистр
- в обработчике производится вывод на следующий по порядку индикатор; определение интервала 1 секунды с помощью 16-разрядного регистра и, если секунда прошла, выход из режима ожидания -> преобразование нового значения времени
- переход на ***
Для большей свободы в выборе кварца таймер переводится в режим работы без предделителя, число 1'600мкс в тиках таймера F_cpu/625-1 заносится в регистр сравнения -> отсчитывается 624 периода индикации, а последнем периоде в регистр сравнения заносится досчет до 1 секунды типа F_cpu-(F_cpu/625)*624-1
Ответить

Вернуться в «AVR»