Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: проблема с Timer/Counter
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Sergei_K
Проблема в следующем: пытаюсь заставить работать примитивную программку со счетчиком: работаю в wave mode 10, то есть записываю некое значение в регистр RC, затем жду сравнения, после чего дергаю ногой.. На выходе имею ступеньку с определенной частотой, которая зависит от кидаемого в RC числа..

Так вот, в результате записи числа, скажем 0xCB, имею частоту, скажем 82,98кГц (для удобства цифры беру из результатов), далее при уменьшении данного числа на 1 вместо ожидаемого изменения частоты имею предыдущую частоту (с точностью до сотых, осциллографу верить можно..) Такая же картина наблюдается при изменении числа на 10 единиц, после чего (то есть на значении 0xС1) наблюдается резкий скачек частоты (84,59кГц) и снова это значение остается при уменьшении числа на 10 единиц.. и т.д.

Теоретические расчеты показавают, что 84,59кГц - адекватная величина, однако.. куда делись промежуточные значения?
Dron_Gus
Цитата(Sergei_K @ Oct 10 2007, 17:35) *
затем жду сравнения, после чего дергаю ногой..


Не совсем понятно, кто дергает ногой. Если сам таймер-счечик, то действительно непонятный глюк. Если же приложение по прерыванию от таймера-счетчика то это естественно.
aaarrr
Цитата(Sergei_K @ Oct 10 2007, 17:35) *
...с точностью до сотых, осциллографу верить можно

Я бы скорее не поверил осциллографу. 10 единиц - очень неподходящая величина для каких-либо глюков контроллера.

Цитата(Sergei_K @ Oct 10 2007, 17:35) *
Теоретические расчеты показавают, что 84,59кГц - адекватная величина

Хм. А у меня получается 87,26кГц...
Sergei_K
Ногой дергает PIO контроллер..

Насчет рассчетов: судя по симмуляции Keil на выставление и снятие высокого уровня на ноге контроллеру нужно выполнить 7 команд.. Осциллограф показывает при этом длительность импульса 140ns, то есть на выполнение одной команды требуется 20ns (50MHz).. Далее, из даташита вычитываем, что на увеличение значения счетчика на одну единицу Timer/Counterу требуется один цикл тактовой частоты.. Таким образом, 20ns * 10, получаем 200ns (реальное же число не 10, а 11.. ранее я округлил.. то есть реально 220ns).. высчитываем частоту: 82,98kHz -> 12,051us, тогда новая частота 12,051-0,220=11,831us -> 84,52kHz
Практическая частота 84,59кГц..

Цитата
Я бы скорее не поверил осциллографу. 10 единиц - очень неподходящая величина для каких-либо глюков контроллера.


не уверен, что правильно вас понял.. Осциллограф современный, тектроникс.. причин не доверять ему у меня нет..
aaarrr
Цитата(Sergei_K @ Oct 11 2007, 10:45) *
Ногой дергает PIO контроллер..

Тогда не понятно, как это дерганье связано с таймером. Опишите всю систему.

Цитата(Sergei_K @ Oct 11 2007, 10:45) *
Далее, из даташита вычитываем, что на увеличение значения счетчика на одну единицу Timer/Counterу требуется один цикл тактовой частоты..

Где такое написано? Максимальная частота таймера - MCK/2.
Dron_Gus
Если Вы ногой дергаете из прерывания - тогда "дисктретность" перестройки вполне понятна... Прерывание епроисходит не моментально и время реакции зависит от текущего состояния. Чем Вас не устраивает "RA Compare Effect on TIOA" и иже с ними?..
Sergei_K
Цитата
Где такое написано? Максимальная частота таймера - MCK/2


это я действительно просчитался, забыл про делитель..

Цитата
Тогда не понятно, как это дерганье связано с таймером. Опишите всю систему


думаю, проще будет привести отрывок из программы..
.....................
pTC_int->TC_RC = Fr_int; // write value to RC

pTC_int->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable clock, start clock

while ((pTC_int->TC_SR & AT91C_TC_CPCS) == 0); // wait for TC RC compare


pPIOB_int->PIO_SODR = 0x80000; // set 1 to PB19

pPIOB_int->PIO_CODR = 0x80000; // clear PB19
.....................

Цитата
Если Вы ногой дергаете из прерывания - тогда "дисктретность" перестройки вполне понятна...


с прерываниями там еще интересней получается, поэтому пока программа максимально упрощена..
aaarrr
Цитата(Sergei_K @ Oct 11 2007, 13:56) *
while ((pTC_int->TC_SR & AT91C_TC_CPCS) == 0); // wait for TC RC compare

