Правильная инициализация таймера

Обсуждаем контроллеры компании Atmel.
Ответить
Грызет канифоль
Сообщения: 269
Зарегистрирован: Чт мар 11, 2010 17:45:37
Откуда: г.фрязино

Сообщение mastech »

Как правильно инициализировать с | или без?
В некоторых примерах можно встретить такое:

TCCR0 = 0;
TCCR0 = (0<<COM01)|(1<<COM00)|(0<<WGM01)|(0<<WGM00);
TCNT0 = 0;
OCR0 = 0;
TIMSK = 0;
TCCR0 |= (1<<CS02)|(0<<CS01)|(1<<CS00);
Реклама
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

при начальной настройке - однозначно без |
т.к. во первых через команду с палкой может просочиться мусор, а во вторых команда с палкой занимает во флеше больше места и дольше выполняется...
дальше в коде, когда регистр уже настроен, можно и так, и так в зависимости от ситуации
если точно знаешь какими должны быть все байты регистра - выгодней написать без |
если не знаешь (например, скорость таймера настроилась в процессе работы, или модикация регистра происходит в подпрограмме и может быть вызвана при разных состояниях таймера) то без "|" и/или "&" не обойтись.

Добавлено after 19 minutes 28 seconds:
или. в твоем примере палка была применена только для того, чтобы заново не набивать названия регистров таймера... (возможно, оптимизатор это поймёт и, дописав недостающие биты, напишет эту команду без палки)
1 команда - обнуление регистра (имхо лишняя, т.к. 2 команда его всёравно установит в точно определенное состояние, что бы в нём ни находилось)
2- настройка режима таймера
3-5 - очистка регистров таймера
6- запуск таймера (изменяются только биты, отвечающие за прескалер)
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="Ivanoff-iv",url="/forum/viewtopic.php?p=3778063#p3778063"](возможно, оптимизатор это поймёт и, дописав недостающие биты, напишет эту команду без палки)[/uquote]Всё верно пишешь, кроме вот этой фразы. Регистры это volatile сущности, компилятор не имеет права ничего менять в доступе к ним.
Это не хвост, это антенна
Сообщения: 1492
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Первоначальная инициализация таймера (при включении питания, после сброса) непосредственное задание значения. То есть, TCCR0A = (1<<CS0); Регистры, общие для таймеров (TIMSK) - первые команды задание значений, последующие - |.
Совет, сначала задать режим работы таймера, затем разрешать флаги прерываний. Этот совет касается всего, где есть прерывания. В противном случае, если сначала разрешить прерывание, может выполниться условие и установится флаг прерывания и сработает соответствующее прерывание.
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

[uquote="VladislavS",url="/forum/viewtopic.php?p=3778071#p3778071"]Регистры это volatile сущности, компилятор не имеет права ничего менять в доступе к ним.[/uquote]наверно... но при перенастройке собаки или делителя тактовой оптимизацию отключать всёравно приходится, а иначе он таки забывает о том что это сущности...
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Реклама
Друг Кота
Аватара пользователя
Сообщения: 15713
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

В случае с ассемблером предварительное преобразование делает препроцессор, а в команду подставляется только готовая величина.
Для Си...
Возможно удобнее выполнить предварительно определение командного байта как константы, а затем уже ту константу подставлять в текст программы.
Допустим
const unsigned char com_word = (0<<COM01)|(1<<COM00)|(0<<WGM01)|(0<<WGM00);
(хотя... сдвиг нуля лишен смысла, поскольку достаточно 1<<COM00, чтобы остальные биты результата были сброшены в 0...)
а затем уже
TCCR0 = com_word;
:roll:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

С тоже пересчитывает сам... (даже не представляю насколько надо укуриться, чтоб это на камень возложить...)
тут как удобней программисту... если эта одинаковая настройка мелькает несколько раз или есть вероятность менять её перед компиляцией, то удобней её вынести из кода в начало (объявить константой или задефайнить), а если нет, то ... просто оставить где была...:)
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Грызет канифоль
Сообщения: 269
Зарегистрирован: Чт мар 11, 2010 17:45:37
Откуда: г.фрязино

Сообщение mastech »

Правильно ли я понимаю:

TCCR0 = (0<<COM01)|(1<<COM00)|(0<<WGM01)|(0<<WGM00); - это непосредственная запись в регистр (значения)?
TCCR0 = 0b00010000 (16)
----------------------------------------------------------------------------------------------------------------------------------------------------
TCCR0 |= (1<<CS02)|(0<<CS01)|(1<<CS00); - это наложение битовой маски(через битовое "или")?
TCCR0 = 0b00010000 - значение регистра установленное выше
|
0b00000101 - накладываем маску ((1<<CS02)|(0<<CS01)|(1<<CS00))
=
0b00010101 - результат

Во второй настройке таймера если не будем использовать маску то COM00 сбросится в 0?


Справедливо ли это для других регистров, например для АЦП?
В настройках АЦП такого вроде не встречал, всегда используется |.
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

| — прбитовое или, где бы ни применялось.
|= (а также -=, +=, %=, /=, *=, &=... и т.д.) это просто сокращенная запись..
твоё TCCR0 |= (1<<CS02)|(0<<CS01)|(1<<CS00);
означает TCCR0 = (TCCR0)|(1<<CS02)|(0<<CS01)|(1<<CS00);
и выполняется в МК за 3 команды:
R16 <— TCCR0;
R16 <— R16|(0b00000101); значение в скобках вычисляется ещё при компиляции и в мк закладывается уже в таком виде,
TCCR0 <— R16;
в регистр общего назначения содержимое TCCR0 выгружается потому, что мк не умеет с ним работать напрямую... простая (без |) запись в него фиксированного значения также будет происходить через РОН, но уже без выгрузки в РОН исходного состояния регистра (т.е. займёт 2 команды).
Последний раз редактировалось Ivanoff-iv Чт янв 23, 2020 05:55:25, всего редактировалось 1 раз.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

mastech, Вы что, прикалываетесь? Откройте любой учебнике по Си и почитайте про оператор "|=".
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3778600#p3778600"]mastech, Вы что, прикалываетесь? Откройте любой учебнике по Си и почитайте про оператор "|=".[/uquote]
Вот с этого надо было начинать. А то остальные понаписали тут для ТС "сначала таймер через =, а потом через |=". Да ну нахер. Нет никакого "правильного" в данном случае. ТС просто надо прочитать чем оператор = отличается от |=. Тогда и понимание будет, а не тупо копирование без понимания. Битовые операции используются, когда надо "не трогать" другие биты. Присваивание - когда другие биты нужно установить однозначно в 0.

ТС, читай: http://www.c-cpp.ru/books/bitovye-operatory
Может лучше ссылка есть, первая что нашел. Просто учти что a |= b, это тоже самое, что a = a | b. Аналогично как a &= b == a = a & b и т.д.
Ответить

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