Обсуждаем контроллеры компании Atmel.
Ответить

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

Сб сен 11, 2021 15:35:30

Собирал на днях подобное, для экспериментов. Но я потенциометры повесил на АЦП. Один задаёт скважность, второй меняет коэффициент деления. Естественно, плавной регулировки частоты не получилось, думаю как реализовать..

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

Сб сен 11, 2021 16:25:44

Потенциометр без АЦП конечно работать не будет. Я не упомянул его, потому что он подразумевается по умолчанию.
Я вижу это так:
1) На одном канале АЦП снимаем показания с потенциометра и задаем уровень для сравнения (число для регистра OCRх) по 1-му таймеру в режиме СТС - это для скважности.
2) С другого канала АЦП снимаем уровень сравнения для 2-го таймера в режиме СТС - это для частоты (формирует период).
3) Число из 1 пункта не может быть больше числа из 2 пункта. Ну или может... только это уже не имеет смысла. :) Если брать период (время работы 2-го таймера) за 100%, то не может :)
4) По прерыванию 2-го таймера сбрасываем оба счетчика, включаем высокий уровень на сигнальной ноге и счет начинается сначала (стартуют оба счетчика).
5) По прерыванию 1-го таймера на сигнальной ноге формируется низкий уровень и 1-й таймер останавливается.

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

Сб сен 11, 2021 21:37:01

Kalisnik, в АТмега8 у таймера1 есть режим ШИМ номер 8 и режим номер 14, где период задается регистром ICR1.
поэтому максимальное число равно 65535 (0xFFFF), и частоту можно изменять относительно плавно, изменяя число в этом регистре через 1.
а скважность можно задавать по каналу А в регистре OCR1A.

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

Вс сен 12, 2021 16:31:32

Starichok51, да, так проще. Спасибо!

Добавлено after 7 hours 24 minutes 57 seconds:
Что-то не пойму, почему шим начинает работать с задержкой в 5 сек.?



Добавлено after 1 minute 1 second:
Моделирую в Proteus.

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

Сб ноя 27, 2021 15:12:55

Какой ещё протез? Софт для МК надо отлаживать на МК.

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

Сб дек 04, 2021 21:25:29

mickbell, все верно. На МК задержек не было.

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

Ср апр 27, 2022 22:29:12

опечатка

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

Пн авг 29, 2022 14:33:19

Господа коты, а можно ли как-то заставить таймер (в данном случае ATtiny13) аппаратно генерировать частоту (режимы CTC с переключением выхода или один из режимов PWM с переключением выхода), но при этом воспользоваться прерыванием по переполнению, для отсчета интервалов и задержек?
Проблема еще заключается в том, что мне нужно менять генерируемую частоту по ходу пьесы, соответственно содержимое регистра OCR0A в процессе меняется. И получается, что привязаться вообще не к чему. Т.е. получается таймер в режимах CTC, PWM не считает по кругу, а считает до "отметки" в регистрах OCR0A и OCR0B, причем в последнем значение должно быть меньше чем в первом. Я многого хочу и нужен второй таймер? (менять МК, например на ATtiny25)

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

Пн авг 29, 2022 16:10:36

нет, напрямую не получится, т.к. период таймера нестабилен, но можно сделать немного по другому — использовать прерывание сравнения с оср1а , в котором к 16, 24 или 32 битному аккумулятору прибаввлять значение оср1а+1 и, затем сравнивать с определяющей период величиной, в случае превышения - тикать часами и вычитать из аккумулятора значение этой величины.
конечно, будет небольшой джиттер, но общий ход часов сбиваться не будет

Добавлено after 2 minutes 48 seconds:
ну, и важное замечание - мк должен всё это успевать сделать (например при делителе 1 и значении в оср1а 1 он полюбому не успеет....

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

Пн авг 29, 2022 17:57:44

для отсчета интервалов и задержек?

Ну, для отсчёта интервалов и задержек в таком случае можно использовать и сторожевой таймер… и по его прерыванию производить отсчёт… минимальное время у тини13 это 16 мс, а максимальное 8,2 сек. Так что вполне удобно при необходимости… :)

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

Пн авг 29, 2022 18:25:12

Ivanoff-iv, спасибо за идею, но что-то я не соображу как это сделать. Не хватает опыта...
Вот у меня настройки сейчас такие:
Код:
TCCR0A |=(1<<COM0A0)|(1<<WGM00); // режим Phase Correct PWM с переключением выхода OCR0A (PB0 должен быть настроен как выход)
TCCR0B |=(1<<CS01)|(1<<WGM02); // запуск таймера с соотв. делителем на 8 (1200000/8=150000)
OCR0A = 15; // начальное значение

Значение регистра OCR0A в процессе меняется не сильно от 12 до 20. Чаще всего работа идет на значении 15.
Что надо сделать? Надо включить прерывание по регистру сравнения А.
Код:
TIMSK0 |= (1<<OCIE0A);

