Прерывания по таймеру

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

Прошу помощи в пояснении по принципу работы с таймерами. Искал долго и много но так ответы на вопросы и не были найдены.
Пример кода из интернета

Я его немного переделал чтобы визуально всё было понятно.

В интернете я нашёл таблицу  в которой написаны все прерывания для arduino. Но приведённый пример я так и не смог разобрать. Мне в нём непонятно ВСЁ. Весь setup включая знаки & | ~ (в конкретном случае), TIMSK2, TCCR2A, WGM22, ASSR и прочее. Откуда всё это берётся?

Основной смысл: сделать блинк на прерываниях по таймеру.

Библиотеки не предлагать!

Также мне интересно как сделать прерывания по зависанию мк? Название прерывания из таблицы WDT_vect
 

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

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

TIMSK2, TCCR2A, WGM22 - это регистры управления процессора, связанные с таймерами. Они объявлены в общем хедере для процессора, так что ненужно их искать. Прежде чем работать с таймерами, почитайте про них в статьях или даташите

Про прерывание по зависанию, ищите про ватчдог.

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

 Про символы я разобрался.
НО всё остальное просто жесть какая-то. Прочитал статью. Понял на 50% хотя и то не уверен.
Нашёл сборник статей на эту тему. Но они не очень хорошо написаны.(((

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Читайте как можно больше, чтобы работать с таймерами, нужно понимать, как они работают. Легче всего понять, если Вы разбираетесь в схемах и немножко читаете по аглицки, потому что о принципе работы, на самом деле, даташит дает исчерпывающую информацию, но трудноусваимую.

Не знаю, что входит в 50%, которые Вы не поняли, но поясню по программе:

&= ~(1<<TOIE2) - сброс бита номер TOIE2.  Берется "1", сдвигается влево на 6-ю позицию (TOIE2=6), получается 0b01000000, инвертируется операцией "~", получается 0b10111111, производится логическое умножение (операция И), результат кладется обратно. Таким образом "0" попадает в нужный бит регистра. Если не инвертировать и применить операцию битового сложения (ИЛИ), то в нужное место попадет единичка.

В общем случае, то, что в скобках, зовется маской, ее накладывают на регистр через "&", если нужно сбросить биты там, где у маски "0", или через "|", чтобы установить биты там, где у маски "1".

Все это можно делать и через функции bitSet() и bitClear(), но будет медленнее и "неуниверсально"

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

 Я …. Что то вообще ничего не понял(((
По статьям:
Чтобы установить бит в регистре в значение 1, не изменяя значения других битов, используется команда вида:

регистр |= (1 << номер_бита);

А чтобы установить бит в регистре в значение 0, так же не изменяя значения других битов, ис-пользуется команда вида:

регистр &= ~ (1 << номер_бита);

Следовательно давайте разберём первую строчку. TIMSK2 &= ~(1<<TOIE2);

По статьям:
TIMSK - регистр маски прерываний таймеров/счетчиков

Бит 7 - OCIE2: прерывание по совпадению ТС2
Бит 6 - TOIE2: прерывание по переполнению ТС2
Бит 5 - TICIE1: прерывание по захвату ТС1
Бит 4 - OCIE1A: прерывание по совпадению A ТС1
Бит 3 - OCIE1B: прерывание по совпадению В ТС1
Бит 2 - TOIE1: прерывание по переполнению ТС1
Бит 1 - не используется
Бит 0 - TOIE0: прерывание по переполнению ТС0
Если соответствующий бит установлен в "1" и бит I (7-й бит) регистра состояний SREG установлен в "1", тогда соответствующее прерывание будет срабатывать.

В этом месте уже непонятно. Как я это вижу:
При старте мк в регистрах TIMSK записано 0b00000000 (так ли я это понимаю?)(то есть нули и всё прерывания выключены) или всё наоборот ?

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

 Ок ступил. Всё логично получается с единицами. Только я не понял раз стоит 0 то значит прерывание включено а если 1 то выключено?

step962
Offline
Зарегистрирован: 23.05.2011

LEVV2006 пишет:

По статьям:
TIMSK - регистр маски прерываний таймеров/счетчиков

Бит 7 - OCIE2: прерывание по совпадению ТС2
Бит 6 - TOIE2: прерывание по переполнению ТС2
Бит 5 - TICIE1: прерывание по захвату ТС1
Бит 4 - OCIE1A: прерывание по совпадению A ТС1
Бит 3 - OCIE1B: прерывание по совпадению В ТС1
Бит 2 - TOIE1: прерывание по переполнению ТС1
Бит 1 - не используется
Бит 0 - TOIE0: прерывание по переполнению ТС0

Не можете ли указать источник столь полезной информации.

По моим сведениям (да и Atmel так считает - см. даташит) в микроконтроллерах ATMega48/88/168/328 существует аж 3 регистра, занимающихся маскированием - соответственно TIMSK0, TIMSK1, TIMSK2 (страницы 111, 139 и 163 "большого" даташита). И у этих регистров только младшие биты имеют значение (3, 4 и 3 бита соответственно). А у вас - целый байт...

step962
Offline
Зарегистрирован: 23.05.2011

LEVV2006 пишет:

Только я не понял раз стоит 0 то значит прерывание включено а если 1 то выключено?

Еще раз - даташит на соответствующий контроллер является истиной в последней инстанции. Там все предельно ясно сказано. Например, бит 2 регистра TIMSK0:

"Bit 2 – OCIE0B: Timer/Counter Output Compare Match B Interrupt Enable
When the OCIE0B bit is written to one, and the I-bit in the Status Register is set, the
Timer/Counter Compare Match B interrupt is enabled. The corresponding interrupt is executed if
a Compare Match in Timer/Counter occurs, i.e., when the OCF0B bit is set in the Timer/Counter
Interrupt Flag Register – TIFR0."

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

LEVV2006 пишет:

 Ок ступил. Всё логично получается с единицами. Только я не понял раз стоит 0 то значит прерывание включено а если 1 то выключено?

Если "1" - то включено, если "0" - то выключено.

У Вас в первом скетче просто ошибка в комментарии, первая строчка ЗАПРЕЩАЕТ прерывание, там все сделано правильно:

  1. запрещаем прерывание
  2. изменяем настройки таймера
  3. разрешаем прерывание

Делается так для того, чтобы во время настройки таймера у нас прерывание не сработало случайно.

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

Дело всё в том что скетч из примера вообще не работает! один раз только срабатывает прерывание!
Хотел написать сам как в статьях всё равно не работает!
 

 

step962
Offline
Зарегистрирован: 23.05.2011

 В строке 11 скетча вы присваиваете регистру TIMSK2 значение 64. Другими словами, устанавливаете бит 6.

Если открыть даташит на микроконтроллер и посмотреть, что же там пишется об этом регистре, то можно уяснить, что смысл имеет лишь установка трех младших битов:

Это так - в качестве примера достоверности тех данных, которыми вы пытаетесь пользоваться. Неудивительно, что ваше прерывание сыплется.

UPD1: Далее, в процедуре обработки прерывания вы вызываете функцию, которая слишком тяжела для обработки в прерываниях: в ней вызывается не слишком быстрая функция digitalWrite(), а также Serial.print, которой для вывода 3 символов (да плюс еще CR+LF) потребуется около 5 миллисекунд. Сколько раз за это время произойдет очередное переполнение вашего таймера? 40? или 50? (таймер "щелкает" с частотой 500 кГц в диапазоне 150-255, т.е. переполняется где-то 5 раз в миллисекунду).

UPD2: Упс, у вас выбран режим 0 - нормальный режим счета. В этом режиме счетчик считает от 0 до 255. Величина в TCNT2 значения не имеет. Стало быть счет в диапазоне 0-255 и переполнение "всего" 2 раза в миллисекунду.

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

Скачал даташит. На 12 главе описываются прерывания по таймеру. Подобного рисунка с надписью TIMSK2 замечено не было. Я не знаю английского языка поэтому в даташит и не лазаю. Пробовал перевести переводчиком. Полная чушь!
(да плюс еще CR+LF)-что это такое?
Мне кажется надо как то систематизировать данные по даташиту. Ибо возможно мы говорим об одном и том же, а я ничего понять не могу. Также мне не понятно как высчитывать секунды или полсекунды.
 

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

Используя пример из интернета вот что получилось.

Мне не понятно как настроить и вычислить такты. То есть как рассчитать так чтобы прерывание срабатывало скажем каждую секунду.
И мне не всё понятно с регистром маски прерываний так как в строчке TIMSK2 |= (1 << TOIE2); мы чётко ставим 1 в бит 6! А если записать как 64 то ничего не работает.

Также не ясно. Какие режимы может принимать регистр управления В. (выбор тактирования таймера)

PS пример который я привёл получился методом тыка!!! Мне стыдно что так и не смог разобраться((((
 

step962
Offline
Зарегистрирован: 23.05.2011

LEVV2006 пишет:

(да плюс еще CR+LF)-что это такое?

CR (Carriage Return - возврат каретки) и LF (Line Feed - перевод строки) - те символы, которые добавляются к пересылаемой строке в случае использования функции Serial.println().

step962
Offline
Зарегистрирован: 23.05.2011

LEVV2006 пишет:

И мне не всё понятно с регистром маски прерываний так как в строчке TIMSK2 |= (1 << TOIE2); мы чётко ставим 1 в бит 6! А если записать как 64 то ничего не работает. 

А с чего вы взяли, что TOIE2 равен 6? А не, скажем, 0?

Попробуйте в скетче вывести его значение на экран:

Serial.println(TOIE2,DEC);

step962
Offline
Зарегистрирован: 23.05.2011

LEVV2006 пишет:

Скачал даташит. На 12 главе описываются прерывания по таймеру. 
 

"Preliminary"? Но и там в 12 главе описывается таймер/счетчик0, а второй - соответственно - в 15-й.

[quote]
Я не знаю английского языка поэтому в даташит и не лазаю
[/quite]
Ну, тогда вам остается мигать диодом с помощью delay().

Если уж совсем никак, найдите книжку Евстифеева. Практически даташит, только переведенный на русский язык, ну и урезанный мало-мало.

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

Всё разобрался (вроде как). Смотрел какой-то левый даташит + не дошёл до раздела который нужно было использовать. Спасибо!  

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Замечу, что Serial.print использовать в прерываниях нерекомендуется. Если все же очень надо, советую почитать статью о неблокирующем Serial 

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

 Ок спасибо. Статья интересная. Но я не буду применять печать в прерываниях.
Я так понял что мало кто разбирается на тему прерываний и настройки таймеров.
Сейчас ищу про WATCHDOG. К сожалению описания на русском нет. Также удалось выяснить, что для нормальной работы необходимо перепрошить бутлогер. Конечно всё бы решил даташит! Но я пока не нашёл переводчика))) а гугл сами знаете что выдаёт.

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

По сторожевому таймеру уже было на форуме. Что гугль выдает - не знаю, потому что в свое время зарекся переводить технические тексты компьютерными переводчиками (это было после фразы "ОСТРЫЙ не несет ответственности при ношении устройства в запасных карманах Вашего времени") 

Найдите "Англо-русский словарь по программированию" (как-то видел в продаже в книжном магазине и обратил на него внимание) и переводите потихоньку по-старинке - заодно и язык выучите, пригодится. Я в свое время выучил читая хелп для с++.

dzmitry
Offline
Зарегистрирован: 12.08.2012

LEVV2006

Если у вас остались какие-нибудь конкретные вопросы по таймерам, то я с радостью попытаюсь на них ответить (не так давно пришлось разбиратся в этой теме :) )

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

А у меня мечта... с таймерами в STM32 разобраться... :)

dzmitry
Offline
Зарегистрирован: 12.08.2012

:)

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

AlexFisher пишет:

А у меня мечта... с таймерами в STM32 разобраться... :)

 

 

Скоро и у меня такая же мечта появится))))

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

 

