Arduino UNO Совпадение по таймеру 1 с OCR1A

SpectrumGP
Offline
Зарегистрирован: 14.08.2013

Здравствуйте!

С 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) таких проблем не возникало. 

 

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

SpectrumGP пишет:

Работаю напрямую с регистрами TCCR1B, TIMSK1 и OCR1A.

Записываю в OCR1A=10000. Программирую...  Таймер работает по совпадению, но результат аналогичен OCR1A=55 ??? OCR1A=10000-округление(10000/255) Т.е. в регистр воспринимает число не более 255.

Объясните в чем проблема?

Вы бы код показали - как записываете, как программируете...

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

OCR1A=10000L;

Или еще что-то...

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Насколько я понимаю, если правильно записывать 16 битное число, то всё работает прекрасно. Важна последовательность записи, сначала старший байт, потом младший. Здесь, например, можно почитать http://eugenemcu.ru/publ/5-1-0-49.

Да и у нас тут наверняка море вариантов

SpectrumGP
Offline
Зарегистрирован: 14.08.2013

step962 пишет:

Вы бы код показали - как записываете, как программируете...

void setup ()
{
pinMode(7, OUTPUT);
OCR1A=10000;
TCNT1=0;
TCCR1B=0b00001101; // сброс при совпадении и делитель 1024
TIMSK1=0b00000010; // разрешение прерываний по совпадению OCR1A
sei(); 
}

ISR(TIMER1_COMPA_vect)
{
  digitalWrite(7,!digitalRead(7));
} 

sei() можно убрать, результат тот же. Раздельная запись 10000 в верхний и нижний регистры OCR1A  дает тот же результат.

OCR1AL=0x10;
OCR1AH=0x27; 

По интернету полазил... подобные записи кода применяют и все фыркает... но примеры реализованы на Arduino Mega 1280 или 2560

SpectrumGP
Offline
Зарегистрирован: 14.08.2013

kisoft пишет:

Насколько я понимаю, если правильно записывать 16 битное число, то всё работает прекрасно. Важна последовательность записи, сначала старший байт, потом младший. Здесь, например, можно почитать http://eugenemcu.ru/publ/5-1-0-49.

Да и у нас тут наверняка море вариантов

Знакомо :-) В описаниях по микроконтроллерам все это описано.

Проблема только с платформой Arduino UNO возникла. Прямое программирование разрабатываемых устройств через ISP из CodeVision или Avr Studio не вызывает таких проблем.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Может и знакомо, однако Вы почему то пишите

OCR1AL=0x10;
OCR1AH=0x27; 

вместо:

OCR1AH=0x27;
OCR1AL=0x10;

 

SpectrumGP
Offline
Зарегистрирован: 14.08.2013

Результат одинаков :-(

В основном пишу OCR1A=ЧИСЛО; CodeVision AVR без проблем обрабатывает.

SpectrumGP
Offline
Зарегистрирован: 14.08.2013

В общем ситуация такая...

OCR1A=10 -> частота на выходе 709 Гц

OCR1A=50 -> частота на выходе 153 Гц

OCR1A=255 -> частота на выходе 30,49 Гц

OCR1A=510 -> частота на выходе 30,61 Гц

OCR1A=765 -> частота на выходе 30,72 Гц

OCR1A=10000 -> частота на выходе 459 Гц

OCR1A=50000 -> частота на выходе 96 Гц

Вот и не пойму как оно считает...

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

Добавьте к своим кодам инициализации

TCCR1A = 0; 

отпишитесь о результатах.

Попробуйте объяснить причину.

SpectrumGP
Offline
Зарегистрирован: 14.08.2013

step962 пишет:

Добавьте к своим кодам инициализации

TCCR1A = 0; 

отпишитесь о результатах.

Попробуйте объяснить причину.

Спасибо!!!

Уф... наконец... заработало!!! :-))) В CodeVision это описывать не требовалось, он по умолчанию 0 если не описан :-) А в Arduino получается необходимо обрисовывать все. Кстати, строчка в начале работы присутствовала :-))) потом выкинул... Но, дополнительно накопал нюанс, а именно строгая последовательность активации таймера... из-за чего проблема выресовывалась...

Вот так все работает правильно и замечательно:

TCNT1=0;
TCCR1A=0;
TCCR1B=0b00001010;
OCR1A=5000;
TIMSK1=0b00000010;
sei();

или

TCNT1=0;
TCCR1A=0;
OCR1A=5000;
TCCR1B=0b00001010;
TIMSK1=0b00000010;
sei();

Но если OCR1A перенести и поставить выше TCCR1А  или выкинуть TCCR1А ...

TCNT1=0;
OCR1A=5000;
TCCR1A=0;
TCCR1B=0b00001010;
TIMSK1=0b00000010;
sei();
то можно парится целыми днями безрезультатно:-))))
Почему так, это вопрос к создателю ардуины :-))) подозреваю, что зарыто это в компиляторе кода. Таймер имеет какое-то исходное значение заданное ардуиной или вносится загрузчиком... Вывод один обрисовывать все :-)
step962
Offline
Зарегистрирован: 23.05.2011

Нет, все гораздо проще. Компилятор тут ни при чем - это тот же GNU C, что и во многих других пакетах

И гораздо сложнее одновременно. Создатели Arduino IDE создавали среду для неспециалистов, поэтому напридумывали разных аналоговых входов и выходов, которых у микроконтроллеров никогда не бывало, а были блоки ADC и PWM. Напридумывав всяких analogWrite(), они вынуждены были выполнять некоторые начальные настройки тех же таймеров - чтобы ШИМ-режимы присутствовали по умолчанию. Как итог, ШИМ-режимы присутствуют, а о возможных побочных явлениях создатели умалчивают. И действительно, зачем забивать головы неспециалистов, во благо которых все это затевалось. Они же все равно в 99% процентах случаев только по проложенным дорожкам ходят.

В результате регистр TCCR1A имеет в своем самом младшем разряде единичку. Если посмотреть в соответствующую таблицу режимов таймера, WGM10=1 - это режимы 8-/10-битового ШИМа. Так что "по умолчанию" в регистр OCR1A можно записать не более 8 бит информации. Что у вас и происходило.

А эффект "обрезания" вы в любом компиляторе можете воспроизвести, настроив предварительно режим работы таймера на 8-/10-битовый ШИМ...

SpectrumGP
Offline
Зарегистрирован: 14.08.2013

Спасибо... Будем дальше повнимательней :-)

LarryFlint
Offline
Зарегистрирован: 19.02.2022

Огромное спасибо! Почти неделю бился.

Вот прям все встало на свои места.

bwn
Offline
Зарегистрирован: 25.08.2014

LarryFlint пишет:

Огромное спасибо! Почти неделю бился.

Вот прям все встало на свои места.

"Пятнадцать лет он не был дома"(С). ))))