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

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
VNS
Говорящий с текстолитом
Сообщения: 1627
Зарегистрирован: Пт дек 10, 2021 12:48:46
Откуда: Тюмень

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

Сообщение VNS »

[uquote="B@R5uk",url="/forum/viewtopic.php?p=4315356#p4315356"]хотелось бы знать, как работает предделитель таймеров, есть ли у него "железный" сброс?[/uquote]
В даташите наверняка всё описано… не пробовали почитать даташит?
Реклама
Аватара пользователя
Starichok51
Модератор
Сообщения: 19053
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

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

Сообщение Starichok51 »

так это же читать надо...
а чукча - писатель, а не читатель...
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Реклама
Аватара пользователя
B@R5uk
Собутыльник Кота
Сообщения: 2896
Зарегистрирован: Сб ноя 13, 2010 12:53:25
Откуда: приходит весна?

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

Сообщение B@R5uk »

Даташит зачитал до дыр в мониторе. Ничего конкретного не нашёл. Может ап-ноут какой посоветуете почитать про таймеры?
Аватара пользователя
Starichok51
Модератор
Сообщения: 19053
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

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

Сообщение Starichok51 »

плохо читал.
есть регистр SFIOR, там есть биты для сброса предделителей таймеров.
если сомневаешься, что после подачи питания предделители в нуле, сбрось их самостоятельно.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
B@R5uk
Собутыльник Кота
Сообщения: 2896
Зарегистрирован: Сб ноя 13, 2010 12:53:25
Откуда: приходит весна?

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

Сообщение B@R5uk »

Про регистр я в курсе, использую на всякий случай. Вопрос не в том, что я сомневаюсь, а в том, как оно на самом деле.
Реклама
veso74
Поставщик валерьянки для Кота
Сообщения: 1907
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

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

Сообщение veso74 »

Попробуйте сам написать тест. Просто пишите в UART состояние преди и след установки напр. таймера.
Ниже: на ATmega328 (Arduino UNO):

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

void setup() {
  for (uint32_t i = 0; i < 10000000; i++) {
  }

  Serial.begin(57600);
  Serial.println("--- start ---");
  Serial.println(TCCR1B, BIN);

  noInterrupts();                        // initialize timer1 and disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;

  OCR1A = 62500;                         // compare match register 16 MHz / 256 / 1 Hz
  TCCR1B |= (1 << WGM12);                // CTC mode
  TCCR1B |= (1 << CS12);                 // 256 prescaler
  TIMSK1 |= (1 << OCIE1A);               // enable timer compare interrupt
  interrupts();                          // enable all interrupts
}

void loop() {
}

ISR(TIMER1_COMPA_vect) {
  Serial.println(TCCR1B, BIN);
}
резултат:

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

21:31:52.575 -> --- start ---
21:31:52.575 -> 11
21:31:53.575 -> 1100
21:31:54.575 -> 1100
21:31:55.575 -> 1100
21:31:56.575 -> 1100
21:31:58.455 -> --- start ---
21:31:58.455 -> 11
21:31:59.455 -> 1100
21:32:00.455 -> 1100
21:32:01.455 -> 1100
21:32:02.455 -> 1100
...
в --- start --- нажимаю кнопку RESET
TCCR1B = 0b00000011 - начальное состояние
TCCR1B = 0b00001100 - после установки для 1 Hz
Реклама
akl
Друг Кота
Сообщения: 4445
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

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

Сообщение akl »

veso74 писал(а): в --- start --- нажимаю кнопку RESET
TCCR1B = 0b00000011 - начальное состояние
TCCR1B = 0b00001100 - после установки для 1 Hz
Можно понимать, что после внешнего сброса таймер 1 начинает считать тактовую с предделителем 64??? :shock:
OCR1A = 62500; // compare match register 16 MHz / 256 / 1 Hz
Уточню, для получения интервала 1 секунда, задавать нужно
OCR1A = 62500-1, иначе интервал будет на 256 тактов длиннее. https://radiokot.ru/forum/viewtopic.php ... 4#p4222274
veso74
Поставщик валерьянки для Кота
Сообщения: 1907
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

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

Сообщение veso74 »

[uquote="akl",url="/forum/viewtopic.php?p=4315520#p4315520"]... для получения интервала 1 секунда, задавать нужно OCR1A = 62500-1[/uquote]
Это понятно, спс, в спешке, не обращайте внимания :).
Untitled-1.jpg
(92.71 КБ) 93 скачивания
Из других систем и языков мне осталос правило: в начале, по возможности: все с первоначальным установлением. Как в случае и с используем Таймер_х: в начальном состоянии все регистры.
Аватара пользователя
B@R5uk
Собутыльник Кота
Сообщения: 2896
Зарегистрирован: Сб ноя 13, 2010 12:53:25
Откуда: приходит весна?

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

Сообщение B@R5uk »