Хотел рассказать, чем же закончилась моя эпопея с таймерами))))

Я вроде разобрался, как всё это работает и даже написал «блик» основываясь на таймере. (Кстати данный совет: чем больше вы будите перечитывать информации о таймере, тем лучше поймёте его работу!!!!! Действительно работает!!!! Я начел понимать после 20 прочтений текстов!!!).

Но дело далеко не в блинке. Я делаю свой проект и в нём я решил использовать прерывание по таймеру, чтобы он в свою очередь управлял переменными отвечающие за задержки. К сожалению, я не смог придумать лучить код (г..о-код) для реализации псевдо-многозадачности.

Код который был написан для блинка не стал работать в моём проекте. Я поленился разбираться в чём дело и самая главная отговорка была в том что блинк был написан под МК 328  а проект на 168. Так и задвинул это дело. Выходом из ситуации стала библиотека, которая вроде как стабильно работает.

Почему «вроде». Сейчас я просто не понимаю что происходит с контроллером. У меня для проекта есть две версии кода. Одна вообще убогая, но рабочая (без прерываний и на одних delay). Вторая более менее структурированная и с прерываниями по таймеру.

Дело всё в том, что первая работает как часы: МК не зависает. Одним словом всё чётко!

А вот со второй проблемы и не понятно, какого характера. МК может работать день нормально на второй зависнуть 2 раза подряд. В чём кроется причина так и не ясно. Ковыряюсь с этой проблемой уже месяц. Перелопатил весь код (улучшил его, исправил ошибки, в том числе и ошибки по использованию библиотеке для таймера).

