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

Обсуждаем контроллеры компании Atmel.
Ответить
Встал на лапы
Аватара пользователя
Сообщения: 134
Зарегистрирован: Пн ноя 07, 2016 12:14:14

Сообщение bezzabotna »

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

#define BUTTON_UP		(1<<PD4)							//4 ножка
#define BUTTON_DOWN		(1<<PD5)							//5 ножка
#define BUTTON_START	(1<<PD6)							//6 ножка
#define BUTTON_STOP		(1<<PD7)							//7 ножка
Я конечно все понимаю, но этого я не понимаю.
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 677
Зарегистрирован: Чт янв 20, 2011 09:07:08
Откуда: Пермь

Сообщение prinv »

Смотрю я ваш BUTTON_Handler - что-то больно накручено. Некоторые куски кода вообще никогда не выполнятся.
Например, секция else

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

   if (!(PIND & pin_state))                        //если кнопка физически нажата (логический 0 на n ножке порта D)
   {
      if(Button_count<20)   Button_count++;               //подавление дребезга при нажатии (кнопка физически нажата 20 тактов)
      else
      {
         Button_state=1;                           //регистрируем нажатие кнопки
         key_delay++;                           //как долго кнопка нажата
      }
Никакая контра не уйдёт от нас
Контактная информация:
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 134
Зарегистрирован: Пн ноя 07, 2016 12:14:14

Сообщение bezzabotna »

Почему? Я этот кусок кода на stm32 использовала, на реальном камне. Все работало. Но там естественно по другому выглядит условие физического нажатия.
Может условие иначе надо прописать?
Я конечно все понимаю, но этого я не понимаю.
Вымогатель припоя
Аватара пользователя
Сообщения: 677
Зарегистрирован: Чт янв 20, 2011 09:07:08
Откуда: Пермь

Сообщение prinv »

Как почему? У вас при вызове функции Button_count = 0.
И потом вы проверяете Button_count<20
У вас никогда Button_count никогда не станет больше 20, следовательно ветка else никогда не выполнится.

Вот здесь наоборот - только ветка else и будет выпоняться, в которой условие key_delay<20000 будет выполняться всегда.

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

      if (Button_count>0)Button_count--;               //подавление дребезга при отжатии
      else
      {
         Button_state=0;                           //регистрируем отжатие кнопки
         if (key_delay<20000)   Flag=1;               //регистрируем короткое нажатие
         else               Flag=2;               //регистрируем длительное нажатие
      
Но это всё уже к таймерам отношения не имеет, imho.
Никакая контра не уйдёт от нас
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Встал на лапы
Аватара пользователя
Сообщения: 134
Зарегистрирован: Пн ноя 07, 2016 12:14:14

Сообщение bezzabotna »

Спасибо, буду разбирать
Я конечно все понимаю, но этого я не понимаю.
Реклама
afz
Опытный кот
Аватара пользователя
Сообщения: 744
Зарегистрирован: Сб дек 22, 2012 08:17:42
Откуда: Караганда, Казахстан

Сообщение afz »

bezzabotna писал(а):int Button_count=0,Button_state=0,key_delay=0,Flag=0; //служебные переменные
Неудивительно, что кнопки не опознаются. Процитированная строка по каждому прерыванию от таймера инитит эти самые служебные переменные, поэтому при сравнении if'ами в Button_count ничего, кроме единицы, быть не может.

Когда-то я решал подобную задачу - принять данные с сильно дребезжащего контакта. Я тогда, по-простому, сделал программные аналоги последовательно включенных интегратора и триггера Шмидта. Аналоги грубые, сильно упрощенные, тем не менее...

Итак, предположим, что таймерные прерывания у нас будут с периодом 1 мс (1 кГц). Заводим в статической памяти, вне (до) всех функций (чтобы не возиться с передачей параметров) табличку, которая для каждой из кнопок содержит следующие данные (навскидку)
1) время замкнутого состояния контактов кнопки.
2) флажок "распознанное состояние кнопки"
3) флажок "предыдущее состояние кнопки"
4) (возможно) флажок "состояние кнопки изменилось" в качестве сигнала главной программе, мол проснись и поработай. :)
5) (если нужно) время распознанного нажатого состояния кнопки, например, для распознавания коротких и длительных нажатий.

