Arduino UNO Совпадение по таймеру 1 с OCR1A
- Войдите на сайт для отправки комментариев
Здравствуйте!
С ATMega работаю давно, в основном 8, 16, 162L. Писал на ассемблере, сейчас в основном работаю в CodeVision AVR на с++.
Сейчас стоит задача собрать велокомпьютер для велостанка с сбросом результатов тренировки на SD карту.
С работой SD в Arduino разобрался, простота работы с SD в Arduino стала основной причиной выбора платформы. (как приклеить SD физически к процессору сообразил и сделал, а вот как программно работать с ней в CodeVision AVR пока не доходит. Если у кого то есть опыт буду очень благодарен за помощь в познании :-) ).
Вопрос по использованию таймеров. А именно 16-ти разрядного Timer1, совпадения по OCR1A или OCR1B.
Обращаться с таймерами умею, запрограммировать и запустить не проблема... В Arduino Uno столкнулся с проблемой совпадения...
Согласно описанию ATMega328P тамймер 1 16-ти разрядный, и регистр OCR1A имеет 16-ть разрядов.
Работаю напрямую с регистрами TCCR1B, TIMSK1 и OCR1A.
Записываю в OCR1A=10000. Программирую... Таймер работает по совпадению, но результат аналогичен OCR1A=55 ??? OCR1A=10000-округление(10000/255) Т.е. в регистр воспринимает число не более 255.
Объясните в чем проблема?
Просто не хотелось бы подключать какие то библиотеки, т.к. прямая работа с тамерами привычней.
При работе непосредственно с процессорами в CodeVision Avr (с++) и Avr Studio (assembler) таких проблем не возникало.
Работаю напрямую с регистрами TCCR1B, TIMSK1 и OCR1A.
Записываю в OCR1A=10000. Программирую... Таймер работает по совпадению, но результат аналогичен OCR1A=55 ??? OCR1A=10000-округление(10000/255) Т.е. в регистр воспринимает число не более 255.
Объясните в чем проблема?
Вы бы код показали - как записываете, как программируете...
А то, м.б., оптимизация какая-нибудь вкралась и поможет добавление явного спецификатора типа, что-то вроде:
OCR1A=10000L;
Или еще что-то...
Насколько я понимаю, если правильно записывать 16 битное число, то всё работает прекрасно. Важна последовательность записи, сначала старший байт, потом младший. Здесь, например, можно почитать http://eugenemcu.ru/publ/5-1-0-49.
Да и у нас тут наверняка море вариантов
Вы бы код показали - как записываете, как программируете...
sei() можно убрать, результат тот же. Раздельная запись 10000 в верхний и нижний регистры OCR1A дает тот же результат.
По интернету полазил... подобные записи кода применяют и все фыркает... но примеры реализованы на Arduino Mega 1280 или 2560
Насколько я понимаю, если правильно записывать 16 битное число, то всё работает прекрасно. Важна последовательность записи, сначала старший байт, потом младший. Здесь, например, можно почитать http://eugenemcu.ru/publ/5-1-0-49.
Да и у нас тут наверняка море вариантов
Знакомо :-) В описаниях по микроконтроллерам все это описано.
Проблема только с платформой Arduino UNO возникла. Прямое программирование разрабатываемых устройств через ISP из CodeVision или Avr Studio не вызывает таких проблем.
Может и знакомо, однако Вы почему то пишите
вместо:
Результат одинаков :-(
В основном пишу OCR1A=ЧИСЛО; CodeVision AVR без проблем обрабатывает.
В общем ситуация такая...
OCR1A=10 -> частота на выходе 709 Гц
OCR1A=50 -> частота на выходе 153 Гц
OCR1A=255 -> частота на выходе 30,49 Гц
OCR1A=510 -> частота на выходе 30,61 Гц
OCR1A=765 -> частота на выходе 30,72 Гц
OCR1A=10000 -> частота на выходе 459 Гц
OCR1A=50000 -> частота на выходе 96 Гц
Вот и не пойму как оно считает...
Добавьте к своим кодам инициализации
отпишитесь о результатах.
Попробуйте объяснить причину.
Добавьте к своим кодам инициализации
отпишитесь о результатах.
Попробуйте объяснить причину.
Спасибо!!!
Уф... наконец... заработало!!! :-))) В CodeVision это описывать не требовалось, он по умолчанию 0 если не описан :-) А в Arduino получается необходимо обрисовывать все. Кстати, строчка в начале работы присутствовала :-))) потом выкинул... Но, дополнительно накопал нюанс, а именно строгая последовательность активации таймера... из-за чего проблема выресовывалась...
Вот так все работает правильно и замечательно:
или
Но если OCR1A перенести и поставить выше TCCR1А или выкинуть TCCR1А ...
Нет, все гораздо проще. Компилятор тут ни при чем - это тот же GNU C, что и во многих других пакетах
И гораздо сложнее одновременно. Создатели Arduino IDE создавали среду для неспециалистов, поэтому напридумывали разных аналоговых входов и выходов, которых у микроконтроллеров никогда не бывало, а были блоки ADC и PWM. Напридумывав всяких analogWrite(), они вынуждены были выполнять некоторые начальные настройки тех же таймеров - чтобы ШИМ-режимы присутствовали по умолчанию. Как итог, ШИМ-режимы присутствуют, а о возможных побочных явлениях создатели умалчивают. И действительно, зачем забивать головы неспециалистов, во благо которых все это затевалось. Они же все равно в 99% процентах случаев только по проложенным дорожкам ходят.
В результате регистр TCCR1A имеет в своем самом младшем разряде единичку. Если посмотреть в соответствующую таблицу режимов таймера, WGM10=1 - это режимы 8-/10-битового ШИМа. Так что "по умолчанию" в регистр OCR1A можно записать не более 8 бит информации. Что у вас и происходило.
А эффект "обрезания" вы в любом компиляторе можете воспроизвести, настроив предварительно режим работы таймера на 8-/10-битовый ШИМ...
Спасибо... Будем дальше повнимательней :-)
Огромное спасибо! Почти неделю бился.
Вот прям все встало на свои места.
Огромное спасибо! Почти неделю бился.
Вот прям все встало на свои места.
"Пятнадцать лет он не был дома"(С). ))))