В результате ничего не изменилось. МК по-прежнему зависает правда не часто. А однажды слетела толи прошивка толи eeprom. МК работал, отвечал на нажатия клавиш, но не выполнял никаких действий. Лечился только пере заливкой скетча.

И да оставшейся оперативной памяти после компиляции остаётся много (200). Так что вряд ли зависания от того что заканчивается оперативная память.

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Могу порекомендовать использовать другой таймер или разобраться с вачдогом...

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

 

С вачдогом я тоже разобрался. Я использую другой загрузчик и стандартную библиотеку. В принципе он может решить проблему зависания. Но он не устраняет саму причину.

ich
Offline
Зарегистрирован: 10.06.2012

Ну вот и я "докатился" до прерываний. Как уже было выше написанно: "чем больше об этом читаешь, тем понятнее". Пока я только читал и моргал диодиком, вроде всё понятно. Окончательно разобраться помогла вот эта статья. Понятия не имею почему именно она стала ключём к разгадки, но я кое-что понял.

Но хотелось бы уточнить парачку нюансов:

1) что такое Prescaler и зачем он нужен? (Вроди как для точности счётчика !?)

2) вот по этой формуле высчитывается количество тиков для определённого времени:

Цитата:
(# timer counts + 1) = (target time) / (timer resolution)

т.е. если у меня Prescaler = 1024 и тактер 16MHz то для одной секунды я решаю так:

количество тиков = (1 с) / (1024 / 16000000) = 15625-1 = 15624

но если я прескалер не устанавливал вовсе, как я должен решать? С 0 или с 1 ?

Во я блин даю, пока писал вопрос сам с ним разобрался но один фиг оставлю это на форуме, может кому поможет разобраться с этой темой.

А ответ на мой вопрос "1", ведь МК работает с частотой 16MHz что значит 16000000 "тиков/операций/инструкций или как это ещё называется " в секунду. => чтобы прерыване сработало через 1 сек. нужно подождать 16000000 - 1 = 15999999 "тиков".

К стати вопрос номер (1. что такое Prescaler и зачем он нужен?) так и не отпал. Один  фиг не понятно, если без Prescalerа счётчик считает точней всего, зачем оно тогда надо?

step962
Offline
Зарегистрирован: 23.05.2011

ich пишет:

1) что такое Prescaler и зачем он нужен? (Вроди как для точности счётчика !?)

