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

Обсуждаем контроллеры компании Atmel.
Игорь_396
Встал на лапы
Сообщения: 102
Зарегистрирован: Ср дек 25, 2019 21:17:31
Откуда: Саратов

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

Сообщение Игорь_396 »

Собирал на днях подобное, для экспериментов. Но я потенциометры повесил на АЦП. Один задаёт скважность, второй меняет коэффициент деления. Естественно, плавной регулировки частоты не получилось, думаю как реализовать..
Реклама
Kalisnik
Мучитель микросхем
Сообщения: 430
Зарегистрирован: Вс апр 18, 2021 15:43:55

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

Сообщение Kalisnik »

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

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

Сообщение Starichok51 »

Kalisnik, в АТмега8 у таймера1 есть режим ШИМ номер 8 и режим номер 14, где период задается регистром ICR1.
поэтому максимальное число равно 65535 (0xFFFF), и частоту можно изменять относительно плавно, изменяя число в этом регистре через 1.
а скважность можно задавать по каналу А в регистре OCR1A.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Kalisnik
Мучитель микросхем
Сообщения: 430
Зарегистрирован: Вс апр 18, 2021 15:43:55

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

Сообщение Kalisnik »

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

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

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

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 15,625 kHz
// Mode: Ph. & fr. cor. PWM top=ICR1
// OC1A output: Non-Inverted PWM
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer Period: 2,9999 s
// Output Pulse(s):
// OC1A Period: 2,9999 s Width: 1,4999 s
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=(1<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (1<<WGM13) | (0<<WGM12) | (0<<CS12) | (1<<CS11) | (1<<CS10);
TCNT1H=0x00;
TCNT1L=0x01;
ICR1H=0x5B;
ICR1L=0x8D;
OCR1AH=0x2D;
OCR1AL=0xC6;
OCR1BH=0x05;
OCR1BL=0x00;
Добавлено after 1 minute 1 second:
Моделирую в Proteus.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
mickbell
Друг Кота
Сообщения: 16422
Зарегистрирован: Пт мар 30, 2012 05:17:29
Откуда: Екатеринбург

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

Сообщение mickbell »

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

На каждый РКН
Найдётся VPN.
Реклама
Kalisnik
Мучитель микросхем
Сообщения: 430
Зарегистрирован: Вс апр 18, 2021 15:43:55

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

Сообщение Kalisnik »

mickbell, все верно. На МК задержек не было.
Реклама
alex68md
Грызет канифоль
Сообщения: 275
Зарегистрирован: Сб янв 03, 2015 21:03:24

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

Сообщение alex68md »

опечатка
Аватара пользователя
Мокренькая кисонька
Открыл глаза
Сообщения: 59
Зарегистрирован: Вт сен 27, 2011 07:28:44
Откуда: Москва
Контактная информация:

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

Сообщение Мокренькая кисонька »

Господа коты, а можно ли как-то заставить таймер (в данном случае ATtiny13) аппаратно генерировать частоту (режимы CTC с переключением выхода или один из режимов PWM с переключением выхода), но при этом воспользоваться прерыванием по переполнению, для отсчета интервалов и задержек?
Проблема еще заключается в том, что мне нужно менять генерируемую частоту по ходу пьесы, соответственно содержимое регистра OCR0A в процессе меняется. И получается, что привязаться вообще не к чему. Т.е. получается таймер в режимах CTC, PWM не считает по кругу, а считает до "отметки" в регистрах OCR0A и OCR0B, причем в последнем значение должно быть меньше чем в первом. Я многого хочу и нужен второй таймер? (менять МК, например на ATtiny25)
ИзвЕните от слова - веник, ИзвИните от слова - вина.
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

Сообщение Ivanoff-iv »

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

Добавлено after 2 minutes 48 seconds:
ну, и важное замечание - мк должен всё это успевать сделать (например при делителе 1 и значении в оср1а 1 он полюбому не успеет....
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Аватара пользователя
VNS
Говорящий с текстолитом
Сообщения: 1627
Зарегистрирован: Пт дек 10, 2021 12:48:46
Откуда: Тюмень

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

Сообщение VNS »

[uquote="Мокренькая кисонька",url="/forum/viewtopic.php?p=4280113#p4280113"]для отсчета интервалов и задержек?[/uquote]
Ну, для отсчёта интервалов и задержек в таком случае можно использовать и сторожевой таймер… и по его прерыванию производить отсчёт… минимальное время у тини13 это 16 мс, а максимальное 8,2 сек. Так что вполне удобно при необходимости… :)
Аватара пользователя
Мокренькая кисонька
Открыл глаза
Сообщения: 59
Зарегистрирован: Вт сен 27, 2011 07:28:44
Откуда: Москва
Контактная информация:

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

Сообщение Мокренькая кисонька »

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.
ИзвЕните от слова - веник, ИзвИните от слова - вина.
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

Сообщение Ivanoff-iv »

1) частоту я бы поднял, 12х8=96 тактов, конечно, тут хватит, но ведь тиня ещё чтото делает...
2) код правильный, но я бы цифру 5 задефайнил, чтобы при сравнении и при вычитании числа всегда совпадали.
3) 5 для этого места катастрофически мало, т.к. при каждом вызове прерывания в накопитель складывается от 13 до 21.
я бы использовал числа, кратные 256, так если оптимизатор хороший, то он оптимизирует (уберёт) операции с младшим разрядом. (например число 5*256 даст интервал в 5 полных 0—ff оборотов таймера, т.е. 10240 тактов = 117 Гц)
переменную для накопителя не стоит брать с избытком (большей разрядности чем величина с которой он сравнивается), в вашем случае достаточно 16 бит.
—————
у сторожевого таймера нужно после каждой сработки вновь взводить режим прерывания, иначе вторая и последующие сработки вызовут уже не прерывание, а перезагрузку.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Аватара пользователя
Мокренькая кисонька
Открыл глаза
Сообщения: 59
Зарегистрирован: Вт сен 27, 2011 07:28:44
Откуда: Москва
Контактная информация:

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