На частоте таймера MCK/2, конечно, получится ерунда - эта проверка выполняется много дольше, чем за 2 такта процессора. Если хотите генерировать стабильный сигнал наружу, используйте выходы TIOA/TIOB.
Sergei_K
Цитата(aaarrr @ Oct 11 2007, 17:34) *
На частоте таймера MCK/2, конечно, получится ерунда - эта проверка выполняется много дольше, чем за 2 такта процессора. Если хотите генерировать стабильный сигнал наружу, используйте выходы TIOA/TIOB.


Что-то я вас не понял.. ну и что, что она выполняется болше, чем 2 такта.. При одном значении регистра RC она выполняется одно время.. запишем в регистр число немного большее (меньшее), и она будет выполняться немного дольше (быстрее).. разве не так?
aaarrr
Я не о том. Вот этот фрагмент кода:
Код
while ((pTC_int->TC_SR & AT91C_TC_CPCS) == 0); // wait for TC RC compare

выполняется за время большее, чем нужно таймеру для инкремента.
То есть если, допустим, в RC записано значение 100, то на момент выхода из цикла while таймер будет иметь значение больше 100 (102 - 110, в зависимости от оптимизации, расположения звезд и т.п.), и это число будет плавать от цикла к циклу.
Sergei_K
Цитата(aaarrr @ Oct 12 2007, 16:55) *
Я не о том. Вот этот фрагмент кода:
Код
while ((pTC_int->TC_SR & AT91C_TC_CPCS) == 0); // wait for TC RC compare

выполняется за время большее, чем нужно таймеру для инкремента.
То есть если, допустим, в RC записано значение 100, то на момент выхода из цикла while таймер будет иметь значение больше 100 (102 - 110, в зависимости от оптимизации, расположения звезд и т.п.), и это число будет плавать от цикла к циклу.



Так хорошо бы оно плавало, но, как я уже говорил, реально ничего не плавает.. идут 11 одинаковых значений, затем скачок.. Показания осциллографа проверены, полностью совпадают с показаниями частотомера.. (до сотых)

Попробовал использовать TIOA, результат полностью аналогичен предыдущему..
aaarrr
Цитата(Sergei_K @ Oct 12 2007, 14:59) *
Так хорошо бы оно плавало, но, как я уже говорил, реально ничего не плавает.. идут 11 одинаковых значений, затем скачок.. Показания осциллографа проверены, полностью совпадают с показаниями частотомера.. (до сотых)

Оно может плавать, а может и не плавать - зависит, как я уже писал, от многих факторов.

Цитата(Sergei_K @ Oct 12 2007, 14:59) *
Попробовал использовать TIOA, результат полностью аналогичен предыдущему..

Как пробовали? Настройками таймера?
Dron_Gus
Я думаю Вам хотели сказать, что Ваша конструкция while ((pTC_int->TC_SR & AT91C_TC_CPCS) == 0); состоит из нескольких команд. Поэтому вы получаете "степеньку" при перестройке частоты.

Например в виде машинных кодов это выглядит так:

0) загрузить pTC_int->TC_SR
1) применить маску AT91C_TC_CPCS
2) сравнить результат с 0
3) если нет прыжок на 5
4) если да - прыжок на 0.

И это все у вас бесконечно крутиться. Теперь представьте, что перед тем как бит AT91C_TC_CPCS взвелся эта проверка прокрутилась 9 раз и сейчас выполняется команда 1. Т.к. в неком регистре соедержится еще старое значение регистра pTC_int->TC_SR с НЕВЗВЕДЕННЫМ флагом AT91C_TC_CPCS то цикл все равно повторяется 10 раз. Теперь вы меняете значение делителя на 1 (2, 3...) и в этот раз эта проверка выполняется все те же 9 раз, только бит взводится на 2, 3, 4 команде. Какое время пройдет до "прыжка на 5"? Все то же.

Именно поэтому Вам советуют использовать спечиальные выводы, которыми счетчик-таймер будет управлять независимо от ядра. Читайте раздел по таймеру и pio.
Ivan_Petrov
Частоты переферийного блока и процессора могут отличатся, и для того чтобы их синхронизировать через регистры управления может понадобится какоето время (если писали подобные блоки под плисы, то думаю поймете о чем я). Как вариант, можно попробовать сбрасывать переферийны блок перед каждой инициализацией, синхронный сброс обычно проходит за 1 такт.
Если важна стабилность отклика, то лучше использовать
Цитата
TIOA, TIOB
или выводы PWM контроллера.
aaarrr
Таймер и так сбрасывается по SWTRG, только вот на делители входных частот этот сброс не распространяется.
Ivan_Petrov
Цитата(aaarrr @ Oct 13 2007, 23:52) *
Таймер и так сбрасывается по SWTRG, только вот на делители входных частот этот сброс не распространяется.

Я имел ввиду сброс по SWRST, который присутсвует почти во всех переферийных блоках, но в таймере его нет, извиняюсь недосмотрел.
Sergei_K
Цитата(aaarrr @ Oct 12 2007, 18:09) *
Как пробовали? Настройками таймера?