Ну, можно и так сказать (тогда уж - для снижения точности счета). Скорее, аналогом прескалера в окружающей нас действительность будет селектоор диапазонов радиоприемника: с одним положением ручки "слушаем" УКВ1, с другим - УКВ2, с надцатым и до ДВ добираемся. При этом на шкале самая левая частота больше самой правой (или в другую сторону? давно на приемник не смотрел) в одно и то же число раз - раза в два-четыре (в зависимости от модели приемника):

. Так же и с таймерами - мы либо считаем от 0 до 255 (Т/С0, Т/С2) или от 0 до 65535 (Т/С1) на самой высокой частоте (16 МГц или "УКВ2") или на иной, вплоть до самой низкой (16/1024 - 5,86 кГц или "ДВ"). Отсчитываемые кванты времени г-о-о-ораздо грубее, но зато и охватываемый диапазон в миллисекундах (уже в них) весьма приличный.

ich пишет:

2) вот по этой формуле высчитывается количество тиков для определённого времени:

 (# timer counts + 1) = (target time) / (timer resolution)

т.е. если у меня Prescaler = 1024 и тактер 16MHz то для одной секунды я решаю так:

количество тиков = (1 с) / (1024 / 16000000) = 15625-1 = 15624

но если я прескалер не устанавливал вовсе, как я должен решать? С 0 или с 1 ?

Если переводить дословно, то прескалер суть делитель. Частота без обработки прескалером - суть число без делителя или поделенное на что? Правильно, на единичку.

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Я тоже напишу - как это я понимаю.

Допустим, мы таймером измеряем длину импульса (запуск по переднему фронту, захват значения таймера - по заднему). Тогда:

Точность измерения (относительная) зависит от разрядности счетчика, а абсолютная - от прескалера. И от этих же двух параметров зависит диапазон измерения. Это понятно, что чем точнее, тем лучше, то есть берем 16 - разядный счетчик. Масимальное значение (максимальная длина импулься) будет 65535/16000000=0,0041(с) - тоесть 4,1 мс. Точность измерения ±1 тик, то есть 0,0625 мкс. А если у нас, скажем, импульс 1с ? Вводим прескалер. Для 1024 максимальная длина импульса 4,2 с. Но и точность падает в 1024 раза (получается 64 мкс)

Axell
Offline
Зарегистрирован: 23.03.2013

Здравствуйте..
Подскажите по такому вопросу..Какой таймер/счетчик в Мега 2560 может синхронизироваться с внешней частотой(Т0,Т2)..? Только 2-ой..? Мне необходимо посчитать входящие импульсы и ни одного не пропустить, а так же, если возможно, высчитать их другие параметры(скважность, длительность и т.д.).
И еще..Можно ли в устанавливать биты в регистрах таким образом EIMSK=0x58, TIFR=0x55..?

Спасибо..

step962
Offline
Зарегистрирован: 23.05.2011

Axell пишет:
Здравствуйте.. Подскажите по такому вопросу..Какой таймер/счетчик в Мега 2560 может синхронизироваться с внешней частотой(Т0,Т2)..? Только 2-ой..?

Судя по картинке со схемой единственного 8-битового таймера в этих мегах, считать можно как импульсы от предделителя, так и внешние:

Судя по картинке для таймеров 1,3-5, у них те же возможности по тактированию.

Цитата:
Мне необходимо посчитать входящие импульсы и ни одного не пропустить, а так же, если возможно, высчитать их другие параметры(скважность, длительность и т.д.).

А диапазон интересующих вас частот какой?

Один счетчик запускается в нормальном режиме с тактированием от внешнего источника - вот вам точное количество импульсов за определенный период времени.

Другой счетчик запускается по переднему фронту внешнего сигнала и ведет подсчет системных тактов до момента поступления заднего фронта - вот вам длительность (положительного) импульса.

Третий счетчик запускается по заднему фронту внешнего сигнала и ведет подсчет системных тактов до момента поступления переднего фронта - вот вам длительность паузы.

"Длительность"+"пауза" = "период" вашего сигнала. Скважность определяется простым делением одной величины на другую...

Цитата:
И еще..Можно ли в устанавливать биты в регистрах таким образом EIMSK=0x58, TIFR=0x55..?

А почему бы и нет? Если в описании регистра для всех его битов указано ".../w", то запишете - хоть по-отдельности, хоть скопом. Ну а если не указано - то никак (ну или это не будет иметь никакого влияния на поведение микроконтроллера).

Axell
Offline
Зарегистрирован: 23.03.2013

step962 пишет:

..Другой счетчик запускается по переднему фронту внешнего сигнала и ведет подсчет системных тактов до момента поступления заднего фронта - вот вам длительность (положительного) импульса.

Третий счетчик запускается по заднему фронту внешнего сигнала и ведет подсчет системных тактов до момента поступления переднего фронта - вот вам длительность паузы.

"Длительность"+"пауза" = "период" вашего сигнала. Скважность определяется простым делением одной величины на другую...

А на одном счетчике это сделать разве нельзя..?

У меня мысль реализовать это так: Захват по переднему и вкл.подсчета импульсов, переключение на захват по заднему..По приходу заднего -- записать количество в ячейку, переключение на захват по переднему с продолжением счета..По приходу второго переднего -- остановить счет и вывести оба результата на ЛСД..

Для запуска счетчика 1 мне нужно установить регистр TCCR1B=0x07(внешн.1->0) или TCCR1B=0x06(внешн.0->1) + сбросить флаг переполнения TIFR=0x01(если было), разрешить глобальные прерывания SREG=0x80, TCCR1A=0 и вроде все..Или еще что упустил..?

И еще..Судя по этому синтаксису attachInterrupt(interrupt, function, mode) можно сколько угодно использовать обработчиков прерваний..Я правильно понял..?

step962
Offline
Зарегистрирован: 23.05.2011

Axell пишет:

А на одном счетчике это сделать разве нельзя..?

Можно. После того, как освоитесь с использованием таймеров.

Опять же - все весьма существенно зависит от диапазона частот, который вы пытаетесь оседлать.

Цитата:
И еще..Судя по этому синтаксису attachInterrupt(interrupt, function, mode) можно сколько угодно использовать обработчиков прерваний..Я правильно понял..?

Судить лучше не по синтаксису, а по даташиту. А в даташите (ATmega1280-2560) говорится о восьми векторах запросов внешних прерываний - INT0...INT7. Кстати, судя по описанию функции attachInterrupt(), в Мегах поддерживаются только шесть из них.

Axell
Offline
Зарегистрирован: 23.03.2013

step962 пишет:

Можно. После того, как освоитесь с использованием таймеров.

Уже потихоньку дело идет..Счетчик запускается по прерыванию TNT0, но пока не считает то, что нужно :(

 

step962 пишет:

Опять же - все весьма существенно зависит от диапазона частот, который вы пытаетесь оседлать.

Диапазон частот..Вообщем есть оптический энкодер и мне необходимо измерить кол-во импульсов, которое он выдает..Для начала-окончания отсчета исп.НОЛЬ-метка на нем(подкл. к TNT0)..Скорость вращения энкодера может быть разной(в зависимости от ск-ти вращения двигателя) и период импульсов тоже разный..И нужно подсчитать кол-во импульсов.

На ПИКе было полегче(меньше регистров и таймеров)

Вот это и хочу перенести на Ардуину и использовать ее дополнительные возможности, которых нет на ПИКе

И с Ардуино осилим.. :)

Axell
Offline
Зарегистрирован: 23.03.2013

Подскажите, плизз, с флагами прерываний..Если флаг установлен, то он в 0, а если сброшен, то в 1..Так..?

step962
Offline
Зарегистрирован: 23.05.2011

Axell пишет:

Подскажите, плизз, с флагами прерываний..Если флаг установлен, то он в 0, а если сброшен, то в 1..Так..?

Так.

С точностью до наоборот.

Axell
Offline
Зарегистрирован: 23.03.2013

step962 пишет:

Так.

С точностью до наоборот.

А как же даташит

Цитата:
..can be cleared by writing a ligic one to its bit location

 

step962
Offline
Зарегистрирован: 23.05.2011

Читать следует весь абзац (в конкретном случае даже два, но маленьких):

"When an edge or logic change on the INT1 pin triggers an interrupt request, INTF1 becomes set (one). If the I-bit in SREG and the INT1 bit in EIMSK are set (one), the MCU will jump to the corresponding Interrupt Vector.

The flag is cleared when the interrupt routine is executed. Alternatively, the flag can be cleared by writing a logical one to it. This flag is always cleared when INT1 is configured as a level interrupt."

В (любое) прерывание вы входите с соответствующим флагом прерывания в соответствующем управляющем регистре установленным в единицу. Эта единица сбрасывается аппаратно при выполнении операции IRET. Либо - альтернативно - программным способом, а именно посылкой единицы в соответствующий бит. При этом происходит чудо чудное - была в флаге единица, мы туда посылаем единицу. А в результате получается нулик.

Странно? да не совсем - это особенность флаговых регистров: при засылке битов в них происходит не загрузка бита, а операция двоичного сложения с потерей переноса. Грубо: 1+1 должно получиться 10, но единичка в старший разряд не переносится (это же не арифметический регистр, а флаговый) а просто теряется. То есть получаем 1+1=0...

В результате, кстати, экономится как минимум два программных такта. Ведь для манипуляции битами в тех же портах необходимо:

1) считать значение порта в РОН