[uquote="veso74",url="/forum/viewtopic.php?p=4315450#p4315450"]Попробуйте сам написать тест[/uquote]
Да, пожалуй, хороший совет, на корифеев надейся, а сам не плошай. Написал следующую программу. На выводе PB0 весит светодиод. Идея заключается в следующем. Программа инициализирует таймер 0, подключая его к предделителю на 1024, затем выжидает 768 (с хвостиком) тактов и читает значение счётчика этого таймера. Если значение отлично от нуля, то светодиод на PB0 выключается. Смысл в том, чтобы загрузить эту программу в МК и периодически делать reset. Если предделитель аппаратно не сбрасывается, то хотя бы иногда за 3/4 периода он будет выдавать импульс на таймер 0 за счёт того, что его содержимое было отлично от нуля в начале работы МК. Поэтому светодиод иногда будет гаснуть. Если же он аппаратно сбрасывается, то содержимое счётчика таймера в момент чтения программой будет 0 всегда, светодиод будет гореть всегда.

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

.include"m8def.inc"

;==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==
;   Инициализация периферии МК
                ;   Настройка портов ввода-вывода
                ldi     r16,    0xFF    ;   На входах -- подтяжка
                out     PORTB,  r16
                out     PORTD,  r16
                out     PORTC,  r16
                ldi     r16,    0x01    ;   PB0 -- выход, остальные биты
                out     DDRB,   r16     ;       порта B -- входы
                clr     r16             ;   Порты C и D -- входы
                out     DDRC,   r16
                out     DDRD,   r16
                ;   Настройка таймера 0
                clr     r16
                out     TCNT0,  r16
                ldi     r16,    0x05    ;   Предделитель 1024
                out     TCCR0,  r16
;==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==
;   Основная программа
                ;   Выжидание 768 тактов
                clr     r16
pauseLoop:      dec     r16
                brne    pauseLoop
                ;   Проверка содержимого счётчика таймера 0
                in      r16,    TCNT0
                tst     r16
                breq    finalLoop
                ;   Если счётчик отличен от нуля, сброс пина PB0 в ноль
                ldi     r16,    0xFE
                out     PORTB,  r16
                ;   Конец программы
finalLoop:      rjmp    finalLoop
;==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==
Результат эксперимента: светодиод горит всегда. Конечно, если я ОЧЕНЬ несчастливый человек, и мне жутко не везёт КАЖДЫЙ раз, то это ничего не значит. В противном случае с вероятностью экспоненциально стремящейся к 100%, предделитель таймеров аппаратно сбрасывается при хардовом ресэте. Вопрос решён, всем спасибо за дискуссию!

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

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

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

Господа коты, помогите разобраться с формированием интервалов.
Я использую WDT-таймер настроенный на интервал 16мс.
В прерывании таймера я инкрементирую 8-и битную переменную.

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

ISR(WDT_vect)
{
	WDTCR |=(1<<WDTIE);
	ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
	{systime++;}
}
А в главном цикле использую такой код:

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

if (systime - tmr1 >= 10U)
{
        tmr1 = systime;
        PORTB ^= (1 << PB3);
}
1. Без явного указания беззнаковости интервала (10U) оно не работает, почему так? Со всякими millis()'ами ведь работает?
2. Экономлю память, поэтому все переменные uint8_t, соотв. ловлю переполнение и происходит "дрыг". Как сделать, чтобы переполнение было пофиг? Самого диапазона интервалов при 1 тике раз в 16мс мне хватает, разобраться бы с переполнением.
Я подсмотрел вот такой код у Гайвера, он работает, но значение интервала желательно выбрать кратным степени двойки, т.к. используется деление, а это не всегда возможно...

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

	uint8_t timeLeft = systime - tmr1;
	if (timeLeft >=8)
	{
	   tmr1 += 8 * (timeLeft / 8);
		PORTB ^= (1 << PB3);
	}
ИзвЕните от слова - веник, ИзвИните от слова - вина.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18547
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

внутри обработчика прерывания не нужно использовать ATOMIC_BLOCK, поскольку обработчик прерывания уже "атомно" исполняется по отношению к остальному коду.

поскольку я не помню (и не собираюсь запоминать) приоритеты операций, рекомендую взять разность в скобки

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

if ((systime - tmr1) >= 10U)
влияние U может быть в том, что по умолчанию все результаты и константы имеют тип int, т.е. со знаком, а вам знак не нужен...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
OKF
Это не хвост, это антенна
Сообщения: 1393
Зарегистрирован: Вт июн 07, 2011 08:03:18

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

Сообщение OKF »

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

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

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

Со скобками полезный совет, спасибо! Т.к. у меня тоже приоритеты не запоминаются, всегда подглядываю в таблицу.
В общем с этим U непонятно, у меня переменная таймера и переменная "подтаймера" строго uint8_t. Значит минус туда не запихнешь.
Но интересно другое! Если используется промежуточная переменная или счет времени обернуть в функцию, то тогда явное указание беззнаковости не нужно.
Например:

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