ну естественно.. а как же еще..
прописал бит ACPC (RC Compare Effect on TIOA) на переключение уровня.. Настроил PIO на работу с периферией A..

Результат: переключает уровни на TIOA при сравнении с RC.. в целом же картина с увеличением (уменьшением) значения в RC, как уже говорил, не изменилась..
Dron_Gus
Выкладывайте код - будут советы...
Sergei_K
Цитата(Dron_Gus @ Oct 17 2007, 02:20) *
Выкладывайте код - будут советы...


инициализация..
.................................
pTC->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | // TIMER_CLOCK1 selected
AT91C_TC_WAVE | // waveform mode
AT91C_TC_WAVESEL_UP_AUTO | // WAVSEL=10
AT91C_TC_CPCSTOP | // stop clock
AT91C_TC_CPCDIS | // disable clock
AT91C_TC_ACPC_TOGGLE; // RC Compare Effect on TIOA

*AT91C_PMC_PCER = (1<<AT91C_ID_TC1); // enable TC1
pPMC->PMC_MCKR = AT91C_PMC_CSS_PLL_CLK | // select PLL clock
AT91C_PMC_PRES_CLK; // selected clock divided by 1

pPIOB->PIO_PDR = ((unsigned int) 0x1 << 25); // disable PB25
pPIOB->PIO_ODR = ((unsigned int) 0x1 << 25); // disable PB25 to be driven
pPIOB->PIO_ASR = ((unsigned int) 0x1 << 25); // enable Peripheral A
.................................

программа..
.................................

pTC_int->TC_RC = Fr_int; // write value to RC
pTC_int->TC_CCR = AT91C_TC_CLKEN | // enable clock
AT91C_TC_SWTRG; // start clock

while ((pTC_int->TC_SR & AT91C_TC_CPCS) == 0); // wait for TC RC compare
..................................

собственно, все..
aaarrr
Цитата(Sergei_K @ Oct 17 2007, 12:33) *
AT91C_TC_CPCSTOP | // stop clock
AT91C_TC_CPCDIS | // disable clock

Т.е. запукается таймер один раз - откуда тогда частота берется? И в RA ничего не пишется.
Вопросов меньше не стало.
Sergei_K
Цитата(aaarrr @ Oct 17 2007, 15:46) *
Т.е. запукается таймер один раз - откуда тогда частота берется? И в RA ничего не пишется.
Вопросов меньше не стало.


то, что инициализация, выполняется один раз..
то, что программа, естественно, зацикленно.. просто мне казалось, что это очевидно..
таким образом, таймер запускается каждый раз при выполнении:
Цитата
pTC_int->TC_CCR = AT91C_TC_CLKEN | // enable clock
AT91C_TC_SWTRG; // start clock


RA не используется.. используется только RC.. Как видно, уровень на ноге переключается при RC сравнении..
aaarrr
Цитата(Sergei_K @ Oct 22 2007, 13:14) *
просто мне казалось, что это очевидно..

Нет, далеко не очевидно.

Цитата(Sergei_K @ Oct 22 2007, 13:14) *
таким образом, таймер запускается каждый раз при выполнении:
RA не используется.. используется только RC.. Как видно, уровень на ноге переключается при RC сравнении..

И что Вы тогда пытались получить на RA здесь:
Цитата(Sergei_K @ Oct 16 2007, 17:17) *
прописал бит ACPC (RC Compare Effect on TIOA) на переключение уровня.. Настроил PIO на работу с периферией A..
???????

Еще раз повторяю, что конструкция:
Код
while ((pTC_int->TC_SR & AT91C_TC_CPCS) == 0); // wait for TC RC compare

может дать непредсказуемое дрожание фазы.
Если хотите что-то измерять, перезапускайте таймер аппаратными средствами - режим WAVSEL = 10 придуман именно для этого.
Sergei_K
Цитата
И что Вы тогда пытались получить на RA..


что-то либо я ничего не понимаю, либо вы меня неправильно поняли.. Я в принципе с регистром RA не работаю и получить от него ничего не хотел и не хочу.. Когда счетчик досчитывает до значения, помещенного в регистр RC (для этого как раз устанавливается бит прописал бит ACPC), на портовой ножке TIOA происходит смена уровня..

Цитата
Если хотите что-то измерять, перезапускайте таймер аппаратными средствами - режим WAVSEL = 10 придуман именно для этого


не уверен, что понял вас правильно.. Каким образом это делается?
aaarrr
Цитата(Sergei_K @ Oct 23 2007, 15:44) *
не уверен, что понял вас правильно.. Каким образом это делается?

Уберите из инициализации AT91C_TC_CPCSTOP и AT91C_TC_CPCDIS, тогда таймер будет автоматически перезапускаться при достижении значения, записанного в RC.
После этого можно будет достоверно измерять частоту.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.