2) модифицировать содержимое РОН

3) сохранить значение из РОН в порт

(РОН - регистр общего назначения)

А тут - имеем, скажем, такое состояние флагового регистра: b11110000. Посылаем в флаговый регистр байт b00100000. В итоге получаем в регистре b11010000.  И все это за один такт.

Axell
Offline
Зарегистрирован: 23.03.2013

step962, cпасибо..уже успел и сам разобраться, наложив на TIFR1 маску 0xFF..

Подскажите еще, что не правильно делаю..В прерывании не хочет запускаться Timer1 на тактирование по внешнему сигналу на Т1..

Вот сама функция прерывания..По второму обращению к ней необходимо запустить Counter1, а по третьему -- остановить и сбросить таймер в 0

что здесь не так..?

И вопрос по внешним прерываниям INT0-INT7..При поступлении события на эти прерывания я могу вывести обработку их в отдельные функции(как в attachInterrupt), или мне только через goto можно на них выйти..

step962
Offline
Зарегистрирован: 23.05.2011

Axell пишет:

что здесь не так..?

"не так" здесь прежде всего так называемое "применение магических чисел" (например, TCCR1B=0x06;). Таким образом вы запутываете и себя и тех, к кому вы обращаетесь за советом.

Куда как понятнее было бы написать:

TCCR1B = (1<<CS12) | (1<<CS11);

Сразу видно, что вы пытаетесь установить режим работы предделителя "110" для первого канала таймера 1. Осталось открыть соответствующую табличку и узнать, что это работа от внешнего источника тактовых сигналов по переднему фронту.

Во-вторых - отсутствие комментариев в приводимых участках кода и описания назначения переменных в сопроводительном тексте. Как мне догадаться, для чего служит переменная nul и чем она отличается от переменной nul_s?

В-третьих, приведенный участок кода - это далеко не все, относящееся к теме управления таймером. Что записано в регистр TCCR1A, остается только догадываться, а ведь от этого очень сильно зависит поведение таймера/счетчика.

В-четвертых, как уже предлагалось ранее, ходить надо шагами. А не прыжками. Отладьте части своей задачи (их три, если я правильно помню?) по-отдельности. В процессе отладки более-менее изучите, как настраивается и работает таймер/счетчик. А отладив отдельные подзадачи и повысив уровень своих знаний вы сможете более уверенно браться за решение этих трех подзадач в рамках одной функции.

Цитата:
И вопрос по внешним прерываниям INT0-INT7..При поступлении события на эти прерывания я могу вывести обработку их в отдельные функции(как в attachInterrupt), или мне только через goto можно на них выйти..