Сообщение Мокренькая кисонька »

Да, что-то я совсем запутался.
Когда на асме писал, я там такты высчитывал, а когда на Си перешел, что-то все внимание переключилось на сам язык.
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 не получается.
ИзвЕните от слова - веник, ИзвИните от слова - вина.
Аватара пользователя
VNS
Говорящий с текстолитом
Сообщения: 1627
Зарегистрирован: Пт дек 10, 2021 12:48:46
Откуда: Тюмень

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

Сообщение VNS »

[uquote="Мокренькая кисонька",url="/forum/viewtopic.php?p=4280220#p4280220"]Судя по ДШ, мне нужно было включить только бит WDTIE, который разрешает просто прерывание без ресета. Возьмем минимальный интервал 16мс, поэтому делитель оставляем по нулям.[/uquote]
Включить таймер и разрешить прерывание (1 -> WDTIE), а так же разрешить глобальные прерывания (1 -> I)… далее чтобы не происходило сброса МК в прерывании по таймеру (WDT) каждый раз выполняете процедуру (1 -> WDTIE) - разрешить прерывание, а так же взводите флаг отслеживания данного прерывания… затем выходите из данного прерывания… в основном цикле программы отслеживаете данный флаг и производите отсчёт интервала с последующим сбросом этого флага… тем самым не будет никаких глюков при подсчёте необходимого времени… :)


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

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

Сообщение Мокренькая кисонька »

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

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

/*
 * Example2.c
 *
 * Created: 29.08.2022 22:44:09
 * Author : vadeg
 * FUSE: LF=0x6A; HF=0xFD (1.2MHz; BOD=1.8V)
 */ 

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define FLAG 0

volatile uint8_t wdt_flag = 0;

ISR(WDT_vect)
{
	WDTCR |=(1<<WDTIE);
	wdt_flag |=(1<<FLAG);
}

int main(void)
{
	ACSR |=(1<<ACD); // отключение компаратора
	DDRB |=(1<<PB3)|(1<<PB4); // эти порты на выход
	PORTB |=(1<<PB4); // включаем зеленый
	_delay_ms(10);
	PORTB &=~(1<<PB4); // выключаем зеленый
	WDTCR |=(1<<WDTIE)|(1<<WDP1)|(1<<WDP2); // разрешаем прерывание от WDT и выставляем делитель на 1 сек.
	sei(); // глобальное разрешение прерываний
    /* Replace with your application code */
    while (1) 
    {
		if (wdt_flag&(1<<FLAG))
		{
			wdt_flag &=~(1<<FLAG);
			PORTB ^=(1<<PB3);
		}
    } // end while(1)
} // end main
UPD:
Забыл добавить ШИМ, только он у меня не совсем ШИМ, а генератор.

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

TCCR0A |=(1<<COM0A0)|(1<<WGM00); // режим Phase Correct PWM с переключением выхода OCR0A (PB0 должен быть настроен как выход)
TCCR0B |=(1<<CS01)|(1<<WGM02); // запуск таймера с соотв. делителем на 8
OCR0A = 15; // начальное значение регистра сравнения
В общем работает нормально, как и на Вашей прошивке.
ИзвЕните от слова - веник, ИзвИните от слова - вина.
Аватара пользователя
VNS
Говорящий с текстолитом
Сообщения: 1627
Зарегистрирован: Пт дек 10, 2021 12:48:46
Откуда: Тюмень

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

Сообщение VNS »

[uquote="Мокренькая кисонька",url="/forum/viewtopic.php?p=4280391#p4280391"]Вот посмотрите[/uquote]
Я не понимаю Си… но так или иначе, раз всё получилось значить всё верно… :)
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

Сообщение Ivanoff-iv »

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 тактов) да + ещё выходную частоту можно более точно выставлять
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
catrock
Родился
Сообщения: 18
Зарегистрирован: Вс окт 16, 2022 10:28:09

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

Сообщение catrock »

Понадобилось сделать переключатель 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 КБ) 87 скачиваний
veso74
Поставщик валерьянки для Кота
Сообщения: 1907
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

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

Сообщение veso74 »

Будете контролировать яркость фонарика? :) 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;
catrock
Родился
Сообщения: 18
Зарегистрирован: Вс окт 16, 2022 10:28:09

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

Сообщение catrock »

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

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

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

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