При инициализации, обязательно до разрешения таймерных прерываний, все эти поля надо очистить (обнулить).

В программе прерывания по таймеру, для каждой изх кнопок, проверяем, замкнута она, или нет. Если замкнута, инкрементируем поле (1) и, если оно совпадет с порогом срабатывания "триггера Шмидта", взводим флажок (2), если надо, сравниваем этот флажок с (3) и, если они не совпадают взводим флажок (4) и обновляем (3). Далее проверим, не пора ли нашему "интегратору" входить в насыщение. если да, организовываем это насыщение, то есть отменяем инкремент поля (1). Здесь же, обнаружив распознанное состояние кнопки, можно начать инкрементировать (5) и, обнаружив длительное нажатие, послать соответствующий сигнал.

Если же кнопик разомкнут, декрементируем поле (1) и, если оно совпадает с порогом отпускания триггера Шмитта, очищаем флажок (2) и, опять же, сравниваем (2) и (3), действия при несовпадении те же, что и выше. Далее, опять же, проверяем на насыщение (отрицательное), то есть, если (1) станет отрицательным, обнуляем его, и вперед.

Теперь о порогах. Навскидку, порог отпускания триггера Шмитта нужно взять 5-10, порог срабатывания его же - 20-25 и порог насыщения - на 5-10 больше, чем порог срабатывания.

А основная программа должна мониторить поля (2) каждой из кнопок и, обнаружив нажатие, предпринимать соответствующие действия. Или, может быть, флажок (4), если он очищен, можно заснуть (Sleep). Может быть флажок (4) нужен не каждой кнопке, а один на всех, это уже по вкусу.

Да, зачем для этого дела 16-битный таймер 1 ? Там и 8-битного за глаза, только нужен таймер с Clear to Compare (CTC). У 8-й Меги это Т2, 328-ю я наизусть не помню. А так, прескалером делим на 1024, даже из 20 МГц получим порядка 20 кГц, делим таймером на 20 и вот он, желаемый 1 кГц прерываний. Да, 1024 - это не 1000, но точность этой миллисекунды здесь и даром не нужна.
bezzabotna писал(а):Почему? Я этот кусок кода на stm32 использовала, на реальном камне. Все работало.
Может быть неудачно скопипастила?
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 677
Зарегистрирован: Чт янв 20, 2011 09:07:08
Откуда: Пермь

Сообщение prinv »

[uquote="afz",url="/forum/viewtopic.php?p=3396503#p3396503"]Заводим в статической памяти, вне (до) всех функций (чтобы не возиться с передачей параметров) табличку, которая для каждой из кнопок содержит следующие данные (навскидку)[/uquote]
Можно завести и внутри обработчика, только с использованием модификатора static - так будет правильнее в точки зрения области видимости переменных.
Никакая контра не уйдёт от нас
Контактная информация:
afz
Опытный кот
Аватара пользователя
Сообщения: 744
Зарегистрирован: Сб дек 22, 2012 08:17:42
Откуда: Караганда, Казахстан

Сообщение afz »

Нет, здесь, как раз, нужна довольно широкая видимость. Таблицу надо проинитить, ее надо видеть из программы обслуживания прерывания, по крайней мере, флажки нужно видеть в программе реакции на нажатие клавиш, там же нужен счетчик длительного нажатия, в общем, проще сделать полную видимость этой таблицы везде и не морочить себе голову.
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Встал на лапы
Аватара пользователя
Сообщения: 121
Зарегистрирован: Пт сен 04, 2015 13:10:49
Откуда: г. Ижевск

Сообщение artemik32 »

Добрый день! Подскажите пожалуйста, как сделать, чтобы в режиме ШИМ - два канала таймера работали попеременно, т.е. допустим на канале А идут импульсы ШИМ, а на канале В - никаких импульсов не должно быть, даже "иголок". А то даже при OCR0B = 0, присутствуют "иголки". Два канала таймера работают на Н-мост и поэтому из-за "иголок" происходит "сквозняк". Можно ли выключить отдельно тот или другой канал?
Истина где-то рядом...
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18751
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