Не совсем понятен вопрос. attachInterrupt именно с внешними прерываниями и работает.

Axell
Offline
Зарегистрирован: 23.03.2013

step962, не ругайтесь, мне легче с HEXсом работать, поэтому и пишу так..

Вот пример скетча

А какие таймеры можно подключить на внешнее тактирование в МегаР3..Только Т0 и Т5..?

step962
Offline
Зарегистрирован: 23.05.2011

Axell пишет:

step962, не ругайтесь,

Ну это вы еще не слышали, как я ругаюсь...

Цитата:
мне легче с HEXсом работать, поэтому и пишу так..

И упускаете смысл работаемого. Вот, например, строка 21 ("TCCR5A=0x00;//  обнуляем"). Обнулением регистра это было бы только в том случае, если дальше шла бы установка нужных битов. А так как ее нет (и вообще это единственная инструкция в скетче, где производится манипуляция с регистром TCCR5A), то здесь не обнуление, а установка режима работы таймера, а именно:

WGM51..WGM50=00, да еще WGM53..WGM52=00 (в "обнуляемом" регистре TCCR1B). Итого 0000 - нормальный режим работы счетчика.

Цитата:
А какие таймеры можно подключить на внешнее тактирование в МегаР3..Только Т0 и Т5..?

А тут необходимо внимательно прочитать разделы 16.3, 17.4, 18.1 и 18.3 в даташите, а также посмотреть на   распиновку камня. Можно увидеть, что