Добавить глобальную переменную
Код:
uint32_t accum = 0 ;

И добавить обработчик:
Код:
ISR(TIM0_COMPA_vect)
{
    accum += (OCR0A +1);
    if (accum >= 5) // допустим 5
    действие
    accum -= 5;
}


Добавлено after 14 minutes 57 seconds:
VNS, спасибо за идею, я пробовал. Но словил некоторые глюки.
Судя по ДШ, мне нужно было включить только бит WDTIE, который разрешает просто прерывание без ресета. Возьмем минимальный интервал 16мс, поэтому делитель оставляем по нулям.
Собственно это все, чтобы оно заработало, ну описать обработчик еще в самом коде. В обработчике инкрементирую глобальную переменную. Проверяю в главном цикле когда натикает, натикало - сбрасываю эту переменную и "делаю дело". Но при этом Таимер0 (основной) у меня генерирует некоторую частоту в режиме Phase Correct PWM и вот когда наступает прерывание от WDT появляется какой-то джиттер. Если в обработчик помимо инкремента засунуть что-то еще, становится еще заметнее. Работаю на частоте 1,2МГц. Это первый глюк.
Второй глюк, что бывает после сброса наступает циклический сброс, но не всегда, а как повезет. Видимо я что-то не учитываю с этим WDT.

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

Пн авг 29, 2022 20:16:19

1) частоту я бы поднял, 12х8=96 тактов, конечно, тут хватит, но ведь тиня ещё чтото делает...
2) код правильный, но я бы цифру 5 задефайнил, чтобы при сравнении и при вычитании числа всегда совпадали.
3) 5 для этого места катастрофически мало, т.к. при каждом вызове прерывания в накопитель складывается от 13 до 21.
я бы использовал числа, кратные 256, так если оптимизатор хороший, то он оптимизирует (уберёт) операции с младшим разрядом. (например число 5*256 даст интервал в 5 полных 0—ff оборотов таймера, т.е. 10240 тактов = 117 Гц)
переменную для накопителя не стоит брать с избытком (большей разрядности чем величина с которой он сравнивается), в вашем случае достаточно 16 бит.
—————
у сторожевого таймера нужно после каждой сработки вновь взводить режим прерывания, иначе вторая и последующие сработки вызовут уже не прерывание, а перезагрузку.

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

Пн авг 29, 2022 20:50:52

Да, что-то я совсем запутался.
Когда на асме писал, я там такты высчитывал, а когда на Си перешел, что-то все внимание переключилось на сам язык.
1) Что за цифра 96, можно подробнее?
2) Само собой, я тоже не люблю "магические" числа.
3) Допустим я поднимаю частоту МК до 4800000, соотв. для генерации таких же частот у меня вместо 15, в регистре будет 60.
Размерность переменной само собой потом приведу к минимально необходимому значению, когда разберусь.
Было: 1200000/8=150000/15=10000/2/2=2500Гц
Станет: 4800000/8=600000/60=10000/2/2=2500Гц
Вернемся к алгоритму. Диапазон значений в регистре сравнения у меня получается теперь такой 48-80, вместо 12-20.
Если частоту сделать 9600000, то я уже не влезаю в нижний предел по генерируемой частоте, т.к. 320 > 256...
Так какое же число мне выбрать? Все равно кратно 2 не получается.

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

Пн авг 29, 2022 21:25:50

Судя по ДШ, мне нужно было включить только бит WDTIE, который разрешает просто прерывание без ресета. Возьмем минимальный интервал 16мс, поэтому делитель оставляем по нулям.

Включить таймер и разрешить прерывание (1 -> WDTIE), а так же разрешить глобальные прерывания (1 -> I)… далее чтобы не происходило сброса МК в прерывании по таймеру (WDT) каждый раз выполняете процедуру (1 -> WDTIE) - разрешить прерывание, а так же взводите флаг отслеживания данного прерывания… затем выходите из данного прерывания… в основном цикле программы отслеживаете данный флаг и производите отсчёт интервала с последующим сбросом этого флага… тем самым не будет никаких глюков при подсчёте необходимого времени… :)


Вот как пример (прошивка)… тактовая (1,2 МГц)… на выводах РВ3 и РВ4 светодиоды… РВ3 – показывает цикличность отсчёта таймера (в данном примере 496 мс), а РВ4 – загорается при сбросе (перезагрузки) МК… вывод РВ1 – ШИМ… который изменяется периодично (при каждом отсчёте таймера)… и никто некому не мешает… :)
wdt timer.hex
(402 байт) Скачиваний: 56

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

Пн авг 29, 2022 23:06:20

VNS, спасибо. Вот посмотрите, так, вроде работает как Ваша:

UPD:
Забыл добавить ШИМ, только он у меня не совсем ШИМ, а генератор.
Код:
TCCR0A |=(1<<COM0A0)|(1<<WGM00); // режим Phase Correct PWM с переключением выхода OCR0A (PB0 должен быть настроен как выход)
TCCR0B |=(1<<CS01)|(1<<WGM02); // запуск таймера с соотв. делителем на 8
OCR0A = 15; // начальное значение регистра сравнения

В общем работает нормально, как и на Вашей прошивке.

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

Вт авг 30, 2022 01:16:41

Вот посмотрите

Я не понимаю Си… но так или иначе, раз всё получилось значить всё верно… :)

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

Вт авг 30, 2022 07:34:35

1) делитель таймера =8, значит за 1 такт таймера проходит 8 тактов АЛУ, минимальное значение OCR1A =12, значит между прерываниями, генерируемыми таймером может быть всего 13 тактов таймера, перемножаем, получаем 104... т.е. основная программа может прерываться каждые 104 такта АЛУ (извиняюсь 96 — это я посчитал неправильно) и к этому надо быть готовым - надо успеть зайти в прерывание, сохранить регистры в стек, выполнить тело прерывания, вернуть регистры из стека, вернутьсф на прежнее место выполнения программы и чтото ещё в ней успеть сделать...

нужно увеличить скорость работы АЛУ и при этом не сбить частоту генерации (выходной), —> надо замедлить генерацию отностиельно тактирования АЛУ и поднять частоту самого АЛУ.
Есть 2 варианта - увеличение значения ОCR1A (ты это делал и видишь плюсы, минусы и ограничения),
можно увеличить делитель (дш под рукой нет, не помню там шаг 2 или 8....) увеличиваем тактирование кристалла до 9,6МГц (1,2 х 8), а делитель ставим 64 (8 х 8), больше ничего не меняем и получаем ту-же частоту на выходе но 64х13=832 такта АЛУ между прерываниями

Добавлено after 2 hours 38 minutes 16 seconds:
вариант с тактированием 4,8 МГц тоже хорош (около 400 тактов) да + ещё выходную частоту можно более точно выставлять

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

Вс окт 16, 2022 15:59:08

Понадобилось сделать переключатель switch на atmega328 для переключения между генераторами меандра (на различные частоты). Генератор на таймере Т0 в режиме СТС, разница между подключаемыми генераторами только в численном значении OCR0A. При первом нажатии на кнопку после подачи питания зажигается светодиод(case1). Затем при последовательном нажатии кнопки происходит вызов функций генераторов (case2, case3, case4). Проблема в том что вызвать функцию генератора можно, но вернуть ее назад (если так можно сказать) при следующем нажатии кнопки (например case5) не получается. Я попробовал просто отключать выход OC0А (в моем случае это DDRD&=~(1<<PD6)) но после возвращения из case5 в case1 светодиод не горит (т.к. в предыдущем case5 было отключение ОС0А (DDRD&=~(1<<PD6)). Если ввести еще один case6 для включения ОС0А (DDRD|=(1<<PD6)) то получается что генератор из case4 (последний по списку) вновь получил возможность подавать меандр на теперь подключенный ОС0А (и подключение ОС0А в case6).Поэтому после первого прохождения прохождении case1...case6 при последующем переключении в case1 получаем работающий на выход ОС0А генератор из case4. Возможно применение отключения выхода ОС0А это моя ошибка. Я еще начинающий, хоть и не молодой. Пробовал вводить переменную (типа флаг) и использовать оператор if() который в зависимости ит наличия установленного или сброшенного флага включал бы или отключал бы генератор в кейсах switch.К сожалению не помогло. Прошу помощи у опытных форумчан. Спасибо за терпение.

Добавлено after 4 hours 29 minutes 19 seconds:
файлы
Вложения
TEST TIMER.rar
(103.43 KiB) Скачиваний: 49

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

Вс окт 16, 2022 17:53:35

Будете контролировать яркость фонарика? :) 5-я (и 0-я) позиция: off?
Код:
        case 5:
          k = 0;
          TCCR0A &= ~(1 << COM0A0);
          TCCR0A &= ~(1 << COM0A1);
          TCCR0B &= ~(1 << COM0B0);
          TCCR0B &= ~(1 << COM0B1);
          DDRD |= (1 << PD6);
          PORTD &= ~(1 << PD6);
          break;

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

Вс окт 16, 2022 20:58:37

veso74 Спасибо за помощь. Что то вроде гирлянды.

Добавлено after 2 hours 32 minutes 51 second:
veso74 Для таймера Т0 все работает. Но я попытался переделать код для таймера Т1 потерпел неудачу. Вроде сделал все точно но не работает.
Во вложении файлы для Т0 и Т1.
Спасибо

Добавлено after 1 minute 46 seconds:
файлы
Вложения
TESN_TIMER1.rar
(59.03 KiB) Скачиваний: 46
TEST TIMER.rar
(104.43 KiB) Скачиваний: 47
Ответить