uint8_t timeLeft = systime - tmr1;
   if (timeLeft >=10)
   {
      tmr1 += timeLeft;
      PORTB ^= (1 << PB3);
   }
Подозреваю эффект открытия новых чудес, когда плохо читал документацию... Но что-то я упускаю.
И еще про этот кусок кода, он корректно отрабатывает переполнение щ0ччика, интервалы все ровные, но смущает вот что:
Изначально было так:

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

 tmr1 += 8 * (timeLeft / 8);
Я на бумажке посчитал, результат такой же, как если бы просто значение этой переменной прибавить к tmr1. Зачем тут эти выкрутасы с делением и умножением?

Добавлено after 7 minutes 45 seconds:
[uquote="OKF",url="/forum/viewtopic.php?p=4328352#p4328352"]кисонька, вы покажите определения переменных, а то по огрызкам сложно судить.[/uquote]
Пардон.

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

volatile uint8_t systime = 0; // глобальная переменная, которую крутит прерывание таймера 
int main(void)
{
       uint8_t tmr1 = 0; // локальная переменная, для интервала софт-таймера
       while(1);
       {
            if()...
       } 
}
ИзвЕните от слова - веник, ИзвИните от слова - вина.
veso74
Поставщик валерьянки для Кота
Сообщения: 1907
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

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

Сообщение veso74 »

[uquote="Мокренькая кисонька",url="/forum/viewtopic.php?p=4328358#p4328358"]... как если бы просто значение этой переменной прибавить к tmr1. Зачем тут эти выкрутасы с делением и умножением?[/uquote]
Вероятно "округление" до кратного 8.
Пример:
123 / 8 = 15,375;
15 * 8 = 120;

Я бы удалил последние 3 бита побитово:

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

a &= 0b11111000;
Из примера:
123 = 0b01111011;
123 & 0b11111000 = 0b01111011 & 0b11111000 = 0b01111000 = 120;

Я почти уверен, что оптимизатор уже это сделал.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18547
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

я же вам писал: результат выражения по умолчанию int, т.е. со знаком.

uint8 - uint8 это не uint8, а int! а потом идет сравнение с 10, и это 10 тоже переделывается в int.

а когда вы пишите 10u, вы говорите компилятору: э, дарагой, тут знак нэ нада, давай, досвидания!

Добавлено after 3 minutes 27 seconds:
кстати, 123/8 в целых числах и так 15, а не 15,3.

Добавлено after 1 hour 24 seconds:
[uquote="Мокренькая кисонька",url="/forum/viewtopic.php?p=4328358#p4328358"]Зачем тут эти выкрутасы с делением и умножением?[/uquote]точного ответа у меня нет, но есть предположение.

я думаю, вы просто взяли за основу обучения код такого же, как вы, начинающего. т.е. того, кто "так работает - ну и ладно!". нельзя учиться на коде "от гуру" и на коде от "начинающего", надо учиться на коде опытного, но но не настолько, чтобы свободно применять конструкции типа

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

v = {1,2,3,4}[i > 0 ? 17 ^ b * *с[x]++ : 136 / '\012'];
но уже отказавшегося от конструкций типа

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

if(x == 0) y = 'a';
else if(x == 1) y = 'b';
else if(x == 2) у = 'c';
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

[uquote="ARV",url="/forum/viewtopic.php?p=4328836#p4328836"]uint8 - uint8 это не uint8, а int![/uquote]Вот уж мне эта юношеская категоричность :)
Смотрим
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18547
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

[uquote="VladislavS",url="/forum/viewtopic.php?p=4328900#p4328900"][uquote="ARV",url="/forum/viewtopic.php?p=4328836#p4328836"]uint8 - uint8 это не uint8, а int![/uquote]Вот уж мне эта юношеская категоричность :)
Смотрим[/uquote]
опять плюсы в сишную тему приносите? integer promotions C
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

Плюсы там только чтобы тип можно было посмотреть.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18547
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

[uquote="VladislavS",url="/forum/viewtopic.php?p=4329011#p4329011"]Плюсы там только чтобы тип можно было посмотреть.[/uquote]что вы предлагали мне увидеть по вашей ссылке? или integer promotions уже отменили?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

[uquote="ARV",url="/forum/viewtopic.php?p=4329116#p4329116"]что вы предлагали мне увидеть по вашей ссылке?[/uquote]Что ваше "uint8 - uint8 это не uint8, а int!" это ложное утверждение.

[uquote="ARV",url="/forum/viewtopic.php?p=4329116#p4329116"]или integer promotions уже отменили?[/uquote]Зачем вы употребляете термины, значение которых не знаете? Есть же стандарт. Читаем 6.3.1.1 и обнаруживаем, что может быть как int, так и unsigned int. Что примеры по моей ссылке и подтверждают.
Ответить

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