T0 - это 50-й вывод (PD7)
T1 - это 49-й вывод (PD6)
T3 - это 8-й вывод (PE6)
T4 - это 27-й вывод (PH7)
T5 - это 37-й вывод (PL2)

Кстати, внешнее прерывание INT0 сидит на 19-м выводе (PB0). Но это так - к слову...

Axell
Offline
Зарегистрирован: 23.03.2013

step962 пишет:

А тут необходимо внимательно прочитать разделы 16.3, 17.4, 18.1 и 18.3 в даташите, а также посмотреть на   распиновку камня. Можно увидеть, что

T0 - это 50-й вывод (PD7)
T1 - это 49-й вывод (PD6)
T3 - это 8-й вывод (PE6)
T4 - это 27-й вывод (PH7)
T5 - это 37-й вывод (PL2)

Кстати, внешнее прерывание INT0 сидит на 19-м выводе (PB0). Но это так - к слову...

Про распиновку и Даташит камня я в курсе...Я про распиновку ArduinoMega 2560R3.

В Ардуине не все прерывания и счетчики можно задействовать..Большинство(Т1,Т3 и Т4) висят в воздухе..Подпоять контакты к ним для меня не проблема..

Axell
Offline
Зарегистрирован: 23.03.2013

step962 пишет:

WGM51..WGM50=00, да еще WGM53..WGM52=00 (в "обнуляемом" регистре TCCR1B). Итого 0000 - нормальный режим работы счетчика.

Но у меня при подключенном внешнем такитровании Т5 на вывод 28 Ардуино счетчик не работает, т.е. он в нуле. Или мне еще надо переключить вывод 37 камня на вход(pinMode(37, INPUT))..?

step962
Offline
Зарегистрирован: 23.05.2011

приводя номера выводов, я имел в виду выводы камня, а не Arduino-платки. Так что тут еще надо перевести 37-й вывод камня в Dxx.

step962
Offline
Зарегистрирован: 23.05.2011

Axell пишет:

Про распиновку и Даташит камня я в курсе...

При этом в скетче никак не упоминается вывод No37 (Dxx?), с которого таймер/счетчик5 будет подсчитывать импульсы в режиме тактирования от внешнего источника.

Axell
Offline
Зарегистрирован: 23.03.2013

step962 пишет:

При этом в скетче никак не упоминается вывод No37 (Dxx?), с которого таймер/счетчик5 будет подсчитывать импульсы в режиме тактирования от внешнего источника.

Я чуть выше написал pinMode(37, INPUT) -- вот этого еще в скетче не хватает..? Или еще какие манипуляции с 37 выводом делать надо..?

 

step962
Offline
Зарегистрирован: 23.05.2011

Да. Необходимо проверить, соответствует ли 37-й вывод камня 37-му выводу Arduino Mega.

 

PS: Судя по этой картинке - нет такого вывода, доступного через плату Arduino Mega.

Axell
Offline
Зарегистрирован: 23.03.2013

step962 пишет:

PS: Судя по этой картинке - нет такого вывода, доступного через плату Arduino Mega.

Эта картинка для Ардуино Мега 2560, а у меня 2560R3..Я выше выкладывал скрин, и там этот вывод задействован на 28 выводе Ардуино..

 

step962
Offline
Зарегистрирован: 23.05.2011

Так какой вывод платы соответствует 37-му выводу камня (т.е. PL2)?