artemik32 писал(а):Можно ли выключить отдельно тот или другой канал?
во-первых, можно выключить. во-вторых, иголки - это, как правило, ЕСТЕСТВЕННОЕ состояние для Fast-PWM при одном из "крайних" значений регистра сравнения.
то есть либо надо выбирать правильный режим PWM, либо отключать канал программно в нужный момент. вы же как-то включали оба канала? значит, и выключить один сумеете.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Это не хвост, это антенна
Сообщения: 1491
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

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

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

Подскажите, пожалуйста, в каких моделях AVR, кроме ATtiny2313A, есть одновременно 16-битный таймер с захватом и 8-битный с внешними входом и выходом?
afz
Опытный кот
Аватара пользователя
Сообщения: 744
Зарегистрирован: Сб дек 22, 2012 08:17:42
Откуда: Караганда, Казахстан

Сообщение afz »

Детально я, конечно, не вникал, но у Мег 48-88-168-328 блок-схема таймера 0 та же, что и у 2313А. Да и у 16-й (без А) у таймера 0 есть вход и выход. Как мне кажется, только у 8-й Меги такого нет, у остальных Мег должно быть.
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Собутыльник Кота
Аватара пользователя
Сообщения: 2896
Зарегистрирован: Сб ноя 13, 2010 12:53:25
Откуда: приходит весна?

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

Понятно, спасибо. Что-то 8-я мега какая-то обделённая получается. У всех другим мег есть такой таймер, а у 8-й нет. А у меня их целых три не при делах лежит.
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Доброго времени суток. Прошу прощения за нубский вопрос. Смотрю даташит на Мегу8, а именно на режимы работы Timer1, и вижу, что режим 4 фактически идентичен режиму 12, режим 8 - режиму 9, режим 10 - режиму 11, а режим 13 - режиму 14. Все эти пары режимов отличаются только регистром, из которого они берут значение для сравнения. В одном случае это ICR1, во втором - OCR1A. И я не понимаю, зачем было так делать, ведь режим таймера может быть включен все равно только один. Какой тогда смысл в таком дублировании ? Может быть я чего-то не понимаю, тогда приведите пожалуйста пример, когда такая организация может пригодится.
Собутыльник Кота
Аватара пользователя
Сообщения: 2896
Зарегистрирован: Сб ноя 13, 2010 12:53:25
Откуда: приходит весна?

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

У таймера 1 есть два выхода: OC1A и OC1B. При реализации ШИМа каждый из этих выходов управляется, соответственно, регистрами OCR1A и OCR1B. Если нужен ШИМ с какой-нибудь нестандартной длительностью, то нужен ещё один регистр для хранения этого нестандартного потолка таймера. Этим регистром может являться либо OCR1A, либо ICR1. Если использовать первый регистр, то невозможно будет управлять скважностью канала A, то есть сразу лишимся одного ШИМ-канала. Если же использовать второй регистр, то не будет возможности использовать захват по событию.

Конструкторы чипа просто предоставили своим коллегам, которые этот чип будут использовать в своих разработках, некоторую гибкость: можно в зависимости от потребностей использовать тот или иной регистр. Хотя, разумеется, наиболее правильно было бы завести для этого дела отдельный регистр. Но AVR — это не STM32 с её четырьмя гигабайтами на всё-про-всё. У AVR область портов ввода-вывода ограничена. Поэтому конструкторы решили сэкономить: использовать регистры с двойным назначением в зависимости от режима.
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

[uquote="B@R5uk",url="/forum/viewtopic.php?p=3430214#p3430214"]... Если нужен ШИМ с какой-нибудь нестандартной длительностью...[/uquote]
Спасибо, вроде как кое-что прояснилось. Но не все :oops: Непонятно, что значит "нестандартной длительностью" ?
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

не равной разрядности счетчика, а с любым числом, например 100 (будет шим ровно в 100 шагов, например для получения шага ровно в 1%)
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Спасибо за разъяснение.
Встал на лапы
Сообщения: 99
Зарегистрирован: Сб апр 28, 2018 20:29:42

Сообщение Dream555 »

Всем привет!

Предисловие:
Я делаю себе таймер на ATmeg48 с внутренним тактированием от RC 8MHz. Хочу повесить часовой кварц для точного счета.

А вот теперь вопрос:
Правильно ли я понимаю, что для данной задачи подойдет только Timer/Counter2? По крайней мере в даташите говориться, что для асинхронного тактирования используется этот счетчик.
Ответить

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